Home | History | Annotate | Download | only in wgl
      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 
     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    { 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 
     88 static const struct stw_pf_color_info
     89 stw_pf_color_extended[] = {
     90     { PIPE_FORMAT_R32G32B32A32_FLOAT, { 32,  32, 32,  32}, { 0,  32, 64, 96} }
     91 };
     92 
     93 static const struct stw_pf_depth_info
     94 stw_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 
    106 static const boolean
    107 stw_pf_doublebuffer[] = {
    108    FALSE,
    109    TRUE,
    110 };
    111 
    112 
    113 const unsigned
    114 stw_pf_multisample[] = {
    115    0,
    116    4
    117 };
    118 
    119 
    120 static void
    121 stw_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 
    213 
    214 /**
    215  * Add the depth/stencil/accum/ms variants for a particular color format.
    216  */
    217 static void
    218 add_color_format_variants(const struct stw_pf_color_info *color,
    219                           boolean extended)
    220 {
    221    struct pipe_screen *screen = stw_dev->screen;
    222    unsigned ms, db, ds, acc;
    223    unsigned bind_flags = PIPE_BIND_RENDER_TARGET;
    224 
    225    if (!extended) {
    226       bind_flags |= PIPE_BIND_DISPLAY_TARGET;
    227    }
    228 
    229    if (!screen->is_format_supported(screen, color->format,
    230                                     PIPE_TEXTURE_2D, 0, bind_flags)) {
    231       return;
    232    }
    233 
    234    for (ms = 0; ms < Elements(stw_pf_multisample); ms++) {
    235       unsigned samples = stw_pf_multisample[ms];
    236 
    237       /* FIXME: re-enabled MSAA when we can query it */
    238       if (samples)
    239          continue;
    240 
    241       for (db = 0; db < Elements(stw_pf_doublebuffer); db++) {
    242          unsigned doublebuffer = stw_pf_doublebuffer[db];
    243 
    244          for (ds = 0; ds < Elements(stw_pf_depth_stencil); ds++) {
    245             const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[ds];
    246 
    247             if (!screen->is_format_supported(screen, depth->format,
    248                                              PIPE_TEXTURE_2D, 0,
    249                                              PIPE_BIND_DEPTH_STENCIL)) {
    250                continue;
    251             }
    252 
    253             for (acc = 0; acc < 2; acc++) {
    254                stw_pixelformat_add(stw_dev, extended, color, depth,
    255                                    acc * 16, doublebuffer, samples);
    256             }
    257          }
    258       }
    259    }
    260 }
    261 
    262 
    263 void
    264 stw_pixelformat_init( void )
    265 {
    266    unsigned i;
    267 
    268    assert( !stw_dev->pixelformat_count );
    269    assert( !stw_dev->pixelformat_extended_count );
    270 
    271    /* normal, displayable formats */
    272    for (i = 0; i < Elements(stw_pf_color); i++) {
    273       add_color_format_variants(&stw_pf_color[i], FALSE);
    274    }
    275 
    276    /* extended, pbuffer-only formats */
    277    for (i = 0; i < Elements(stw_pf_color_extended); i++) {
    278       add_color_format_variants(&stw_pf_color_extended[i], TRUE);
    279    }
    280 
    281    assert( stw_dev->pixelformat_count <= stw_dev->pixelformat_extended_count );
    282    assert( stw_dev->pixelformat_extended_count <= STW_MAX_PIXELFORMATS );
    283 }
    284 
    285 uint
    286 stw_pixelformat_get_count( void )
    287 {
    288    return stw_dev->pixelformat_count;
    289 }
    290 
    291 uint
    292 stw_pixelformat_get_extended_count( void )
    293 {
    294    return stw_dev->pixelformat_extended_count;
    295 }
    296 
    297 const struct stw_pixelformat_info *
    298 stw_pixelformat_get_info( int iPixelFormat )
    299 {
    300    int index;
    301 
    302    if (iPixelFormat <= 0) {
    303       return NULL;
    304    }
    305 
    306    index = iPixelFormat - 1;
    307    if (index >= stw_dev->pixelformat_extended_count) {
    308       return NULL;
    309    }
    310 
    311    return &stw_dev->pixelformats[index];
    312 }
    313 
    314 
    315 LONG APIENTRY
    316 DrvDescribePixelFormat(
    317    HDC hdc,
    318    INT iPixelFormat,
    319    ULONG cjpfd,
    320    PIXELFORMATDESCRIPTOR *ppfd )
    321 {
    322    uint count;
    323    const struct stw_pixelformat_info *pfi;
    324 
    325    (void) hdc;
    326 
    327    if (!stw_dev)
    328       return 0;
    329 
    330    count = stw_pixelformat_get_count();
    331 
    332    if (ppfd == NULL)
    333       return count;
    334    if (cjpfd != sizeof( PIXELFORMATDESCRIPTOR ))
    335       return 0;
    336 
    337    pfi = stw_pixelformat_get_info( iPixelFormat );
    338    if (!pfi) {
    339       return 0;
    340    }
    341 
    342    memcpy(ppfd, &pfi->pfd, sizeof( PIXELFORMATDESCRIPTOR ));
    343 
    344    return count;
    345 }
    346 
    347 BOOL APIENTRY
    348 DrvDescribeLayerPlane(
    349    HDC hdc,
    350    INT iPixelFormat,
    351    INT iLayerPlane,
    352    UINT nBytes,
    353    LPLAYERPLANEDESCRIPTOR plpd )
    354 {
    355    assert(0);
    356    return FALSE;
    357 }
    358 
    359 int APIENTRY
    360 DrvGetLayerPaletteEntries(
    361    HDC hdc,
    362    INT iLayerPlane,
    363    INT iStart,
    364    INT cEntries,
    365    COLORREF *pcr )
    366 {
    367    assert(0);
    368    return 0;
    369 }
    370 
    371 int APIENTRY
    372 DrvSetLayerPaletteEntries(
    373    HDC hdc,
    374    INT iLayerPlane,
    375    INT iStart,
    376    INT cEntries,
    377    CONST COLORREF *pcr )
    378 {
    379    assert(0);
    380    return 0;
    381 }
    382 
    383 BOOL APIENTRY
    384 DrvRealizeLayerPalette(
    385    HDC hdc,
    386    INT iLayerPlane,
    387    BOOL bRealize )
    388 {
    389    assert(0);
    390    return FALSE;
    391 }
    392 
    393 /* Only used by the wgl code, but have it here to avoid exporting the
    394  * pixelformat.h functionality.
    395  */
    396 int stw_pixelformat_choose( HDC hdc,
    397                             CONST PIXELFORMATDESCRIPTOR *ppfd )
    398 {
    399    uint count;
    400    uint index;
    401    uint bestindex;
    402    uint bestdelta;
    403 
    404    (void) hdc;
    405 
    406    count = stw_pixelformat_get_extended_count();
    407    bestindex = 0;
    408    bestdelta = ~0U;
    409 
    410    for (index = 1; index <= count; index++) {
    411       uint delta = 0;
    412       const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info( index );
    413 
    414       if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
    415           !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) !=
    416           !!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))
    417          continue;
    418 
    419       /* FIXME: Take in account individual channel bits */
    420       if (ppfd->cColorBits != pfi->pfd.cColorBits)
    421          delta += 8;
    422 
    423       if (ppfd->cDepthBits != pfi->pfd.cDepthBits)
    424          delta += 4;
    425 
    426       if (ppfd->cStencilBits != pfi->pfd.cStencilBits)
    427          delta += 2;
    428 
    429       if (ppfd->cAlphaBits != pfi->pfd.cAlphaBits)
    430          delta++;
    431 
    432       if (delta < bestdelta) {
    433          bestindex = index;
    434          bestdelta = delta;
    435          if (bestdelta == 0)
    436             break;
    437       }
    438    }
    439 
    440    return bestindex;
    441 }
    442