static void get_pixel_formats_to_try(HDC dc, const SkWGLExtensions& extensions, bool doubleBuffered, int msaaSampleCount, bool deepColor, int formatsToTry[2]) { auto appendAttr = [](SkTDArray<int>& attrs, int attr, int value) { attrs.push(attr); attrs.push(value); }; SkTDArray<int> iAttrs; appendAttr(iAttrs, SK_WGL_DRAW_TO_WINDOW, TRUE); appendAttr(iAttrs, SK_WGL_DOUBLE_BUFFER, (doubleBuffered ? TRUE : FALSE)); appendAttr(iAttrs, SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION); appendAttr(iAttrs, SK_WGL_SUPPORT_OPENGL, TRUE); if (deepColor) { appendAttr(iAttrs, SK_WGL_RED_BITS, 10); appendAttr(iAttrs, SK_WGL_GREEN_BITS, 10); appendAttr(iAttrs, SK_WGL_BLUE_BITS, 10); appendAttr(iAttrs, SK_WGL_ALPHA_BITS, 2); } else { appendAttr(iAttrs, SK_WGL_COLOR_BITS, 24); appendAttr(iAttrs, SK_WGL_ALPHA_BITS, 8); } appendAttr(iAttrs, SK_WGL_STENCIL_BITS, 8); float fAttrs[] = {0, 0}; // Get a MSAA format if requested and possible. if (msaaSampleCount > 0 && extensions.hasExtension(dc, "WGL_ARB_multisample")) { SkTDArray<int> msaaIAttrs = iAttrs; appendAttr(msaaIAttrs, SK_WGL_SAMPLE_BUFFERS, TRUE); appendAttr(msaaIAttrs, SK_WGL_SAMPLES, msaaSampleCount); appendAttr(msaaIAttrs, 0, 0); unsigned int num; int formats[64]; extensions.choosePixelFormat(dc, msaaIAttrs.begin(), fAttrs, 64, formats, &num); num = SkTMin(num, 64U); formatsToTry[0] = extensions.selectFormat(formats, num, dc, msaaSampleCount); } // Get a non-MSAA format int* format = -1 == formatsToTry[0] ? &formatsToTry[0] : &formatsToTry[1]; unsigned int num; appendAttr(iAttrs, 0, 0); extensions.choosePixelFormat(dc, iAttrs.begin(), fAttrs, 1, format, &num); }
SkWGLPbufferContext* SkWGLPbufferContext::Create(HDC parentDC, int msaaSampleCount, SkWGLContextRequest contextType) { SkWGLExtensions extensions; if (!extensions.hasExtension(parentDC, "WGL_ARB_pixel_format") || !extensions.hasExtension(parentDC, "WGL_ARB_pbuffer")) { return nullptr; } // try for single buffer first for (int dblBuffer = 0; dblBuffer < 2; ++dblBuffer) { int pixelFormatsToTry[] = { -1, -1 }; get_pixel_formats_to_try(parentDC, extensions, (0 != dblBuffer), msaaSampleCount, false, pixelFormatsToTry); for (int f = 0; -1 != pixelFormatsToTry[f] && f < SK_ARRAY_COUNT(pixelFormatsToTry); ++f) { HPBUFFER pbuf = extensions.createPbuffer(parentDC, pixelFormatsToTry[f], 1, 1, nullptr); if (0 != pbuf) { HDC dc = extensions.getPbufferDC(pbuf); if (dc) { HGLRC glrc = create_gl_context(dc, extensions, contextType); if (glrc) { return new SkWGLPbufferContext(pbuf, dc, glrc); } extensions.releasePbufferDC(pbuf, dc); } extensions.destroyPbuffer(pbuf); } } } return nullptr; }
bool SkOSWindow::attachGL(int msaaSampleCount, bool deepColor, AttachmentInfo* info) { HDC dc = GetDC((HWND)fHWND); if (NULL == fHGLRC) { fHGLRC = SkCreateWGLContext(dc, msaaSampleCount, deepColor, kGLPreferCompatibilityProfile_SkWGLContextRequest); if (NULL == fHGLRC) { return false; } glClearStencil(0); glClearColor(0, 0, 0, 0); glStencilMask(0xffffffff); glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); } if (wglMakeCurrent(dc, (HGLRC)fHGLRC)) { // use DescribePixelFormat to get the stencil and color bit depth. int pixelFormat = GetPixelFormat(dc); PIXELFORMATDESCRIPTOR pfd; DescribePixelFormat(dc, pixelFormat, sizeof(pfd), &pfd); info->fStencilBits = pfd.cStencilBits; // pfd.cColorBits includes alpha, so it will be 32 in 8/8/8/8 and 10/10/10/2 info->fColorBits = pfd.cRedBits + pfd.cGreenBits + pfd.cBlueBits; // Get sample count if the MSAA WGL extension is present SkWGLExtensions extensions; if (extensions.hasExtension(dc, "WGL_ARB_multisample")) { static const int kSampleCountAttr = SK_WGL_SAMPLES; extensions.getPixelFormatAttribiv(dc, pixelFormat, 0, 1, &kSampleCountAttr, &info->fSampleCount); } else { info->fSampleCount = 0; } glViewport(0, 0, SkScalarRoundToInt(this->width()), SkScalarRoundToInt(this->height())); return true; } return false; }
HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, bool deepColor, SkWGLContextRequest contextType) { SkWGLExtensions extensions; if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) { return nullptr; } BOOL set = FALSE; int pixelFormatsToTry[] = { -1, -1 }; get_pixel_formats_to_try(dc, extensions, true, msaaSampleCount, deepColor, pixelFormatsToTry); for (int f = 0; !set && -1 != pixelFormatsToTry[f] && f < SK_ARRAY_COUNT(pixelFormatsToTry); ++f) { PIXELFORMATDESCRIPTOR pfd; DescribePixelFormat(dc, pixelFormatsToTry[f], sizeof(pfd), &pfd); set = SetPixelFormat(dc, pixelFormatsToTry[f], &pfd); } if (!set) { return nullptr; } return create_gl_context(dc, extensions, contextType);}
static HGLRC create_gl_context(HDC dc, SkWGLExtensions extensions, SkWGLContextRequest contextType) { HDC prevDC = wglGetCurrentDC(); HGLRC prevGLRC = wglGetCurrentContext(); HGLRC glrc = nullptr; if (kGLES_SkWGLContextRequest == contextType) { if (!extensions.hasExtension(dc, "WGL_EXT_create_context_es2_profile")) { wglMakeCurrent(prevDC, prevGLRC); return nullptr; } static const int glesAttribs[] = { SK_WGL_CONTEXT_MAJOR_VERSION, 3, SK_WGL_CONTEXT_MINOR_VERSION, 0, SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_ES2_PROFILE_BIT, 0, }; glrc = extensions.createContextAttribs(dc, nullptr, glesAttribs); if (nullptr == glrc) { wglMakeCurrent(prevDC, prevGLRC); return nullptr; } } else { if (kGLPreferCoreProfile_SkWGLContextRequest == contextType && extensions.hasExtension(dc, "WGL_ARB_create_context")) { static const int kCoreGLVersions[] = { 4, 3, 4, 2, 4, 1, 4, 0, 3, 3, 3, 2, }; int coreProfileAttribs[] = { SK_WGL_CONTEXT_MAJOR_VERSION, -1, SK_WGL_CONTEXT_MINOR_VERSION, -1, SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_CORE_PROFILE_BIT, 0, }; for (int v = 0; v < SK_ARRAY_COUNT(kCoreGLVersions) / 2; ++v) { coreProfileAttribs[1] = kCoreGLVersions[2 * v]; coreProfileAttribs[3] = kCoreGLVersions[2 * v + 1]; glrc = extensions.createContextAttribs(dc, nullptr, coreProfileAttribs); if (glrc) { break; } } } } if (nullptr == glrc) { glrc = wglCreateContext(dc); } SkASSERT(glrc); wglMakeCurrent(prevDC, prevGLRC); // This might help make the context non-vsynced. if (extensions.hasExtension(dc, "WGL_EXT_swap_control")) { extensions.swapInterval(-1); } return glrc; }
void SkOSWindow::setVsync(bool enable) { SkWGLExtensions wgl; wgl.swapInterval(enable ? 1 : 0); }
HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, bool preferCoreProfile) { SkWGLExtensions extensions; if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) { return NULL; } HDC prevDC = wglGetCurrentDC(); HGLRC prevGLRC = wglGetCurrentContext(); PIXELFORMATDESCRIPTOR pfd; int format = 0; static const int iAttrs[] = { SK_WGL_DRAW_TO_WINDOW, TRUE, SK_WGL_DOUBLE_BUFFER, TRUE, SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION, SK_WGL_SUPPORT_OPENGL, TRUE, SK_WGL_COLOR_BITS, 24, SK_WGL_ALPHA_BITS, 8, SK_WGL_STENCIL_BITS, 8, 0, 0 }; float fAttrs[] = {0, 0}; if (msaaSampleCount > 0 && extensions.hasExtension(dc, "WGL_ARB_multisample")) { static const int kIAttrsCount = SK_ARRAY_COUNT(iAttrs); int msaaIAttrs[kIAttrsCount + 6]; memcpy(msaaIAttrs, iAttrs, sizeof(int) * kIAttrsCount); SkASSERT(0 == msaaIAttrs[kIAttrsCount - 2] && 0 == msaaIAttrs[kIAttrsCount - 1]); msaaIAttrs[kIAttrsCount - 2] = SK_WGL_SAMPLE_BUFFERS; msaaIAttrs[kIAttrsCount - 1] = TRUE; msaaIAttrs[kIAttrsCount + 0] = SK_WGL_SAMPLES; msaaIAttrs[kIAttrsCount + 1] = msaaSampleCount; if (extensions.hasExtension(dc, "WGL_NV_multisample_coverage")) { msaaIAttrs[kIAttrsCount + 2] = SK_WGL_COLOR_SAMPLES; // We want the fewest number of color samples possible. // Passing 0 gives only the formats where all samples are color // samples. msaaIAttrs[kIAttrsCount + 3] = 1; msaaIAttrs[kIAttrsCount + 4] = 0; msaaIAttrs[kIAttrsCount + 5] = 0; } else { msaaIAttrs[kIAttrsCount + 2] = 0; msaaIAttrs[kIAttrsCount + 3] = 0; } unsigned int num; int formats[64]; extensions.choosePixelFormat(dc, msaaIAttrs, fAttrs, 64, formats, &num); num = min(num,64); int formatToTry = extensions.selectFormat(formats, num, dc, msaaSampleCount); DescribePixelFormat(dc, formatToTry, sizeof(pfd), &pfd); if (SetPixelFormat(dc, formatToTry, &pfd)) { format = formatToTry; } } if (0 == format) { // Either MSAA wasn't requested or creation failed unsigned int num; extensions.choosePixelFormat(dc, iAttrs, fAttrs, 1, &format, &num); DescribePixelFormat(dc, format, sizeof(pfd), &pfd); SkDEBUGCODE(BOOL set =) SetPixelFormat(dc, format, &pfd); SkASSERT(TRUE == set); }