Index: trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/ogltest/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/ogltest/Makefile.kmk	(revision 81027)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/ogltest/Makefile.kmk	(revision 81081)
@@ -25,4 +25,6 @@
 
 ogltest_TEMPLATE = VBOXR3STATIC
+ogltest_INCS = \
+	$(PATH_ROOT)/src/VBox/Devices/Graphics/vmsvga_glext
 ogltest_SOURCES = \
 	ogltest.cpp \
Index: trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/ogltest/oglrender.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/ogltest/oglrender.cpp	(revision 81027)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/ogltest/oglrender.cpp	(revision 81081)
@@ -129,4 +129,260 @@
 
 
+/*
+ * DrawArraysInstanced. Uses shaders from a guest.
+ */
+class OGLRenderDrawArrays : public OGLRender
+{
+    static const int cArrays = 4;
+
+    struct VertexAttribDesc
+    {
+        GLint     size;
+        GLenum    type;
+        GLboolean normalized;
+        GLsizei   stride;
+    };
+
+    static VertexAttribDesc aVertexAttribs[cArrays];
+    GLuint vbNames[cArrays];
+
+    GLuint vertexShader;
+    GLuint fragmentShader;
+    GLuint program;
+
+    virtual HRESULT InitRender();
+    virtual HRESULT DoRender();
+};
+
+static const GLchar *apszVertexShader[] =
+{
+    "  #version 120\n"
+    "  #extension GL_EXT_gpu_shader4 : enable\n"
+    "  uniform vec4 VC[2048];\n"
+    "  uniform vec4 posFixup;\n"
+    "  void order_ps_input(in vec4[12]);\n"
+    "  vec4 OUT[12];\n"
+    "  vec4 R0;\n"
+    "  vec4 R1;\n"
+    "  vec4 R2;\n"
+    "  attribute vec4 attrib0;\n"
+    "  attribute vec4 attrib1;\n"
+    "  attribute vec4 attrib2;\n"
+    "  attribute vec4 attrib3;\n"
+    "  vec4 tmp0;\n"
+    "  vec4 tmp1;\n"
+    "  bool p0[4];\n"
+    "  uniform vec4 VC1 = { 0.000000, 0.000000, 1.00000, 1.000000 };\n"
+    "  uniform vec4 VLC2 = { 1.000000, -1.000000, 0.500000, 0.000000 };\n"
+    "  const float FLT_MAX = 1e38;\n"
+    "  void main() {"
+    "      R0.xy = (attrib0.xy);\n"
+    "      R0.yzw = (R0.yyy * attrib2.xyz);\n"
+    "      R0.xyz = ((attrib1.xyz * R0.xxx) + R0.yzw);\n"
+    "      R0.xyz = (R0.xyz + attrib3.xyz);\n"
+    "      R1.xyzw = (R0.xzyz * VC1.zxwy); // (R0.xzyz * VC[1].zxwy);\n"
+    "      R1.xy = (R1.yw + R1.xz);\n"
+    "      R2.xy = (R1.xy * VLC2.xy);\n"
+    "      R2.zw = (R0.zz * VLC2.zx);\n"
+    "      OUT[1].xyw = (R0.xyz);\n"
+    "      OUT[1].z = (VLC2.w);\n"
+    "      OUT[0].xyzw = (R2.xyzw);\n"
+    "      gl_Position.xyzw = OUT[0].xyzw;\n"
+    "      gl_FogFragCoord = 0.0;\n"
+    "      //gl_Position.y = gl_Position.y * posFixup.y;\n"
+    "      //gl_Position.xy += posFixup.zw * gl_Position.ww;\n"
+    "      //gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n"
+    "  }\n"
+};
+
+static const char *passthrough_vshader[] =
+{
+    "  #version 120\n"
+    "  vec4 R0;\n"
+    "  attribute vec4 attrib0;\n"
+    "  attribute vec4 attrib1;\n"
+    "  attribute vec4 attrib2;\n"
+    "  attribute vec4 attrib3;\n"
+    "  void main(void)\n"
+    "  {\n"
+    "      R0   = attrib0;\n"
+    "      R0.w = 1.0;\n"
+    "      R0.z = 0.0;\n"
+    "      gl_Position   = R0;\n"
+    "  }\n"
+};
+
+static const GLchar *apszFragmentShader[] =
+{
+    "  #version 120\n"
+    "  #extension GL_EXT_gpu_shader4 : enable\n"
+    "  uniform vec4 PC[2048];\n"
+    "  varying vec4 IN[31];\n"
+    "  vec4 tmp0;\n"
+    "  vec4 tmp1;\n"
+    "  bool p0[4];\n"
+    "  uniform vec4 PLC0;\n"
+    "  const float FLT_MAX = 1e38;\n"
+    "  void main() {"
+    "      gl_FragData[0].xyzw = vec4(1.0, 1.0, 1.0, 1.0); //(PLC0.xyzw);\n"
+    "  }\n"
+};
+
+/* static */ OGLRenderDrawArrays::VertexAttribDesc OGLRenderDrawArrays::aVertexAttribs[OGLRenderDrawArrays::cArrays] =
+{
+    {2, GL_FLOAT, GL_FALSE, 8 },
+    {4, GL_FLOAT, GL_FALSE, 0 },
+    {4, GL_FLOAT, GL_FALSE, 0 },
+    {4, GL_FLOAT, GL_FALSE, 0 }
+};
+
+/* Triangle fan. */
+static float aAttrib0[] =
+{
+    0.0f,  200.0f,
+  300.0f,  200.0f,
+  300.0f,  400.0f,
+    0.0f,  400.0f
+};
+
+static float aAttrib0a[] =
+{
+  -1.0f,  -1.0f,
+   1.0f,  -1.0f,
+   0.0f,   0.0f,
+   0.0f,   2.0f
+};
+
+static float aAttrib1[] =
+{
+    // 1 / (w / 2)
+    0.001556f, 0.000000f, 0.000000f, 1.000000f,
+};
+
+static float aAttrib2[] =
+{
+               // 1/ (h / 2)
+    0.000000f, -0.001874f, 0.000000f, 1.000000f,
+};
+
+static float aAttrib3[] =
+{
+    -1.000000f,  1.000000f, 1.000000f, 1.000000f,
+};
+
+HRESULT OGLRenderDrawArrays::InitRender()
+{
+    glClearColor(0.0, 0.0, 1.0, 1.0);
+
+    int success;
+    char szInfoLog[1024];
+
+    vertexShader = glCreateShader(GL_VERTEX_SHADER);
+    GL_CHECK_ERROR();
+    glShaderSource(vertexShader, 1, apszVertexShader, NULL);
+    GL_CHECK_ERROR();
+    glCompileShader(vertexShader);
+    GL_CHECK_ERROR();
+    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
+    GL_CHECK_ERROR();
+    if (!success)
+    {
+        glGetShaderInfoLog(vertexShader, sizeof(szInfoLog), NULL, szInfoLog);
+        GL_CHECK_ERROR();
+        TestShowError(E_FAIL, szInfoLog);
+    };
+
+    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+    GL_CHECK_ERROR();
+    glShaderSource(fragmentShader, 1, apszFragmentShader, NULL);
+    GL_CHECK_ERROR();
+    glCompileShader(fragmentShader);
+    GL_CHECK_ERROR();
+    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
+    GL_CHECK_ERROR();
+    if (!success)
+    {
+        glGetShaderInfoLog(fragmentShader, sizeof(szInfoLog), NULL, szInfoLog);
+        GL_CHECK_ERROR();
+        TestShowError(E_FAIL, szInfoLog);
+    };
+
+    program = glCreateProgram();
+    GL_CHECK_ERROR();
+    glAttachShader(program, vertexShader);
+    GL_CHECK_ERROR();
+    glAttachShader(program, fragmentShader);
+    GL_CHECK_ERROR();
+    glLinkProgram(program);
+    GL_CHECK_ERROR();
+    glGetProgramiv(program, GL_LINK_STATUS, &success);
+    if(!success)
+    {
+        glGetProgramInfoLog(program, sizeof(szInfoLog), NULL, szInfoLog);
+        GL_CHECK_ERROR();
+        TestShowError(E_FAIL, szInfoLog);
+    }
+
+    glUseProgram(program);
+    GL_CHECK_ERROR();
+
+    glGenBuffers(cArrays, vbNames);
+    GL_CHECK_ERROR();
+
+    struct AttribData
+    {
+        GLsizeiptr size;
+        const GLvoid * data;
+    };
+
+    static struct AttribData attribData[cArrays] =
+    {
+        { sizeof(aAttrib0), aAttrib0 },
+        { sizeof(aAttrib1), aAttrib1 },
+        { sizeof(aAttrib2), aAttrib2 },
+        { sizeof(aAttrib3), aAttrib3 },
+    };
+
+    GLuint index;
+    for (index = 0; index < cArrays; ++index)
+    {
+        glBindBuffer(GL_ARRAY_BUFFER, vbNames[index]);
+        GL_CHECK_ERROR();
+
+        glBufferData(GL_ARRAY_BUFFER, attribData[index].size, attribData[index].data, GL_DYNAMIC_DRAW);
+        GL_CHECK_ERROR();
+
+        glEnableVertexAttribArray(index);
+        GL_CHECK_ERROR();
+        glVertexAttribPointer(index, aVertexAttribs[index].size, aVertexAttribs[index].type,
+                              aVertexAttribs[index].normalized, aVertexAttribs[index].stride,
+                              (const GLvoid *)(uintptr_t)0);
+        GL_CHECK_ERROR();
+
+        GLuint const divisor = aVertexAttribs[index].stride ?
+                               0 : /* Once per vertex. */
+                               1;  /* Once for one (1) set of vertices (or instance). */
+        glVertexAttribDivisor(index, divisor);
+        GL_CHECK_ERROR();
+    }
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    GL_CHECK_ERROR();
+
+    return S_OK;
+}
+
+HRESULT OGLRenderDrawArrays::DoRender()
+{
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, 1);
+    GL_CHECK_ERROR();
+
+    glFlush();
+    return S_OK;
+}
+
+
 OGLRender *CreateRender(int iRenderId)
 {
@@ -136,4 +392,5 @@
         case 0: pRender = new OGLRenderTriangle(); break;
         case 1: pRender = new OGLRenderTexture2D(); break;
+        case 2: pRender = new OGLRenderDrawArrays(); break;
         default:
             break;
Index: trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/ogltest/oglrender.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/ogltest/oglrender.h	(revision 81027)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/ogltest/oglrender.h	(revision 81081)
@@ -29,4 +29,5 @@
 #include <GL/gl.h>
 #include <GL/glu.h>
+#include <glext.h>
 
 inline void TestShowError(HRESULT hr, const char *pszString)
@@ -35,4 +36,9 @@
     MessageBoxA(0, pszString, 0, 0);
 }
