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 /**
     29  * @file
     30  *
     31  * WGL_ARB_pixel_format extension implementation.
     32  *
     33  * @sa http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
     34  */
     35 
     36 
     37 #include <windows.h>
     38 
     39 #define WGL_WGLEXT_PROTOTYPES
     40 
     41 #include <GL/gl.h>
     42 #include <GL/wglext.h>
     43 
     44 #include "pipe/p_compiler.h"
     45 #include "util/u_format.h"
     46 #include "util/u_memory.h"
     47 #include "stw_device.h"
     48 #include "stw_pixelformat.h"
     49 
     50 
     51 static boolean
     52 stw_query_attrib(
     53    int iPixelFormat,
     54    int iLayerPlane,
     55    int attrib,
     56    int *pvalue )
     57 {
     58    uint count;
     59    const struct stw_pixelformat_info *pfi;
     60 
     61    count = stw_pixelformat_get_extended_count();
     62 
     63    if (attrib == WGL_NUMBER_PIXEL_FORMATS_ARB) {
     64       *pvalue = (int) count;
     65       return TRUE;
     66    }
     67 
     68    pfi = stw_pixelformat_get_info( iPixelFormat );
     69    if (!pfi) {
     70       return FALSE;
     71    }
     72 
     73    switch (attrib) {
     74    case WGL_DRAW_TO_WINDOW_ARB:
     75       *pvalue = pfi->pfd.dwFlags & PFD_DRAW_TO_WINDOW ? TRUE : FALSE;
     76       return TRUE;
     77 
     78    case WGL_DRAW_TO_BITMAP_ARB:
     79       *pvalue = pfi->pfd.dwFlags & PFD_DRAW_TO_BITMAP ? TRUE : FALSE;
     80       return TRUE;
     81 
     82    case WGL_NEED_PALETTE_ARB:
     83       *pvalue = pfi->pfd.dwFlags & PFD_NEED_PALETTE ? TRUE : FALSE;
     84       return TRUE;
     85 
     86    case WGL_NEED_SYSTEM_PALETTE_ARB:
     87       *pvalue = pfi->pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE ? TRUE : FALSE;
     88       return TRUE;
     89 
     90    case WGL_SWAP_METHOD_ARB:
     91       if (pfi->pfd.dwFlags & PFD_SWAP_COPY)
     92          *pvalue = WGL_SWAP_COPY_ARB;
     93       else if (pfi->pfd.dwFlags & PFD_SWAP_EXCHANGE)
     94          *pvalue = WGL_SWAP_EXCHANGE_EXT;
     95       else
     96          *pvalue = WGL_SWAP_UNDEFINED_ARB;
     97       return TRUE;
     98 
     99    case WGL_SWAP_LAYER_BUFFERS_ARB:
    100       *pvalue = FALSE;
    101       return TRUE;
    102 
    103    case WGL_NUMBER_OVERLAYS_ARB:
    104       *pvalue = 0;
    105       return TRUE;
    106 
    107    case WGL_NUMBER_UNDERLAYS_ARB:
    108       *pvalue = 0;
    109       return TRUE;
    110 
    111    case WGL_BIND_TO_TEXTURE_RGB_ARB:
    112       /* WGL_ARB_render_texture */
    113       *pvalue = pfi->bindToTextureRGB;
    114       return TRUE;
    115 
    116    case WGL_BIND_TO_TEXTURE_RGBA_ARB:
    117       /* WGL_ARB_render_texture */
    118       *pvalue = pfi->bindToTextureRGBA;
    119       return TRUE;
    120    }
    121 
    122    if (iLayerPlane != 0)
    123       return FALSE;
    124 
    125    switch (attrib) {
    126    case WGL_ACCELERATION_ARB:
    127       *pvalue = WGL_FULL_ACCELERATION_ARB;
    128       break;
    129 
    130    case WGL_TRANSPARENT_ARB:
    131       *pvalue = FALSE;
    132       break;
    133 
    134    case WGL_TRANSPARENT_RED_VALUE_ARB:
    135    case WGL_TRANSPARENT_GREEN_VALUE_ARB:
    136    case WGL_TRANSPARENT_BLUE_VALUE_ARB:
    137    case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
    138    case WGL_TRANSPARENT_INDEX_VALUE_ARB:
    139       break;
    140 
    141    case WGL_SHARE_DEPTH_ARB:
    142    case WGL_SHARE_STENCIL_ARB:
    143    case WGL_SHARE_ACCUM_ARB:
    144       *pvalue = TRUE;
    145       break;
    146 
    147    case WGL_SUPPORT_GDI_ARB:
    148       *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_GDI ? TRUE : FALSE;
    149       break;
    150 
    151    case WGL_SUPPORT_OPENGL_ARB:
    152       *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_OPENGL ? TRUE : FALSE;
    153       break;
    154 
    155    case WGL_DOUBLE_BUFFER_ARB:
    156       *pvalue = pfi->pfd.dwFlags & PFD_DOUBLEBUFFER ? TRUE : FALSE;
    157       break;
    158 
    159    case WGL_STEREO_ARB:
    160       *pvalue = pfi->pfd.dwFlags & PFD_STEREO ? TRUE : FALSE;
    161       break;
    162 
    163    case WGL_PIXEL_TYPE_ARB:
    164       switch (pfi->pfd.iPixelType) {
    165       case PFD_TYPE_RGBA:
    166          if (util_format_is_float(pfi->stvis.color_format)) {
    167             *pvalue = WGL_TYPE_RGBA_FLOAT_ARB;
    168          }
    169          else {
    170             *pvalue = WGL_TYPE_RGBA_ARB;
    171          }
    172          break;
    173       case PFD_TYPE_COLORINDEX:
    174          *pvalue = WGL_TYPE_COLORINDEX_ARB;
    175          break;
    176       default:
    177          return FALSE;
    178       }
    179       break;
    180 
    181    case WGL_COLOR_BITS_ARB:
    182       *pvalue = pfi->pfd.cColorBits;
    183       break;
    184 
    185    case WGL_RED_BITS_ARB:
    186       *pvalue = pfi->pfd.cRedBits;
    187       break;
    188 
    189    case WGL_RED_SHIFT_ARB:
    190       *pvalue = pfi->pfd.cRedShift;
    191       break;
    192 
    193    case WGL_GREEN_BITS_ARB:
    194       *pvalue = pfi->pfd.cGreenBits;
    195       break;
    196 
    197    case WGL_GREEN_SHIFT_ARB:
    198       *pvalue = pfi->pfd.cGreenShift;
    199       break;
    200 
    201    case WGL_BLUE_BITS_ARB:
    202       *pvalue = pfi->pfd.cBlueBits;
    203       break;
    204 
    205    case WGL_BLUE_SHIFT_ARB:
    206       *pvalue = pfi->pfd.cBlueShift;
    207       break;
    208 
    209    case WGL_ALPHA_BITS_ARB:
    210       *pvalue = pfi->pfd.cAlphaBits;
    211       break;
    212 
    213    case WGL_ALPHA_SHIFT_ARB:
    214       *pvalue = pfi->pfd.cAlphaShift;
    215       break;
    216 
    217    case WGL_ACCUM_BITS_ARB:
    218       *pvalue = pfi->pfd.cAccumBits;
    219       break;
    220 
    221    case WGL_ACCUM_RED_BITS_ARB:
    222       *pvalue = pfi->pfd.cAccumRedBits;
    223       break;
    224 
    225    case WGL_ACCUM_GREEN_BITS_ARB:
    226       *pvalue = pfi->pfd.cAccumGreenBits;
    227       break;
    228 
    229    case WGL_ACCUM_BLUE_BITS_ARB:
    230       *pvalue = pfi->pfd.cAccumBlueBits;
    231       break;
    232 
    233    case WGL_ACCUM_ALPHA_BITS_ARB:
    234       *pvalue = pfi->pfd.cAccumAlphaBits;
    235       break;
    236 
    237    case WGL_DEPTH_BITS_ARB:
    238       *pvalue = pfi->pfd.cDepthBits;
    239       break;
    240 
    241    case WGL_STENCIL_BITS_ARB:
    242       *pvalue = pfi->pfd.cStencilBits;
    243       break;
    244 
    245    case WGL_AUX_BUFFERS_ARB:
    246       *pvalue = pfi->pfd.cAuxBuffers;
    247       break;
    248 
    249    case WGL_SAMPLE_BUFFERS_ARB:
    250       *pvalue = (pfi->stvis.samples > 1);
    251       break;
    252 
    253    case WGL_SAMPLES_ARB:
    254       *pvalue = pfi->stvis.samples;
    255       break;
    256 
    257 
    258    /* WGL_ARB_pbuffer */
    259 
    260    case WGL_MAX_PBUFFER_WIDTH_ARB:
    261    case WGL_MAX_PBUFFER_HEIGHT_ARB:
    262       *pvalue = stw_dev->max_2d_length;
    263       break;
    264 
    265    case WGL_MAX_PBUFFER_PIXELS_ARB:
    266       *pvalue = stw_dev->max_2d_length * stw_dev->max_2d_length;
    267       break;
    268 
    269    case WGL_DRAW_TO_PBUFFER_ARB:
    270       *pvalue = 1;
    271       break;
    272 
    273 
    274    default:
    275       return FALSE;
    276    }
    277 
    278    return TRUE;
    279 }
    280 
    281 struct attrib_match_info
    282 {
    283    int attribute;
    284    int weight;
    285    BOOL exact;
    286 };
    287 
    288 static const struct attrib_match_info attrib_match[] = {
    289 
    290    /* WGL_ARB_pixel_format */
    291    { WGL_DRAW_TO_WINDOW_ARB,      0, TRUE },
    292    { WGL_DRAW_TO_BITMAP_ARB,      0, TRUE },
    293    { WGL_ACCELERATION_ARB,        0, TRUE },
    294    { WGL_NEED_PALETTE_ARB,        0, TRUE },
    295    { WGL_NEED_SYSTEM_PALETTE_ARB, 0, TRUE },
    296    { WGL_SWAP_LAYER_BUFFERS_ARB,  0, TRUE },
    297    { WGL_SWAP_METHOD_ARB,         0, TRUE },
    298    { WGL_NUMBER_OVERLAYS_ARB,     4, FALSE },
    299    { WGL_NUMBER_UNDERLAYS_ARB,    4, FALSE },
    300    /*{ WGL_SHARE_DEPTH_ARB,         0, TRUE },*/     /* no overlays -- ignore */
    301    /*{ WGL_SHARE_STENCIL_ARB,       0, TRUE },*/   /* no overlays -- ignore */
    302    /*{ WGL_SHARE_ACCUM_ARB,         0, TRUE },*/     /* no overlays -- ignore */
    303    { WGL_SUPPORT_GDI_ARB,         0, TRUE },
    304    { WGL_SUPPORT_OPENGL_ARB,      0, TRUE },
    305    { WGL_DOUBLE_BUFFER_ARB,       0, TRUE },
    306    { WGL_STEREO_ARB,              0, TRUE },
    307    { WGL_PIXEL_TYPE_ARB,          0, TRUE },
    308    { WGL_COLOR_BITS_ARB,          1, FALSE },
    309    { WGL_RED_BITS_ARB,            1, FALSE },
    310    { WGL_GREEN_BITS_ARB,          1, FALSE },
    311    { WGL_BLUE_BITS_ARB,           1, FALSE },
    312    { WGL_ALPHA_BITS_ARB,          1, FALSE },
    313    { WGL_ACCUM_BITS_ARB,          1, FALSE },
    314    { WGL_ACCUM_RED_BITS_ARB,      1, FALSE },
    315    { WGL_ACCUM_GREEN_BITS_ARB,    1, FALSE },
    316    { WGL_ACCUM_BLUE_BITS_ARB,     1, FALSE },
    317    { WGL_ACCUM_ALPHA_BITS_ARB,    1, FALSE },
    318    { WGL_DEPTH_BITS_ARB,          1, FALSE },
    319    { WGL_STENCIL_BITS_ARB,        1, FALSE },
    320    { WGL_AUX_BUFFERS_ARB,         2, FALSE },
    321 
    322    /* WGL_ARB_multisample */
    323    { WGL_SAMPLE_BUFFERS_ARB,      2, FALSE },
    324    { WGL_SAMPLES_ARB,             2, FALSE },
    325 
    326    /* WGL_ARB_render_texture */
    327    { WGL_BIND_TO_TEXTURE_RGB_ARB, 0, FALSE },
    328    { WGL_BIND_TO_TEXTURE_RGBA_ARB, 0, FALSE },
    329 };
    330 
    331 struct stw_pixelformat_score
    332 {
    333    int points;
    334    uint index;
    335 };
    336 
    337 static BOOL
    338 score_pixelformats(
    339    struct stw_pixelformat_score *scores,
    340    uint count,
    341    int attribute,
    342    int expected_value )
    343 {
    344    uint i;
    345    const struct attrib_match_info *ami = NULL;
    346    uint index;
    347 
    348    /* Find out if a given attribute should be considered for score calculation.
    349     */
    350    for (i = 0; i < sizeof( attrib_match ) / sizeof( attrib_match[0] ); i++) {
    351       if (attrib_match[i].attribute == attribute) {
    352          ami = &attrib_match[i];
    353          break;
    354       }
    355    }
    356    if (ami == NULL)
    357       return TRUE;
    358 
    359    /* Iterate all pixelformats, query the requested attribute and calculate
    360     * score points.
    361     */
    362    for (index = 0; index < count; index++) {
    363       int actual_value;
    364 
    365       if (!stw_query_attrib( index + 1, 0, attribute, &actual_value ))
    366          return FALSE;
    367 
    368       if (ami->exact) {
    369          /* For an exact match criteria, if the actual and expected values differ,
    370           * the score is set to 0 points, effectively removing the pixelformat
    371           * from a list of matching pixelformats.
    372           */
    373          if (actual_value != expected_value)
    374             scores[index].points = 0;
    375       }
    376       else {
    377          /* For a minimum match criteria, if the actual value is smaller than the expected
    378           * value, the pixelformat is rejected (score set to 0). However, if the actual
    379           * value is bigger, the pixelformat is given a penalty to favour pixelformats that
    380           * more closely match the expected values.
    381           */
    382          if (actual_value < expected_value)
    383             scores[index].points = 0;
    384          else if (actual_value > expected_value)
    385             scores[index].points -= (actual_value - expected_value) * ami->weight;
    386       }
    387    }
    388 
    389    return TRUE;
    390 }
    391 
    392 WINGDIAPI BOOL APIENTRY
    393 wglChoosePixelFormatARB(
    394    HDC hdc,
    395    const int *piAttribIList,
    396    const FLOAT *pfAttribFList,
    397    UINT nMaxFormats,
    398    int *piFormats,
    399    UINT *nNumFormats )
    400 {
    401    uint count;
    402    struct stw_pixelformat_score *scores;
    403    uint i;
    404 
    405    *nNumFormats = 0;
    406 
    407    /* Allocate and initialize pixelformat score table -- better matches
    408     * have higher scores. Start with a high score and take out penalty
    409     * points for a mismatch when the match does not have to be exact.
    410     * Set a score to 0 if there is a mismatch for an exact match criteria.
    411     */
    412    count = stw_pixelformat_get_extended_count();
    413    scores = (struct stw_pixelformat_score *) MALLOC( count * sizeof( struct stw_pixelformat_score ) );
    414    if (scores == NULL)
    415       return FALSE;
    416    for (i = 0; i < count; i++) {
    417       scores[i].points = 0x7fffffff;
    418       scores[i].index = i;
    419    }
    420 
    421    /* Given the attribute list calculate a score for each pixelformat.
    422     */
    423    if (piAttribIList != NULL) {
    424       while (*piAttribIList != 0) {
    425          if (!score_pixelformats( scores, count, piAttribIList[0], piAttribIList[1] )) {
    426             FREE( scores );
    427             return FALSE;
    428          }
    429          piAttribIList += 2;
    430       }
    431    }
    432    if (pfAttribFList != NULL) {
    433       while (*pfAttribFList != 0) {
    434          if (!score_pixelformats( scores, count, (int) pfAttribFList[0], (int) pfAttribFList[1] )) {
    435             FREE( scores );
    436             return FALSE;
    437          }
    438          pfAttribFList += 2;
    439       }
    440    }
    441 
    442    /* Bubble-sort the resulting scores. Pixelformats with higher scores go first.
    443     * TODO: Find out if there are any patent issues with it.
    444     */
    445    if (count > 1) {
    446       uint n = count;
    447       boolean swapped;
    448 
    449       do {
    450          swapped = FALSE;
    451          for (i = 1; i < n; i++) {
    452             if (scores[i - 1].points < scores[i].points) {
    453                struct stw_pixelformat_score score = scores[i - 1];
    454 
    455                scores[i - 1] = scores[i];
    456                scores[i] = score;
    457                swapped = TRUE;
    458             }
    459          }
    460          n--;
    461       }
    462       while (swapped);
    463    }
    464 
    465    /* Return a list of pixelformats that are the best match.
    466     * Reject pixelformats with non-positive scores.
    467     */
    468    for (i = 0; i < count; i++) {
    469       if (scores[i].points > 0) {
    470 	 piFormats[*nNumFormats] = scores[i].index + 1;
    471          (*nNumFormats)++;
    472 	 if (*nNumFormats >= nMaxFormats) {
    473 	    break;
    474 	 }
    475       }
    476    }
    477 
    478    FREE( scores );
    479    return TRUE;
    480 }
    481 
    482 WINGDIAPI BOOL APIENTRY
    483 wglGetPixelFormatAttribfvARB(
    484    HDC hdc,
    485    int iPixelFormat,
    486    int iLayerPlane,
    487    UINT nAttributes,
    488    const int *piAttributes,
    489    FLOAT *pfValues )
    490 {
    491    UINT i;
    492 
    493    (void) hdc;
    494 
    495    for (i = 0; i < nAttributes; i++) {
    496       int value;
    497 
    498       if (!stw_query_attrib( iPixelFormat, iLayerPlane, piAttributes[i], &value ))
    499          return FALSE;
    500       pfValues[i] = (FLOAT) value;
    501    }
    502 
    503    return TRUE;
    504 }
    505 
    506 WINGDIAPI BOOL APIENTRY
    507 wglGetPixelFormatAttribivARB(
    508    HDC hdc,
    509    int iPixelFormat,
    510    int iLayerPlane,
    511    UINT nAttributes,
    512    const int *piAttributes,
    513    int *piValues )
    514 {
    515    UINT i;
    516 
    517    (void) hdc;
    518 
    519    for (i = 0; i < nAttributes; i++) {
    520       if (!stw_query_attrib( iPixelFormat, iLayerPlane, piAttributes[i], &piValues[i] ))
    521          return FALSE;
    522    }
    523 
    524    return TRUE;
    525 }
    526