Home | History | Annotate | Download | only in win
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "SkWGL.h"
     10 
     11 #include "SkTDArray.h"
     12 #include "SkTSearch.h"
     13 
     14 bool SkWGLExtensions::hasExtension(HDC dc, const char* ext) const {
     15     if (NULL == this->fGetExtensionsString) {
     16         return false;
     17     }
     18     if (!strcmp("WGL_ARB_extensions_string", ext)) {
     19         return true;
     20     }
     21     const char* extensionString = this->getExtensionsString(dc);
     22     int extLength = strlen(ext);
     23 
     24     while (true) {
     25         int n = strcspn(extensionString, " ");
     26         if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
     27             return true;
     28         }
     29         if (0 == extensionString[n]) {
     30             return false;
     31         }
     32         extensionString += n+1;
     33     }
     34 
     35     return false;
     36 }
     37 
     38 const char* SkWGLExtensions::getExtensionsString(HDC hdc) const {
     39     return fGetExtensionsString(hdc);
     40 }
     41 
     42 BOOL SkWGLExtensions::choosePixelFormat(HDC hdc,
     43                                         const int* piAttribIList,
     44                                         const FLOAT* pfAttribFList,
     45                                         UINT nMaxFormats,
     46                                         int* piFormats,
     47                                         UINT* nNumFormats) const {
     48     return fChoosePixelFormat(hdc, piAttribIList, pfAttribFList,
     49                               nMaxFormats, piFormats, nNumFormats);
     50 }
     51 
     52 BOOL SkWGLExtensions::getPixelFormatAttribiv(HDC hdc,
     53                                              int iPixelFormat,
     54                                              int iLayerPlane,
     55                                              UINT nAttributes,
     56                                              const int *piAttributes,
     57                                              int *piValues) const {
     58     return fGetPixelFormatAttribiv(hdc, iPixelFormat, iLayerPlane,
     59                                    nAttributes, piAttributes, piValues);
     60 }
     61 
     62 BOOL SkWGLExtensions::getPixelFormatAttribfv(HDC hdc,
     63                                              int iPixelFormat,
     64                                              int iLayerPlane,
     65                                              UINT nAttributes,
     66                                              const int *piAttributes,
     67                                              float *pfValues) const {
     68     return fGetPixelFormatAttribfv(hdc, iPixelFormat, iLayerPlane,
     69                                    nAttributes, piAttributes, pfValues);
     70 }
     71 HGLRC SkWGLExtensions::createContextAttribs(HDC hDC,
     72                                             HGLRC hShareContext,
     73                                             const int *attribList) const {
     74     return fCreateContextAttribs(hDC, hShareContext, attribList);
     75 }
     76 
     77 namespace {
     78 
     79 struct PixelFormat {
     80     int fFormat;
     81     int fCoverageSamples;
     82     int fColorSamples;
     83     int fChoosePixelFormatRank;
     84 };
     85 
     86 int compare_pf(const PixelFormat* a, const PixelFormat* b) {
     87     if (a->fCoverageSamples < b->fCoverageSamples) {
     88         return -1;
     89     } else if (b->fCoverageSamples < a->fCoverageSamples) {
     90         return 1;
     91     } else if (a->fColorSamples < b->fColorSamples) {
     92         return -1;
     93     } else if (b->fColorSamples < a->fColorSamples) {
     94         return 1;
     95     } else if (a->fChoosePixelFormatRank < b->fChoosePixelFormatRank) {
     96         return -1;
     97     } else if (b->fChoosePixelFormatRank < a->fChoosePixelFormatRank) {
     98         return 1;
     99     }
    100     return 0;
    101 }
    102 }
    103 
    104 int SkWGLExtensions::selectFormat(const int formats[],
    105                                   int formatCount,
    106                                   HDC dc,
    107                                   int desiredSampleCount) {
    108     PixelFormat desiredFormat = {
    109         0,
    110         desiredSampleCount,
    111         0,
    112         0,
    113     };
    114     SkTDArray<PixelFormat> rankedFormats;
    115     rankedFormats.setCount(formatCount);
    116     bool supportsCoverage = this->hasExtension(dc,
    117                                                "WGL_NV_multisample_coverage");
    118     for (int i = 0; i < formatCount; ++i) {
    119         static const int queryAttrs[] = {
    120             SK_WGL_COVERAGE_SAMPLES,
    121             // Keep COLOR_SAMPLES at the end so it can be skipped
    122             SK_WGL_COLOR_SAMPLES,
    123         };
    124         int answers[2];
    125         int queryAttrCnt = supportsCoverage ?
    126                                     SK_ARRAY_COUNT(queryAttrs) :
    127                                     SK_ARRAY_COUNT(queryAttrs) - 1;
    128         this->getPixelFormatAttribiv(dc,
    129                                      formats[i],
    130                                      0,
    131                                      queryAttrCnt,
    132                                      queryAttrs,
    133                                      answers);
    134         rankedFormats[i].fFormat =  formats[i];
    135         rankedFormats[i].fCoverageSamples = answers[0];
    136         rankedFormats[i].fColorSamples = answers[supportsCoverage ? 1 : 0];
    137         rankedFormats[i].fChoosePixelFormatRank = i;
    138     }
    139     qsort(rankedFormats.begin(),
    140             rankedFormats.count(),
    141             sizeof(PixelFormat),
    142             SkCastForQSort(compare_pf));
    143     int idx = SkTSearch<PixelFormat>(rankedFormats.begin(),
    144                                      rankedFormats.count(),
    145                                      desiredFormat,
    146                                      sizeof(PixelFormat),
    147                                      compare_pf);
    148     if (idx < 0) {
    149         idx = ~idx;
    150     }
    151     return rankedFormats[idx].fFormat;
    152 }
    153 
    154 
    155 namespace {
    156 
    157 #if defined(UNICODE)
    158     #define STR_LIT(X) L## #X
    159 #else
    160     #define STR_LIT(X) #X
    161 #endif
    162 
    163 #define DUMMY_CLASS STR_LIT("DummyClass")
    164 
    165 HWND create_dummy_window() {
    166     HMODULE module = GetModuleHandle(NULL);
    167     HWND dummy;
    168     RECT windowRect;
    169     windowRect.left = 0;
    170     windowRect.right = 8;
    171     windowRect.top = 0;
    172     windowRect.bottom = 8;
    173 
    174     WNDCLASS wc;
    175 
    176     wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    177     wc.lpfnWndProc = (WNDPROC) DefWindowProc;
    178     wc.cbClsExtra = 0;
    179     wc.cbWndExtra = 0;
    180     wc.hInstance = module;
    181     wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    182     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    183     wc.hbrBackground = NULL;
    184     wc.lpszMenuName = NULL;
    185     wc.lpszClassName = DUMMY_CLASS;
    186 
    187     if(!RegisterClass(&wc)) {
    188         return 0;
    189     }
    190 
    191     DWORD style, exStyle;
    192     exStyle = WS_EX_CLIENTEDGE;
    193     style = WS_SYSMENU;
    194 
    195     AdjustWindowRectEx(&windowRect, style, false, exStyle);
    196     if(!(dummy = CreateWindowEx(exStyle,
    197                                 DUMMY_CLASS,
    198                                 STR_LIT("DummyWindow"),
    199                                 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
    200                                 0, 0,
    201                                 windowRect.right-windowRect.left,
    202                                 windowRect.bottom-windowRect.top,
    203                                 NULL, NULL,
    204                                 module,
    205                                 NULL))) {
    206         UnregisterClass(DUMMY_CLASS, module);
    207         return NULL;
    208     }
    209     ShowWindow(dummy, SW_HIDE);
    210 
    211     return dummy;
    212 }
    213 
    214 void destroy_dummy_window(HWND dummy) {
    215     DestroyWindow(dummy);
    216     HMODULE module = GetModuleHandle(NULL);
    217     UnregisterClass(DUMMY_CLASS, module);
    218 }
    219 }
    220 
    221 #define GET_PROC(NAME, SUFFIX) f##NAME = \
    222                      (##NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX)
    223 
    224 SkWGLExtensions::SkWGLExtensions()
    225     : fGetExtensionsString(NULL)
    226     , fChoosePixelFormat(NULL)
    227     , fGetPixelFormatAttribfv(NULL)
    228     , fGetPixelFormatAttribiv(NULL)
    229     , fCreateContextAttribs(NULL) {
    230     HDC prevDC = wglGetCurrentDC();
    231     HGLRC prevGLRC = wglGetCurrentContext();
    232 
    233     PIXELFORMATDESCRIPTOR dummyPFD;
    234 
    235     ZeroMemory(&dummyPFD, sizeof(dummyPFD));
    236     dummyPFD.nSize = sizeof(dummyPFD);
    237     dummyPFD.nVersion = 1;
    238     dummyPFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
    239     dummyPFD.iPixelType = PFD_TYPE_RGBA;
    240     dummyPFD.cColorBits  = 32;
    241     dummyPFD.cDepthBits  = 0;
    242     dummyPFD.cStencilBits = 8;
    243     dummyPFD.iLayerType = PFD_MAIN_PLANE;
    244     HWND dummyWND = create_dummy_window();
    245     if (dummyWND) {
    246         HDC dummyDC = GetDC(dummyWND);
    247         int dummyFormat = ChoosePixelFormat(dummyDC, &dummyPFD);
    248         SetPixelFormat(dummyDC, dummyFormat, &dummyPFD);
    249         HGLRC dummyGLRC = wglCreateContext(dummyDC);
    250         SkASSERT(dummyGLRC);
    251         wglMakeCurrent(dummyDC, dummyGLRC);
    252 
    253         GET_PROC(GetExtensionsString, ARB);
    254         GET_PROC(ChoosePixelFormat, ARB);
    255         GET_PROC(GetPixelFormatAttribiv, ARB);
    256         GET_PROC(GetPixelFormatAttribfv, ARB);
    257         GET_PROC(CreateContextAttribs, ARB);
    258 
    259         wglMakeCurrent(dummyDC, NULL);
    260         wglDeleteContext(dummyGLRC);
    261         destroy_dummy_window(dummyWND);
    262     }
    263 
    264     wglMakeCurrent(prevDC, prevGLRC);
    265 }
    266