1/************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 4 * Copyright (c) 2008-2010 VMware, Inc. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29 30/** 31 * Mesa / Gallium format conversion and format selection code. 32 * \author Brian Paul 33 */ 34 35 36#include "main/context.h" 37#include "main/enums.h" 38#include "main/formats.h" 39#include "main/glformats.h" 40#include "main/texcompress.h" 41#include "main/texgetimage.h" 42#include "main/teximage.h" 43#include "main/texstore.h" 44#include "main/image.h" 45#include "main/macros.h" 46#include "main/formatquery.h" 47 48#include "pipe/p_context.h" 49#include "pipe/p_defines.h" 50#include "pipe/p_screen.h" 51#include "util/format/u_format.h" 52#include "st_cb_texture.h" 53#include "st_context.h" 54#include "st_format.h" 55#include "st_texture.h" 56 57 58/** 59 * Translate Mesa format to Gallium format. 60 */ 61enum pipe_format 62st_mesa_format_to_pipe_format(const struct st_context *st, 63 mesa_format mesaFormat) 64{ 65 struct pipe_screen *screen = st->screen; 66 67 /* The destination RGBA format mustn't be changed, because it's also 68 * a destination format of the unpack/decompression function. 69 */ 70 if (mesaFormat == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1) 71 return st->transcode_etc ? PIPE_FORMAT_DXT1_RGB : PIPE_FORMAT_R8G8B8A8_UNORM; 72 73 /* ETC2 formats are emulated as uncompressed ones. 74 * The destination formats mustn't be changed, because they are also 75 * destination formats of the unpack/decompression function. 76 */ 77 if (_mesa_is_format_etc2(mesaFormat) && !st->has_etc2) { 78 bool has_bgra_srgb = screen->is_format_supported(screen, 79 PIPE_FORMAT_B8G8R8A8_SRGB, 80 PIPE_TEXTURE_2D, 0, 0, 81 PIPE_BIND_SAMPLER_VIEW); 82 83 switch (mesaFormat) { 84 case MESA_FORMAT_ETC2_RGB8: 85 return st->transcode_etc ? PIPE_FORMAT_DXT1_RGB : PIPE_FORMAT_R8G8B8A8_UNORM; 86 case MESA_FORMAT_ETC2_SRGB8: 87 return st->transcode_etc ? PIPE_FORMAT_DXT1_SRGB : 88 has_bgra_srgb ? PIPE_FORMAT_B8G8R8A8_SRGB : PIPE_FORMAT_R8G8B8A8_SRGB; 89 case MESA_FORMAT_ETC2_RGBA8_EAC: 90 return st->transcode_etc ? PIPE_FORMAT_DXT5_RGBA : PIPE_FORMAT_R8G8B8A8_UNORM; 91 case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: 92 return st->transcode_etc ? PIPE_FORMAT_DXT5_SRGBA : 93 has_bgra_srgb ? PIPE_FORMAT_B8G8R8A8_SRGB : PIPE_FORMAT_R8G8B8A8_SRGB; 94 case MESA_FORMAT_ETC2_R11_EAC: 95 return PIPE_FORMAT_R16_UNORM; 96 case MESA_FORMAT_ETC2_RG11_EAC: 97 return PIPE_FORMAT_R16G16_UNORM; 98 case MESA_FORMAT_ETC2_SIGNED_R11_EAC: 99 return PIPE_FORMAT_R16_SNORM; 100 case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: 101 return PIPE_FORMAT_R16G16_SNORM; 102 case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: 103 return st->transcode_etc ? PIPE_FORMAT_DXT1_RGBA : PIPE_FORMAT_R8G8B8A8_UNORM; 104 case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: 105 return st->transcode_etc ? PIPE_FORMAT_DXT1_SRGBA : 106 has_bgra_srgb ? PIPE_FORMAT_B8G8R8A8_SRGB : PIPE_FORMAT_R8G8B8A8_SRGB; 107 default: 108 unreachable("Unknown ETC2 format"); 109 } 110 } 111 112 if (st_astc_format_fallback(st, mesaFormat)) { 113 if (_mesa_is_format_srgb(mesaFormat)) { 114 return st->transcode_astc ? PIPE_FORMAT_DXT5_SRGBA : 115 PIPE_FORMAT_R8G8B8A8_SRGB; 116 } else { 117 return st->transcode_astc ? PIPE_FORMAT_DXT5_RGBA : 118 PIPE_FORMAT_R8G8B8A8_UNORM; 119 } 120 } 121 122 return mesaFormat; 123} 124 125 126/** 127 * Translate Gallium format to Mesa format. 128 */ 129mesa_format 130st_pipe_format_to_mesa_format(enum pipe_format format) 131{ 132 mesa_format mf = format; 133 if (!_mesa_get_format_name(mf)) 134 return MESA_FORMAT_NONE; 135 return mf; 136} 137 138/** 139 * Map GL texture formats to Gallium pipe formats. 140 */ 141struct format_mapping 142{ 143 GLenum glFormats[18]; /**< list of GLenum formats, 0-terminated */ 144 enum pipe_format pipeFormats[14]; /**< list of pipe formats, 0-terminated */ 145}; 146 147 148#define DEFAULT_RGBA_FORMATS \ 149 PIPE_FORMAT_R8G8B8A8_UNORM, \ 150 PIPE_FORMAT_B8G8R8A8_UNORM, \ 151 PIPE_FORMAT_A8R8G8B8_UNORM, \ 152 PIPE_FORMAT_A8B8G8R8_UNORM, \ 153 0 154 155#define DEFAULT_RGB_FORMATS \ 156 PIPE_FORMAT_R8G8B8X8_UNORM, \ 157 PIPE_FORMAT_B8G8R8X8_UNORM, \ 158 PIPE_FORMAT_X8R8G8B8_UNORM, \ 159 PIPE_FORMAT_X8B8G8R8_UNORM, \ 160 PIPE_FORMAT_B5G6R5_UNORM, \ 161 DEFAULT_RGBA_FORMATS 162 163#define DEFAULT_SRGBA_FORMATS \ 164 PIPE_FORMAT_R8G8B8A8_SRGB, \ 165 PIPE_FORMAT_B8G8R8A8_SRGB, \ 166 PIPE_FORMAT_A8R8G8B8_SRGB, \ 167 PIPE_FORMAT_A8B8G8R8_SRGB, \ 168 0 169 170#define DEFAULT_DEPTH_FORMATS \ 171 PIPE_FORMAT_Z24X8_UNORM, \ 172 PIPE_FORMAT_X8Z24_UNORM, \ 173 PIPE_FORMAT_Z16_UNORM, \ 174 PIPE_FORMAT_Z24_UNORM_S8_UINT, \ 175 PIPE_FORMAT_S8_UINT_Z24_UNORM, \ 176 0 177 178#define DEFAULT_SNORM8_RGBA_FORMATS \ 179 PIPE_FORMAT_R8G8B8A8_SNORM, \ 180 0 181 182#define DEFAULT_UNORM16_RGBA_FORMATS \ 183 PIPE_FORMAT_R16G16B16A16_UNORM, \ 184 DEFAULT_RGBA_FORMATS 185 186 187/** 188 * This table maps OpenGL texture format enums to Gallium pipe_format enums. 189 * Multiple GL enums might map to multiple pipe_formats. 190 * The first pipe format in the list that's supported is the one that's chosen. 191 */ 192static const struct format_mapping format_map[] = { 193 /* Basic RGB, RGBA formats */ 194 { 195 { GL_RGB10, 0 }, 196 { PIPE_FORMAT_R10G10B10X2_UNORM, PIPE_FORMAT_B10G10R10X2_UNORM, 197 PIPE_FORMAT_R10G10B10A2_UNORM, PIPE_FORMAT_B10G10R10A2_UNORM, 198 DEFAULT_RGB_FORMATS } 199 }, 200 { 201 { GL_RGB10_A2, 0 }, 202 { PIPE_FORMAT_R10G10B10A2_UNORM, PIPE_FORMAT_B10G10R10A2_UNORM, 203 DEFAULT_RGBA_FORMATS } 204 }, 205 { 206 { 4, GL_RGBA, GL_RGBA8, 0 }, 207 { PIPE_FORMAT_R8G8B8A8_UNORM, DEFAULT_RGBA_FORMATS } 208 }, 209 { 210 { GL_BGRA, 0 }, 211 { DEFAULT_RGBA_FORMATS } 212 }, 213 { 214 { 3, GL_RGB, GL_RGB8, 0 }, 215 { PIPE_FORMAT_R8G8B8X8_UNORM, DEFAULT_RGB_FORMATS } 216 }, 217 { 218 { GL_RGB12, GL_RGB16, 0 }, 219 { PIPE_FORMAT_R16G16B16X16_UNORM, PIPE_FORMAT_R16G16B16A16_UNORM, 220 DEFAULT_RGB_FORMATS } 221 }, 222 { 223 { GL_RGBA12, GL_RGBA16, 0 }, 224 { PIPE_FORMAT_R16G16B16A16_UNORM, DEFAULT_RGBA_FORMATS } 225 }, 226 { 227 { GL_RGBA4, GL_RGBA2, 0 }, 228 { PIPE_FORMAT_B4G4R4A4_UNORM, PIPE_FORMAT_A4B4G4R4_UNORM, 229 DEFAULT_RGBA_FORMATS } 230 }, 231 { 232 { GL_RGB5_A1, 0 }, 233 { PIPE_FORMAT_B5G5R5A1_UNORM, PIPE_FORMAT_A1B5G5R5_UNORM, 234 DEFAULT_RGBA_FORMATS } 235 }, 236 { 237 { GL_R3_G3_B2, 0 }, 238 { PIPE_FORMAT_B2G3R3_UNORM, PIPE_FORMAT_R3G3B2_UNORM, 239 PIPE_FORMAT_B5G6R5_UNORM, PIPE_FORMAT_B5G5R5A1_UNORM, 240 DEFAULT_RGB_FORMATS } 241 }, 242 { 243 { GL_RGB4, 0 }, 244 { PIPE_FORMAT_B4G4R4X4_UNORM, PIPE_FORMAT_B4G4R4A4_UNORM, 245 PIPE_FORMAT_A4B4G4R4_UNORM, 246 DEFAULT_RGB_FORMATS } 247 }, 248 { 249 { GL_RGB5, 0 }, 250 { PIPE_FORMAT_B5G5R5X1_UNORM, PIPE_FORMAT_X1B5G5R5_UNORM, 251 PIPE_FORMAT_B5G5R5A1_UNORM, PIPE_FORMAT_A1B5G5R5_UNORM, 252 DEFAULT_RGB_FORMATS } 253 }, 254 { 255 { GL_RGB565, 0 }, 256 { PIPE_FORMAT_B5G6R5_UNORM, DEFAULT_RGB_FORMATS } 257 }, 258 259 /* basic Alpha formats */ 260 { 261 { GL_ALPHA12, GL_ALPHA16, 0 }, 262 { PIPE_FORMAT_A16_UNORM, PIPE_FORMAT_R16G16B16A16_UNORM, 263 PIPE_FORMAT_A8_UNORM, DEFAULT_RGBA_FORMATS } 264 }, 265 { 266 { GL_ALPHA, GL_ALPHA4, GL_ALPHA8, GL_COMPRESSED_ALPHA, 0 }, 267 { PIPE_FORMAT_A8_UNORM, DEFAULT_RGBA_FORMATS } 268 }, 269 270 /* basic Luminance formats */ 271 { 272 { GL_LUMINANCE12, GL_LUMINANCE16, 0 }, 273 { PIPE_FORMAT_L16_UNORM, PIPE_FORMAT_R16G16B16A16_UNORM, 274 PIPE_FORMAT_L8_UNORM, DEFAULT_RGB_FORMATS } 275 }, 276 { 277 { 1, GL_LUMINANCE, GL_LUMINANCE4, GL_LUMINANCE8, 0 }, 278 { PIPE_FORMAT_L8_UNORM, PIPE_FORMAT_L8A8_UNORM, DEFAULT_RGB_FORMATS } 279 }, 280 281 /* basic Luminance/Alpha formats */ 282 { 283 { GL_LUMINANCE12_ALPHA4, GL_LUMINANCE12_ALPHA12, 284 GL_LUMINANCE16_ALPHA16, 0}, 285 { PIPE_FORMAT_L16A16_UNORM, PIPE_FORMAT_R16G16B16A16_UNORM, 286 PIPE_FORMAT_L8A8_UNORM, DEFAULT_RGBA_FORMATS } 287 }, 288 { 289 { 2, GL_LUMINANCE_ALPHA, GL_LUMINANCE6_ALPHA2, GL_LUMINANCE8_ALPHA8, 0 }, 290 { PIPE_FORMAT_L8A8_UNORM, DEFAULT_RGBA_FORMATS } 291 }, 292 { 293 { GL_LUMINANCE4_ALPHA4, 0 }, 294 { PIPE_FORMAT_L4A4_UNORM, PIPE_FORMAT_L8A8_UNORM, 295 DEFAULT_RGBA_FORMATS } 296 }, 297 298 /* basic Intensity formats */ 299 { 300 { GL_INTENSITY12, GL_INTENSITY16, 0 }, 301 { PIPE_FORMAT_I16_UNORM, PIPE_FORMAT_R16G16B16A16_UNORM, 302 PIPE_FORMAT_I8_UNORM, DEFAULT_RGBA_FORMATS } 303 }, 304 { 305 { GL_INTENSITY, GL_INTENSITY4, GL_INTENSITY8, 306 GL_COMPRESSED_INTENSITY, 0 }, 307 { PIPE_FORMAT_I8_UNORM, DEFAULT_RGBA_FORMATS } 308 }, 309 310 /* YCbCr */ 311 { 312 { GL_YCBCR_MESA, 0 }, 313 { PIPE_FORMAT_UYVY, PIPE_FORMAT_YUYV, 0 } 314 }, 315 316 /* compressed formats */ /* XXX PIPE_BIND_SAMPLER_VIEW only */ 317 { 318 { GL_COMPRESSED_RGB, 0 }, 319 { PIPE_FORMAT_DXT1_RGB, DEFAULT_RGB_FORMATS } 320 }, 321 { 322 { GL_COMPRESSED_RGBA, 0 }, 323 { PIPE_FORMAT_DXT5_RGBA, DEFAULT_RGBA_FORMATS } 324 }, 325 { 326 { GL_RGB_S3TC, GL_RGB4_S3TC, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 0 }, 327 { PIPE_FORMAT_DXT1_RGB, 0 } 328 }, 329 { 330 { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0 }, 331 { PIPE_FORMAT_DXT1_RGBA, 0 } 332 }, 333 { 334 { GL_RGBA_S3TC, GL_RGBA4_S3TC, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 0 }, 335 { PIPE_FORMAT_DXT3_RGBA, 0 } 336 }, 337 { 338 { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 0 }, 339 { PIPE_FORMAT_DXT5_RGBA, 0 } 340 }, 341 342 { 343 { GL_COMPRESSED_RGB_FXT1_3DFX, 0 }, 344 { PIPE_FORMAT_FXT1_RGB, 0 } 345 }, 346 { 347 { GL_COMPRESSED_RGBA_FXT1_3DFX, 0 }, 348 { PIPE_FORMAT_FXT1_RGBA, 0 } 349 }, 350 351 /* Depth formats */ 352 { 353 { GL_DEPTH_COMPONENT16, 0 }, 354 { PIPE_FORMAT_Z16_UNORM, DEFAULT_DEPTH_FORMATS } 355 }, 356 { 357 { GL_DEPTH_COMPONENT24, 0 }, 358 { PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM, 359 DEFAULT_DEPTH_FORMATS } 360 }, 361 { 362 { GL_DEPTH_COMPONENT32, 0 }, 363 { PIPE_FORMAT_Z32_UNORM, DEFAULT_DEPTH_FORMATS } 364 }, 365 { 366 { GL_DEPTH_COMPONENT, 0 }, 367 { DEFAULT_DEPTH_FORMATS } 368 }, 369 { 370 { GL_DEPTH_COMPONENT32F, 0 }, 371 { PIPE_FORMAT_Z32_FLOAT, 0 } 372 }, 373 374 /* stencil formats */ 375 { 376 { GL_STENCIL_INDEX, GL_STENCIL_INDEX1_EXT, GL_STENCIL_INDEX4_EXT, 377 GL_STENCIL_INDEX8_EXT, GL_STENCIL_INDEX16_EXT, 0 }, 378 { 379 PIPE_FORMAT_S8_UINT, PIPE_FORMAT_Z24_UNORM_S8_UINT, 380 PIPE_FORMAT_S8_UINT_Z24_UNORM, 0 381 } 382 }, 383 384 /* Depth / Stencil formats */ 385 { 386 { GL_DEPTH_STENCIL_EXT, GL_DEPTH24_STENCIL8_EXT, 0 }, 387 { PIPE_FORMAT_Z24_UNORM_S8_UINT, PIPE_FORMAT_S8_UINT_Z24_UNORM, 0 } 388 }, 389 { 390 { GL_DEPTH32F_STENCIL8, 0 }, 391 { PIPE_FORMAT_Z32_FLOAT_S8X24_UINT, 0 } 392 }, 393 394 /* sRGB formats */ 395 { 396 { GL_SRGB_EXT, GL_SRGB8_EXT, 0 }, 397 { PIPE_FORMAT_R8G8B8X8_SRGB, PIPE_FORMAT_B8G8R8X8_SRGB, 398 DEFAULT_SRGBA_FORMATS } 399 }, 400 { 401 { GL_SRGB_ALPHA_EXT, GL_SRGB8_ALPHA8_EXT, 0 }, 402 { PIPE_FORMAT_R8G8B8A8_SRGB, DEFAULT_SRGBA_FORMATS } 403 }, 404 { 405 { GL_COMPRESSED_SRGB_EXT, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 0 }, 406 { PIPE_FORMAT_DXT1_SRGB, PIPE_FORMAT_R8G8B8X8_SRGB, 407 PIPE_FORMAT_B8G8R8X8_SRGB, DEFAULT_SRGBA_FORMATS } 408 }, 409 { 410 { GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0 }, 411 { PIPE_FORMAT_DXT1_SRGBA, 0 } 412 }, 413 { 414 { GL_COMPRESSED_SRGB_ALPHA_EXT, 415 GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0 }, 416 { PIPE_FORMAT_DXT3_SRGBA, DEFAULT_SRGBA_FORMATS } 417 }, 418 { 419 { GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0 }, 420 { PIPE_FORMAT_DXT5_SRGBA, 0 } 421 }, 422 { 423 { GL_SLUMINANCE_ALPHA_EXT, GL_SLUMINANCE8_ALPHA8_EXT, 424 GL_COMPRESSED_SLUMINANCE_ALPHA_EXT, 0 }, 425 { PIPE_FORMAT_L8A8_SRGB, DEFAULT_SRGBA_FORMATS } 426 }, 427 { 428 { GL_SLUMINANCE_EXT, GL_SLUMINANCE8_EXT, GL_COMPRESSED_SLUMINANCE_EXT, 429 0 }, 430 { PIPE_FORMAT_L8_SRGB, DEFAULT_SRGBA_FORMATS } 431 }, 432 { 433 { GL_SR8_EXT, 0 }, 434 { PIPE_FORMAT_R8_SRGB, 0 } 435 }, 436 { 437 { GL_SRG8_EXT, 0 }, 438 { PIPE_FORMAT_R8G8_SRGB, 0 } 439 }, 440 441 /* 16-bit float formats */ 442 { 443 { GL_RGBA16F_ARB, 0 }, 444 { PIPE_FORMAT_R16G16B16A16_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 445 }, 446 { 447 { GL_RGB16F_ARB, 0 }, 448 { PIPE_FORMAT_R16G16B16_FLOAT, PIPE_FORMAT_R16G16B16X16_FLOAT, 449 PIPE_FORMAT_R16G16B16A16_FLOAT, 450 PIPE_FORMAT_R32G32B32_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 451 }, 452 { 453 { GL_LUMINANCE_ALPHA16F_ARB, 0 }, 454 { PIPE_FORMAT_L16A16_FLOAT, PIPE_FORMAT_R16G16B16A16_FLOAT, 455 PIPE_FORMAT_L32A32_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 456 }, 457 { 458 { GL_ALPHA16F_ARB, 0 }, 459 { PIPE_FORMAT_A16_FLOAT, PIPE_FORMAT_L16A16_FLOAT, 460 PIPE_FORMAT_A32_FLOAT, PIPE_FORMAT_R16G16B16A16_FLOAT, 461 PIPE_FORMAT_L32A32_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 462 }, 463 { 464 { GL_INTENSITY16F_ARB, 0 }, 465 { PIPE_FORMAT_I16_FLOAT, PIPE_FORMAT_L16A16_FLOAT, 466 PIPE_FORMAT_I32_FLOAT, PIPE_FORMAT_R16G16B16A16_FLOAT, 467 PIPE_FORMAT_L32A32_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 468 }, 469 { 470 { GL_LUMINANCE16F_ARB, 0 }, 471 { PIPE_FORMAT_L16_FLOAT, PIPE_FORMAT_L16A16_FLOAT, 472 PIPE_FORMAT_L32_FLOAT, PIPE_FORMAT_R16G16B16A16_FLOAT, 473 PIPE_FORMAT_L32A32_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 474 }, 475 { 476 { GL_R16F, 0 }, 477 { PIPE_FORMAT_R16_FLOAT, PIPE_FORMAT_R16G16_FLOAT, 478 PIPE_FORMAT_R32_FLOAT, PIPE_FORMAT_R16G16B16A16_FLOAT, 479 PIPE_FORMAT_R32G32_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 480 }, 481 { 482 { GL_RG16F, 0 }, 483 { PIPE_FORMAT_R16G16_FLOAT, PIPE_FORMAT_R16G16B16A16_FLOAT, 484 PIPE_FORMAT_R32G32_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 485 }, 486 487 /* 32-bit float formats */ 488 { 489 { GL_RGBA32F_ARB, 0 }, 490 { PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 491 }, 492 { 493 { GL_RGB32F_ARB, 0 }, 494 { PIPE_FORMAT_R32G32B32_FLOAT, PIPE_FORMAT_R32G32B32X32_FLOAT, 495 PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 496 }, 497 { 498 { GL_LUMINANCE_ALPHA32F_ARB, 0 }, 499 { PIPE_FORMAT_L32A32_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 500 }, 501 { 502 { GL_ALPHA32F_ARB, 0 }, 503 { PIPE_FORMAT_A32_FLOAT, PIPE_FORMAT_L32A32_FLOAT, 504 PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 505 }, 506 { 507 { GL_INTENSITY32F_ARB, 0 }, 508 { PIPE_FORMAT_I32_FLOAT, PIPE_FORMAT_L32A32_FLOAT, 509 PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 510 }, 511 { 512 { GL_LUMINANCE32F_ARB, 0 }, 513 { PIPE_FORMAT_L32_FLOAT, PIPE_FORMAT_L32A32_FLOAT, 514 PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 515 }, 516 { 517 { GL_R32F, 0 }, 518 { PIPE_FORMAT_R32_FLOAT, PIPE_FORMAT_R32G32_FLOAT, 519 PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 520 }, 521 { 522 { GL_RG32F, 0 }, 523 { PIPE_FORMAT_R32G32_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT, 0 } 524 }, 525 526 /* R, RG formats */ 527 { 528 { GL_RED, GL_R8, 0 }, 529 { PIPE_FORMAT_R8_UNORM, PIPE_FORMAT_R8G8_UNORM, DEFAULT_RGBA_FORMATS } 530 }, 531 { 532 { GL_RG, GL_RG8, 0 }, 533 { PIPE_FORMAT_R8G8_UNORM, DEFAULT_RGBA_FORMATS } 534 }, 535 { 536 { GL_R16, 0 }, 537 { PIPE_FORMAT_R16_UNORM, PIPE_FORMAT_R16G16_UNORM, 538 DEFAULT_UNORM16_RGBA_FORMATS } 539 }, 540 { 541 { GL_RG16, 0 }, 542 { PIPE_FORMAT_R16G16_UNORM, DEFAULT_UNORM16_RGBA_FORMATS } 543 }, 544 545 /* compressed R, RG formats */ 546 { 547 { GL_COMPRESSED_RED, GL_COMPRESSED_RED_RGTC1, 0 }, 548 { PIPE_FORMAT_RGTC1_UNORM, PIPE_FORMAT_R8_UNORM, DEFAULT_RGBA_FORMATS } 549 }, 550 { 551 { GL_COMPRESSED_SIGNED_RED_RGTC1, 0 }, 552 { PIPE_FORMAT_RGTC1_SNORM, DEFAULT_SNORM8_RGBA_FORMATS } 553 }, 554 { 555 { GL_COMPRESSED_RG, GL_COMPRESSED_RG_RGTC2, 0 }, 556 { PIPE_FORMAT_RGTC2_UNORM, PIPE_FORMAT_R8G8_UNORM, DEFAULT_RGBA_FORMATS } 557 }, 558 { 559 { GL_COMPRESSED_SIGNED_RG_RGTC2, 0 }, 560 { PIPE_FORMAT_RGTC2_SNORM, DEFAULT_SNORM8_RGBA_FORMATS } 561 }, 562 { 563 { GL_COMPRESSED_LUMINANCE, GL_COMPRESSED_LUMINANCE_LATC1_EXT, 0 }, 564 { PIPE_FORMAT_LATC1_UNORM, PIPE_FORMAT_L8_UNORM, DEFAULT_RGBA_FORMATS } 565 }, 566 { 567 { GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT, 0 }, 568 { PIPE_FORMAT_LATC1_SNORM, DEFAULT_SNORM8_RGBA_FORMATS } 569 }, 570 { 571 { GL_COMPRESSED_LUMINANCE_ALPHA, GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, 572 GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, 0 }, 573 { PIPE_FORMAT_LATC2_UNORM, PIPE_FORMAT_L8A8_UNORM, DEFAULT_RGBA_FORMATS } 574 }, 575 { 576 { GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT, 0 }, 577 { PIPE_FORMAT_LATC2_SNORM, DEFAULT_SNORM8_RGBA_FORMATS } 578 }, 579 580 /* ETC1 */ 581 { 582 { GL_ETC1_RGB8_OES, 0 }, 583 { PIPE_FORMAT_ETC1_RGB8, 0 } 584 }, 585 586 /* ETC2 */ 587 { 588 { GL_COMPRESSED_RGB8_ETC2, 0 }, 589 { PIPE_FORMAT_ETC2_RGB8, 0 } 590 }, 591 { 592 { GL_COMPRESSED_SRGB8_ETC2, 0 }, 593 { PIPE_FORMAT_ETC2_SRGB8, 0 } 594 }, 595 { 596 { GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 0 }, 597 { PIPE_FORMAT_ETC2_RGB8A1, 0 } 598 }, 599 { 600 { GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 0 }, 601 { PIPE_FORMAT_ETC2_SRGB8A1, 0 } 602 }, 603 { 604 { GL_COMPRESSED_RGBA8_ETC2_EAC, 0 }, 605 { PIPE_FORMAT_ETC2_RGBA8, 0 } 606 }, 607 { 608 { GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 0 }, 609 { PIPE_FORMAT_ETC2_SRGBA8, 0 } 610 }, 611 { 612 { GL_COMPRESSED_R11_EAC, 0 }, 613 { PIPE_FORMAT_ETC2_R11_UNORM, 0 } 614 }, 615 { 616 { GL_COMPRESSED_SIGNED_R11_EAC, 0 }, 617 { PIPE_FORMAT_ETC2_R11_SNORM, 0 } 618 }, 619 { 620 { GL_COMPRESSED_RG11_EAC, 0 }, 621 { PIPE_FORMAT_ETC2_RG11_UNORM, 0 } 622 }, 623 { 624 { GL_COMPRESSED_SIGNED_RG11_EAC, 0 }, 625 { PIPE_FORMAT_ETC2_RG11_SNORM, 0 } 626 }, 627 628 /* BPTC */ 629 { 630 { GL_COMPRESSED_RGBA_BPTC_UNORM, 0 }, 631 { PIPE_FORMAT_BPTC_RGBA_UNORM, 0 }, 632 }, 633 { 634 { GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, 0 }, 635 { PIPE_FORMAT_BPTC_SRGBA, 0 }, 636 }, 637 { 638 { GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, 0 }, 639 { PIPE_FORMAT_BPTC_RGB_FLOAT, 0 }, 640 }, 641 { 642 { GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, 0 }, 643 { PIPE_FORMAT_BPTC_RGB_UFLOAT, 0 }, 644 }, 645 646 /* ASTC */ 647 { 648 { GL_COMPRESSED_RGBA_ASTC_4x4_KHR, 0 }, 649 { PIPE_FORMAT_ASTC_4x4, 0}, 650 }, 651 { 652 { GL_COMPRESSED_RGBA_ASTC_5x4_KHR, 0 }, 653 { PIPE_FORMAT_ASTC_5x4, 0}, 654 }, 655 { 656 { GL_COMPRESSED_RGBA_ASTC_5x5_KHR, 0 }, 657 { PIPE_FORMAT_ASTC_5x5, 0}, 658 }, 659 { 660 { GL_COMPRESSED_RGBA_ASTC_6x5_KHR, 0 }, 661 { PIPE_FORMAT_ASTC_6x5, 0}, 662 }, 663 { 664 { GL_COMPRESSED_RGBA_ASTC_6x6_KHR, 0 }, 665 { PIPE_FORMAT_ASTC_6x6, 0}, 666 }, 667 { 668 { GL_COMPRESSED_RGBA_ASTC_8x5_KHR, 0 }, 669 { PIPE_FORMAT_ASTC_8x5, 0}, 670 }, 671 { 672 { GL_COMPRESSED_RGBA_ASTC_8x6_KHR, 0 }, 673 { PIPE_FORMAT_ASTC_8x6, 0}, 674 }, 675 { 676 { GL_COMPRESSED_RGBA_ASTC_8x8_KHR, 0 }, 677 { PIPE_FORMAT_ASTC_8x8, 0}, 678 }, 679 { 680 { GL_COMPRESSED_RGBA_ASTC_10x5_KHR, 0 }, 681 { PIPE_FORMAT_ASTC_10x5, 0}, 682 }, 683 { 684 { GL_COMPRESSED_RGBA_ASTC_10x6_KHR, 0 }, 685 { PIPE_FORMAT_ASTC_10x6, 0}, 686 }, 687 { 688 { GL_COMPRESSED_RGBA_ASTC_10x8_KHR, 0 }, 689 { PIPE_FORMAT_ASTC_10x8, 0}, 690 }, 691 { 692 { GL_COMPRESSED_RGBA_ASTC_10x10_KHR, 0 }, 693 { PIPE_FORMAT_ASTC_10x10, 0}, 694 }, 695 { 696 { GL_COMPRESSED_RGBA_ASTC_12x10_KHR, 0 }, 697 { PIPE_FORMAT_ASTC_12x10, 0}, 698 }, 699 { 700 { GL_COMPRESSED_RGBA_ASTC_12x12_KHR, 0 }, 701 { PIPE_FORMAT_ASTC_12x12, 0}, 702 }, 703 704 { 705 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, 0 }, 706 { PIPE_FORMAT_ASTC_4x4_SRGB, 0}, 707 }, 708 { 709 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, 0 }, 710 { PIPE_FORMAT_ASTC_5x4_SRGB, 0}, 711 }, 712 { 713 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, 0 }, 714 { PIPE_FORMAT_ASTC_5x5_SRGB, 0}, 715 }, 716 { 717 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, 0 }, 718 { PIPE_FORMAT_ASTC_6x5_SRGB, 0}, 719 }, 720 { 721 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, 0 }, 722 { PIPE_FORMAT_ASTC_6x6_SRGB, 0}, 723 }, 724 { 725 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, 0 }, 726 { PIPE_FORMAT_ASTC_8x5_SRGB, 0}, 727 }, 728 { 729 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, 0 }, 730 { PIPE_FORMAT_ASTC_8x6_SRGB, 0}, 731 }, 732 { 733 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, 0 }, 734 { PIPE_FORMAT_ASTC_8x8_SRGB, 0}, 735 }, 736 { 737 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, 0 }, 738 { PIPE_FORMAT_ASTC_10x5_SRGB, 0}, 739 }, 740 { 741 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, 0 }, 742 { PIPE_FORMAT_ASTC_10x6_SRGB, 0}, 743 }, 744 { 745 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, 0 }, 746 { PIPE_FORMAT_ASTC_10x8_SRGB, 0}, 747 }, 748 { 749 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, 0 }, 750 { PIPE_FORMAT_ASTC_10x10_SRGB, 0}, 751 }, 752 { 753 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, 0 }, 754 { PIPE_FORMAT_ASTC_12x10_SRGB, 0}, 755 }, 756 { 757 { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 0 }, 758 { PIPE_FORMAT_ASTC_12x12_SRGB, 0}, 759 }, 760 761 /* signed/unsigned integer formats. 762 */ 763 { 764 { GL_RGBA_INTEGER_EXT, 765 GL_BGRA_INTEGER_EXT, 766 GL_RGBA8I_EXT, 0 }, 767 { PIPE_FORMAT_R8G8B8A8_SINT, 0 } 768 }, 769 { 770 { GL_RGB_INTEGER_EXT, 771 GL_BGR_INTEGER_EXT, 772 GL_RGB8I_EXT, 773 GL_BLUE_INTEGER_EXT, 0 }, 774 { PIPE_FORMAT_R8G8B8_SINT, PIPE_FORMAT_R8G8B8X8_SINT, 775 PIPE_FORMAT_R8G8B8A8_SINT, 0 } 776 }, 777 { 778 { GL_ALPHA_INTEGER_EXT, 779 GL_ALPHA8I_EXT, 0 }, 780 { PIPE_FORMAT_A8_SINT, PIPE_FORMAT_R8G8B8A8_SINT, 0 } 781 }, 782 { 783 { GL_ALPHA16I_EXT, 0 }, 784 { PIPE_FORMAT_A16_SINT, PIPE_FORMAT_R16G16B16A16_SINT, 0 } 785 }, 786 { 787 { GL_ALPHA32I_EXT, 0 }, 788 { PIPE_FORMAT_A32_SINT, PIPE_FORMAT_R32G32B32A32_SINT, 0 } 789 }, 790 { 791 { GL_ALPHA8UI_EXT, 0 }, 792 { PIPE_FORMAT_A8_UINT, PIPE_FORMAT_R8G8B8A8_UINT, 0 } 793 }, 794 { 795 { GL_ALPHA16UI_EXT, 0 }, 796 { PIPE_FORMAT_A16_UINT, PIPE_FORMAT_R16G16B16A16_UINT, 0 } 797 }, 798 { 799 { GL_ALPHA32UI_EXT, 0 }, 800 { PIPE_FORMAT_A32_UINT, PIPE_FORMAT_R32G32B32A32_UINT, 0 } 801 }, 802 { 803 { GL_INTENSITY8I_EXT, 0 }, 804 { PIPE_FORMAT_I8_SINT, PIPE_FORMAT_R8G8B8A8_SINT, 0 } 805 }, 806 { 807 { GL_INTENSITY16I_EXT, 0 }, 808 { PIPE_FORMAT_I16_SINT, PIPE_FORMAT_R16G16B16A16_SINT, 0 } 809 }, 810 { 811 { GL_INTENSITY32I_EXT, 0 }, 812 { PIPE_FORMAT_I32_SINT, PIPE_FORMAT_R32G32B32A32_SINT, 0 } 813 }, 814 { 815 { GL_INTENSITY8UI_EXT, 0 }, 816 { PIPE_FORMAT_I8_UINT, PIPE_FORMAT_R8G8B8A8_UINT, 0 } 817 }, 818 { 819 { GL_INTENSITY16UI_EXT, 0 }, 820 { PIPE_FORMAT_I16_UINT, PIPE_FORMAT_R16G16B16A16_UINT, 0 } 821 }, 822 { 823 { GL_INTENSITY32UI_EXT, 0 }, 824 { PIPE_FORMAT_I32_UINT, PIPE_FORMAT_R32G32B32A32_UINT, 0 } 825 }, 826 { 827 { GL_LUMINANCE8I_EXT, 0 }, 828 { PIPE_FORMAT_L8_SINT, PIPE_FORMAT_R8G8B8A8_SINT, 0 } 829 }, 830 { 831 { GL_LUMINANCE16I_EXT, 0 }, 832 { PIPE_FORMAT_L16_SINT, PIPE_FORMAT_R16G16B16A16_SINT, 0 } 833 }, 834 { 835 { GL_LUMINANCE32I_EXT, 0 }, 836 { PIPE_FORMAT_L32_SINT, PIPE_FORMAT_R32G32B32A32_SINT, 0 } 837 }, 838 { 839 { GL_LUMINANCE_INTEGER_EXT, 840 GL_LUMINANCE8UI_EXT, 0 }, 841 { PIPE_FORMAT_L8_UINT, PIPE_FORMAT_R8G8B8A8_UINT, 0 } 842 }, 843 { 844 { GL_LUMINANCE16UI_EXT, 0 }, 845 { PIPE_FORMAT_L16_UINT, PIPE_FORMAT_R16G16B16A16_UINT, 0 } 846 }, 847 { 848 { GL_LUMINANCE32UI_EXT, 0 }, 849 { PIPE_FORMAT_L32_UINT, PIPE_FORMAT_R32G32B32A32_UINT, 0 } 850 }, 851 { 852 { GL_LUMINANCE_ALPHA_INTEGER_EXT, 853 GL_LUMINANCE_ALPHA8I_EXT, 0 }, 854 { PIPE_FORMAT_L8A8_SINT, PIPE_FORMAT_R8G8B8A8_SINT, 0 } 855 }, 856 { 857 { GL_LUMINANCE_ALPHA16I_EXT, 0 }, 858 { PIPE_FORMAT_L16A16_SINT, PIPE_FORMAT_R16G16B16A16_SINT, 0 } 859 }, 860 { 861 { GL_LUMINANCE_ALPHA32I_EXT, 0 }, 862 { PIPE_FORMAT_L32A32_SINT, PIPE_FORMAT_R32G32B32A32_SINT, 0 } 863 }, 864 { 865 { GL_LUMINANCE_ALPHA8UI_EXT, 0 }, 866 { PIPE_FORMAT_L8A8_UINT, PIPE_FORMAT_R8G8B8A8_UINT, 0 } 867 }, 868 { 869 { GL_LUMINANCE_ALPHA16UI_EXT, 0 }, 870 { PIPE_FORMAT_L16A16_UINT, PIPE_FORMAT_R16G16B16A16_UINT, 0 } 871 }, 872 { 873 { GL_LUMINANCE_ALPHA32UI_EXT, 0 }, 874 { PIPE_FORMAT_L32A32_UINT, PIPE_FORMAT_R32G32B32A32_UINT, 0 } 875 }, 876 { 877 { GL_RGB16I_EXT, 0 }, 878 { PIPE_FORMAT_R16G16B16_SINT, PIPE_FORMAT_R16G16B16X16_SINT, 879 PIPE_FORMAT_R16G16B16A16_SINT, 0 }, 880 }, 881 { 882 { GL_RGBA16I_EXT, 0 }, 883 { PIPE_FORMAT_R16G16B16A16_SINT, 0 }, 884 }, 885 { 886 { GL_RGB32I_EXT, 0 }, 887 { PIPE_FORMAT_R32G32B32_SINT, PIPE_FORMAT_R32G32B32X32_SINT, 888 PIPE_FORMAT_R32G32B32A32_SINT, 0 }, 889 }, 890 { 891 { GL_RGBA32I_EXT, 0 }, 892 { PIPE_FORMAT_R32G32B32A32_SINT, 0 } 893 }, 894 { 895 { GL_RGBA8UI_EXT, 0 }, 896 { PIPE_FORMAT_R8G8B8A8_UINT, 0 } 897 }, 898 { 899 { GL_RGB8UI_EXT, 0 }, 900 { PIPE_FORMAT_R8G8B8_UINT, PIPE_FORMAT_R8G8B8X8_UINT, 901 PIPE_FORMAT_R8G8B8A8_UINT, 0 } 902 }, 903 { 904 { GL_RGB16UI_EXT, 0 }, 905 { PIPE_FORMAT_R16G16B16_UINT, PIPE_FORMAT_R16G16B16X16_UINT, 906 PIPE_FORMAT_R16G16B16A16_UINT, 0 } 907 }, 908 { 909 { GL_RGBA16UI_EXT, 0 }, 910 { PIPE_FORMAT_R16G16B16A16_UINT, 0 } 911 }, 912 { 913 { GL_RGB32UI_EXT, 0}, 914 { PIPE_FORMAT_R32G32B32_UINT, PIPE_FORMAT_R32G32B32X32_UINT, 915 PIPE_FORMAT_R32G32B32A32_UINT, 0 } 916 }, 917 { 918 { GL_RGBA32UI_EXT, 0}, 919 { PIPE_FORMAT_R32G32B32A32_UINT, 0 } 920 }, 921 { 922 { GL_R8I, GL_RED_INTEGER_EXT, 0}, 923 { PIPE_FORMAT_R8_SINT, PIPE_FORMAT_R8G8_SINT, 0}, 924 }, 925 { 926 { GL_R16I, 0}, 927 { PIPE_FORMAT_R16_SINT, 0}, 928 }, 929 { 930 { GL_R32I, 0}, 931 { PIPE_FORMAT_R32_SINT, 0}, 932 }, 933 { 934 { GL_R8UI, 0}, 935 { PIPE_FORMAT_R8_UINT, PIPE_FORMAT_R8G8_UINT, 0}, 936 }, 937 { 938 { GL_R16UI, 0}, 939 { PIPE_FORMAT_R16_UINT, 0}, 940 }, 941 { 942 { GL_R32UI, 0}, 943 { PIPE_FORMAT_R32_UINT, 0}, 944 }, 945 { 946 { GL_RG8I, GL_GREEN_INTEGER_EXT, 0}, 947 { PIPE_FORMAT_R8G8_SINT, 0}, 948 }, 949 { 950 { GL_RG16I, 0}, 951 { PIPE_FORMAT_R16G16_SINT, 0}, 952 }, 953 { 954 { GL_RG32I, 0}, 955 { PIPE_FORMAT_R32G32_SINT, 0}, 956 }, 957 { 958 { GL_RG8UI, 0}, 959 { PIPE_FORMAT_R8G8_UINT, 0}, 960 }, 961 { 962 { GL_RG16UI, 0}, 963 { PIPE_FORMAT_R16G16_UINT, 0}, 964 }, 965 { 966 { GL_RG32UI, 0}, 967 { PIPE_FORMAT_R32G32_UINT, 0}, 968 }, 969 /* signed normalized formats */ 970 { 971 { GL_RED_SNORM, GL_R8_SNORM, 0 }, 972 { PIPE_FORMAT_R8_SNORM, PIPE_FORMAT_R8G8_SNORM, 973 PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 974 }, 975 { 976 { GL_R16_SNORM, 0 }, 977 { PIPE_FORMAT_R16_SNORM, 978 PIPE_FORMAT_R16G16_SNORM, 979 PIPE_FORMAT_R16G16B16A16_SNORM, 980 PIPE_FORMAT_R8_SNORM, 981 PIPE_FORMAT_R8G8_SNORM, 982 PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 983 }, 984 { 985 { GL_RG_SNORM, GL_RG8_SNORM, 0 }, 986 { PIPE_FORMAT_R8G8_SNORM, PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 987 }, 988 { 989 { GL_RG16_SNORM, 0 }, 990 { PIPE_FORMAT_R16G16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, 991 PIPE_FORMAT_R8G8_SNORM, PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 992 }, 993 { 994 { GL_RGB_SNORM, GL_RGB8_SNORM, 0 }, 995 { PIPE_FORMAT_R8G8B8X8_SNORM, PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 996 }, 997 { 998 { GL_RGBA_SNORM, GL_RGBA8_SNORM, 0 }, 999 { PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 1000 }, 1001 { 1002 { GL_RGB16_SNORM, 0 }, 1003 { PIPE_FORMAT_R16G16B16X16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, 1004 PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 1005 }, 1006 { 1007 { GL_RGBA16_SNORM, 0 }, 1008 { PIPE_FORMAT_R16G16B16A16_SNORM, PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 1009 }, 1010 { 1011 { GL_ALPHA_SNORM, GL_ALPHA8_SNORM, 0 }, 1012 { PIPE_FORMAT_A8_SNORM, PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 1013 }, 1014 { 1015 { GL_ALPHA16_SNORM, 0 }, 1016 { PIPE_FORMAT_A16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, 1017 PIPE_FORMAT_A8_SNORM, PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 1018 }, 1019 { 1020 { GL_LUMINANCE_SNORM, GL_LUMINANCE8_SNORM, 0 }, 1021 { PIPE_FORMAT_L8_SNORM, PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 1022 }, 1023 { 1024 { GL_LUMINANCE16_SNORM, 0 }, 1025 { PIPE_FORMAT_L16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, 1026 PIPE_FORMAT_L8_SNORM, PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 1027 }, 1028 { 1029 { GL_LUMINANCE_ALPHA_SNORM, GL_LUMINANCE8_ALPHA8_SNORM, 0 }, 1030 { PIPE_FORMAT_L8A8_SNORM, PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 1031 }, 1032 { 1033 { GL_LUMINANCE16_ALPHA16_SNORM, 0 }, 1034 { PIPE_FORMAT_L16A16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, 1035 PIPE_FORMAT_L8A8_SNORM, PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 1036 }, 1037 { 1038 { GL_INTENSITY_SNORM, GL_INTENSITY8_SNORM, 0 }, 1039 { PIPE_FORMAT_I8_SNORM, PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 1040 }, 1041 { 1042 { GL_INTENSITY16_SNORM, 0 }, 1043 { PIPE_FORMAT_I16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, 1044 PIPE_FORMAT_I8_SNORM, PIPE_FORMAT_R8G8B8A8_SNORM, 0 } 1045 }, 1046 { 1047 { GL_RGB9_E5, 0 }, 1048 { PIPE_FORMAT_R9G9B9E5_FLOAT, 0 } 1049 }, 1050 { 1051 { GL_R11F_G11F_B10F, 0 }, 1052 { PIPE_FORMAT_R11G11B10_FLOAT, 0 } 1053 }, 1054 { 1055 { GL_RGB10_A2UI, 0 }, 1056 { PIPE_FORMAT_R10G10B10A2_UINT, PIPE_FORMAT_B10G10R10A2_UINT, 0 } 1057 }, 1058}; 1059 1060 1061/** 1062 * Return first supported format from the given list. 1063 * \param allow_dxt indicates whether it's OK to return a DXT format. 1064 */ 1065static enum pipe_format 1066find_supported_format(struct pipe_screen *screen, 1067 const enum pipe_format formats[], 1068 enum pipe_texture_target target, 1069 unsigned sample_count, 1070 unsigned storage_sample_count, 1071 unsigned bindings, 1072 boolean allow_dxt) 1073{ 1074 uint i; 1075 for (i = 0; formats[i]; i++) { 1076 if (!bindings || screen->is_format_supported(screen, formats[i], target, 1077 sample_count, storage_sample_count, 1078 bindings)) { 1079 if (!allow_dxt && util_format_is_s3tc(formats[i])) { 1080 /* we can't return a dxt format, continue searching */ 1081 continue; 1082 } 1083 1084 return formats[i]; 1085 } 1086 } 1087 return PIPE_FORMAT_NONE; 1088} 1089 1090/** 1091 * Given an OpenGL internalFormat value for a texture or surface, return 1092 * the best matching PIPE_FORMAT_x, or PIPE_FORMAT_NONE if there's no match. 1093 * This is called during glTexImage2D, for example. 1094 * 1095 * The bindings parameter typically has PIPE_BIND_SAMPLER_VIEW set, plus 1096 * either PIPE_BINDING_RENDER_TARGET or PIPE_BINDING_DEPTH_STENCIL if 1097 * we want render-to-texture ability. 1098 * If bindings is zero, the driver doesn't need to support the returned format. 1099 * 1100 * \param internalFormat the user value passed to glTexImage2D 1101 * \param target one of PIPE_TEXTURE_x 1102 * \param bindings bitmask of PIPE_BIND_x flags. 1103 * \param allow_dxt indicates whether it's OK to return a DXT format. This 1104 * only matters when internalFormat names a generic or 1105 * specific compressed format. And that should only happen 1106 * when we're getting called from gl[Copy]TexImage(). 1107 */ 1108enum pipe_format 1109st_choose_format(struct st_context *st, GLenum internalFormat, 1110 GLenum format, GLenum type, 1111 enum pipe_texture_target target, unsigned sample_count, 1112 unsigned storage_sample_count, 1113 unsigned bindings, bool swap_bytes, bool allow_dxt) 1114{ 1115 struct pipe_screen *screen = st->screen; 1116 unsigned i; 1117 int j; 1118 enum pipe_format pf; 1119 1120 /* can't render to compressed formats at this time */ 1121 if (_mesa_is_compressed_format(st->ctx, internalFormat) 1122 && (bindings & ~PIPE_BIND_SAMPLER_VIEW)) { 1123 return PIPE_FORMAT_NONE; 1124 } 1125 1126 /* If we have an unsized internalFormat, and the driver supports a format 1127 * that exactly matches format/type such that we can just memcpy, pick that 1128 * (unless the format wouldn't still be unorm, which is the expectation for 1129 * unsized formats). 1130 */ 1131 if (_mesa_is_enum_format_unsized(internalFormat) && format != 0 && 1132 _mesa_is_type_unsigned(type)) { 1133 pf = st_choose_matching_format(st, bindings, format, type, 1134 swap_bytes); 1135 1136 if (pf != PIPE_FORMAT_NONE && 1137 (!bindings || screen->is_format_supported(screen, pf, target, sample_count, 1138 storage_sample_count, bindings)) && 1139 _mesa_get_format_base_format(st_pipe_format_to_mesa_format(pf)) == 1140 internalFormat) { 1141 goto success; 1142 } 1143 } 1144 1145 /* For an unsized GL_RGB but a 2_10_10_10 type, try to pick one of the 1146 * 2_10_10_10 formats. This is important for 1147 * GL_EXT_texture_type_2_10_10_10_EXT support, which says that these 1148 * formats are not color-renderable. Mesa's check for making those 1149 * non-color-renderable is based on our chosen format being 2101010. 1150 */ 1151 if (type == GL_UNSIGNED_INT_2_10_10_10_REV) { 1152 if (internalFormat == GL_RGB) 1153 internalFormat = GL_RGB10; 1154 else if (internalFormat == GL_RGBA) 1155 internalFormat = GL_RGB10_A2; 1156 } 1157 1158 if (type == GL_UNSIGNED_SHORT_5_5_5_1) { 1159 if (internalFormat == GL_RGB) 1160 internalFormat = GL_RGB5; 1161 else if (internalFormat == GL_RGBA) 1162 internalFormat = GL_RGB5_A1; 1163 } 1164 1165 /* search table for internalFormat */ 1166 for (i = 0; i < ARRAY_SIZE(format_map); i++) { 1167 const struct format_mapping *mapping = &format_map[i]; 1168 for (j = 0; mapping->glFormats[j]; j++) { 1169 if (mapping->glFormats[j] == internalFormat) { 1170 /* Found the desired internal format. Find first pipe format 1171 * which is supported by the driver. 1172 */ 1173 pf = find_supported_format(screen, mapping->pipeFormats, 1174 target, sample_count, 1175 storage_sample_count, bindings, 1176 allow_dxt); 1177 goto success; 1178 } 1179 } 1180 } 1181 1182 _mesa_problem(NULL, "unhandled format!\n"); 1183 return PIPE_FORMAT_NONE; 1184 1185success: 1186 if (0) { 1187 debug_printf("%s(fmt=%s, type=%s, intFmt=%s) = %s\n", 1188 __FUNCTION__, 1189 _mesa_enum_to_string(format), 1190 _mesa_enum_to_string(type), 1191 _mesa_enum_to_string(internalFormat), 1192 util_format_name(pf)); 1193 } 1194 return pf; 1195} 1196 1197 1198/** 1199 * Called by FBO code to choose a PIPE_FORMAT_ for drawing surfaces. 1200 */ 1201enum pipe_format 1202st_choose_renderbuffer_format(struct st_context *st, 1203 GLenum internalFormat, unsigned sample_count, 1204 unsigned storage_sample_count) 1205{ 1206 unsigned bindings; 1207 if (_mesa_is_depth_or_stencil_format(internalFormat)) 1208 bindings = PIPE_BIND_DEPTH_STENCIL; 1209 else 1210 bindings = PIPE_BIND_RENDER_TARGET; 1211 return st_choose_format(st, internalFormat, GL_NONE, GL_NONE, 1212 PIPE_TEXTURE_2D, sample_count, 1213 storage_sample_count, bindings, 1214 false, false); 1215} 1216 1217 1218/** 1219 * Given an OpenGL user-requested format and type, and swapBytes state, 1220 * return the format which exactly matches those parameters, so that 1221 * a memcpy-based transfer can be done. 1222 * 1223 * If no match format exists, return PIPE_FORMAT_NONE. 1224 */ 1225enum pipe_format 1226st_choose_matching_format_noverify(struct st_context *st, 1227 GLenum format, GLenum type, GLboolean swapBytes) 1228{ 1229 if (swapBytes && !_mesa_swap_bytes_in_type_enum(&type)) 1230 return PIPE_FORMAT_NONE; 1231 1232 mesa_format mesa_format = _mesa_format_from_format_and_type(format, type); 1233 if (_mesa_format_is_mesa_array_format(mesa_format)) 1234 mesa_format = _mesa_format_from_array_format(mesa_format); 1235 if (mesa_format != MESA_FORMAT_NONE) 1236 return st_mesa_format_to_pipe_format(st, mesa_format); 1237 1238 return PIPE_FORMAT_NONE; 1239} 1240 1241 1242/** 1243 * Given an OpenGL user-requested format and type, and swapBytes state, 1244 * return the format which exactly matches those parameters, so that 1245 * a memcpy-based transfer can be done. 1246 * 1247 * If no format is supported, return PIPE_FORMAT_NONE. 1248 */ 1249enum pipe_format 1250st_choose_matching_format(struct st_context *st, unsigned bind, 1251 GLenum format, GLenum type, GLboolean swapBytes) 1252{ 1253 struct pipe_screen *screen = st->screen; 1254 enum pipe_format pformat = st_choose_matching_format_noverify(st, format, type, swapBytes); 1255 if (pformat != PIPE_FORMAT_NONE && 1256 (!bind || screen->is_format_supported(screen, pformat, PIPE_TEXTURE_2D, 0, 0, bind))) 1257 return pformat; 1258 1259 return PIPE_FORMAT_NONE; 1260} 1261 1262 1263/** 1264 * Called via ctx->Driver.ChooseTextureFormat(). 1265 */ 1266mesa_format 1267st_ChooseTextureFormat(struct gl_context *ctx, GLenum target, 1268 GLint internalFormat, 1269 GLenum format, GLenum type) 1270{ 1271 struct st_context *st = st_context(ctx); 1272 enum pipe_format pFormat; 1273 mesa_format mFormat; 1274 unsigned bindings; 1275 bool is_renderbuffer = false; 1276 enum pipe_texture_target pTarget; 1277 1278 if (target == GL_RENDERBUFFER) { 1279 pTarget = PIPE_TEXTURE_2D; 1280 is_renderbuffer = true; 1281 } else { 1282 pTarget = gl_target_to_pipe(target); 1283 } 1284 1285 if (target == GL_TEXTURE_1D || target == GL_TEXTURE_1D_ARRAY) { 1286 /* We don't do compression for these texture targets because of 1287 * difficulty with sub-texture updates on non-block boundaries, etc. 1288 * So change the internal format request to an uncompressed format. 1289 */ 1290 internalFormat = 1291 _mesa_generic_compressed_format_to_uncompressed_format(internalFormat); 1292 } 1293 1294 /* GL textures may wind up being render targets, but we don't know 1295 * that in advance. Specify potential render target flags now for formats 1296 * that we know should always be renderable. 1297 */ 1298 bindings = PIPE_BIND_SAMPLER_VIEW; 1299 if (_mesa_is_depth_or_stencil_format(internalFormat)) 1300 bindings |= PIPE_BIND_DEPTH_STENCIL; 1301 else if (is_renderbuffer || internalFormat == 3 || internalFormat == 4 || 1302 internalFormat == GL_RGB || internalFormat == GL_RGBA || 1303 internalFormat == GL_RGBA2 || 1304 internalFormat == GL_RGB4 || internalFormat == GL_RGBA4 || 1305 internalFormat == GL_RGB8 || internalFormat == GL_RGBA8 || 1306 internalFormat == GL_BGRA || 1307 internalFormat == GL_RGB16F || 1308 internalFormat == GL_RGBA16F || 1309 internalFormat == GL_RGB32F || 1310 internalFormat == GL_RGBA32F || 1311 internalFormat == GL_RED || 1312 internalFormat == GL_RED_SNORM || 1313 internalFormat == GL_R8I || 1314 internalFormat == GL_R8UI) 1315 bindings |= PIPE_BIND_RENDER_TARGET; 1316 1317 /* GLES allows the driver to choose any format which matches 1318 * the format+type combo, because GLES only supports unsized internal 1319 * formats and expects the driver to choose whatever suits it. 1320 */ 1321 if (_mesa_is_gles(ctx)) { 1322 GLenum baseFormat = _mesa_base_tex_format(ctx, internalFormat); 1323 GLenum basePackFormat = _mesa_base_pack_format(format); 1324 GLenum iformat = internalFormat; 1325 1326 /* Treat GL_BGRA as GL_RGBA. */ 1327 if (iformat == GL_BGRA) 1328 iformat = GL_RGBA; 1329 1330 /* Check if the internalformat is unsized and compatible 1331 * with the "format". 1332 */ 1333 if (iformat == baseFormat && iformat == basePackFormat) { 1334 pFormat = st_choose_matching_format(st, bindings, format, type, 1335 ctx->Unpack.SwapBytes); 1336 1337 if (pFormat != PIPE_FORMAT_NONE) 1338 return st_pipe_format_to_mesa_format(pFormat); 1339 1340 if (!is_renderbuffer) { 1341 /* try choosing format again, this time without render 1342 * target bindings. 1343 */ 1344 pFormat = st_choose_matching_format(st, PIPE_BIND_SAMPLER_VIEW, 1345 format, type, 1346 ctx->Unpack.SwapBytes); 1347 if (pFormat != PIPE_FORMAT_NONE) 1348 return st_pipe_format_to_mesa_format(pFormat); 1349 } 1350 } 1351 } 1352 1353 pFormat = st_choose_format(st, internalFormat, format, type, 1354 pTarget, 0, 0, bindings, 1355 ctx->Unpack.SwapBytes, true); 1356 1357 if (pFormat == PIPE_FORMAT_NONE && !is_renderbuffer) { 1358 /* try choosing format again, this time without render target bindings */ 1359 pFormat = st_choose_format(st, internalFormat, format, type, 1360 pTarget, 0, 0, PIPE_BIND_SAMPLER_VIEW, 1361 ctx->Unpack.SwapBytes, true); 1362 } 1363 1364 if (pFormat == PIPE_FORMAT_NONE) { 1365 mFormat = _mesa_glenum_to_compressed_format(internalFormat); 1366 if (st_compressed_format_fallback(st, mFormat)) 1367 return mFormat; 1368 1369 /* no luck at all */ 1370 return MESA_FORMAT_NONE; 1371 } 1372 1373 mFormat = st_pipe_format_to_mesa_format(pFormat); 1374 1375 /* Debugging aid */ 1376 if (0) { 1377 debug_printf("%s(intFormat=%s, format=%s, type=%s) -> %s, %s\n", 1378 __func__, 1379 _mesa_enum_to_string(internalFormat), 1380 _mesa_enum_to_string(format), 1381 _mesa_enum_to_string(type), 1382 util_format_name(pFormat), 1383 _mesa_get_format_name(mFormat)); 1384 } 1385 1386 return mFormat; 1387} 1388 1389 1390/** 1391 * Called via ctx->Driver.QueryInternalFormat(). 1392 */ 1393static size_t 1394st_QuerySamplesForFormat(struct gl_context *ctx, GLenum target, 1395 GLenum internalFormat, int samples[16]) 1396{ 1397 struct st_context *st = st_context(ctx); 1398 enum pipe_format format; 1399 unsigned i, bind, num_sample_counts = 0; 1400 unsigned min_max_samples; 1401 1402 (void) target; 1403 1404 if (_mesa_is_depth_or_stencil_format(internalFormat)) 1405 bind = PIPE_BIND_DEPTH_STENCIL; 1406 else 1407 bind = PIPE_BIND_RENDER_TARGET; 1408 1409 if (_mesa_is_enum_format_integer(internalFormat)) 1410 min_max_samples = ctx->Const.MaxIntegerSamples; 1411 else if (_mesa_is_depth_or_stencil_format(internalFormat)) 1412 min_max_samples = ctx->Const.MaxDepthTextureSamples; 1413 else 1414 min_max_samples = ctx->Const.MaxColorTextureSamples; 1415 1416 /* If an sRGB framebuffer is unsupported, sRGB formats behave like linear 1417 * formats. 1418 */ 1419 if (!ctx->Extensions.EXT_sRGB) { 1420 internalFormat = _mesa_get_linear_internalformat(internalFormat); 1421 } 1422 1423 /* Set sample counts in descending order. */ 1424 for (i = 16; i > 1; i--) { 1425 format = st_choose_format(st, internalFormat, GL_NONE, GL_NONE, 1426 PIPE_TEXTURE_2D, i, i, bind, 1427 false, false); 1428 1429 if (format != PIPE_FORMAT_NONE || i == min_max_samples) { 1430 samples[num_sample_counts++] = i; 1431 } 1432 } 1433 1434 if (!num_sample_counts) { 1435 samples[num_sample_counts++] = 1; 1436 } 1437 1438 return num_sample_counts; 1439} 1440 1441 1442/** 1443 * ARB_internalformat_query2 driver hook. 1444 */ 1445void 1446st_QueryInternalFormat(struct gl_context *ctx, GLenum target, 1447 GLenum internalFormat, GLenum pname, GLint *params) 1448{ 1449 struct st_context *st = st_context(ctx); 1450 /* The API entry-point gives us a temporary params buffer that is non-NULL 1451 * and guaranteed to have at least 16 elements. 1452 */ 1453 assert(params != NULL); 1454 1455 switch (pname) { 1456 case GL_SAMPLES: 1457 st_QuerySamplesForFormat(ctx, target, internalFormat, params); 1458 break; 1459 1460 case GL_NUM_SAMPLE_COUNTS: { 1461 int samples[16]; 1462 size_t num_samples; 1463 num_samples = st_QuerySamplesForFormat(ctx, target, internalFormat, 1464 samples); 1465 params[0] = (GLint) num_samples; 1466 break; 1467 } 1468 case GL_INTERNALFORMAT_PREFERRED: { 1469 params[0] = GL_NONE; 1470 1471 /* We need to resolve an internal format that is compatible with 1472 * the passed internal format, and optimal to the driver. By now, 1473 * we just validate that the passed internal format is supported by 1474 * the driver, and if so return the same internal format, otherwise 1475 * return GL_NONE. 1476 */ 1477 unsigned bindings; 1478 if (_mesa_is_depth_or_stencil_format(internalFormat)) 1479 bindings = PIPE_BIND_DEPTH_STENCIL; 1480 else 1481 bindings = PIPE_BIND_RENDER_TARGET; 1482 enum pipe_format pformat = st_choose_format(st, 1483 internalFormat, 1484 GL_NONE, 1485 GL_NONE, 1486 PIPE_TEXTURE_2D, 0, 0, 1487 bindings, 1488 false, false); 1489 if (pformat) 1490 params[0] = internalFormat; 1491 break; 1492 } 1493 case GL_TEXTURE_REDUCTION_MODE_ARB: { 1494 mesa_format format = st_ChooseTextureFormat(ctx, target, internalFormat, GL_NONE, GL_NONE); 1495 enum pipe_format pformat = st_mesa_format_to_pipe_format(st, format); 1496 struct pipe_screen *screen = st->screen; 1497 params[0] = pformat != PIPE_FORMAT_NONE && 1498 screen->is_format_supported(screen, pformat, PIPE_TEXTURE_2D, 1499 0, 0, PIPE_BIND_SAMPLER_REDUCTION_MINMAX); 1500 break; 1501 } 1502 default: 1503 /* For the rest of the pnames, we call back the Mesa's default 1504 * function for drivers that don't implement ARB_internalformat_query2. 1505 */ 1506 _mesa_query_internal_format_default(ctx, target, internalFormat, pname, 1507 params); 1508 } 1509} 1510 1511 1512/** 1513 * This is used for translating texture border color and the clear 1514 * color. For example, the clear color is interpreted according to 1515 * the renderbuffer's base format. For example, if clearing a 1516 * GL_LUMINANCE buffer, we'll return colorOut[0] = colorOut[1] = 1517 * colorOut[2] = colorIn[0]. 1518 * Similarly for texture border colors. 1519 */ 1520void 1521st_translate_color(union pipe_color_union *color, 1522 GLenum baseFormat, GLboolean is_integer) 1523{ 1524 if (is_integer) { 1525 int *ci = color->i; 1526 1527 switch (baseFormat) { 1528 case GL_RED: 1529 ci[1] = 0; 1530 ci[2] = 0; 1531 ci[3] = 1; 1532 break; 1533 case GL_RG: 1534 ci[2] = 0; 1535 ci[3] = 1; 1536 break; 1537 case GL_RGB: 1538 ci[3] = 1; 1539 break; 1540 case GL_ALPHA: 1541 ci[0] = ci[1] = ci[2] = 0; 1542 break; 1543 case GL_LUMINANCE: 1544 ci[1] = ci[2] = ci[0]; 1545 ci[3] = 1; 1546 break; 1547 case GL_LUMINANCE_ALPHA: 1548 ci[1] = ci[2] = ci[0]; 1549 break; 1550 case GL_INTENSITY: 1551 ci[1] = ci[2] = ci[3] = ci[0]; 1552 break; 1553 } 1554 } 1555 else { 1556 float *cf = color->f; 1557 1558 switch (baseFormat) { 1559 case GL_RED: 1560 cf[1] = 0.0F; 1561 cf[2] = 0.0F; 1562 cf[3] = 1.0F; 1563 break; 1564 case GL_RG: 1565 cf[2] = 0.0F; 1566 cf[3] = 1.0F; 1567 break; 1568 case GL_RGB: 1569 cf[3] = 1.0F; 1570 break; 1571 case GL_ALPHA: 1572 cf[0] = cf[1] = cf[2] = 0.0F; 1573 break; 1574 case GL_LUMINANCE: 1575 cf[1] = cf[2] = cf[0]; 1576 cf[3] = 1.0F; 1577 break; 1578 case GL_LUMINANCE_ALPHA: 1579 cf[1] = cf[2] = cf[0]; 1580 break; 1581 /* Stencil border is tricky on some hw. Help drivers a little here. */ 1582 case GL_STENCIL_INDEX: 1583 case GL_INTENSITY: 1584 cf[1] = cf[2] = cf[3] = cf[0]; 1585 break; 1586 } 1587 } 1588} 1589