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