Home | History | Annotate | Download | only in wgl
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 VMware, Inc.
      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 VMWARE 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 
     42 struct 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 
     59 struct 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 
     72 static const struct stw_pf_color_info
     73 stw_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    /* alpha */
     78    { PIPE_FORMAT_B8G8R8A8_UNORM,    { 8,  8,  8,  8}, {16,  8,  0, 24} },
     79    { PIPE_FORMAT_A8R8G8B8_UNORM,    { 8,  8,  8,  8}, { 8, 16, 24,  0} },
     80    /* shallow bit depths */
     81    { PIPE_FORMAT_B5G6R5_UNORM,      { 5,  6,  5,  0}, {11,  5,  0,  0} },
     82 #if 0
     83    { PIPE_FORMAT_R10G10B10A2_UNORM, {10, 10, 10,  2}, { 0, 10, 20, 30} },
     84 #endif
     85    { PIPE_FORMAT_B5G5R5A1_UNORM,    { 5,  5,  5,  1}, {10,  5,  0, 15} },
     86    { PIPE_FORMAT_B4G4R4A4_UNORM,    { 4,  4,  4,  4}, {16,  4,  0, 12} }
     87 };
     88 
     89 static const struct stw_pf_color_info
     90 stw_pf_color_extended[] = {
     91    { PIPE_FORMAT_R32G32B32A32_FLOAT, {32, 32, 32, 32}, {0, 32, 64, 96} }
     92 };
     93 
     94 static const struct stw_pf_depth_info
     95 stw_pf_depth_stencil[] = {
     96    /* pure depth */
     97    { PIPE_FORMAT_Z32_UNORM,   {32, 0} },
     98    { PIPE_FORMAT_X8Z24_UNORM, {24, 0} },
     99    { PIPE_FORMAT_Z24X8_UNORM, {24, 0} },
    100    { PIPE_FORMAT_Z16_UNORM,   {16, 0} },
    101    /* combined depth-stencil */
    102    { PIPE_FORMAT_Z24_UNORM_S8_UINT, {24, 8} },
    103    { PIPE_FORMAT_S8_UINT_Z24_UNORM, {24, 8} }
    104 };
    105 
    106 
    107 static const boolean
    108 stw_pf_doublebuffer[] = {
    109    FALSE,
    110    TRUE,
    111 };
    112 
    113 
    114 const unsigned
    115 stw_pf_multisample[] = {
    116    0,
    117    4,
    118    8,
    119    16
    120 };
    121 
    122 
    123 static void
    124 stw_pixelformat_add(struct stw_device *stw_dev,
    125                     boolean extended,
    126                     const struct stw_pf_color_info *color,
    127                     const struct stw_pf_depth_info *depth,
    128                     unsigned accum,
    129                     boolean doublebuffer,
    130                     unsigned samples)
    131 {
    132    struct stw_pixelformat_info *pfi;
    133 
    134    assert(stw_dev->pixelformat_extended_count < STW_MAX_PIXELFORMATS);
    135    if (stw_dev->pixelformat_extended_count >= STW_MAX_PIXELFORMATS)
    136       return;
    137 
    138    assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 0) == color->bits.red);
    139    assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 1) == color->bits.green);
    140    assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 2) == color->bits.blue);
    141    assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 3) == color->bits.alpha);
    142    assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 0) == depth->bits.depth);
    143    assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 1) == depth->bits.stencil);
    144 
    145    pfi = &stw_dev->pixelformats[stw_dev->pixelformat_extended_count];
    146 
    147    memset(pfi, 0, sizeof *pfi);
    148 
    149    pfi->pfd.nSize = sizeof pfi->pfd;
    150    pfi->pfd.nVersion = 1;
    151 
    152    pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL;
    153 
    154    /* TODO: also support non-native pixel formats */
    155    if (!extended) {
    156       pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW;
    157    }
    158 
    159    /* See http://www.opengl.org/pipeline/article/vol003_7/ */
    160    pfi->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION;
    161 
    162    if (doublebuffer)
    163       pfi->pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE;
    164 
    165    pfi->pfd.iPixelType = PFD_TYPE_RGBA;
    166 
    167    pfi->pfd.cColorBits =
    168       color->bits.red + color->bits.green + color->bits.blue + color->bits.alpha;
    169    pfi->pfd.cRedBits = color->bits.red;
    170    pfi->pfd.cRedShift = color->shift.red;
    171    pfi->pfd.cGreenBits = color->bits.green;
    172    pfi->pfd.cGreenShift = color->shift.green;
    173    pfi->pfd.cBlueBits = color->bits.blue;
    174    pfi->pfd.cBlueShift = color->shift.blue;
    175    pfi->pfd.cAlphaBits = color->bits.alpha;
    176    pfi->pfd.cAlphaShift = color->shift.alpha;
    177    pfi->pfd.cAccumBits = 4*accum;
    178    pfi->pfd.cAccumRedBits = accum;
    179    pfi->pfd.cAccumGreenBits = accum;
    180    pfi->pfd.cAccumBlueBits = accum;
    181    pfi->pfd.cAccumAlphaBits = accum;
    182    pfi->pfd.cDepthBits = depth->bits.depth;
    183    pfi->pfd.cStencilBits = depth->bits.stencil;
    184    pfi->pfd.cAuxBuffers = 0;
    185    pfi->pfd.iLayerType = 0;
    186    pfi->pfd.bReserved = 0;
    187    pfi->pfd.dwLayerMask = 0;
    188    pfi->pfd.dwVisibleMask = 0;
    189    pfi->pfd.dwDamageMask = 0;
    190 
    191    /*
    192     * since state trackers can allocate depth/stencil/accum buffers, we provide
    193     * only color buffers here
    194     */
    195    pfi->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
    196    if (doublebuffer)
    197       pfi->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
    198 
    199    pfi->stvis.color_format = color->format;
    200    pfi->stvis.depth_stencil_format = depth->format;
    201 
    202    pfi->stvis.accum_format = (accum) ?
    203       PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
    204 
    205    pfi->stvis.samples = samples;
    206    pfi->stvis.render_buffer = ST_ATTACHMENT_INVALID;
    207 
    208    /* WGL_ARB_render_texture */
    209    if (color->bits.alpha)
    210       pfi->bindToTextureRGBA = TRUE;
    211 
    212    pfi->bindToTextureRGB = TRUE;
    213 
    214    ++stw_dev->pixelformat_extended_count;
    215 
    216    if (!extended) {
    217       ++stw_dev->pixelformat_count;
    218       assert(stw_dev->pixelformat_count == stw_dev->pixelformat_extended_count);
    219    }
    220 }
    221 
    222 
    223 /**
    224  * Add the depth/stencil/accum/ms variants for a list of color formats.
    225  */
    226 static unsigned
    227 add_color_format_variants(const struct stw_pf_color_info *color_formats,
    228                           unsigned num_color_formats, boolean extended)
    229 {
    230    struct pipe_screen *screen = stw_dev->screen;
    231    unsigned cfmt, ms, db, ds, acc;
    232    unsigned bind_flags = PIPE_BIND_RENDER_TARGET;
    233    unsigned num_added = 0;
    234    int force_samples = 0;
    235 
    236    /* Since GLUT for Windows doesn't support MSAA we have an env var
    237     * to force all pixel formats to have a particular number of samples.
    238     */
    239    {
    240       const char *samples= getenv("SVGA_FORCE_MSAA");
    241       if (samples)
    242          force_samples = atoi(samples);
    243    }
    244 
    245    if (!extended) {
    246       bind_flags |= PIPE_BIND_DISPLAY_TARGET;
    247    }
    248 
    249    for (ms = 0; ms < ARRAY_SIZE(stw_pf_multisample); ms++) {
    250       unsigned samples = stw_pf_multisample[ms];
    251 
    252       if (force_samples && samples != force_samples)
    253          continue;
    254 
    255       for (cfmt = 0; cfmt < num_color_formats; cfmt++) {
    256          if (!screen->is_format_supported(screen, color_formats[cfmt].format,
    257                                           PIPE_TEXTURE_2D, samples,
    258                                           bind_flags)) {
    259             continue;
    260          }
    261 
    262          for (db = 0; db < ARRAY_SIZE(stw_pf_doublebuffer); db++) {
    263             unsigned doublebuffer = stw_pf_doublebuffer[db];
    264 
    265             for (ds = 0; ds < ARRAY_SIZE(stw_pf_depth_stencil); ds++) {
    266                const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[ds];
    267 
    268                if (!screen->is_format_supported(screen, depth->format,
    269                                                 PIPE_TEXTURE_2D, samples,
    270                                                 PIPE_BIND_DEPTH_STENCIL)) {
    271                   continue;
    272                }
    273 
    274                for (acc = 0; acc < 2; acc++) {
    275                   stw_pixelformat_add(stw_dev, extended, &color_formats[cfmt],
    276                                       depth,
    277                                       acc * 16, doublebuffer, samples);
    278                   num_added++;
    279                }
    280             }
    281          }
    282       }
    283    }
    284 
    285    return num_added;
    286 }
    287 
    288 
    289 void
    290 stw_pixelformat_init(void)
    291 {
    292    unsigned num_formats;
    293 
    294    assert(!stw_dev->pixelformat_count);
    295    assert(!stw_dev->pixelformat_extended_count);
    296 
    297    /* normal, displayable formats */
    298    num_formats = add_color_format_variants(stw_pf_color,
    299                                            ARRAY_SIZE(stw_pf_color), FALSE);
    300    assert(num_formats > 0);
    301 
    302    /* extended, pbuffer-only formats */
    303    add_color_format_variants(stw_pf_color_extended,
    304                              ARRAY_SIZE(stw_pf_color_extended), TRUE);
    305 
    306    assert(stw_dev->pixelformat_count <= stw_dev->pixelformat_extended_count);
    307    assert(stw_dev->pixelformat_extended_count <= STW_MAX_PIXELFORMATS);
    308 }
    309 
    310 
    311 uint
    312 stw_pixelformat_get_count(void)
    313 {
    314    return stw_dev->pixelformat_count;
    315 }
    316 
    317 
    318 uint
    319 stw_pixelformat_get_extended_count(void)
    320 {
    321    return stw_dev->pixelformat_extended_count;
    322 }
    323 
    324 
    325 const struct stw_pixelformat_info *
    326 stw_pixelformat_get_info(int iPixelFormat)
    327 {
    328    unsigned index;
    329 
    330    if (iPixelFormat <= 0) {
    331       return NULL;
    332    }
    333 
    334    index = iPixelFormat - 1;
    335    if (index >= stw_dev->pixelformat_extended_count) {
    336       return NULL;
    337    }
    338 
    339    return &stw_dev->pixelformats[index];
    340 }
    341 
    342 
    343 LONG APIENTRY
    344 DrvDescribePixelFormat(HDC hdc, INT iPixelFormat, ULONG cjpfd,
    345                        PIXELFORMATDESCRIPTOR *ppfd)
    346 {
    347    uint count;
    348    const struct stw_pixelformat_info *pfi;
    349 
    350    (void) hdc;
    351 
    352    if (!stw_dev)
    353       return 0;
    354 
    355    count = stw_pixelformat_get_count();
    356 
    357    if (ppfd == NULL)
    358       return count;
    359 
    360    if (cjpfd != sizeof(PIXELFORMATDESCRIPTOR))
    361       return 0;
    362 
    363    pfi = stw_pixelformat_get_info(iPixelFormat);
    364    if (!pfi) {
    365       return 0;
    366    }
    367 
    368    memcpy(ppfd, &pfi->pfd, sizeof(PIXELFORMATDESCRIPTOR));
    369 
    370    return count;
    371 }
    372 
    373 
    374 BOOL APIENTRY
    375 DrvDescribeLayerPlane(HDC hdc, INT iPixelFormat, INT iLayerPlane,
    376                       UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd)
    377 {
    378    assert(0);
    379    return FALSE;
    380 }
    381 
    382 
    383 int APIENTRY
    384 DrvGetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart,
    385                           INT cEntries, COLORREF *pcr)
    386 {
    387    assert(0);
    388    return 0;
    389 }
    390 
    391 
    392 int APIENTRY
    393 DrvSetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart,
    394                           INT cEntries, CONST COLORREF *pcr)
    395 {
    396    assert(0);
    397    return 0;
    398 }
    399 
    400 
    401 BOOL APIENTRY
    402 DrvRealizeLayerPalette(HDC hdc, INT iLayerPlane, BOOL bRealize)
    403 {
    404    assert(0);
    405    return FALSE;
    406 }
    407 
    408 
    409 /* Only used by the wgl code, but have it here to avoid exporting the
    410  * pixelformat.h functionality.
    411  */
    412 int
    413 stw_pixelformat_choose(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd)
    414 {
    415    uint count;
    416    uint index;
    417    uint bestindex;
    418    uint bestdelta;
    419 
    420    (void) hdc;
    421 
    422    count = stw_pixelformat_get_extended_count();
    423    bestindex = 0;
    424    bestdelta = ~0U;
    425 
    426    for (index = 1; index <= count; index++) {
    427       uint delta = 0;
    428       const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info(index);
    429 
    430       if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
    431           !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) !=
    432           !!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))
    433          continue;
    434 
    435       /* Selection logic:
    436       * - Enabling a feature (depth, stencil...) is given highest priority.
    437       * - Giving as many bits as requested is given medium priority.
    438       * - Giving no more bits than requested is given lowest priority.
    439       */
    440 
    441       /* FIXME: Take in account individual channel bits */
    442       if (ppfd->cColorBits && !pfi->pfd.cColorBits)
    443          delta += 10000;
    444       else if (ppfd->cColorBits > pfi->pfd.cColorBits)
    445          delta += 100;
    446       else if (ppfd->cColorBits < pfi->pfd.cColorBits)
    447          delta++;
    448 
    449       if (ppfd->cDepthBits && !pfi->pfd.cDepthBits)
    450          delta += 10000;
    451       else if (ppfd->cDepthBits > pfi->pfd.cDepthBits)
    452          delta += 200;
    453       else if (ppfd->cDepthBits < pfi->pfd.cDepthBits)
    454          delta += 2;
    455 
    456       if (ppfd->cStencilBits && !pfi->pfd.cStencilBits)
    457          delta += 10000;
    458       else if (ppfd->cStencilBits > pfi->pfd.cStencilBits)
    459          delta += 400;
    460       else if (ppfd->cStencilBits < pfi->pfd.cStencilBits)
    461          delta++;
    462 
    463       if (ppfd->cAlphaBits && !pfi->pfd.cAlphaBits)
    464          delta += 10000;
    465       else if (ppfd->cAlphaBits > pfi->pfd.cAlphaBits)
    466          delta += 100;
    467       else if (ppfd->cAlphaBits < pfi->pfd.cAlphaBits)
    468          delta++;
    469 
    470       if (delta < bestdelta) {
    471          bestindex = index;
    472          bestdelta = delta;
    473          if (bestdelta == 0)
    474             break;
    475       }
    476    }
    477 
    478    return bestindex;
    479 }
    480