+/* Expand __LINE__ number to a string. */
+#define OGLTEST_S(n) #n
+#define OGLTEST_N2S(n) OGLTEST_S(n)
+
+#define GL_CHECK_ERROR() do { if (glGetError() != GL_NO_ERROR) TestShowError((E_FAIL), __FILE__ "@" OGLTEST_N2S(__LINE__)); } while(0)
 
 class OGLRender
@@ -49,3 +55,29 @@
 void DeleteRender(OGLRender *pRender);
 
+extern PFNGLBINDBUFFERPROC                             glBindBuffer;
+extern PFNGLDELETEBUFFERSPROC                          glDeleteBuffers;
+extern PFNGLGENBUFFERSPROC                             glGenBuffers;
+extern PFNGLBUFFERDATAPROC                             glBufferData;
+extern PFNGLMAPBUFFERPROC                              glMapBuffer;
+extern PFNGLUNMAPBUFFERPROC                            glUnmapBuffer;
+extern PFNGLENABLEVERTEXATTRIBARRAYPROC                glEnableVertexAttribArray;
+extern PFNGLDISABLEVERTEXATTRIBARRAYPROC               glDisableVertexAttribArray;
+extern PFNGLVERTEXATTRIBPOINTERPROC                    glVertexAttribPointer;
+extern PFNGLCREATESHADERPROC                           glCreateShader;
+extern PFNGLATTACHSHADERPROC                           glAttachShader;
+extern PFNGLCOMPILESHADERPROC                          glCompileShader;
+extern PFNGLCREATEPROGRAMPROC                          glCreateProgram;
+extern PFNGLDELETEPROGRAMPROC                          glDeleteProgram;
+extern PFNGLDELETESHADERPROC                           glDeleteShader;
+extern PFNGLDETACHSHADERPROC                           glDetachShader;
+extern PFNGLLINKPROGRAMPROC                            glLinkProgram;
+extern PFNGLSHADERSOURCEPROC                           glShaderSource;
+extern PFNGLUSEPROGRAMPROC                             glUseProgram;
+extern PFNGLGETPROGRAMIVPROC                           glGetProgramiv;
+extern PFNGLGETPROGRAMINFOLOGPROC                      glGetProgramInfoLog;
+extern PFNGLGETSHADERIVPROC                            glGetShaderiv;
+extern PFNGLGETSHADERINFOLOGPROC                       glGetShaderInfoLog;
+extern PFNGLVERTEXATTRIBDIVISORPROC                    glVertexAttribDivisor;
+extern PFNGLDRAWARRAYSINSTANCEDPROC                    glDrawArraysInstanced;
+
 #endif /* !GA_INCLUDED_SRC_WINNT_Graphics_Video_disp_wddm_gallium_ogltest_oglrender_h */
