Recommit r2510 now that mac build bot issue has been fixed.



git-svn-id: http://skia.googlecode.com/svn/trunk@2521 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gyp/tests.gyp b/gyp/tests.gyp
index c5c3ff6..ede5885 100644
--- a/gyp/tests.gyp
+++ b/gyp/tests.gyp
@@ -30,6 +30,7 @@
         '../tests/FillPathTest.cpp',
         '../tests/FlateTest.cpp',
         '../tests/GeometryTest.cpp',
+        '../tests/GLInterfaceValidation.cpp',
         '../tests/GLProgramsTest.cpp',
         '../tests/InfRectTest.cpp',
         '../tests/MathTest.cpp',
diff --git a/include/gpu/GrGLInterface.h b/include/gpu/GrGLInterface.h
index b3e0cf1..20b74ab 100644
--- a/include/gpu/GrGLInterface.h
+++ b/include/gpu/GrGLInterface.h
@@ -69,8 +69,17 @@
 
 const GrGLInterface* GrGLDefaultInterface();
 
+/**
+ * Creates a GrGLInterface for a "native" GL context (e.g. WGL on windows,
+ * GLX on linux, AGL on Mac). On platforms that have context-specific function
+ * pointers for GL extensions (e.g. windows) the returned interface is only 
+ * valid for the context that was current at creation.
+ */
 const GrGLInterface* GrGLCreateNativeInterface();
 
+/**
+ * Creates a GrGLInterface for an OSMesa context.
+ */
 const GrGLInterface* GrGLCreateMesaInterface();
 
 typedef unsigned int GrGLenum;
diff --git a/include/gpu/SkGLContext.h b/include/gpu/SkGLContext.h
index d36a9f9..f92a770 100644
--- a/include/gpu/SkGLContext.h
+++ b/include/gpu/SkGLContext.h
@@ -20,6 +20,9 @@
     SkGLContext();
     virtual ~SkGLContext();
 
+    /**
+     * Initializes the context and makes it current.
+     */
     bool init(const int width, const int height);
 
     int getFBOID() const { return fFBO; }
diff --git a/include/gpu/SkMesaGLContext.h b/include/gpu/SkMesaGLContext.h
index 4351f66..b7578f3 100644
--- a/include/gpu/SkMesaGLContext.h
+++ b/include/gpu/SkMesaGLContext.h
@@ -13,6 +13,9 @@
 #if SK_MESA
 
 class SkMesaGLContext : public SkGLContext {
+private:
+    typedef intptr_t Context;
+
 public:
     SkMesaGLContext();
 
@@ -20,16 +23,28 @@
 
     virtual void makeCurrent() const SK_OVERRIDE;
 
+    class AutoContextRestore {
+    public:
+        AutoContextRestore();
+        ~AutoContextRestore();
+
+    private:
+        Context fOldContext;
+        GLint   fOldWidth;
+        GLint   fOldHeight;
+        GLint   fOldFormat;
+        void*   fOldImage;
+    };
+
 protected:
     virtual const GrGLInterface* createGLContext() SK_OVERRIDE;
     void destroyGLContext() SK_OVERRIDE;
 
 private:
-    typedef intptr_t Context;
     Context fContext;
     GrGLubyte *fImage;
 };
 
 #endif
 
-#endif
\ No newline at end of file
+#endif
diff --git a/include/gpu/SkNativeGLContext.h b/include/gpu/SkNativeGLContext.h
index 512e66a..f2037cf 100644
--- a/include/gpu/SkNativeGLContext.h
+++ b/include/gpu/SkNativeGLContext.h
@@ -28,6 +28,24 @@
 
     virtual void makeCurrent() const SK_OVERRIDE;
 
+    class AutoContextRestore {
+    public:
+        AutoContextRestore();
+        ~AutoContextRestore();
+
+    private:
+    #if defined(SK_BUILD_FOR_MAC)
+        AGLContext fOldAGLContext;
+    #elif defined(SK_BUILD_FOR_UNIX)
+        GLXContext fOldGLXContext;
+        Display* fOldDisplay;
+        GLXDrawable fOldDrawable;
+    #elif defined(SK_BUILD_FOR_WIN32)
+        HDC fOldHDC;
+        HGLRC fOldHGLRC;
+    #endif
+    };
+
 protected:
     virtual const GrGLInterface* createGLContext() SK_OVERRIDE;
     void destroyGLContext() SK_OVERRIDE;
diff --git a/src/gpu/mac/SkNativeGLContext_mac.cpp b/src/gpu/mac/SkNativeGLContext_mac.cpp
index 3f864c2..ad68c40 100644
--- a/src/gpu/mac/SkNativeGLContext_mac.cpp
+++ b/src/gpu/mac/SkNativeGLContext_mac.cpp
@@ -7,6 +7,16 @@
  */
 #include "SkNativeGLContext.h"
 
