aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/gpu/gl/SkGLContextHelper.h4
-rw-r--r--include/gpu/gl/SkNativeGLContext.h2
-rw-r--r--include/utils/SkWGL.h53
-rw-r--r--src/gpu/gl/win/SkNativeGLContext_win.cpp58
-rw-r--r--src/utils/win/SkWGL_win.cpp160
5 files changed, 230 insertions, 47 deletions
diff --git a/include/gpu/gl/SkGLContextHelper.h b/include/gpu/gl/SkGLContextHelper.h
index 9da8741840..a06c6e1f9b 100644
--- a/include/gpu/gl/SkGLContextHelper.h
+++ b/include/gpu/gl/SkGLContextHelper.h
@@ -78,9 +78,9 @@ private:
* SK_GL(glCtx, GenTextures(1, &texID));
*/
#define SK_GL(ctx, X) (ctx).gl()->fFunctions.f ## X; \
- SkASSERT(GR_GL_NO_ERROR == (ctx).gl()->fFunctions.fGetError())
+ SkASSERT(0 == (ctx).gl()->fFunctions.fGetError())
#define SK_GL_RET(ctx, RET, X) (RET) = (ctx).gl()->fFunctions.f ## X; \
- SkASSERT(GR_GL_NO_ERROR == (ctx).gl()->fFunctions.fGetError())
+ SkASSERT(0 == (ctx).gl()->fFunctions.fGetError())
#define SK_GL_NOERRCHECK(ctx, X) (ctx).gl()->fFunctions.f ## X
#define SK_GL_RET_NOERRCHECK(ctx, RET, X) (RET) = (ctx).gl()->fFunctions.f ## X
diff --git a/include/gpu/gl/SkNativeGLContext.h b/include/gpu/gl/SkNativeGLContext.h
index fac52b354f..01b73094fb 100644
--- a/include/gpu/gl/SkNativeGLContext.h
+++ b/include/gpu/gl/SkNativeGLContext.h
@@ -21,6 +21,7 @@
#elif defined(SK_BUILD_FOR_WIN32)
#include <windows.h>
#include <GL/GL.h>
+ #include "SkWGL.h"
#endif
class SkNativeGLContext : public SkGLContextHelper {
@@ -78,6 +79,7 @@ private:
HDC fDeviceContext;
HGLRC fGlRenderContext;
static ATOM gWC;
+ SkWGLPbufferContext* fPbufferContext;
#elif defined(SK_BUILD_FOR_IOS)
void* fEAGLContext;
#endif
diff --git a/include/utils/SkWGL.h b/include/utils/SkWGL.h
index 5272f17c87..d502eb0aa7 100644
--- a/include/utils/SkWGL.h
+++ b/include/utils/SkWGL.h
@@ -56,6 +56,8 @@
#define SK_ERROR_INVALID_VERSION 0x2095
#define SK_ERROR_INVALID_PROFILE 0x2096
+DECLARE_HANDLE(HPBUFFER);
+
class SkWGLExtensions {
public:
SkWGLExtensions();
@@ -73,6 +75,13 @@ public:
BOOL getPixelFormatAttribfv(HDC hdc, int, int, UINT, const int*, FLOAT*) const;
HGLRC createContextAttribs(HDC, HGLRC, const int *) const;
+ BOOL swapInterval(int interval) const;
+
+ HPBUFFER createPbuffer(HDC, int , int, int, const int*) const;
+ HDC getPbufferDC(HPBUFFER) const;
+ int releasePbufferDC(HPBUFFER, HDC) const;
+ BOOL destroyPbuffer(HPBUFFER) const;
+
/**
* WGL doesn't have precise rules for the ordering of formats returned
* by wglChoosePixelFormat. This function helps choose among the set of
@@ -89,19 +98,29 @@ public:
int selectFormat(const int formats[],
int formatCount,
HDC dc,
- int desiredSampleCount);
+ int desiredSampleCount) const;
private:
- typedef const char* (WINAPI *GetExtensionsStringProc)(HDC hdc);
- typedef BOOL (WINAPI *ChoosePixelFormatProc)(HDC hdc, const int *, const FLOAT *, UINT, int *, UINT *);
+ typedef const char* (WINAPI *GetExtensionsStringProc)(HDC);
+ typedef BOOL (WINAPI *ChoosePixelFormatProc)(HDC, const int *, const FLOAT *, UINT, int *, UINT *);
typedef BOOL (WINAPI *GetPixelFormatAttribivProc)(HDC, int, int, UINT, const int*, int*);
- typedef BOOL (WINAPI *GetPixelFormatAttribfvProc)(HDC hdc, int, int, UINT, const int*, FLOAT*);
- typedef HGLRC (WINAPI *CreateContextAttribsProc)(HDC hDC, HGLRC, const int *);
+ typedef BOOL (WINAPI *GetPixelFormatAttribfvProc)(HDC, int, int, UINT, const int*, FLOAT*);
+ typedef HGLRC (WINAPI *CreateContextAttribsProc)(HDC, HGLRC, const int *);
+ typedef BOOL (WINAPI* SwapIntervalProc)(int);
+ typedef HPBUFFER (WINAPI* CreatePbufferProc)(HDC, int , int, int, const int*);
+ typedef HDC (WINAPI* GetPbufferDCProc)(HPBUFFER);
+ typedef int (WINAPI* ReleasePbufferDCProc)(HPBUFFER, HDC);
+ typedef BOOL (WINAPI* DestroyPbufferProc)(HPBUFFER);
GetExtensionsStringProc fGetExtensionsString;
ChoosePixelFormatProc fChoosePixelFormat;
GetPixelFormatAttribfvProc fGetPixelFormatAttribfv;
GetPixelFormatAttribivProc fGetPixelFormatAttribiv;
CreateContextAttribsProc fCreateContextAttribs;
+ SwapIntervalProc fSwapInterval;
+ CreatePbufferProc fCreatePbuffer;
+ GetPbufferDCProc fGetPbufferDC;
+ ReleasePbufferDCProc fReleasePbufferDC;
+ DestroyPbufferProc fDestroyPbuffer;
};
enum SkWGLContextRequest {
@@ -122,4 +141,28 @@ enum SkWGLContextRequest {
*/
HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, SkWGLContextRequest context);
+/**
+ * Helper class for creating a pbuffer context and deleting all the handles when finished. This
+ * requires that a device context has been created. However, the pbuffer gets its own device
+ * context. The original device context can be released once the pbuffer context is created.
+ */
+class SkWGLPbufferContext : public SkRefCnt {
+public:
+ static SkWGLPbufferContext* Create(HDC parentDC, int msaaSampleCount,
+ SkWGLContextRequest contextType);
+
+ virtual ~SkWGLPbufferContext();
+
+ HDC getDC() const { return fDC; }
+ HGLRC getGLRC() const { return fGLRC; }
+
+private:
+ SkWGLPbufferContext(HPBUFFER pbuffer, HDC dc, HGLRC glrc);
+
+ HPBUFFER fPbuffer;
+ HDC fDC;
+ HGLRC fGLRC;
+ SkWGLExtensions fExtensions;
+};
+
#endif
diff --git a/src/gpu/gl/win/SkNativeGLContext_win.cpp b/src/gpu/gl/win/SkNativeGLContext_win.cpp
index f085fdc6ee..ab66ba4d55 100644
--- a/src/gpu/gl/win/SkNativeGLContext_win.cpp
+++ b/src/gpu/gl/win/SkNativeGLContext_win.cpp
@@ -7,7 +7,6 @@
*/
#include "gl/SkNativeGLContext.h"
-#include "SkWGL.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -28,7 +27,8 @@ ATOM SkNativeGLContext::gWC = 0;
SkNativeGLContext::SkNativeGLContext()
: fWindow(NULL)
, fDeviceContext(NULL)
- , fGlRenderContext(0) {
+ , fGlRenderContext(0)
+ , fPbufferContext(NULL) {
}
SkNativeGLContext::~SkNativeGLContext() {
@@ -36,14 +36,18 @@ SkNativeGLContext::~SkNativeGLContext() {
}
void SkNativeGLContext::destroyGLContext() {
+ SkSafeSetNull(fPbufferContext);
if (fGlRenderContext) {
wglDeleteContext(fGlRenderContext);
+ fGlRenderContext = 0;
}
if (fWindow && fDeviceContext) {
ReleaseDC(fWindow, fDeviceContext);
+ fDeviceContext = 0;
}
if (fWindow) {
DestroyWindow(fWindow);
+ fWindow = 0;
}
}
@@ -91,17 +95,35 @@ const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAP
kGLES_GrGLStandard == forcedGpuAPI ?
kGLES_SkWGLContextRequest : kGLPreferCompatibilityProfile_SkWGLContextRequest;
- if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, contextType))) {
- SkDebugf("Could not create rendering context.\n");
- this->destroyGLContext();
- return NULL;
+ fPbufferContext = SkWGLPbufferContext::Create(fDeviceContext, 0, contextType);
+
+ HDC dc;
+ HGLRC glrc;
+
+ if (NULL == fPbufferContext) {
+ if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, contextType))) {
+ SkDebugf("Could not create rendering context.\n");
+ this->destroyGLContext();
+ return NULL;
+ }
+ dc = fDeviceContext;
+ glrc = fGlRenderContext;
+ } else {
+ ReleaseDC(fWindow, fDeviceContext);
+ fDeviceContext = 0;
+ DestroyWindow(fWindow);
+ fWindow = 0;
+
+ dc = fPbufferContext->getDC();
+ glrc = fPbufferContext->getGLRC();
}
- if (!(wglMakeCurrent(fDeviceContext, fGlRenderContext))) {
+ if (!(wglMakeCurrent(dc, glrc))) {
SkDebugf("Could not set the context.\n");
this->destroyGLContext();
return NULL;
}
+
const GrGLInterface* interface = GrGLCreateNativeInterface();
if (NULL == interface) {
SkDebugf("Could not create GL interface.\n");
@@ -113,13 +135,31 @@ const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAP
}
void SkNativeGLContext::makeCurrent() const {
- if (!wglMakeCurrent(fDeviceContext, fGlRenderContext)) {
+ HDC dc;
+ HGLRC glrc;
+
+ if (NULL == fPbufferContext) {
+ dc = fDeviceContext;
+ glrc = fGlRenderContext;
+ } else {
+ dc = fPbufferContext->getDC();
+ glrc = fPbufferContext->getGLRC();
+ }
+
+ if (!wglMakeCurrent(dc, glrc)) {
SkDebugf("Could not create rendering context.\n");
}
}
void SkNativeGLContext::swapBuffers() const {
- if (!SwapBuffers(fDeviceContext)) {
+ HDC dc;
+
+ if (NULL == fPbufferContext) {
+ dc = fDeviceContext;
+ } else {
+ dc = fPbufferContext->getDC();
+ }
+ if (!SwapBuffers(dc)) {
SkDebugf("Could not complete SwapBuffers.\n");
}
}
diff --git a/src/utils/win/SkWGL_win.cpp b/src/utils/win/SkWGL_win.cpp
index a8552a8ea3..9c0c2d4bbb 100644
--- a/src/utils/win/SkWGL_win.cpp
+++ b/src/utils/win/SkWGL_win.cpp
@@ -75,6 +75,30 @@ HGLRC SkWGLExtensions::createContextAttribs(HDC hDC,
return fCreateContextAttribs(hDC, hShareContext, attribList);
}
+BOOL SkWGLExtensions::swapInterval(int interval) const {
+ return fSwapInterval(interval);
+}
+
+HPBUFFER SkWGLExtensions::createPbuffer(HDC hDC,
+ int iPixelFormat,
+ int iWidth,
+ int iHeight,
+ const int *piAttribList) const {
+ return fCreatePbuffer(hDC, iPixelFormat, iWidth, iHeight, piAttribList);
+}
+
+HDC SkWGLExtensions::getPbufferDC(HPBUFFER hPbuffer) const {
+ return fGetPbufferDC(hPbuffer);
+}
+
+int SkWGLExtensions::releasePbufferDC(HPBUFFER hPbuffer, HDC hDC) const {
+ return fReleasePbufferDC(hPbuffer, hDC);
+}
+
+BOOL SkWGLExtensions::destroyPbuffer(HPBUFFER hPbuffer) const {
+ return fDestroyPbuffer(hPbuffer);
+}
+
namespace {
struct PixelFormat {
@@ -98,7 +122,7 @@ bool pf_less(const PixelFormat& a, const PixelFormat& b) {
int SkWGLExtensions::selectFormat(const int formats[],
int formatCount,
HDC dc,
- int desiredSampleCount) {
+ int desiredSampleCount) const {
PixelFormat desiredFormat = {
0,
desiredSampleCount,
@@ -207,7 +231,13 @@ SkWGLExtensions::SkWGLExtensions()
, fChoosePixelFormat(NULL)
, fGetPixelFormatAttribfv(NULL)
, fGetPixelFormatAttribiv(NULL)
- , fCreateContextAttribs(NULL) {
+ , fCreateContextAttribs(NULL)
+ , fSwapInterval(NULL)
+ , fCreatePbuffer(NULL)
+ , fGetPbufferDC(NULL)
+ , fReleasePbufferDC(NULL)
+ , fDestroyPbuffer(NULL)
+ {
HDC prevDC = wglGetCurrentDC();
HGLRC prevGLRC = wglGetCurrentContext();
@@ -236,6 +266,11 @@ SkWGLExtensions::SkWGLExtensions()
GET_PROC(GetPixelFormatAttribiv, ARB);
GET_PROC(GetPixelFormatAttribfv, ARB);
GET_PROC(CreateContextAttribs, ARB);
+ GET_PROC(SwapInterval, EXT);
+ GET_PROC(CreatePbuffer, ARB);
+ GET_PROC(GetPbufferDC, ARB);
+ GET_PROC(ReleasePbufferDC, ARB);
+ GET_PROC(DestroyPbuffer, ARB);
wglMakeCurrent(dummyDC, NULL);
wglDeleteContext(dummyGLRC);
@@ -245,21 +280,14 @@ SkWGLExtensions::SkWGLExtensions()
wglMakeCurrent(prevDC, prevGLRC);
}
-HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, SkWGLContextRequest contextType) {
- 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[] = {
+static void get_pixel_formats_to_try(HDC dc, const SkWGLExtensions& extensions,
+ bool doubleBuffered, int msaaSampleCount,
+ int formatsToTry[2]) {
+ int iAttrs[] = {
SK_WGL_DRAW_TO_WINDOW, TRUE,
- SK_WGL_DOUBLE_BUFFER, TRUE,
+ SK_WGL_DOUBLE_BUFFER, (doubleBuffered ? TRUE : FALSE),
SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION,
SK_WGL_SUPPORT_OPENGL, TRUE,
SK_WGL_COLOR_BITS, 24,
@@ -270,6 +298,7 @@ HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, SkWGLContextRequest contex
float fAttrs[] = {0, 0};
+ // Get a MSAA format if requested and possible.
if (msaaSampleCount > 0 &&
extensions.hasExtension(dc, "WGL_ARB_multisample")) {
static const int kIAttrsCount = SK_ARRAY_COUNT(iAttrs);
@@ -287,28 +316,23 @@ HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, SkWGLContextRequest contex
int formats[64];
extensions.choosePixelFormat(dc, msaaIAttrs, fAttrs, 64, formats, &num);
num = SkTMin(num, 64U);
- int formatToTry = extensions.selectFormat(formats,
- num,
- dc,
- msaaSampleCount);
- DescribePixelFormat(dc, formatToTry, sizeof(pfd), &pfd);
- if (SetPixelFormat(dc, formatToTry, &pfd)) {
- format = formatToTry;
- }
+ formatsToTry[0] = extensions.selectFormat(formats, num, dc, msaaSampleCount);
}
- 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);
- }
+ // Get a non-MSAA format
+ int* format = -1 == formatsToTry[0] ? &formatsToTry[0] : &formatsToTry[1];
+ unsigned int num;
+ extensions.choosePixelFormat(dc, iAttrs, fAttrs, 1, format, &num);
+}
+
+static HGLRC create_gl_context(HDC dc, SkWGLExtensions extensions, SkWGLContextRequest contextType) {
+ HDC prevDC = wglGetCurrentDC();
+ HGLRC prevGLRC = wglGetCurrentContext();
HGLRC glrc = NULL;
if (kGLES_SkWGLContextRequest == contextType) {
if (!extensions.hasExtension(dc, "WGL_EXT_create_context_es2_profile")) {
+ wglMakeCurrent(prevDC, prevGLRC);
return NULL;
}
static const int glesAttribs[] = {
@@ -319,6 +343,7 @@ HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, SkWGLContextRequest contex
};
glrc = extensions.createContextAttribs(dc, NULL, glesAttribs);
if (NULL == glrc) {
+ wglMakeCurrent(prevDC, prevGLRC);
return NULL;
}
} else {
@@ -355,5 +380,78 @@ HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, SkWGLContextRequest contex
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;
}
+
+HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, SkWGLContextRequest contextType) {
+ SkWGLExtensions extensions;
+ if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) {
+ return NULL;
+ }
+
+ BOOL set = FALSE;
+
+ int pixelFormatsToTry[] = { -1, -1 };
+ get_pixel_formats_to_try(dc, extensions, true, msaaSampleCount, 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 NULL;
+ }
+
+ return create_gl_context(dc, extensions, contextType);}
+
+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 NULL;
+ }
+
+ // 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,
+ pixelFormatsToTry);
+ for (int f = 0; -1 != pixelFormatsToTry[f] && f < SK_ARRAY_COUNT(pixelFormatsToTry); ++f) {
+ HPBUFFER pbuf = extensions.createPbuffer(parentDC, pixelFormatsToTry[f], 1, 1, NULL);
+ if (0 != pbuf) {
+ HDC dc = extensions.getPbufferDC(pbuf);
+ if (NULL != dc) {
+ HGLRC glrc = create_gl_context(dc, extensions, contextType);
+ if (NULL != glrc) {
+ return SkNEW_ARGS(SkWGLPbufferContext, (pbuf, dc, glrc));
+ }
+ extensions.releasePbufferDC(pbuf, dc);
+ }
+ extensions.destroyPbuffer(pbuf);
+ }
+ }
+ }
+ return NULL;
+}
+
+SkWGLPbufferContext::~SkWGLPbufferContext() {
+ SkASSERT(fExtensions.hasExtension(fDC, "WGL_ARB_pbuffer"));
+ wglDeleteContext(fGLRC);
+ fExtensions.releasePbufferDC(fPbuffer, fDC);
+ fExtensions.destroyPbuffer(fPbuffer);
+}
+
+SkWGLPbufferContext::SkWGLPbufferContext(HPBUFFER pbuffer, HDC dc, HGLRC glrc)
+ : fPbuffer(pbuffer)
+ , fDC(dc)
+ , fGLRC(glrc) {
+}