Index: trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/ogltest/ogltest.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/ogltest/ogltest.cpp	(revision 81027)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/ogltest/ogltest.cpp	(revision 81081)
@@ -17,4 +17,30 @@
 
 #include "oglrender.h"
+
+PFNGLBINDBUFFERPROC                             glBindBuffer;
+PFNGLDELETEBUFFERSPROC                          glDeleteBuffers;
+PFNGLGENBUFFERSPROC                             glGenBuffers;
+PFNGLBUFFERDATAPROC                             glBufferData;
+PFNGLMAPBUFFERPROC                              glMapBuffer;
+PFNGLUNMAPBUFFERPROC                            glUnmapBuffer;
+PFNGLENABLEVERTEXATTRIBARRAYPROC                glEnableVertexAttribArray;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC               glDisableVertexAttribArray;
+PFNGLVERTEXATTRIBPOINTERPROC                    glVertexAttribPointer;
+PFNGLCREATESHADERPROC                           glCreateShader;
+PFNGLATTACHSHADERPROC                           glAttachShader;
+PFNGLCOMPILESHADERPROC                          glCompileShader;
+PFNGLCREATEPROGRAMPROC                          glCreateProgram;
+PFNGLDELETEPROGRAMPROC                          glDeleteProgram;
+PFNGLDELETESHADERPROC                           glDeleteShader;
+PFNGLDETACHSHADERPROC                           glDetachShader;
+PFNGLLINKPROGRAMPROC                            glLinkProgram;
+PFNGLSHADERSOURCEPROC                           glShaderSource;
+PFNGLUSEPROGRAMPROC                             glUseProgram;
+PFNGLGETPROGRAMIVPROC                           glGetProgramiv;
+PFNGLGETPROGRAMINFOLOGPROC                      glGetProgramInfoLog;
+PFNGLGETSHADERIVPROC                            glGetShaderiv;
+PFNGLGETSHADERINFOLOGPROC                       glGetShaderInfoLog;
+PFNGLVERTEXATTRIBDIVISORPROC                    glVertexAttribDivisor;
+PFNGLDRAWARRAYSINSTANCEDPROC                    glDrawArraysInstanced;
 
 class OGLTest