+SkNativeGLContext::AutoContextRestore::AutoContextRestore() {
+    fOldAGLContext = aglGetCurrentContext();
+}
+
+SkNativeGLContext::AutoContextRestore::~AutoContextRestore() {
+    aglSetCurrentContext(fOldAGLContext);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 SkNativeGLContext::SkNativeGLContext() 
     : fContext(NULL) {
 }
diff --git a/src/gpu/mesa/SkMesaGLContext.cpp b/src/gpu/mesa/SkMesaGLContext.cpp
index 23ccc95..5440a90 100644
--- a/src/gpu/mesa/SkMesaGLContext.cpp
+++ b/src/gpu/mesa/SkMesaGLContext.cpp
@@ -10,6 +10,23 @@
 
 #include "SkMesaGLContext.h"
 
+SkMesaGLContext::AutoContextRestore::AutoContextRestore() {
+    fOldContext = (Context)OSMesaGetCurrentContext();
+    if (NULL != (OSMesaContext)fOldContext) {
+        OSMesaGetColorBuffer((OSMesaContext)fOldContext,
+                              &fOldWidth, &fOldHeight,
+                              &fOldFormat, &fOldImage); 
+    }
+}
+
+SkMesaGLContext::AutoContextRestore::~AutoContextRestore() {
+    if (NULL != fOldContext) {
+        OSMesaMakeCurrent((OSMesaContext)fOldContext, fOldImage, 
+                          fOldFormat, fOldWidth, fOldHeight);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
 
 SkMesaGLContext::SkMesaGLContext()
     : fContext(NULL)
diff --git a/src/gpu/unix/SkNativeGLContext_unix.cpp b/src/gpu/unix/SkNativeGLContext_unix.cpp
index 870ff45..907e2b8 100644
--- a/src/gpu/unix/SkNativeGLContext_unix.cpp
+++ b/src/gpu/unix/SkNativeGLContext_unix.cpp
@@ -9,6 +9,19 @@
 
 #include <GL/glu.h>
 
+SkNativeGLContext::AutoContextRestore::AutoContextRestore() {
+    fOldGLXContext = glXGetCurrentContext();
+    fOldDisplay = glXGetCurrentDisplay();
+    fOldDrawable = glXGetCurrentDrawable();
+}
+
+SkNativeGLContext::AutoContextRestore::~AutoContextRestore() {
+    if (NULL != fOldDisplay) {
+        glXMakeCurrent(fOldDisplay, fOldDrawable, fOldGLXContext);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
 
 static bool ctxErrorOccurred = false;
 static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) {
diff --git a/src/gpu/win/SkNativeGLContext_win.cpp b/src/gpu/win/SkNativeGLContext_win.cpp
index c19f7cc..5d518dd 100644
--- a/src/gpu/win/SkNativeGLContext_win.cpp
+++ b/src/gpu/win/SkNativeGLContext_win.cpp
@@ -11,12 +11,23 @@
 #define WIN32_LEAN_AND_MEAN
 #include <Windows.h>
 
+SkNativeGLContext::AutoContextRestore::AutoContextRestore() {
+    fOldHGLRC = wglGetCurrentContext();
+    fOldHDC = wglGetCurrentDC();
+}
+
+SkNativeGLContext::AutoContextRestore::~AutoContextRestore() {
+    wglMakeCurrent(fOldHDC, fOldHGLRC);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 ATOM SkNativeGLContext::gWC = 0;
 
 SkNativeGLContext::SkNativeGLContext()
-        : fWindow(NULL)
-        , fDeviceContext(NULL)
-        , fGlRenderContext(0) {
+    : fWindow(NULL)
+    , fDeviceContext(NULL)
+    , fGlRenderContext(0) {
 }
 
 SkNativeGLContext::~SkNativeGLContext() {
diff --git a/tests/GLInterfaceValidation.cpp b/tests/GLInterfaceValidation.cpp
new file mode 100755
index 0000000..758f303
--- /dev/null
+++ b/tests/GLInterfaceValidation.cpp
@@ -0,0 +1,63 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Test.h"
+#include "SkNativeGLContext.h"
+#include "SkMesaGLContext.h"
+
+static void GLInterfaceValidationTest(skiatest::Reporter* reporter) {
+    typedef const GrGLInterface* (*interfaceFactory)();
+    struct {
+       interfaceFactory fFactory;
+       const char* fName;
+    } interfaceFactories[] = {
+        {GrGLCreateNativeInterface, "Native"},
+#if SK_MESA
+        {GrGLCreateMesaInterface, "Mesa"},
+#endif
+    };
+
+    // On some platforms GrGLCreateNativeInterface will fail unless an OpenGL
+    // context has been created. Also, preserve the current context that may
+    // be in use by outer test harness.
+    SkNativeGLContext::AutoContextRestore nglacr;
+    SkNativeGLContext nglctx;
+    static const int gBOGUS_SIZE = 16;
+    bool nativeContextInit = nglctx.init(gBOGUS_SIZE, gBOGUS_SIZE);
+    REPORTER_ASSERT(reporter, nativeContextInit);
+    if (!nativeContextInit) {
+        return;
+    }
+#if SK_MESA
+    // We must have a current OSMesa context to initialize an OSMesa
+    // GrGLInterface
+    SkMesaGLContext::AutoContextRestore mglacr;
+    SkMesaGLContext mglctx;
+    bool mesaContextInit = mglctx.init(gBOGUS_SIZE, gBOGUS_SIZE);
+    REPORTER_ASSERT(reporter, mesaContextInit);
+    if(!mesaContextInit) {
+        return;
+    }
+#endif
+
+    SkAutoTUnref<const GrGLInterface> iface;
+    for (size_t i = 0; i < SK_ARRAY_COUNT(interfaceFactories); ++i) {
+        iface.reset(interfaceFactories[i].fFactory());
+        REPORTER_ASSERT(reporter, NULL != iface.get());
+        if (iface.get()) {
+            REPORTER_ASSERT(reporter, iface.get()->validate(kOpenGL_Shaders_GrEngine));
+        }
+    }
+}
+
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("GLInterfaceValidation",
+                 GLInterfaceValidationTestClass,
+                 GLInterfaceValidationTest)
+
diff --git a/tests/Test.cpp b/tests/Test.cpp
index d91eeed..1c3b691 100644
--- a/tests/Test.cpp
+++ b/tests/Test.cpp
@@ -89,6 +89,9 @@
             gGrContext.reset(GrContext::Create(kOpenGL_Shaders_GrEngine, ctx));
         }
     }
+    if (gGLContext.get()) {
+        gGLContext.get()->makeCurrent();
+    }
     return gGrContext.get();
 }