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