@@ -168,4 +194,39 @@
             mhGLRC = wglCreateContext(hDC);
             setCurrentGLCtx(mhGLRC);
+
+/* Get a function address, return VERR_NOT_IMPLEMENTED on failure. */
+#define GLGETPROC_(ProcType, ProcName, NameSuffix) do { \
+    ProcName = (ProcType)wglGetProcAddress(#ProcName NameSuffix); \
+    if (!ProcName) { TestShowError(E_FAIL, #ProcName NameSuffix " missing"); } \
+} while(0)
+
+            GLGETPROC_(PFNGLBINDBUFFERPROC                       , glBindBuffer, "");
+            GLGETPROC_(PFNGLDELETEBUFFERSPROC                    , glDeleteBuffers, "");
+            GLGETPROC_(PFNGLGENBUFFERSPROC                       , glGenBuffers, "");
+            GLGETPROC_(PFNGLBUFFERDATAPROC                       , glBufferData, "");
+            GLGETPROC_(PFNGLMAPBUFFERPROC                        , glMapBuffer, "");
+            GLGETPROC_(PFNGLUNMAPBUFFERPROC                      , glUnmapBuffer, "");
+            GLGETPROC_(PFNGLENABLEVERTEXATTRIBARRAYPROC          , glEnableVertexAttribArray, "");
+            GLGETPROC_(PFNGLDISABLEVERTEXATTRIBARRAYPROC         , glDisableVertexAttribArray, "");
+            GLGETPROC_(PFNGLVERTEXATTRIBPOINTERPROC              , glVertexAttribPointer, "");
+            GLGETPROC_(PFNGLCREATESHADERPROC                     , glCreateShader, "");
+            GLGETPROC_(PFNGLATTACHSHADERPROC                     , glAttachShader, "");
+            GLGETPROC_(PFNGLCOMPILESHADERPROC                    , glCompileShader, "");
+            GLGETPROC_(PFNGLCREATEPROGRAMPROC                    , glCreateProgram, "");
+            GLGETPROC_(PFNGLDELETEPROGRAMPROC                    , glDeleteProgram, "");
+            GLGETPROC_(PFNGLDELETESHADERPROC                     , glDeleteShader, "");
+            GLGETPROC_(PFNGLDETACHSHADERPROC                     , glDetachShader, "");
+            GLGETPROC_(PFNGLLINKPROGRAMPROC                      , glLinkProgram, "");
+            GLGETPROC_(PFNGLSHADERSOURCEPROC                     , glShaderSource, "");
+            GLGETPROC_(PFNGLUSEPROGRAMPROC                       , glUseProgram, "");
+            GLGETPROC_(PFNGLGETPROGRAMIVPROC                     , glGetProgramiv, "");
+            GLGETPROC_(PFNGLGETPROGRAMINFOLOGPROC                , glGetProgramInfoLog, "");
+            GLGETPROC_(PFNGLGETSHADERIVPROC                      , glGetShaderiv, "");
+            GLGETPROC_(PFNGLGETSHADERINFOLOGPROC                 , glGetShaderInfoLog, "");
+            GLGETPROC_(PFNGLVERTEXATTRIBDIVISORPROC              , glVertexAttribDivisor, "");
+            GLGETPROC_(PFNGLDRAWARRAYSINSTANCEDPROC              , glDrawArraysInstanced, "");
+
+#undef GLGETPROC_
+
         }
         else
