stw_pixelformat.c revision 5706d7fcaf3c3238c652593d5669b9f793c6cdce
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 "main/mtypes.h" 29#include "main/context.h" 30 31#include "pipe/p_format.h" 32#include "pipe/p_defines.h" 33#include "pipe/p_screen.h" 34 35#include "util/u_format.h" 36#include "util/u_debug.h" 37 38#include "stw_icd.h" 39#include "stw_device.h" 40#include "stw_pixelformat.h" 41#include "stw_tls.h" 42 43 44struct stw_pf_color_info 45{ 46 enum pipe_format format; 47 struct { 48 unsigned char red; 49 unsigned char green; 50 unsigned char blue; 51 unsigned char alpha; 52 } bits; 53 struct { 54 unsigned char red; 55 unsigned char green; 56 unsigned char blue; 57 unsigned char alpha; 58 } shift; 59}; 60 61struct stw_pf_depth_info 62{ 63 enum pipe_format format; 64 struct { 65 unsigned char depth; 66 unsigned char stencil; 67 } bits; 68}; 69 70 71/* NOTE: order matters, since in otherwise equal circumstances the first 72 * format listed will get chosen */ 73 74static const struct stw_pf_color_info 75stw_pf_color[] = { 76 /* no-alpha */ 77 { PIPE_FORMAT_B8G8R8X8_UNORM, { 8, 8, 8, 0}, {16, 8, 0, 0} }, 78 { PIPE_FORMAT_X8R8G8B8_UNORM, { 8, 8, 8, 0}, { 8, 16, 24, 0} }, 79 { PIPE_FORMAT_B5G6R5_UNORM, { 5, 6, 5, 0}, {11, 5, 0, 0} }, 80 /* alpha */ 81 { PIPE_FORMAT_B8G8R8A8_UNORM, { 8, 8, 8, 8}, {16, 8, 0, 24} }, 82 { PIPE_FORMAT_A8R8G8B8_UNORM, { 8, 8, 8, 8}, { 8, 16, 24, 0} }, 83#if 0 84 { PIPE_FORMAT_R10G10B10A2_UNORM, {10, 10, 10, 2}, { 0, 10, 20, 30} }, 85#endif 86 { PIPE_FORMAT_B5G5R5A1_UNORM, { 5, 5, 5, 1}, {10, 5, 0, 15} }, 87 { PIPE_FORMAT_B4G4R4A4_UNORM, { 4, 4, 4, 4}, {16, 4, 0, 12} } 88}; 89 90 91static const struct stw_pf_depth_info 92stw_pf_depth_stencil[] = { 93 /* pure depth */ 94 { PIPE_FORMAT_Z32_UNORM, {32, 0} }, 95 { PIPE_FORMAT_X8Z24_UNORM, {24, 0} }, 96 { PIPE_FORMAT_Z24X8_UNORM, {24, 0} }, 97 { PIPE_FORMAT_Z16_UNORM, {16, 0} }, 98 /* combined depth-stencil */ 99 { PIPE_FORMAT_Z24S8_UNORM, {24, 8} }, 100 { PIPE_FORMAT_S8Z24_UNORM, {24, 8} } 101}; 102 103 104static const boolean 105stw_pf_doublebuffer[] = { 106 FALSE, 107 TRUE, 108}; 109 110 111const unsigned 112stw_pf_multisample[] = { 113 0, 114 4 115}; 116 117 118static void 119stw_pixelformat_add( 120 struct stw_device *stw_dev, 121 const struct stw_pf_color_info *color, 122 const struct stw_pf_depth_info *depth, 123 unsigned accum, 124 boolean doublebuffer, 125 unsigned samples ) 126{ 127 boolean extended = FALSE; 128 struct stw_pixelformat_info *pfi; 129 130 assert(stw_dev->pixelformat_extended_count < STW_MAX_PIXELFORMATS); 131 if(stw_dev->pixelformat_extended_count >= STW_MAX_PIXELFORMATS) 132 return; 133 134 assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 0) == color->bits.red); 135 assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 1) == color->bits.green); 136 assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 2) == color->bits.blue); 137 assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 3) == color->bits.alpha); 138 assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 0) == depth->bits.depth); 139 assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 1) == depth->bits.stencil); 140 141 pfi = &stw_dev->pixelformats[stw_dev->pixelformat_extended_count]; 142 143 memset(pfi, 0, sizeof *pfi); 144 145 pfi->color_format = color->format; 146 pfi->depth_stencil_format = depth->format; 147 148 pfi->pfd.nSize = sizeof pfi->pfd; 149 pfi->pfd.nVersion = 1; 150 151 pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL; 152 153 /* TODO: also support non-native pixel formats */ 154 pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW; 155 156 /* See http://www.opengl.org/pipeline/article/vol003_7/ */ 157 pfi->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION; 158 159 if (doublebuffer) 160 pfi->pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_COPY; 161 162 pfi->pfd.iPixelType = PFD_TYPE_RGBA; 163 164 pfi->pfd.cColorBits = color->bits.red + color->bits.green + color->bits.blue + color->bits.alpha; 165 pfi->pfd.cRedBits = color->bits.red; 166 pfi->pfd.cRedShift = color->shift.red; 167 pfi->pfd.cGreenBits = color->bits.green; 168 pfi->pfd.cGreenShift = color->shift.green; 169 pfi->pfd.cBlueBits = color->bits.blue; 170 pfi->pfd.cBlueShift = color->shift.blue; 171 pfi->pfd.cAlphaBits = color->bits.alpha; 172 pfi->pfd.cAlphaShift = color->shift.alpha; 173 pfi->pfd.cAccumBits = 4*accum; 174 pfi->pfd.cAccumRedBits = accum; 175 pfi->pfd.cAccumGreenBits = accum; 176 pfi->pfd.cAccumBlueBits = accum; 177 pfi->pfd.cAccumAlphaBits = accum; 178 pfi->pfd.cDepthBits = depth->bits.depth; 179 pfi->pfd.cStencilBits = depth->bits.stencil; 180 pfi->pfd.cAuxBuffers = 0; 181 pfi->pfd.iLayerType = 0; 182 pfi->pfd.bReserved = 0; 183 pfi->pfd.dwLayerMask = 0; 184 pfi->pfd.dwVisibleMask = 0; 185 pfi->pfd.dwDamageMask = 0; 186 187 if(samples) { 188 pfi->numSampleBuffers = 1; 189 pfi->numSamples = samples; 190 extended = TRUE; 191 } 192 193 ++stw_dev->pixelformat_extended_count; 194 195 if(!extended) { 196 ++stw_dev->pixelformat_count; 197 assert(stw_dev->pixelformat_count == stw_dev->pixelformat_extended_count); 198 } 199} 200 201void 202stw_pixelformat_init( void ) 203{ 204 struct pipe_screen *screen = stw_dev->screen; 205 unsigned i, j, k, l; 206 207 assert( !stw_dev->pixelformat_count ); 208 assert( !stw_dev->pixelformat_extended_count ); 209 210 for(i = 0; i < Elements(stw_pf_multisample); ++i) { 211 unsigned samples = stw_pf_multisample[i]; 212 213 /* FIXME: re-enabled MSAA when we can query it */ 214 if(samples) 215 continue; 216 217 for(j = 0; j < Elements(stw_pf_color); ++j) { 218 const struct stw_pf_color_info *color = &stw_pf_color[j]; 219 220 if(!screen->is_format_supported(screen, color->format, PIPE_TEXTURE_2D, 221 PIPE_TEXTURE_USAGE_RENDER_TARGET | 222 PIPE_TEXTURE_USAGE_DISPLAY_TARGET, 0)) 223 continue; 224 225 for(k = 0; k < Elements(stw_pf_doublebuffer); ++k) { 226 unsigned doublebuffer = stw_pf_doublebuffer[k]; 227 228 for(l = 0; l < Elements(stw_pf_depth_stencil); ++l) { 229 const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[l]; 230 231 if(!screen->is_format_supported(screen, depth->format, PIPE_TEXTURE_2D, 232 PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0)) 233 continue; 234 235 stw_pixelformat_add( stw_dev, color, depth, 0, doublebuffer, samples ); 236 stw_pixelformat_add( stw_dev, color, depth, 16, doublebuffer, samples ); 237 } 238 } 239 } 240 } 241 242 assert( stw_dev->pixelformat_count <= stw_dev->pixelformat_extended_count ); 243 assert( stw_dev->pixelformat_extended_count <= STW_MAX_PIXELFORMATS ); 244} 245 246uint 247stw_pixelformat_get_count( void ) 248{ 249 return stw_dev->pixelformat_count; 250} 251 252uint 253stw_pixelformat_get_extended_count( void ) 254{ 255 return stw_dev->pixelformat_extended_count; 256} 257 258const struct stw_pixelformat_info * 259stw_pixelformat_get_info( uint index ) 260{ 261 assert( index < stw_dev->pixelformat_extended_count ); 262 263 return &stw_dev->pixelformats[index]; 264} 265 266 267void 268stw_pixelformat_visual(GLvisual *visual, 269 const struct stw_pixelformat_info *pfi ) 270{ 271 memset(visual, 0, sizeof *visual); 272 _mesa_initialize_visual( 273 visual, 274 (pfi->pfd.iPixelType == PFD_TYPE_RGBA) ? GL_TRUE : GL_FALSE, 275 (pfi->pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE, 276 (pfi->pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE, 277 pfi->pfd.cRedBits, 278 pfi->pfd.cGreenBits, 279 pfi->pfd.cBlueBits, 280 pfi->pfd.cAlphaBits, 281 (pfi->pfd.iPixelType == PFD_TYPE_COLORINDEX) ? pfi->pfd.cColorBits : 0, 282 pfi->pfd.cDepthBits, 283 pfi->pfd.cStencilBits, 284 pfi->pfd.cAccumRedBits, 285 pfi->pfd.cAccumGreenBits, 286 pfi->pfd.cAccumBlueBits, 287 pfi->pfd.cAccumAlphaBits, 288 pfi->numSamples ); 289} 290 291 292LONG APIENTRY 293DrvDescribePixelFormat( 294 HDC hdc, 295 INT iPixelFormat, 296 ULONG cjpfd, 297 PIXELFORMATDESCRIPTOR *ppfd ) 298{ 299 uint count; 300 uint index; 301 const struct stw_pixelformat_info *pfi; 302 303 (void) hdc; 304 305 if (!stw_dev) 306 return 0; 307 308 count = stw_pixelformat_get_extended_count(); 309 index = (uint) iPixelFormat - 1; 310 311 if (ppfd == NULL) 312 return count; 313 if (index >= count || cjpfd != sizeof( PIXELFORMATDESCRIPTOR )) 314 return 0; 315 316 pfi = stw_pixelformat_get_info( index ); 317 318 memcpy(ppfd, &pfi->pfd, sizeof( PIXELFORMATDESCRIPTOR )); 319 320 return count; 321} 322 323BOOL APIENTRY 324DrvDescribeLayerPlane( 325 HDC hdc, 326 INT iPixelFormat, 327 INT iLayerPlane, 328 UINT nBytes, 329 LPLAYERPLANEDESCRIPTOR plpd ) 330{ 331 assert(0); 332 return FALSE; 333} 334 335int APIENTRY 336DrvGetLayerPaletteEntries( 337 HDC hdc, 338 INT iLayerPlane, 339 INT iStart, 340 INT cEntries, 341 COLORREF *pcr ) 342{ 343 assert(0); 344 return 0; 345} 346 347int APIENTRY 348DrvSetLayerPaletteEntries( 349 HDC hdc, 350 INT iLayerPlane, 351 INT iStart, 352 INT cEntries, 353 CONST COLORREF *pcr ) 354{ 355 assert(0); 356 return 0; 357} 358 359BOOL APIENTRY 360DrvRealizeLayerPalette( 361 HDC hdc, 362 INT iLayerPlane, 363 BOOL bRealize ) 364{ 365 assert(0); 366 return FALSE; 367} 368 369/* Only used by the wgl code, but have it here to avoid exporting the 370 * pixelformat.h functionality. 371 */ 372int stw_pixelformat_choose( HDC hdc, 373 CONST PIXELFORMATDESCRIPTOR *ppfd ) 374{ 375 uint count; 376 uint index; 377 uint bestindex; 378 uint bestdelta; 379 380 (void) hdc; 381 382 count = stw_pixelformat_get_count(); 383 bestindex = count; 384 bestdelta = ~0U; 385 386 for (index = 0; index < count; index++) { 387 uint delta = 0; 388 const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info( index ); 389 390 if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) && 391 !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) != 392 !!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) 393 continue; 394 395 /* FIXME: Take in account individual channel bits */ 396 if (ppfd->cColorBits != pfi->pfd.cColorBits) 397 delta += 8; 398 399 if (ppfd->cDepthBits != pfi->pfd.cDepthBits) 400 delta += 4; 401 402 if (ppfd->cStencilBits != pfi->pfd.cStencilBits) 403 delta += 2; 404 405 if (ppfd->cAlphaBits != pfi->pfd.cAlphaBits) 406 delta++; 407 408 if (delta < bestdelta) { 409 bestindex = index; 410 bestdelta = delta; 411 if (bestdelta == 0) 412 break; 413 } 414 } 415 416 if (bestindex == count) 417 return 0; 418 419 return bestindex + 1; 420} 421