180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkWGL.h"
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTDArray.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTSearch.h"
137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkTSort.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkWGLExtensions::hasExtension(HDC dc, const char* ext) const {
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == this->fGetExtensionsString) {
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!strcmp("WGL_ARB_extensions_string", ext)) {
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* extensionString = this->getExtensionsString(dc);
230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    size_t extLength = strlen(ext);
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (true) {
260a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        size_t n = strcspn(extensionString, " ");
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (0 == extensionString[n]) {
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        extensionString += n+1;
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst char* SkWGLExtensions::getExtensionsString(HDC hdc) const {
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fGetExtensionsString(hdc);
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruBOOL SkWGLExtensions::choosePixelFormat(HDC hdc,
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        const int* piAttribIList,
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        const FLOAT* pfAttribFList,
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        UINT nMaxFormats,
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        int* piFormats,
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        UINT* nNumFormats) const {
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fChoosePixelFormat(hdc, piAttribIList, pfAttribFList,
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              nMaxFormats, piFormats, nNumFormats);
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruBOOL SkWGLExtensions::getPixelFormatAttribiv(HDC hdc,
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             int iPixelFormat,
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             int iLayerPlane,
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             UINT nAttributes,
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             const int *piAttributes,
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             int *piValues) const {
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fGetPixelFormatAttribiv(hdc, iPixelFormat, iLayerPlane,
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   nAttributes, piAttributes, piValues);
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruBOOL SkWGLExtensions::getPixelFormatAttribfv(HDC hdc,
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             int iPixelFormat,
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             int iLayerPlane,
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             UINT nAttributes,
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             const int *piAttributes,
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             float *pfValues) const {
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fGetPixelFormatAttribfv(hdc, iPixelFormat, iLayerPlane,
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   nAttributes, piAttributes, pfValues);
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruHGLRC SkWGLExtensions::createContextAttribs(HDC hDC,
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            HGLRC hShareContext,
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            const int *attribList) const {
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fCreateContextAttribs(hDC, hShareContext, attribList);
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustruct PixelFormat {
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int fFormat;
820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    int fSampleCnt;
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int fChoosePixelFormatRank;
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool pf_less(const PixelFormat& a, const PixelFormat& b) {
870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    if (a.fSampleCnt < b.fSampleCnt) {
887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return true;
890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    } else if (b.fSampleCnt < a.fSampleCnt) {
907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return false;
917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } else if (a.fChoosePixelFormatRank < b.fChoosePixelFormatRank) {
927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return true;
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return false;
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkWGLExtensions::selectFormat(const int formats[],
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  int formatCount,
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  HDC dc,
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  int desiredSampleCount) {
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    PixelFormat desiredFormat = {
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        0,
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        desiredSampleCount,
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        0,
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTDArray<PixelFormat> rankedFormats;
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    rankedFormats.setCount(formatCount);
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < formatCount; ++i) {
1100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        static const int kQueryAttr = SK_WGL_SAMPLES;
1110a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        int numSamples;
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->getPixelFormatAttribiv(dc,
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     formats[i],
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     0,
1150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                                     1,
1160a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                                     &kQueryAttr,
1170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                                     &numSamples);
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rankedFormats[i].fFormat =  formats[i];
1190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        rankedFormats[i].fSampleCnt = numSamples;
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rankedFormats[i].fChoosePixelFormatRank = i;
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
1227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkTQSort(rankedFormats.begin(),
1237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger             rankedFormats.begin() + rankedFormats.count() - 1,
1247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger             SkTLessFunctionToFunctorAdaptor<PixelFormat, pf_less>());
1257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int idx = SkTSearch<PixelFormat, pf_less>(rankedFormats.begin(),
1267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                              rankedFormats.count(),
1277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                              desiredFormat,
1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                              sizeof(PixelFormat));
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (idx < 0) {
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        idx = ~idx;
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return rankedFormats[idx].fFormat;
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined(UNICODE)
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define STR_LIT(X) L## #X
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define STR_LIT(X) #X
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define DUMMY_CLASS STR_LIT("DummyClass")
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruHWND create_dummy_window() {
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    HMODULE module = GetModuleHandle(NULL);
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    HWND dummy;
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    RECT windowRect;
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    windowRect.left = 0;
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    windowRect.right = 8;
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    windowRect.top = 0;
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    windowRect.bottom = 8;
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    WNDCLASS wc;
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wc.lpfnWndProc = (WNDPROC) DefWindowProc;
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wc.cbClsExtra = 0;
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wc.cbWndExtra = 0;
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wc.hInstance = module;
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wc.hbrBackground = NULL;
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wc.lpszMenuName = NULL;
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wc.lpszClassName = DUMMY_CLASS;
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if(!RegisterClass(&wc)) {
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    DWORD style, exStyle;
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    exStyle = WS_EX_CLIENTEDGE;
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    style = WS_SYSMENU;
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    AdjustWindowRectEx(&windowRect, style, false, exStyle);
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if(!(dummy = CreateWindowEx(exStyle,
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                DUMMY_CLASS,
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                STR_LIT("DummyWindow"),
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                0, 0,
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                windowRect.right-windowRect.left,
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                windowRect.bottom-windowRect.top,
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                NULL, NULL,
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                module,
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                NULL))) {
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        UnregisterClass(DUMMY_CLASS, module);
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ShowWindow(dummy, SW_HIDE);
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dummy;
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid destroy_dummy_window(HWND dummy) {
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    DestroyWindow(dummy);
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    HMODULE module = GetModuleHandle(NULL);
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    UnregisterClass(DUMMY_CLASS, module);
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GET_PROC(NAME, SUFFIX) f##NAME = \
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                     (##NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX)
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkWGLExtensions::SkWGLExtensions()
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    : fGetExtensionsString(NULL)
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fChoosePixelFormat(NULL)
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fGetPixelFormatAttribfv(NULL)
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fGetPixelFormatAttribiv(NULL)
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fCreateContextAttribs(NULL) {
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    HDC prevDC = wglGetCurrentDC();
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    HGLRC prevGLRC = wglGetCurrentContext();
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    PIXELFORMATDESCRIPTOR dummyPFD;
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ZeroMemory(&dummyPFD, sizeof(dummyPFD));
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dummyPFD.nSize = sizeof(dummyPFD);
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dummyPFD.nVersion = 1;
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dummyPFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dummyPFD.iPixelType = PFD_TYPE_RGBA;
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dummyPFD.cColorBits  = 32;
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dummyPFD.cDepthBits  = 0;
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dummyPFD.cStencilBits = 8;
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dummyPFD.iLayerType = PFD_MAIN_PLANE;
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    HWND dummyWND = create_dummy_window();
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (dummyWND) {
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        HDC dummyDC = GetDC(dummyWND);
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int dummyFormat = ChoosePixelFormat(dummyDC, &dummyPFD);
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SetPixelFormat(dummyDC, dummyFormat, &dummyPFD);
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        HGLRC dummyGLRC = wglCreateContext(dummyDC);
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(dummyGLRC);
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        wglMakeCurrent(dummyDC, dummyGLRC);
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GET_PROC(GetExtensionsString, ARB);
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GET_PROC(ChoosePixelFormat, ARB);
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GET_PROC(GetPixelFormatAttribiv, ARB);
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GET_PROC(GetPixelFormatAttribfv, ARB);
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GET_PROC(CreateContextAttribs, ARB);
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        wglMakeCurrent(dummyDC, NULL);
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        wglDeleteContext(dummyGLRC);
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        destroy_dummy_window(dummyWND);
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wglMakeCurrent(prevDC, prevGLRC);
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
247096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
248096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerHGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, bool preferCoreProfile) {
249096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    SkWGLExtensions extensions;
250096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) {
251096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        return NULL;
252096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
253096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
254096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    HDC prevDC = wglGetCurrentDC();
255096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    HGLRC prevGLRC = wglGetCurrentContext();
256096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    PIXELFORMATDESCRIPTOR pfd;
257096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
258096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    int format = 0;
259096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
260096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    static const int iAttrs[] = {
261096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_WGL_DRAW_TO_WINDOW, TRUE,
262096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_WGL_DOUBLE_BUFFER, TRUE,
263096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION,
264096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_WGL_SUPPORT_OPENGL, TRUE,
265096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_WGL_COLOR_BITS, 24,
266096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_WGL_ALPHA_BITS, 8,
267096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_WGL_STENCIL_BITS, 8,
268096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        0, 0
269096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    };
270096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
271096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    float fAttrs[] = {0, 0};
272096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
273096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    if (msaaSampleCount > 0 &&
274096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        extensions.hasExtension(dc, "WGL_ARB_multisample")) {
275096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        static const int kIAttrsCount = SK_ARRAY_COUNT(iAttrs);
2760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        int msaaIAttrs[kIAttrsCount + 4];
277096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        memcpy(msaaIAttrs, iAttrs, sizeof(int) * kIAttrsCount);
278096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SkASSERT(0 == msaaIAttrs[kIAttrsCount - 2] &&
279096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                 0 == msaaIAttrs[kIAttrsCount - 1]);
280096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        msaaIAttrs[kIAttrsCount - 2] = SK_WGL_SAMPLE_BUFFERS;
281096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        msaaIAttrs[kIAttrsCount - 1] = TRUE;
282096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        msaaIAttrs[kIAttrsCount + 0] = SK_WGL_SAMPLES;
283096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        msaaIAttrs[kIAttrsCount + 1] = msaaSampleCount;
2840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        msaaIAttrs[kIAttrsCount + 2] = 0;
2850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        msaaIAttrs[kIAttrsCount + 3] = 0;
286096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        unsigned int num;
287096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        int formats[64];
288096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        extensions.choosePixelFormat(dc, msaaIAttrs, fAttrs, 64, formats, &num);
289e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        num = SkTMin(num, 64U);
290096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        int formatToTry = extensions.selectFormat(formats,
291096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                                                  num,
292096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                                                  dc,
293096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                                                  msaaSampleCount);
294096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        DescribePixelFormat(dc, formatToTry, sizeof(pfd), &pfd);
295096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (SetPixelFormat(dc, formatToTry, &pfd)) {
296096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            format = formatToTry;
297096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
298096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
299096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
300096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    if (0 == format) {
301096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        // Either MSAA wasn't requested or creation failed
302096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        unsigned int num;
303096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        extensions.choosePixelFormat(dc, iAttrs, fAttrs, 1, &format, &num);
304096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        DescribePixelFormat(dc, format, sizeof(pfd), &pfd);
305e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        SkDEBUGCODE(BOOL set =) SetPixelFormat(dc, format, &pfd);
306096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SkASSERT(TRUE == set);
307096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
308096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
309096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    HGLRC glrc = NULL;
310096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    if (preferCoreProfile && extensions.hasExtension(dc, "WGL_ARB_create_context")) {
311096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        static const int kCoreGLVersions[] = {
312096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            4, 3,
313096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            4, 2,
314096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            4, 1,
315096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            4, 0,
316096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            3, 3,
317096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            3, 2,
318096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        };
319096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        int coreProfileAttribs[] = {
320096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            SK_WGL_CONTEXT_MAJOR_VERSION, -1,
321096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            SK_WGL_CONTEXT_MINOR_VERSION, -1,
322096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            SK_WGL_CONTEXT_PROFILE_MASK,  SK_WGL_CONTEXT_CORE_PROFILE_BIT,
323096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            0,
324096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        };
325096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        for (int v = 0; v < SK_ARRAY_COUNT(kCoreGLVersions) / 2; ++v) {
326096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            coreProfileAttribs[1] = kCoreGLVersions[2 * v];
327096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            coreProfileAttribs[3] = kCoreGLVersions[2 * v + 1];
328096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            glrc = extensions.createContextAttribs(dc, NULL, coreProfileAttribs);
329096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            if (NULL != glrc) {
330096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                break;
331096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            }
332096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
333096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
334096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
335096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    if (NULL == glrc) {
336096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        glrc = wglCreateContext(dc);
337096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
338096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    SkASSERT(glrc);
339096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
340096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    wglMakeCurrent(prevDC, prevGLRC);
341096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    return glrc;
342096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger}
343