stw_pixelformat.c revision 9646762261d976d34bee8c8b1dcda9656cec655c
1/************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28#include "pipe/p_format.h" 29#include "pipe/p_defines.h" 30#include "pipe/p_screen.h" 31 32#include "util/u_format.h" 33#include "util/u_debug.h" 34#include "util/u_memory.h" 35 36#include "stw_icd.h" 37#include "stw_device.h" 38#include "stw_pixelformat.h" 39#include "stw_tls.h" 40 41 42struct stw_pf_color_info 43{ 44 enum pipe_format format; 45 struct { 46 unsigned char red; 47 unsigned char green; 48 unsigned char blue; 49 unsigned char alpha; 50 } bits; 51 struct { 52 unsigned char red; 53 unsigned char green; 54 unsigned char blue; 55 unsigned char alpha; 56 } shift; 57}; 58 59struct stw_pf_depth_info 60{ 61 enum pipe_format format; 62 struct { 63 unsigned char depth; 64 unsigned char stencil; 65 } bits; 66}; 67 68 69/* NOTE: order matters, since in otherwise equal circumstances the first 70 * format listed will get chosen */ 71 72static const struct stw_pf_color_info 73stw_pf_color[] = { 74 /* no-alpha */ 75 { PIPE_FORMAT_B8G8R8X8_UNORM, { 8, 8, 8, 0}, {16, 8, 0, 0} }, 76 { PIPE_FORMAT_X8R8G8B8_UNORM, { 8, 8, 8, 0}, { 8, 16, 24, 0} }, 77 { PIPE_FORMAT_B5G6R5_UNORM, { 5, 6, 5, 0}, {11, 5, 0, 0} }, 78 /* alpha */ 79 { PIPE_FORMAT_B8G8R8A8_UNORM, { 8, 8, 8, 8}, {16, 8, 0, 24} }, 80 { PIPE_FORMAT_A8R8G8B8_UNORM, { 8, 8, 8, 8}, { 8, 16, 24, 0} }, 81#if 0 82 { PIPE_FORMAT_R10G10B10A2_UNORM, {10, 10, 10, 2}, { 0, 10, 20, 30} }, 83#endif 84 { PIPE_FORMAT_B5G5R5A1_UNORM, { 5, 5, 5, 1}, {10, 5, 0, 15} }, 85 { PIPE_FORMAT_B4G4R4A4_UNORM, { 4, 4, 4, 4}, {16, 4, 0, 12} } 86}; 87 88static const struct stw_pf_color_info 89stw_pf_color_extended[] = { 90 { PIPE_FORMAT_R32G32B32A32_FLOAT, { 32, 32, 32, 32}, { 0, 32, 64, 96} } 91}; 92 93static const struct stw_pf_depth_info 94stw_pf_depth_stencil[] = { 95 /* pure depth */ 96 { PIPE_FORMAT_Z32_UNORM, {32, 0} }, 97 { PIPE_FORMAT_X8Z24_UNORM, {24, 0} }, 98 { PIPE_FORMAT_Z24X8_UNORM, {24, 0} }, 99 { PIPE_FORMAT_Z16_UNORM, {16, 0} }, 100 /* combined depth-stencil */ 101 { PIPE_FORMAT_Z24_UNORM_S8_UINT, {24, 8} }, 102 { PIPE_FORMAT_S8_UINT_Z24_UNORM, {24, 8} } 103}; 104 105 106static const boolean 107stw_pf_doublebuffer[] = { 108 FALSE, 109 TRUE, 110}; 111 112 113const unsigned 114stw_pf_multisample[] = { 115 0, 116 4 117}; 118 119 120static void 121stw_pixelformat_add( 122 struct stw_device *stw_dev, 123 boolean extended, 124 const struct stw_pf_color_info *color, 125 const struct stw_pf_depth_info *depth, 126 unsigned accum, 127 boolean doublebuffer, 128 unsigned samples ) 129{ 130 struct stw_pixelformat_info *pfi; 131 132 assert(stw_dev->pixelformat_extended_count < STW_MAX_PIXELFORMATS); 133 if(stw_dev->pixelformat_extended_count >= STW_MAX_PIXELFORMATS) 134 return; 135 136 assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 0) == color->bits.red); 137 assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 1) == color->bits.green); 138 assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 2) == color->bits.blue); 139 assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 3) == color->bits.alpha); 140 assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 0) == depth->bits.depth); 141 assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 1) == depth->bits.stencil); 142 143 pfi = &stw_dev->pixelformats[stw_dev->pixelformat_extended_count]; 144 145 memset(pfi, 0, sizeof *pfi); 146 147 pfi->pfd.nSize = sizeof pfi->pfd; 148 pfi->pfd.nVersion = 1; 149 150 pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL; 151 152 /* TODO: also support non-native pixel formats */ 153 if (!extended) { 154 pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW; 155 } 156 157 /* See http://www.opengl.org/pipeline/article/vol003_7/ */ 158 pfi->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION; 159 160 if (doublebuffer) 161 pfi->pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_COPY; 162 163 pfi->pfd.iPixelType = PFD_TYPE_RGBA; 164 165 pfi->pfd.cColorBits = color->bits.red + color->bits.green + color->bits.blue + color->bits.alpha; 166 pfi->pfd.cRedBits = color->bits.red; 167 pfi->pfd.cRedShift = color->shift.red; 168 pfi->pfd.cGreenBits = color->bits.green; 169 pfi->pfd.cGreenShift = color->shift.green; 170 pfi->pfd.cBlueBits = color->bits.blue; 171 pfi->pfd.cBlueShift = color->shift.blue; 172 pfi->pfd.cAlphaBits = color->bits.alpha; 173 pfi->pfd.cAlphaShift = color->shift.alpha; 174 pfi->pfd.cAccumBits = 4*accum; 175 pfi->pfd.cAccumRedBits = accum; 176 pfi->pfd.cAccumGreenBits = accum; 177 pfi->pfd.cAccumBlueBits = accum; 178 pfi->pfd.cAccumAlphaBits = accum; 179 pfi->pfd.cDepthBits = depth->bits.depth; 180 pfi->pfd.cStencilBits = depth->bits.stencil; 181 pfi->pfd.cAuxBuffers = 0; 182 pfi->pfd.iLayerType = 0; 183 pfi->pfd.bReserved = 0; 184 pfi->pfd.dwLayerMask = 0; 185 pfi->pfd.dwVisibleMask = 0; 186 pfi->pfd.dwDamageMask = 0; 187 188 /* 189 * since state trackers can allocate depth/stencil/accum buffers, we provide 190 * only color buffers here 191 */ 192 pfi->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; 193 if (doublebuffer) 194 pfi->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; 195 196 pfi->stvis.color_format = color->format; 197 pfi->stvis.depth_stencil_format = depth->format; 198 199 pfi->stvis.accum_format = (accum) ? 200 PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; 201 202 pfi->stvis.samples = samples; 203 pfi->stvis.render_buffer = ST_ATTACHMENT_INVALID; 204 205 ++stw_dev->pixelformat_extended_count; 206 207 if(!extended) { 208 ++stw_dev->pixelformat_count; 209 assert(stw_dev->pixelformat_count == stw_dev->pixelformat_extended_count); 210 } 211} 212 213void 214stw_pixelformat_init( void ) 215{ 216 struct pipe_screen *screen = stw_dev->screen; 217 unsigned i, j, k, l; 218 219 assert( !stw_dev->pixelformat_count ); 220 assert( !stw_dev->pixelformat_extended_count ); 221 222 for(i = 0; i < Elements(stw_pf_multisample); ++i) { 223 unsigned samples = stw_pf_multisample[i]; 224 225 /* FIXME: re-enabled MSAA when we can query it */ 226 if(samples) 227 continue; 228 229 for(j = 0; j < Elements(stw_pf_color); ++j) { 230 const struct stw_pf_color_info *color = &stw_pf_color[j]; 231 232 if(!screen->is_format_supported(screen, color->format, PIPE_TEXTURE_2D, 233 0, PIPE_BIND_RENDER_TARGET | 234 PIPE_BIND_DISPLAY_TARGET)) 235 continue; 236 237 for(k = 0; k < Elements(stw_pf_doublebuffer); ++k) { 238 unsigned doublebuffer = stw_pf_doublebuffer[k]; 239 240 for(l = 0; l < Elements(stw_pf_depth_stencil); ++l) { 241 const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[l]; 242 243 if(!screen->is_format_supported(screen, depth->format, PIPE_TEXTURE_2D, 244 0, PIPE_BIND_DEPTH_STENCIL)) 245 continue; 246 247 stw_pixelformat_add( stw_dev, FALSE, color, depth, 0, doublebuffer, samples ); 248 stw_pixelformat_add( stw_dev, FALSE, color, depth, 16, doublebuffer, samples ); 249 } 250 } 251 } 252 } 253 254 /* 255 * Same as above, but for the extended color formats (e.g, float) and without PIPE_BIND_DISPLAY_TARGET bit. 256 */ 257 for(i = 0; i < Elements(stw_pf_multisample); ++i) { 258 unsigned samples = stw_pf_multisample[i]; 259 260 /* FIXME: re-enabled MSAA when we can query it */ 261 if(samples) 262 continue; 263 264 for(j = 0; j < Elements(stw_pf_color_extended); ++j) { 265 const struct stw_pf_color_info *color = &stw_pf_color_extended[j]; 266 267 if(!screen->is_format_supported(screen, color->format, PIPE_TEXTURE_2D, 268 0, PIPE_BIND_RENDER_TARGET)) 269 continue; 270 271 for(k = 0; k < Elements(stw_pf_doublebuffer); ++k) { 272 unsigned doublebuffer = stw_pf_doublebuffer[k]; 273 274 for(l = 0; l < Elements(stw_pf_depth_stencil); ++l) { 275 const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[l]; 276 277 if(!screen->is_format_supported(screen, depth->format, PIPE_TEXTURE_2D, 278 0, PIPE_BIND_DEPTH_STENCIL)) 279 continue; 280 281 stw_pixelformat_add( stw_dev, TRUE, color, depth, 0, doublebuffer, samples ); 282 stw_pixelformat_add( stw_dev, TRUE, color, depth, 16, doublebuffer, samples ); 283 } 284 } 285 } 286 } 287 288 assert( stw_dev->pixelformat_count <= stw_dev->pixelformat_extended_count ); 289 assert( stw_dev->pixelformat_extended_count <= STW_MAX_PIXELFORMATS ); 290} 291 292uint 293stw_pixelformat_get_count( void ) 294{ 295 return stw_dev->pixelformat_count; 296} 297 298uint 299stw_pixelformat_get_extended_count( void ) 300{ 301 return stw_dev->pixelformat_extended_count; 302} 303 304const struct stw_pixelformat_info * 305stw_pixelformat_get_info( int iPixelFormat ) 306{ 307 int index; 308 309 if (iPixelFormat <= 0) { 310 return NULL; 311 } 312 313 index = iPixelFormat - 1; 314 if (index >= stw_dev->pixelformat_extended_count) { 315 return NULL; 316 } 317 318 return &stw_dev->pixelformats[index]; 319} 320 321 322LONG APIENTRY 323DrvDescribePixelFormat( 324 HDC hdc, 325 INT iPixelFormat, 326 ULONG cjpfd, 327 PIXELFORMATDESCRIPTOR *ppfd ) 328{ 329 uint count; 330 const struct stw_pixelformat_info *pfi; 331 332 (void) hdc; 333 334 if (!stw_dev) 335 return 0; 336 337 count = stw_pixelformat_get_count(); 338 339 if (ppfd == NULL) 340 return count; 341 if (cjpfd != sizeof( PIXELFORMATDESCRIPTOR )) 342 return 0; 343 344 pfi = stw_pixelformat_get_info( iPixelFormat ); 345 if (!pfi) { 346 return 0; 347 } 348 349 memcpy(ppfd, &pfi->pfd, sizeof( PIXELFORMATDESCRIPTOR )); 350 351 return count; 352} 353 354BOOL APIENTRY 355DrvDescribeLayerPlane( 356 HDC hdc, 357 INT iPixelFormat, 358 INT iLayerPlane, 359 UINT nBytes, 360 LPLAYERPLANEDESCRIPTOR plpd ) 361{ 362 assert(0); 363 return FALSE; 364} 365 366int APIENTRY 367DrvGetLayerPaletteEntries( 368 HDC hdc, 369 INT iLayerPlane, 370 INT iStart, 371 INT cEntries, 372 COLORREF *pcr ) 373{ 374 assert(0); 375 return 0; 376} 377 378int APIENTRY 379DrvSetLayerPaletteEntries( 380 HDC hdc, 381 INT iLayerPlane, 382 INT iStart, 383 INT cEntries, 384 CONST COLORREF *pcr ) 385{ 386 assert(0); 387 return 0; 388} 389 390BOOL APIENTRY 391DrvRealizeLayerPalette( 392 HDC hdc, 393 INT iLayerPlane, 394 BOOL bRealize ) 395{ 396 assert(0); 397 return FALSE; 398} 399 400/* Only used by the wgl code, but have it here to avoid exporting the 401 * pixelformat.h functionality. 402 */ 403int stw_pixelformat_choose( HDC hdc, 404 CONST PIXELFORMATDESCRIPTOR *ppfd ) 405{ 406 uint count; 407 uint index; 408 uint bestindex; 409 uint bestdelta; 410 411 (void) hdc; 412 413 count = stw_pixelformat_get_extended_count(); 414 bestindex = 0; 415 bestdelta = ~0U; 416 417 for (index = 1; index <= count; index++) { 418 uint delta = 0; 419 const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info( index ); 420 421 if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) && 422 !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) != 423 !!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) 424 continue; 425 426 /* FIXME: Take in account individual channel bits */ 427 if (ppfd->cColorBits != pfi->pfd.cColorBits) 428 delta += 8; 429 430 if (ppfd->cDepthBits != pfi->pfd.cDepthBits) 431 delta += 4; 432 433 if (ppfd->cStencilBits != pfi->pfd.cStencilBits) 434 delta += 2; 435 436 if (ppfd->cAlphaBits != pfi->pfd.cAlphaBits) 437 delta++; 438 439 if (delta < bestdelta) { 440 bestindex = index; 441 bestdelta = delta; 442 if (bestdelta == 0) 443 break; 444 } 445 } 446 447 return bestindex; 448} 449