Index: /trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBQGL.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBQGL.cpp	(revision 22641)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBQGL.cpp	(revision 22641)
@@ -0,0 +1,5113 @@
+/* $Id$ */
+/** @file
+ * VBoxFBQGL Opengl-based FrameBuffer implementation
+ */
+
+/*
+ * Copyright (C) 2009 Sun Microsystems, Inc.
+ *
+ * Sun Microsystems, Inc. confidential
+ * All rights reserved
+ */
+#if defined (VBOX_GUI_USE_QGL)
+
+#include "VBoxFrameBuffer.h"
+
+#include "VBoxConsoleView.h"
+#include "VBoxProblemReporter.h"
+#include "VBoxGlobal.h"
+
+/* Qt includes */
+#include <QGLWidget>
+
+#include <iprt/asm.h>
+
+#ifdef VBOX_WITH_VIDEOHWACCEL
+#include <VBox/VBoxVideo.h>
+#include <VBox/types.h>
+#include <VBox/ssm.h>
+#endif
+#include <iprt/semaphore.h>
+
+#include <QFile>
+#include <QTextStream>
+
+#ifdef VBOXQGL_PROF_BASE
+# ifdef VBOXQGL_DBG_SURF
+#  define VBOXQGL_PROF_WIDTH 1400
+#  define VBOXQGL_PROF_HEIGHT 1050
+# else
+# define VBOXQGL_PROF_WIDTH 1400
+# define VBOXQGL_PROF_HEIGHT 1050
+//#define VBOXQGL_PROF_WIDTH 720
+//#define VBOXQGL_PROF_HEIGHT 480
+# endif
+#endif
+
+#define VBOXQGL_STATE_NAMEBASE "QGLVHWAData"
+#define VBOXQGL_STATE_VERSION 1
+#ifdef DEBUG_misha
+# define VBOXQGL_STATE_DEBUG
+#endif
+
+#ifdef VBOXQGL_STATE_DEBUG
+#define VBOXQGL_STATE_START_MAGIC        0x12345678
+#define VBOXQGL_STATE_STOP_MAGIC         0x87654321
+
+#define VBOXQGL_STATE_SURFSTART_MAGIC    0x9abcdef1
+#define VBOXQGL_STATE_SURFSTOP_MAGIC     0x1fedcba9
+
+#define VBOXQGL_STATE_OVERLAYSTART_MAGIC 0x13579bdf
+#define VBOXQGL_STATE_OVERLAYSTOP_MAGIC  0xfdb97531
+
+#define VBOXQGL_SAVE_START(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_START_MAGIC); AssertRC(rc);}while(0)
+#define VBOXQGL_SAVE_STOP(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_STOP_MAGIC); AssertRC(rc);}while(0)
+
+#define VBOXQGL_SAVE_SURFSTART(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_SURFSTART_MAGIC); AssertRC(rc);}while(0)
+#define VBOXQGL_SAVE_SURFSTOP(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_SURFSTOP_MAGIC); AssertRC(rc);}while(0)
+
+#define VBOXQGL_SAVE_OVERLAYSTART(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_OVERLAYSTART_MAGIC); AssertRC(rc);}while(0)
+#define VBOXQGL_SAVE_OVERLAYSTOP(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_OVERLAYSTOP_MAGIC); AssertRC(rc);}while(0)
+
+#define VBOXQGL_LOAD_CHECK(_pSSM, _v) \
+    do{ \
+        uint32_t _u32; \
+        int rc = SSMR3GetU32(_pSSM, &_u32); AssertRC(rc); \
+        if(_u32 != (_v)) \
+        { \
+            VBOXQGLLOG(("load error: expected magic (0x%x), but was (0x%x)\n", (_v), _u32));\
+        }\
+        Assert(_u32 == (_v)); \
+    }while(0)
+
+#define VBOXQGL_LOAD_START(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_START_MAGIC)
+#define VBOXQGL_LOAD_STOP(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_STOP_MAGIC)
+
+#define VBOXQGL_LOAD_SURFSTART(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_SURFSTART_MAGIC)
+#define VBOXQGL_LOAD_SURFSTOP(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_SURFSTOP_MAGIC)
+
+#define VBOXQGL_LOAD_OVERLAYSTART(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_OVERLAYSTART_MAGIC)
+#define VBOXQGL_LOAD_OVERLAYSTOP(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_OVERLAYSTOP_MAGIC)
+
+#else
+
+#define VBOXQGL_SAVE_START(_pSSM) do{}while(0)
+#define VBOXQGL_SAVE_STOP(_pSSM) do{}while(0)
+
+#define VBOXQGL_SAVE_SURFSTART(_pSSM) do{}while(0)
+#define VBOXQGL_SAVE_SURFSTOP(_pSSM) do{}while(0)
+
+#define VBOXQGL_SAVE_OVERLAYSTART(_pSSM) do{}while(0)
+#define VBOXQGL_SAVE_OVERLAYSTOP(_pSSM) do{}while(0)
+
+#define VBOXQGL_LOAD_START(_pSSM) do{}while(0)
+#define VBOXQGL_LOAD_STOP(_pSSM) do{}while(0)
+
+#define VBOXQGL_LOAD_SURFSTART(_pSSM) do{}while(0)
+#define VBOXQGL_LOAD_SURFSTOP(_pSSM) do{}while(0)
+
+#define VBOXQGL_LOAD_OVERLAYSTART(_pSSM) do{}while(0)
+#define VBOXQGL_LOAD_OVERLAYSTOP(_pSSM) do{}while(0)
+
+#endif
+
+#define VBOXQGL_MAKEFOURCC(ch0, ch1, ch2, ch3)                              \
+                ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) |       \
+                ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 ))
+
+#define FOURCC_AYUV VBOXQGL_MAKEFOURCC('A', 'Y', 'U', 'V')
+#define FOURCC_UYVY VBOXQGL_MAKEFOURCC('U', 'Y', 'V', 'Y')
+#define FOURCC_YUY2 VBOXQGL_MAKEFOURCC('Y', 'U', 'Y', '2')
+#define FOURCC_YV12 VBOXQGL_MAKEFOURCC('Y', 'V', '1', '2')
+#define VBOXVHWA_NUMFOURCC 4
+
+typedef char GLchar;
+
+#ifndef GL_COMPILE_STATUS
+# define GL_COMPILE_STATUS 0x8b81
+#endif
+#ifndef GL_LINK_STATUS
+# define GL_LINK_STATUS    0x8b82
+#endif
+#ifndef GL_FRAGMENT_SHADER
+# define GL_FRAGMENT_SHADER 0x8b30
+#endif
+#ifndef GL_VERTEX_SHADER
+# define GL_VERTEX_SHADER 0x8b31
+#endif
+
+/* GL_ARB_multitexture */
+#ifndef GL_TEXTURE0
+# define GL_TEXTURE0                    0x84c0
+#endif
+#ifndef GL_TEXTURE1
+# define GL_TEXTURE1                    0x84c1
+#endif
+#ifndef GL_MAX_TEXTURE_COORDS
+# define GL_MAX_TEXTURE_COORDS          0x8871
+#endif
+#ifndef GL_MAX_TEXTURE_IMAGE_UNITS
+# define GL_MAX_TEXTURE_IMAGE_UNITS     0x8872
+#endif
+
+#ifndef APIENTRY
+# define APIENTRY
+#endif
+
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_ACTIVE_TEXTURE) (GLenum texture);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_MULTI_TEX_COORD2I) (GLenum texture, GLint v0, GLint v1);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_MULTI_TEX_COORD2F) (GLenum texture, GLfloat v0, GLfloat v1);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_MULTI_TEX_COORD2D) (GLenum texture, GLdouble v0, GLdouble v1);
+
+/* GL_ARB_texture_rectangle */
+#ifndef GL_TEXTURE_RECTANGLE
+# define GL_TEXTURE_RECTANGLE 0x84F5
+#endif
+
+/* GL_ARB_shader_objects */
+/* GL_ARB_fragment_shader */
+
+typedef GLuint (APIENTRY *PFNVBOXVHWA_CREATE_SHADER)  (GLenum type);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_SHADER_SOURCE)  (GLuint shader, GLsizei count, const GLchar **string, const GLint *length);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_COMPILE_SHADER) (GLuint shader);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_DELETE_SHADER)  (GLuint shader);
+
+typedef GLuint (APIENTRY *PFNVBOXVHWA_CREATE_PROGRAM) ();
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_ATTACH_SHADER)  (GLuint program, GLuint shader);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_DETACH_SHADER)  (GLuint program, GLuint shader);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_LINK_PROGRAM)   (GLuint program);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_USE_PROGRAM)    (GLuint program);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_DELETE_PROGRAM) (GLuint program);
+
+typedef GLboolean (APIENTRY *PFNVBOXVHWA_IS_SHADER)   (GLuint shader);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GET_SHADERIV)   (GLuint shader, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRY *PFNVBOXVHWA_IS_PROGRAM)  (GLuint program);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GET_PROGRAMIV)  (GLuint program, GLenum pname, GLint *params);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GET_ATTACHED_SHADERS) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GET_SHADER_INFO_LOG)  (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GET_PROGRAM_INFO_LOG) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef GLint (APIENTRY *PFNVBOXVHWA_GET_UNIFORM_LOCATION) (GLint programObj, const GLchar *name);
+
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM1F)(GLint location, GLfloat v0);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM2F)(GLint location, GLfloat v0, GLfloat v1);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM3F)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM4F)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM1I)(GLint location, GLint v0);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM2I)(GLint location, GLint v0, GLint v1);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM3I)(GLint location, GLint v0, GLint v1, GLint v2);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM4I)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+
+/* GL_ARB_pixel_buffer_object*/
+#ifndef Q_WS_MAC
+/* apears to be defined on mac */
+typedef ptrdiff_t GLsizeiptr;
+#endif
+
+#ifndef GL_READ_ONLY
+# define GL_READ_ONLY                   0x88B8
+#endif
+#ifndef GL_WRITE_ONLY
+# define GL_WRITE_ONLY                  0x88B9
+#endif
+#ifndef GL_READ_WRITE
+# define GL_READ_WRITE                  0x88BA
+#endif
+#ifndef GL_STREAM_DRAW
+# define GL_STREAM_DRAW                 0x88E0
+#endif
+#ifndef GL_STREAM_READ
+# define GL_STREAM_READ                 0x88E1
+#endif
+#ifndef GL_STREAM_COPY
+# define GL_STREAM_COPY                 0x88E2
+#endif
+
+#ifndef GL_PIXEL_PACK_BUFFER
+# define GL_PIXEL_PACK_BUFFER           0x88EB
+#endif
+#ifndef GL_PIXEL_UNPACK_BUFFER
+# define GL_PIXEL_UNPACK_BUFFER         0x88EC
+#endif
+#ifndef GL_PIXEL_PACK_BUFFER_BINDING
+# define GL_PIXEL_PACK_BUFFER_BINDING   0x88ED
+#endif
+#ifndef GL_PIXEL_UNPACK_BUFFER_BINDING
+# define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#endif
+
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GEN_BUFFERS)(GLsizei n, GLuint *buffers);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_DELETE_BUFFERS)(GLsizei n, const GLuint *buffers);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_BIND_BUFFER)(GLenum target, GLuint buffer);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_BUFFER_DATA)(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
+typedef GLvoid* (APIENTRY *PFNVBOXVHWA_MAP_BUFFER)(GLenum target, GLenum access);
+typedef GLboolean (APIENTRY *PFNVBOXVHWA_UNMAP_BUFFER)(GLenum target);
+
+/*****************/
+
+/* functions */
+
+PFNVBOXVHWA_ACTIVE_TEXTURE vboxglActiveTexture = NULL;
+PFNVBOXVHWA_MULTI_TEX_COORD2I vboxglMultiTexCoord2i = NULL;
+PFNVBOXVHWA_MULTI_TEX_COORD2D vboxglMultiTexCoord2d = NULL;
+PFNVBOXVHWA_MULTI_TEX_COORD2F vboxglMultiTexCoord2f = NULL;
+
+
+PFNVBOXVHWA_CREATE_SHADER   vboxglCreateShader  = NULL;
+PFNVBOXVHWA_SHADER_SOURCE   vboxglShaderSource  = NULL;
+PFNVBOXVHWA_COMPILE_SHADER  vboxglCompileShader = NULL;
+PFNVBOXVHWA_DELETE_SHADER   vboxglDeleteShader  = NULL;
+
+PFNVBOXVHWA_CREATE_PROGRAM  vboxglCreateProgram = NULL;
+PFNVBOXVHWA_ATTACH_SHADER   vboxglAttachShader  = NULL;
+PFNVBOXVHWA_DETACH_SHADER   vboxglDetachShader  = NULL;
+PFNVBOXVHWA_LINK_PROGRAM    vboxglLinkProgram   = NULL;
+PFNVBOXVHWA_USE_PROGRAM     vboxglUseProgram    = NULL;
+PFNVBOXVHWA_DELETE_PROGRAM  vboxglDeleteProgram = NULL;
+
+PFNVBOXVHWA_IS_SHADER       vboxglIsShader      = NULL;
+PFNVBOXVHWA_GET_SHADERIV    vboxglGetShaderiv   = NULL;
+PFNVBOXVHWA_IS_PROGRAM      vboxglIsProgram     = NULL;
+PFNVBOXVHWA_GET_PROGRAMIV   vboxglGetProgramiv  = NULL;
+PFNVBOXVHWA_GET_ATTACHED_SHADERS vboxglGetAttachedShaders = NULL;
+PFNVBOXVHWA_GET_SHADER_INFO_LOG  vboxglGetShaderInfoLog   = NULL;
+PFNVBOXVHWA_GET_PROGRAM_INFO_LOG vboxglGetProgramInfoLog  = NULL;
+
+PFNVBOXVHWA_GET_UNIFORM_LOCATION vboxglGetUniformLocation = NULL;
+
+PFNVBOXVHWA_UNIFORM1F vboxglUniform1f;
+PFNVBOXVHWA_UNIFORM2F vboxglUniform2f;
+PFNVBOXVHWA_UNIFORM3F vboxglUniform3f;
+PFNVBOXVHWA_UNIFORM4F vboxglUniform4f;
+
+PFNVBOXVHWA_UNIFORM1I vboxglUniform1i;
+PFNVBOXVHWA_UNIFORM2I vboxglUniform2i;
+PFNVBOXVHWA_UNIFORM3I vboxglUniform3i;
+PFNVBOXVHWA_UNIFORM4I vboxglUniform4i;
+
+PFNVBOXVHWA_GEN_BUFFERS vboxglGenBuffers = NULL;
+PFNVBOXVHWA_DELETE_BUFFERS vboxglDeleteBuffers = NULL;
+PFNVBOXVHWA_BIND_BUFFER vboxglBindBuffer = NULL;
+PFNVBOXVHWA_BUFFER_DATA vboxglBufferData = NULL;
+PFNVBOXVHWA_MAP_BUFFER vboxglMapBuffer = NULL;
+PFNVBOXVHWA_UNMAP_BUFFER vboxglUnmapBuffer = NULL;
+
+#if 0
+#if defined Q_WS_WIN
+#define VBOXVHWA_GETPROCADDRESS(_t, _n) (_t)wglGetProcAddress(_n)
+#elif defined Q_WS_X11
+#include <GL/glx.h>
+#define VBOXVHWA_GETPROCADDRESS(_t, _n) (_t)glXGetProcAddress((const GLubyte *)(_n))
+#else
+#error "Port me!!!"
+#endif
+#endif
+
+#define VBOXVHWA_GETPROCADDRESS(_c, _t, _n) ((_t)(_c).getProcAddress(QString(_n)))
+
+#define VBOXVHWA_PFNINIT_SAME(_c, _t, _v, _rc) \
+    do { \
+        if((vboxgl##_v = VBOXVHWA_GETPROCADDRESS(_c, _t, "gl"#_v)) == NULL) \
+        { \
+            VBOXQGLLOG(("ERROR: '%s' function is not found\n", "gl"#_v));\
+            AssertBreakpoint(); \
+            if((vboxgl##_v = VBOXVHWA_GETPROCADDRESS(_c, _t, "gl"#_v"ARB")) == NULL) \
+            { \
+                VBOXQGLLOG(("ERROR: '%s' function is not found\n", "gl"#_v"ARB"));\
+                AssertBreakpoint(); \
+                if((vboxgl##_v = VBOXVHWA_GETPROCADDRESS(_c, _t, "gl"#_v"EXT")) == NULL) \
+                { \
+                    VBOXQGLLOG(("ERROR: '%s' function is not found\n", "gl"#_v"EXT"));\
+                    AssertBreakpoint(); \
+                    (_rc)++; \
+                } \
+            } \
+        } \
+    }while(0)
+
+#define VBOXVHWA_PFNINIT(_c, _t, _v, _f,_rc) \
+    do { \
+        if((vboxgl##_v = VBOXVHWA_GETPROCADDRESS(_c, _t, "gl"#_f)) == NULL) \
+        { \
+            VBOXQGLLOG(("ERROR: '%s' function is not found\n", "gl"#_f));\
+            AssertBreakpoint(); \
+            (_rc)++; \
+        } \
+    }while(0)
+
+//#define VBOXVHWA_PFNINIT_OBJECT_ARB(_t, _v, _rc) VBOXVHWA_PFNINIT(_t, _v, #_v"ObjectARB" ,_rc)
+#define VBOXVHWA_PFNINIT_OBJECT_ARB(_c, _t, _v, _rc) \
+	    do { \
+	        if((vboxgl##_v = VBOXVHWA_GETPROCADDRESS(_c, _t, "gl"#_v"ObjectARB")) == NULL) \
+	        { \
+	            VBOXQGLLOG(("ERROR: '%s' function is not found\n", "gl"#_v"ObjectARB"));\
+	            AssertBreakpoint(); \
+	            (_rc)++; \
+	        } \
+	    }while(0)
+
+//#define VBOXVHWA_PFNINIT_ARB(_t, _v, _rc) VBOXVHWA_PFNINIT(_t, _v, #_v"ARB" ,_rc)
+#define VBOXVHWA_PFNINIT_ARB(_c, _t, _v, _rc) \
+	    do { \
+	        if((vboxgl##_v = VBOXVHWA_GETPROCADDRESS(_c, _t, "gl"#_v"ARB")) == NULL) \
+	        { \
+                VBOXQGLLOG(("ERROR: '%s' function is not found\n", "gl"#_v"ARB"));\
+	            AssertBreakpoint(); \
+	            (_rc)++; \
+	        } \
+	    }while(0)
+
+
+static bool g_vboxVHWAGlSupportInitialized = false;
+/* vbox version in the format 0x00mjmnbl
+ * in case of a failure contains -1 (0xffffffff) */
+static int g_vboxVHWAGlVersion = 0;
+
+static bool g_GL_ARB_multitexture        = false;
+static bool g_GL_ARB_shader_objects      = false;
+static bool g_GL_ARB_fragment_shader     = false;
+static bool g_GL_ARB_pixel_buffer_object = false;
+static bool g_GL_ARB_texture_rectangle   = false;
+static bool g_GL_EXT_texture_rectangle   = false;
+static bool g_GL_NV_texture_rectangle         = false;
+static bool g_GL_ARB_texture_non_power_of_two = false;
+
+/* gl features supported */
+static bool g_vboxVHWAGlShaderSupported = false;
+static bool g_vboxVHWAGlTextureRectangleSupported = false;
+static bool g_vboxVHWAGlTextureNP2Supported = false;
+static bool g_vboxVHWAGlPBOSupported = false;
+static int g_vboxVHWAGlMultiTexNumSupported = 1; /* 1 would mean it is not supported */
+
+/* vhwa features supported */
+static uint32_t g_vboxVHWAFourccSupportedList[VBOXVHWA_NUMFOURCC];
+static uint32_t g_vboxVHWAFourccSupportedCount = 0;
+
+
+static int vboxVHWAGlParseSubver(const GLubyte * ver, const GLubyte ** pNext, bool bSpacePrefixAllowed)
+{
+    int val = 0;
+
+    for(;;++ver)
+    {
+        if(*ver >= '0' && *ver < '9')
+        {
+            if(!val)
+            {
+                if(*ver == '0')
+                    continue;
+            }
+            else
+            {
+                val *= 10;
+            }
+            val += *ver - '0';
+        }
+        else if(*ver == '.')
+        {
+            *pNext = ver+1;
+            break;
+        }
+        else if(*ver == '\0')
+        {
+            *pNext = NULL;
+            break;
+        }
+        else if(*ver == ' ' || *ver == '\t' ||  *ver == 0x0d || *ver == 0x0a)
+        {
+        	if(bSpacePrefixAllowed)
+        	{
+        		if(!val)
+        		{
+        			continue;
+        		}
+        	}
+
+        	/* treat this as the end ov version string */
+        	*pNext = NULL;
+            break;
+        }
+        else
+        {
+            Assert(0);
+            val = -1;
+            break;
+        }
+    }
+
+    return val;
+}
+
+static int vboxVHWAGlParseVersion(const GLubyte * ver)
+{
+    int iVer = vboxVHWAGlParseSubver(ver, &ver, true);
+    if(iVer)
+    {
+        iVer <<= 16;
+        if(ver)
+        {
+            int tmp = vboxVHWAGlParseSubver(ver, &ver, false);
+            if(tmp >= 0)
+            {
+                iVer |= tmp << 8;
+                if(ver)
+                {
+                    tmp = vboxVHWAGlParseSubver(ver, &ver, false);
+                    if(tmp >= 0)
+                    {
+                        iVer |= tmp;
+                    }
+                    else
+                    {
+                        Assert(0);
+                        iVer = -1;
+                    }
+                }
+            }
+            else
+            {
+                Assert(0);
+                iVer = -1;
+            }
+        }
+    }
+    return iVer;
+}
+
+static void vboxVHWAGlInitExtSupport(const QGLContext & context)
+{
+    int rc = 0;
+    do
+    {
+    	rc = 0;
+    	g_vboxVHWAGlMultiTexNumSupported = 1; /* default, 1 means not supported */
+		if(g_vboxVHWAGlVersion >= 0x010201) /* ogl >= 1.2.1 */
+		{
+			VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_ACTIVE_TEXTURE, ActiveTexture, rc);
+			VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_MULTI_TEX_COORD2I, MultiTexCoord2i, rc);
+			VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_MULTI_TEX_COORD2D, MultiTexCoord2d, rc);
+			VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_MULTI_TEX_COORD2F, MultiTexCoord2f, rc);
+		}
+		else if(g_GL_ARB_multitexture)
+		{
+			VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_ACTIVE_TEXTURE, ActiveTexture, rc);
+			VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_MULTI_TEX_COORD2I, MultiTexCoord2i, rc);
+			VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_MULTI_TEX_COORD2D, MultiTexCoord2d, rc);
+			VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_MULTI_TEX_COORD2F, MultiTexCoord2f, rc);
+		}
+		else
+		{
+			break;
+		}
+
+		if(RT_FAILURE(rc))
+		    break;
+
+        GLint maxCoords, maxUnits;
+        glGetIntegerv(GL_MAX_TEXTURE_COORDS, &maxCoords);
+        glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxUnits);
+
+        VBOXQGLLOG(("Max Tex Coords (%d), Img Units (%d)\n", maxCoords, maxUnits));
+        /* take the minimum of those */
+        if(maxUnits < maxCoords)
+        	maxCoords = maxUnits;
+        if(maxUnits < 2)
+        {
+            VBOXQGLLOG(("Max Tex Coord or Img Units < 2 disabling MultiTex support\n"));
+        	break;
+        }
+
+        g_vboxVHWAGlMultiTexNumSupported = maxUnits;
+    }while(0);
+
+
+    do
+    {
+    	rc = 0;
+    	g_vboxVHWAGlPBOSupported = false;
+
+		if(g_GL_ARB_pixel_buffer_object)
+		{
+			VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_GEN_BUFFERS, GenBuffers, rc);
+			VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_DELETE_BUFFERS, DeleteBuffers, rc);
+			VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_BIND_BUFFER, BindBuffer, rc);
+			VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_BUFFER_DATA, BufferData, rc);
+			VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_MAP_BUFFER, MapBuffer, rc);
+			VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_UNMAP_BUFFER, UnmapBuffer, rc);
+		}
+		else
+		{
+		    break;
+		}
+
+		if(RT_FAILURE(rc))
+		    break;
+
+		g_vboxVHWAGlPBOSupported = true;
+    } while(0);
+
+    do
+    {
+        rc = 0;
+        g_vboxVHWAGlShaderSupported = false;
+
+        if(g_vboxVHWAGlVersion >= 0x020000)  /* if ogl >= 2.0*/
+        {
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_CREATE_SHADER, CreateShader, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_SHADER_SOURCE, ShaderSource, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_COMPILE_SHADER, CompileShader, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_DELETE_SHADER, DeleteShader, rc);
+
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_CREATE_PROGRAM, CreateProgram, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_ATTACH_SHADER, AttachShader, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_DETACH_SHADER, DetachShader, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_LINK_PROGRAM, LinkProgram, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_USE_PROGRAM, UseProgram, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_DELETE_PROGRAM, DeleteProgram, rc);
+
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_IS_SHADER, IsShader, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_GET_SHADERIV, GetShaderiv, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_IS_PROGRAM, IsProgram, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_GET_PROGRAMIV, GetProgramiv, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_GET_ATTACHED_SHADERS, GetAttachedShaders,  rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_GET_SHADER_INFO_LOG, GetShaderInfoLog, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_GET_PROGRAM_INFO_LOG, GetProgramInfoLog, rc);
+
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_GET_UNIFORM_LOCATION, GetUniformLocation, rc);
+
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_UNIFORM1F, Uniform1f, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_UNIFORM2F, Uniform2f, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_UNIFORM3F, Uniform3f, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_UNIFORM4F, Uniform4f, rc);
+
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_UNIFORM1I, Uniform1i, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_UNIFORM2I, Uniform2i, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_UNIFORM3I, Uniform3i, rc);
+            VBOXVHWA_PFNINIT_SAME(context, PFNVBOXVHWA_UNIFORM4I, Uniform4i, rc);
+        }
+        else if(g_GL_ARB_shader_objects && g_GL_ARB_fragment_shader)
+        {
+            VBOXVHWA_PFNINIT_OBJECT_ARB(context, PFNVBOXVHWA_CREATE_SHADER, CreateShader, rc);
+            VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_SHADER_SOURCE, ShaderSource, rc);
+            VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_COMPILE_SHADER, CompileShader, rc);
+            VBOXVHWA_PFNINIT(context, PFNVBOXVHWA_DELETE_SHADER, DeleteShader, DeleteObjectARB, rc);
+
+            VBOXVHWA_PFNINIT_OBJECT_ARB(context, PFNVBOXVHWA_CREATE_PROGRAM, CreateProgram, rc);
+            VBOXVHWA_PFNINIT(context, PFNVBOXVHWA_ATTACH_SHADER, AttachShader, AttachObjectARB, rc);
+            VBOXVHWA_PFNINIT(context, PFNVBOXVHWA_DETACH_SHADER, DetachShader, DetachObjectARB, rc);
+            VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_LINK_PROGRAM, LinkProgram, rc);
+            VBOXVHWA_PFNINIT_OBJECT_ARB(context, PFNVBOXVHWA_USE_PROGRAM, UseProgram, rc);
+            VBOXVHWA_PFNINIT(context, PFNVBOXVHWA_DELETE_PROGRAM, DeleteProgram, DeleteObjectARB, rc);
+
+        //TODO:    VBOXVHWA_PFNINIT(PFNVBOXVHWA_IS_SHADER, IsShader, rc);
+            VBOXVHWA_PFNINIT(context, PFNVBOXVHWA_GET_SHADERIV, GetShaderiv, GetObjectParameterivARB, rc);
+        //TODO:    VBOXVHWA_PFNINIT(PFNVBOXVHWA_IS_PROGRAM, IsProgram, rc);
+            VBOXVHWA_PFNINIT(context, PFNVBOXVHWA_GET_PROGRAMIV, GetProgramiv, GetObjectParameterivARB, rc);
+            VBOXVHWA_PFNINIT(context, PFNVBOXVHWA_GET_ATTACHED_SHADERS, GetAttachedShaders, GetAttachedObjectsARB, rc);
+            VBOXVHWA_PFNINIT(context, PFNVBOXVHWA_GET_SHADER_INFO_LOG, GetShaderInfoLog, GetInfoLogARB, rc);
+            VBOXVHWA_PFNINIT(context, PFNVBOXVHWA_GET_PROGRAM_INFO_LOG, GetProgramInfoLog, GetInfoLogARB, rc);
+
+            VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_GET_UNIFORM_LOCATION, GetUniformLocation, rc);
+
+            VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_UNIFORM1F, Uniform1f, rc);
+            VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_UNIFORM2F, Uniform2f, rc);
+            VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_UNIFORM3F, Uniform3f, rc);
+            VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_UNIFORM4F, Uniform4f, rc);
+
+            VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_UNIFORM1I, Uniform1i, rc);
+            VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_UNIFORM2I, Uniform2i, rc);
+            VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_UNIFORM3I, Uniform3i, rc);
+            VBOXVHWA_PFNINIT_ARB(context, PFNVBOXVHWA_UNIFORM4I, Uniform4i, rc);
+        }
+        else
+        {
+            break;
+        }
+
+        if(RT_FAILURE(rc))
+            break;
+
+        g_vboxVHWAGlShaderSupported = true;
+    } while(0);
+
+    if(g_GL_ARB_texture_rectangle || g_GL_EXT_texture_rectangle || g_GL_NV_texture_rectangle)
+    {
+        g_vboxVHWAGlTextureRectangleSupported = true;
+    }
+    else
+    {
+        g_vboxVHWAGlTextureRectangleSupported = false;
+    }
+
+    g_vboxVHWAGlTextureNP2Supported = g_GL_ARB_texture_non_power_of_two;
+}
+
+static void vboxVHWAGlInitFeatureSupport()
+{
+    if(g_vboxVHWAGlShaderSupported && g_vboxVHWAGlTextureRectangleSupported)
+    {
+        uint32_t num = 0;
+        g_vboxVHWAFourccSupportedList[num++] = FOURCC_AYUV;
+        g_vboxVHWAFourccSupportedList[num++] = FOURCC_UYVY;
+        g_vboxVHWAFourccSupportedList[num++] = FOURCC_YUY2;
+        if(g_vboxVHWAGlMultiTexNumSupported >= 4)
+        {
+            /* YV12 currently requires 3 units (for each color component)
+             * + 1 unit for dst texture for color-keying + 3 units for each color component
+             * TODO: we could store YV12 data in one texture to eliminate this requirement*/
+            g_vboxVHWAFourccSupportedList[num++] = FOURCC_YV12;
+        }
+
+        Assert(num <= VBOXVHWA_NUMFOURCC);
+        g_vboxVHWAFourccSupportedCount = num;
+    }
+    else
+    {
+        g_vboxVHWAFourccSupportedCount = 0;
+    }
+}
+
+static void vboxVHWAGlInit(const QGLContext * pContext)
+{
+    if(g_vboxVHWAGlSupportInitialized)
+        return;
+
+    static QGLWidget *pTmpContextHolder = NULL;
+    const bool bHasGlContext = (pContext != NULL);
+
+    if(!pContext)
+    {
+        if(!pTmpContextHolder)
+        {
+            QGLWidget *pWidget = new QGLWidget();
+            pWidget->makeCurrent();
+            pContext = pWidget->context();
+            pTmpContextHolder = pWidget;
+        }
+
+//        QGLContext * pTmpContext = new QGLContext(QGLFormat::defaultFormat());
+//        bool bCreated = pTmpContext->create();
+//        Assert(pTmpContext);
+//        Assert(pTmpContext->isValid());
+//
+//        pTmpContext->makeCurrent();
+//        pTmpContextHolder = pTmpContext;
+    }
+
+    const GLubyte * str;
+    VBOXQGL_CHECKERR(
+            str = glGetString(GL_VERSION);
+            );
+
+    VBOXQGLLOG (("gl version string: 0%s\n", str));
+
+    g_vboxVHWAGlVersion = vboxVHWAGlParseVersion(str);
+    Assert(g_vboxVHWAGlVersion > 0);
+    if(g_vboxVHWAGlVersion < 0)
+    {
+        g_vboxVHWAGlVersion = 0;
+    }
+    else
+    {
+        VBOXQGLLOG (("gl version: 0x%x\n", g_vboxVHWAGlVersion));
+        VBOXQGL_CHECKERR(
+                str = glGetString(GL_EXTENSIONS);
+                );
+
+        const char * pos = strstr((const char *)str, "GL_ARB_multitexture");
+        g_GL_ARB_multitexture = pos != NULL;
+        VBOXQGLLOG (("GL_ARB_multitexture: %d\n", g_GL_ARB_multitexture));
+
+        pos = strstr((const char *)str, "GL_ARB_shader_objects");
+        g_GL_ARB_shader_objects = pos != NULL;
+        VBOXQGLLOG (("GL_ARB_shader_objects: %d\n", g_GL_ARB_shader_objects));
+
+        pos = strstr((const char *)str, "GL_ARB_fragment_shader");
+        g_GL_ARB_fragment_shader = pos != NULL;
+        VBOXQGLLOG (("GL_ARB_fragment_shader: %d\n", g_GL_ARB_fragment_shader));
+
+        pos = strstr((const char *)str, "GL_ARB_pixel_buffer_object");
+        g_GL_ARB_pixel_buffer_object = pos != NULL;
+        VBOXQGLLOG (("GL_ARB_pixel_buffer_object: %d\n", g_GL_ARB_pixel_buffer_object));
+
+        pos = strstr((const char *)str, "GL_ARB_texture_rectangle");
+        g_GL_ARB_texture_rectangle = pos != NULL;
+        VBOXQGLLOG (("GL_ARB_texture_rectangle: %d\n", g_GL_ARB_texture_rectangle));
+
+        pos = strstr((const char *)str, "GL_EXT_texture_rectangle");
+        g_GL_EXT_texture_rectangle = pos != NULL;
+        VBOXQGLLOG (("GL_EXT_texture_rectangle: %d\n", g_GL_EXT_texture_rectangle));
+
+        pos = strstr((const char *)str, "GL_NV_texture_rectangle");
+        g_GL_NV_texture_rectangle = pos != NULL;
+        VBOXQGLLOG (("GL_NV_texture_rectangle: %d\n", g_GL_NV_texture_rectangle));
+
+        pos = strstr((const char *)str, "GL_ARB_texture_non_power_of_two");
+        g_GL_ARB_texture_non_power_of_two = pos != NULL;
+        VBOXQGLLOG (("GL_ARB_texture_non_power_of_two: %d\n", g_GL_ARB_texture_non_power_of_two));
+
+        vboxVHWAGlInitExtSupport(*pContext);
+
+        vboxVHWAGlInitFeatureSupport();
+    }
+
+    if(!bHasGlContext)
+    {
+        pTmpContextHolder->doneCurrent();
+    }
+
+    g_vboxVHWAGlSupportInitialized = true;
+}
+
+static bool vboxVHWASupportedInternal()
+{
+    if(g_vboxVHWAGlVersion <= 0)
+    {
+        /* error occurred while gl info initialization */
+        return false;
+    }
+
+#ifndef DEBUG
+    /* in case we do not support shaders & multitexturing we can not supprt dst colorkey,
+     * no sense to report Video Acceleration supported */
+    if(!g_vboxVHWAGlShaderSupported)
+        return false;
+#endif
+    if(g_vboxVHWAGlMultiTexNumSupported < 2)
+        return false;
+
+    /* color conversion now supported only GL_TEXTURE_RECTANGLE
+     * in this case only stretching is accelerated
+     * report as unsupported, TODO: probably should report as supported for stretch acceleration */
+    if(!g_vboxVHWAGlTextureRectangleSupported)
+        return false;
+
+    return true;
+}
+
+class VBoxVHWACommandProcessEvent : public QEvent
+{
+public:
+    VBoxVHWACommandProcessEvent (VBoxVHWACommandElement *pEl)
+        : QEvent ((QEvent::Type) VBoxDefs::VHWACommandProcessType)
+    {
+        mCmdPipe.put(pEl);
+    }
+    VBoxVHWACommandElementPipe & pipe() { return mCmdPipe; }
+private:
+    VBoxVHWACommandElementPipe mCmdPipe;
+    VBoxVHWACommandProcessEvent *mpNext;
+
+    friend class VBoxGLWidget;
+};
+
+
+
+VBoxVHWAHandleTable::VBoxVHWAHandleTable(uint32_t initialSize)
+{
+    mTable = new void*[initialSize];
+    memset(mTable, 0, initialSize*sizeof(void*));
+    mcSize = initialSize;
+    mcUsage = 0;
+    mCursor = 1; /* 0 is treated as invalid */
+}
+
+VBoxVHWAHandleTable::~VBoxVHWAHandleTable()
+{
+    delete[] mTable;
+}
+
+uint32_t VBoxVHWAHandleTable::put(void * data)
+{
+    Assert(data);
+    if(!data)
+        return VBOXVHWA_SURFHANDLE_INVALID;
+
+    if(mcUsage == mcSize)
+    {
+        /* @todo: resize */
+        Assert(0);
+    }
+
+    Assert(mcUsage < mcSize);
+    if(mcUsage >= mcSize)
+        return VBOXVHWA_SURFHANDLE_INVALID;
+
+    for(int k = 0; k < 2; ++k)
+    {
+        Assert(mCursor != 0);
+        for(uint32_t i = mCursor; i < mcSize; ++i)
+        {
+            if(!mTable[i])
+            {
+                doPut(i, data);
+                mCursor = i+1;
+                return i;
+            }
+        }
+        mCursor = 1; /* 0 is treated as invalid */
+    }
+
+    Assert(0);
+    return VBOXVHWA_SURFHANDLE_INVALID;
+}
+
+bool VBoxVHWAHandleTable::mapPut(uint32_t h, void * data)
+{
+    if(mcSize <= h)
+        return false;
+    if(h == 0)
+        return false;
+    if(mTable[h])
+        return false;
+
+    doPut(h, data);
+    return true;
+}
+
+void* VBoxVHWAHandleTable::get(uint32_t h)
+{
+    Assert(h < mcSize);
+    Assert(h > 0);
+    return mTable[h];
+}
+
+void* VBoxVHWAHandleTable::remove(uint32_t h)
+{
+    Assert(mcUsage);
+    Assert(h < mcSize);
+    void* val = mTable[h];
+    Assert(val);
+    if(val)
+    {
+        doRemove(h);
+    }
+    return val;
+}
+
+void VBoxVHWAHandleTable::doPut(uint32_t h, void * data)
+{
+    ++mcUsage;
+    mTable[h] = data;
+}
+
+void VBoxVHWAHandleTable::doRemove(uint32_t h)
+{
+    mTable[h] = 0;
+    --mcUsage;
+}
+
+static VBoxVHWATexture* vboxVHWATextureCreate(const QRect & aRect, const VBoxVHWAColorFormat & aFormat, bool bVGA)
+{
+	if(!bVGA && g_GL_ARB_pixel_buffer_object)
+	{
+		VBOXQGLLOG(("VBoxVHWATextureNP2RectPBO\n"));
+		return new VBoxVHWATextureNP2RectPBO(aRect, aFormat);
+	}
+	else if(g_vboxVHWAGlTextureRectangleSupported)
+	{
+		VBOXQGLLOG(("VBoxVHWATextureNP2Rect\n"));
+		return new VBoxVHWATextureNP2Rect(aRect, aFormat);
+	}
+	else if(g_GL_ARB_texture_non_power_of_two)
+	{
+		VBOXQGLLOG(("VBoxVHWATextureNP2\n"));
+		return new VBoxVHWATextureNP2(aRect, aFormat);
+	}
+	VBOXQGLLOG(("VBoxVHWATexture\n"));
+	return new VBoxVHWATexture(aRect, aFormat);
+}
+
+class VBoxVHWAGlShader
+{
+public:
+    VBoxVHWAGlShader(const char *aRcName, GLenum aType) :
+        mShader(0),
+        mRcName(aRcName),
+        mType(aType)
+    {}
+
+//    virtual ~VBoxVHWAGlShader();
+
+    int init();
+//    virtual int initUniforms(class VBoxVHWAGlProgram * pProgram){}
+    void uninit();
+    bool isInitialized() { return mShader; }
+    GLuint shader() {return mShader;}
+private:
+    GLuint mShader;
+    const char *mRcName;
+    GLenum mType;
+};
+
+int VBoxVHWAGlShader::init()
+{
+//    Assert(!isInitialized());
+    if(isInitialized())
+        return VINF_ALREADY_INITIALIZED;
+
+    QFile fi(mRcName);
+    if (!fi.open(QIODevice::ReadOnly))
+    {
+        Assert(0);
+        return VERR_GENERAL_FAILURE;
+    }
+
+    QTextStream is(&fi);
+    QString program = is.readAll();
+
+    mShader = vboxglCreateShader(mType);
+    Assert(mShader);
+    if(!mShader)
+        return VERR_GENERAL_FAILURE;
+
+ //   int length = program.length();
+    QByteArray asciiStr = program.toAscii();
+    const char * contents = asciiStr.constData();
+    GLint length = (GLint)strlen(contents) + 1;
+
+    VBOXQGL_CHECKERR(
+            vboxglShaderSource(mShader, 1, &contents, &length);
+            );
+
+    VBOXQGL_CHECKERR(
+            vboxglCompileShader(mShader);
+            );
+
+    GLint compiled;
+    VBOXQGL_CHECKERR(
+            vboxglGetShaderiv(mShader, GL_COMPILE_STATUS, &compiled);
+            );
+
+#ifdef DEBUG
+    GLchar * pBuf = new GLchar[16300];
+    vboxglGetShaderInfoLog(mShader, 16300, NULL, pBuf);
+    VBOXQGLLOG(("compile log for shader:\n-----------\n%s\n---------\n", contents));
+    VBOXQGLLOG(("%s\n**********\n", pBuf));
+    delete pBuf;
+#endif
+
+    Assert(compiled);
+    if(compiled)
+    {
+        return VINF_SUCCESS;
+    }
+
+
+
+    VBOXQGL_CHECKERR(
+            vboxglDeleteShader(mShader);
+            );
+    mShader = 0;
+    return VERR_GENERAL_FAILURE;
+}
+
+void VBoxVHWAGlShader::uninit()
+{
+    if(!isInitialized())
+        return;
+
+    VBOXQGL_CHECKERR(
+            vboxglDeleteShader(mShader);
+            );
+    mShader = 0;
+}
+
+class VBoxVHWAGlProgram
+{
+public:
+    VBoxVHWAGlProgram(VBoxVHWAGlShader ** apShaders, int acShaders);
+
+    ~VBoxVHWAGlProgram();
+
+    virtual int init();
+    virtual void uninit();
+    virtual int start();
+    virtual int stop();
+    bool isInitialized() { return mProgram; }
+    GLuint program() {return mProgram;}
+private:
+    GLuint mProgram;
+    VBoxVHWAGlShader ** mpShaders;
+    int mcShaders;
+};
+
+VBoxVHWAGlProgram::VBoxVHWAGlProgram(VBoxVHWAGlShader ** apShaders, int acShaders) :
+       mProgram(0),
+       mpShaders(NULL),
+       mcShaders(0)
+{
+    Assert(acShaders);
+    if(acShaders)
+    {
+        mpShaders = (VBoxVHWAGlShader **)malloc(sizeof(VBoxVHWAGlShader *) * acShaders);
+        memcpy(mpShaders, apShaders, sizeof(VBoxVHWAGlShader *) * acShaders);
+        mcShaders = acShaders;
+    }
+}
+
+VBoxVHWAGlProgram::~VBoxVHWAGlProgram()
+{
+    uninit();
+
+    if(mpShaders)
+    {
+        free(mpShaders);
+    }
+}
+
+int VBoxVHWAGlProgram::init()
+{
+    Assert(!isInitialized());
+    if(isInitialized())
+        return VINF_ALREADY_INITIALIZED;
+
+    Assert(mcShaders);
+    if(!mcShaders)
+        return VERR_GENERAL_FAILURE;
+
+    int rc = VINF_SUCCESS;
+    for(int i = 0; i < mcShaders; i++)
+    {
+        int rc = mpShaders[i]->init();
+        Assert(RT_SUCCESS(rc));
+        if(RT_FAILURE(rc))
+        {
+            break;
+        }
+    }
+    if(RT_FAILURE(rc))
+    {
+        return rc;
+    }
+
+    mProgram = vboxglCreateProgram();
+    Assert(mProgram);
+    if(mProgram)
+    {
+        for(int i = 0; i < mcShaders; i++)
+        {
+            VBOXQGL_CHECKERR(
+                    vboxglAttachShader(mProgram, mpShaders[i]->shader());
+                    );
+        }
+
+        VBOXQGL_CHECKERR(
+                vboxglLinkProgram(mProgram);
+                );
+
+
+        GLint linked;
+        vboxglGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+
+#ifdef DEBUG
+        GLchar * pBuf = new GLchar[16300];
+        vboxglGetProgramInfoLog(mProgram, 16300, NULL, pBuf);
+        VBOXQGLLOG(("link log: %s\n", pBuf));
+        Assert(linked);
+        delete pBuf;
+#endif
+
+        if(linked)
+        {
+            return VINF_SUCCESS;
+        }
+
+        VBOXQGL_CHECKERR(
+                vboxglDeleteProgram(mProgram);
+                );
+        mProgram = 0;
+    }
+    return VERR_GENERAL_FAILURE;
+}
+
+void VBoxVHWAGlProgram::uninit()
+{
+    if(!isInitialized())
+        return;
+
+    VBOXQGL_CHECKERR(
+            vboxglDeleteProgram(mProgram);
+            );
+    mProgram = 0;
+}
+
+int VBoxVHWAGlProgram::start()
+{
+    VBOXQGL_CHECKERR(
+            vboxglUseProgram(mProgram);
+            );
+    return VINF_SUCCESS;
+}
+
+int VBoxVHWAGlProgram::stop()
+{
+    VBOXQGL_CHECKERR(
+            vboxglUseProgram(0);
+            );
+    return VINF_SUCCESS;
+}
+
+#define VBOXVHWA_PROGRAM_DSTCOLORKEY  0x00000001
+#define VBOXVHWA_PROGRAM_SRCCOLORKEY  0x00000002
+#define VBOXVHWA_PROGRAM_COLORCONV    0x00000004
+
+class VBoxVHWAGlProgramVHWA : public VBoxVHWAGlProgram
+{
+public:
+    VBoxVHWAGlProgramVHWA(/*class VBoxVHWAGlProgramMngr *aMngr, */uint32_t type, uint32_t fourcc, VBoxVHWAGlShader ** apShaders, int acShaders);
+
+    uint32_t type() const {return mType;}
+    uint32_t fourcc() const {return mFourcc;}
+
+    int setDstCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b);
+
+    int setDstCKeyLowerRange(GLfloat r, GLfloat g, GLfloat b);
+
+    int setSrcCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b);
+
+    int setSrcCKeyLowerRange(GLfloat r, GLfloat g, GLfloat b);
+
+
+    virtual int init();
+
+    bool matches(uint32_t type, uint32_t fourcc)
+    {
+        return mType == type && mFourcc == fourcc;
+    }
+
+    bool equals(const VBoxVHWAGlProgramVHWA & other)
+    {
+        return matches(other.mType, other.mFourcc);
+    }
+
+private:
+    uint32_t mType;
+    uint32_t mFourcc;
+
+    GLfloat mDstUpperR, mDstUpperG, mDstUpperB;
+    GLint mUniDstUpperColor;
+
+    GLfloat mDstLowerR, mDstLowerG, mDstLowerB;
+    GLint mUniDstLowerColor;
+
+    GLfloat mSrcUpperR, mSrcUpperG, mSrcUpperB;
+    GLint mUniSrcUpperColor;
+
+    GLfloat mSrcLowerR, mSrcLowerG, mSrcLowerB;
+    GLint mUniSrcLowerColor;
+
+    GLint mDstTex;
+    GLint mUniDstTex;
+
+    GLint mSrcTex;
+    GLint mUniSrcTex;
+
+    GLint mVTex;
+    GLint mUniVTex;
+
+    GLint mUTex;
+    GLint mUniUTex;
+
+//    VBoxVHWAGlProgram *mpProgram;
+//
+//    class VBoxVHWAGlProgramMngr *mpMngr;
+};
+
+VBoxVHWAGlProgramVHWA::VBoxVHWAGlProgramVHWA(/*VBoxVHWAGlProgramMngr *aMngr, */uint32_t type, uint32_t fourcc, VBoxVHWAGlShader ** apShaders, int acShaders) :
+    VBoxVHWAGlProgram(apShaders, acShaders),
+    mType(type),
+    mFourcc(fourcc),
+    mDstUpperR(0.0), mDstUpperG(0.0), mDstUpperB(0.0),
+    mUniDstUpperColor(-1),
+    mDstLowerR(0.0), mDstLowerG(0.0), mDstLowerB(0.0),
+    mUniDstLowerColor(-1),
+    mSrcUpperR(0.0), mSrcUpperG(0.0), mSrcUpperB(0.0),
+    mUniSrcUpperColor(-1),
+    mSrcLowerR(0.0), mSrcLowerG(0.0), mSrcLowerB(0.0),
+    mUniSrcLowerColor(-1),
+//    mpMngr(aMngr),
+    mDstTex(-1),
+    mUniDstTex(-1),
+    mSrcTex(-1),
+    mUniSrcTex(-1),
+    mVTex(-1),
+    mUniVTex(-1),
+    mUTex(-1),
+    mUniUTex(-1)
+{}
+
+int VBoxVHWAGlProgramVHWA::init()
+{
+    int rc = VBoxVHWAGlProgram::init();
+    if(RT_FAILURE(rc))
+        return rc;
+    if(rc == VINF_ALREADY_INITIALIZED)
+        return rc;
+
+    start();
+
+    rc = VERR_GENERAL_FAILURE;
+
+    do
+    {
+        mUniSrcTex = vboxglGetUniformLocation(program(), "uSrcTex");
+        Assert(mUniSrcTex != -1);
+        if(mUniSrcTex == -1)
+            break;
+        if(type() & VBOXVHWA_PROGRAM_DSTCOLORKEY)
+        {
+            VBOXQGL_CHECKERR(
+                    vboxglUniform1i(mUniSrcTex, 1);
+                    );
+            mSrcTex = 1;
+
+            mUniDstTex = vboxglGetUniformLocation(program(), "uDstTex");
+            Assert(mUniDstTex != -1);
+            if(mUniDstTex == -1)
+                break;
+            VBOXQGL_CHECKERR(
+                    vboxglUniform1i(mUniDstTex, 0);
+                    );
+            mDstTex = 0;
+            mUniDstLowerColor = vboxglGetUniformLocation(program(), "uDstClr");
+            Assert(mUniDstLowerColor != -1);
+            if(mUniDstLowerColor == -1)
+                break;
+
+            mDstLowerR = 0.0; mDstLowerG = 0.0; mDstLowerB = 0.0;
+
+            VBOXQGL_CHECKERR(
+                    vboxglUniform4f(mUniDstLowerColor, 0.0, 0.0, 0.0, 0.0);
+                    );
+        }
+        else
+        {
+            VBOXQGL_CHECKERR(
+                    vboxglUniform1i(mUniSrcTex, 1);
+                    );
+            mSrcTex = 0;
+        }
+
+        if(type() & VBOXVHWA_PROGRAM_SRCCOLORKEY)
+        {
+            mUniSrcLowerColor = vboxglGetUniformLocation(program(), "uSrcClr");
+            Assert(mUniSrcLowerColor != -1);
+            if(mUniSrcLowerColor == -1)
+                break;
+
+            mSrcLowerR = 0.0; mSrcLowerG = 0.0; mSrcLowerB = 0.0;
+            VBOXQGL_CHECKERR(
+                    vboxglUniform4f(mUniSrcLowerColor, 0.0, 0.0, 0.0, 0.0);
+                    );
+        }
+
+        if(type() & VBOXVHWA_PROGRAM_COLORCONV)
+        {
+            switch(fourcc())
+            {
+                case FOURCC_YV12:
+                {
+                    GLint tex = mSrcTex + 1;
+
+                    mUniVTex = vboxglGetUniformLocation(program(), "uVTex");
+
+                    Assert(mUniVTex != -1);
+                    if(mUniVTex == -1)
+                        break;
+
+                    VBOXQGL_CHECKERR(
+                            vboxglUniform1i(mUniVTex, tex);
+                            );
+                    mVTex = tex;
+
+                    tex++;
+
+                    mUniUTex = vboxglGetUniformLocation(program(), "uUTex");
+                    Assert(mUniUTex != -1);
+                    if(mUniUTex == -1)
+                        break;
+
+                    VBOXQGL_CHECKERR(
+                            vboxglUniform1i(mUniUTex, tex);
+                            );
+                    mUTex = tex;
+
+                    break;
+                }
+                case FOURCC_UYVY:
+                case FOURCC_YUY2:
+                case FOURCC_AYUV:
+                    break;
+                default:
+                    Assert(0);
+                    break;
+            }
+        }
+
+        rc = VINF_SUCCESS;
+    } while(0);
+
+
+    stop();
+    if(rc == VINF_SUCCESS)
+        return VINF_SUCCESS;
+
+    Assert(0);
+    VBoxVHWAGlProgram::uninit();
+    return VERR_GENERAL_FAILURE;
+}
+
+int VBoxVHWAGlProgramVHWA::setDstCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b)
+{
+    Assert(isInitialized());
+    if(!isInitialized())
+        return VERR_GENERAL_FAILURE;
+    if(mDstUpperR == r && mDstUpperG == g && mDstUpperB == b)
+        return VINF_ALREADY_INITIALIZED;
+    vboxglUniform4f(mUniDstUpperColor, r, g, b, 0.0);
+    mDstUpperR = r;
+    mDstUpperG = g;
+    mDstUpperB = b;
+    return VINF_SUCCESS;
+}
+
+int VBoxVHWAGlProgramVHWA::setDstCKeyLowerRange(GLfloat r, GLfloat g, GLfloat b)
+{
+    Assert(isInitialized());
+    if(!isInitialized())
+        return VERR_GENERAL_FAILURE;
+    if(mDstLowerR == r && mDstLowerG == g && mDstLowerB == b)
+        return VINF_ALREADY_INITIALIZED;
+
+//    VBOXQGLLOG(("setDstCKeyLowerRange: r(%f), g(%f), b(%f)\n", r, g, b));
+    VBOXQGL_CHECKERR(
+            vboxglUniform4f(mUniDstLowerColor, r, g, b, 0.0);
+            );
+
+    mDstLowerR = r;
+    mDstLowerG = g;
+    mDstLowerB = b;
+    return VINF_SUCCESS;
+}
+
+int VBoxVHWAGlProgramVHWA::setSrcCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b)
+{
+    Assert(isInitialized());
+    if(!isInitialized())
+        return VERR_GENERAL_FAILURE;
+    if(mSrcUpperR == r && mSrcUpperG == g && mSrcUpperB == b)
+        return VINF_ALREADY_INITIALIZED;
+    vboxglUniform4f(mUniSrcUpperColor, r, g, b, 0.0);
+    mSrcUpperR = r;
+    mSrcUpperG = g;
+    mSrcUpperB = b;
+    return VINF_SUCCESS;
+}
+
+int VBoxVHWAGlProgramVHWA::setSrcCKeyLowerRange(GLfloat r, GLfloat g, GLfloat b)
+{
+    Assert(isInitialized());
+    if(!isInitialized())
+        return VERR_GENERAL_FAILURE;
+    if(mSrcLowerR == r && mSrcLowerG == g && mSrcLowerB == b)
+        return VINF_ALREADY_INITIALIZED;
+    VBOXQGL_CHECKERR(
+            vboxglUniform4f(mUniSrcLowerColor, r, g, b, 0.0);
+            );
+    mSrcLowerR = r;
+    mSrcLowerG = g;
+    mSrcLowerB = b;
+    return VINF_SUCCESS;
+}
+
+class VBoxVHWAGlProgramMngr
+{
+public:
+    VBoxVHWAGlProgramMngr() :
+        mShaderCConvApplyAYUV(":/cconvApplyAYUV.c", GL_FRAGMENT_SHADER),
+        mShaderCConvAYUV(":/cconvAYUV.c", GL_FRAGMENT_SHADER),
+        mShaderCConvAYUVVoid(":/cconvAYUV_void.c", GL_FRAGMENT_SHADER),
+        mShaderCConvBGR(":/cconvBGR.c", GL_FRAGMENT_SHADER),
+        mShaderCConvBGRVoid(":/cconvBGR_void.c", GL_FRAGMENT_SHADER),
+        mShaderCConvUYVY(":/cconvUYVY.c", GL_FRAGMENT_SHADER),
+        mShaderCConvUYVYVoid(":/cconvUYVY_void.c", GL_FRAGMENT_SHADER),
+        mShaderCConvYUY2(":/cconvYUY2.c", GL_FRAGMENT_SHADER),
+        mShaderCConvYUY2Void(":/cconvYUY2_void.c", GL_FRAGMENT_SHADER),
+        mShaderCConvYV12(":/cconvYV12.c", GL_FRAGMENT_SHADER),
+        mShaderCConvYV12Void(":/cconvYV12_void.c", GL_FRAGMENT_SHADER),
+        mShaderSplitBGRA(":/splitBGRA.c", GL_FRAGMENT_SHADER),
+        mShaderCKeyDst(":/ckeyDst.c", GL_FRAGMENT_SHADER),
+        mShaderCKeyDstVoid(":/ckeyDst_void.c", GL_FRAGMENT_SHADER),
+    //  mShaderCKeySrc;
+    //  mShaderCKeySrcVoid;
+        mShaderMainOverlay(":/mainOverlay.c", GL_FRAGMENT_SHADER)
+    {}
+
+    VBoxVHWAGlProgramVHWA * getProgram(bool bDstCKey, bool bSrcCKey, const VBoxVHWAColorFormat * pFrom, const VBoxVHWAColorFormat * pTo);
+
+    void stopCurrentProgram()
+    {
+        VBOXQGL_CHECKERR(
+            vboxglUseProgram(0);
+            );
+    }
+private:
+    VBoxVHWAGlProgramVHWA * searchProgram(uint32_t type, uint32_t fourcc, bool bCreate);
+
+    VBoxVHWAGlProgramVHWA * createProgram(uint32_t type, uint32_t fourcc);
+
+//    int startProgram(VBoxVHWAGlProgramVHWA * pProgram) {mCurrentProgram = pProgram; return pProgram->start();}
+
+    typedef std::list <VBoxVHWAGlProgramVHWA*> ProgramList;
+
+//    VBoxVHWAGlProgramVHWA * mCurrentProgram;
+    ProgramList mPrograms;
+
+    VBoxVHWAGlShader mShaderCConvApplyAYUV;
+
+    VBoxVHWAGlShader mShaderCConvAYUV;
+    VBoxVHWAGlShader mShaderCConvAYUVVoid;
+    VBoxVHWAGlShader mShaderCConvBGR;
+    VBoxVHWAGlShader mShaderCConvBGRVoid;
+    VBoxVHWAGlShader mShaderCConvUYVY;
+    VBoxVHWAGlShader mShaderCConvUYVYVoid;
+    VBoxVHWAGlShader mShaderCConvYUY2;
+    VBoxVHWAGlShader mShaderCConvYUY2Void;
+    VBoxVHWAGlShader mShaderCConvYV12;
+    VBoxVHWAGlShader mShaderCConvYV12Void;
+    VBoxVHWAGlShader mShaderSplitBGRA;
+
+    VBoxVHWAGlShader mShaderCKeyDst;
+    VBoxVHWAGlShader mShaderCKeyDstVoid;
+//    VBoxVHWAGlShader mShaderCKeySrc;
+//    VBoxVHWAGlShader mShaderCKeySrcVoid;
+
+    VBoxVHWAGlShader mShaderMainOverlay;
+
+    friend class VBoxVHWAGlProgramVHWA;
+};
+
+VBoxVHWAGlProgramVHWA * VBoxVHWAGlProgramMngr::createProgram(uint32_t type, uint32_t fourcc)
+{
+    VBoxVHWAGlShader * apShaders[16];
+    uint32_t cShaders = 0;
+
+    /* workaround for NVIDIA driver bug: ensure we attach the shader before those it is used in */
+    /* reserve a slot for the mShaderCConvApplyAYUV,
+     * in case it is not used the slot will be occupied by mShaderCConvBGR , which is ok */
+    cShaders++;
+
+    if(type &  VBOXVHWA_PROGRAM_DSTCOLORKEY)
+    {
+        apShaders[cShaders++] = &mShaderCKeyDst;
+    }
+    else
+    {
+        apShaders[cShaders++] = &mShaderCKeyDstVoid;
+    }
+
+    if(type & VBOXVHWA_PROGRAM_SRCCOLORKEY)
+    {
+        Assert(0);
+        /* disabled for now, not really necessary for video overlaying */
+    }
+
+    bool bFound = false;
+
+//    if(type & VBOXVHWA_PROGRAM_COLORCONV)
+    {
+        if(fourcc == FOURCC_UYVY)
+        {
+            apShaders[cShaders++] = &mShaderCConvUYVY;
+            bFound = true;
+        }
+        else
+        {
+            apShaders[cShaders++] = &mShaderCConvUYVYVoid;
+        }
+
+        if(fourcc == FOURCC_YUY2)
+        {
+            apShaders[cShaders++] = &mShaderCConvYUY2;
+            bFound = true;
+        }
+        else
+        {
+            apShaders[cShaders++] = &mShaderCConvYUY2Void;
+        }
+
+        if(fourcc == FOURCC_YV12)
+        {
+            apShaders[cShaders++] = &mShaderSplitBGRA;
+            apShaders[cShaders++] = &mShaderCConvYV12;
+            bFound = true;
+        }
+        else
+        {
+            apShaders[cShaders++] = &mShaderCConvYV12Void;
+        }
+
+        if(fourcc == FOURCC_AYUV)
+        {
+            apShaders[cShaders++] = &mShaderCConvAYUV;
+            bFound = true;
+        }
+        else
+        {
+            apShaders[cShaders++] = &mShaderCConvAYUVVoid;
+        }
+    }
+
+    if(bFound)
+    {
+        type |= VBOXVHWA_PROGRAM_COLORCONV;
+        apShaders[0] = &mShaderCConvApplyAYUV;
+        apShaders[cShaders++] = &mShaderCConvBGRVoid;
+    }
+    else
+    {
+        type &= (~VBOXVHWA_PROGRAM_COLORCONV);
+        apShaders[0] = &mShaderCConvBGR;
+    }
+
+    apShaders[cShaders++] = &mShaderMainOverlay;
+
+    Assert(cShaders <= RT_ELEMENTS(apShaders));
+
+    VBoxVHWAGlProgramVHWA *pProgram =  new VBoxVHWAGlProgramVHWA(/*this, */type, fourcc, apShaders, cShaders);
+    pProgram->init();
+
+    return pProgram;
+}
+
+VBoxVHWAGlProgramVHWA * VBoxVHWAGlProgramMngr::getProgram(bool bDstCKey, bool bSrcCKey, const VBoxVHWAColorFormat * pFrom, const VBoxVHWAColorFormat * pTo)
+{
+	Q_UNUSED(pTo);
+    uint32_t type = 0;
+    uint32_t fourcc = 0;
+    if(bDstCKey)
+    {
+        type |= VBOXVHWA_PROGRAM_DSTCOLORKEY;
+    }
+    if(bSrcCKey)
+    {
+        type |= VBOXVHWA_PROGRAM_SRCCOLORKEY;
+    }
+    if(pFrom && pFrom->fourcc())
+    {
+        fourcc = pFrom->fourcc();
+        type |= VBOXVHWA_PROGRAM_COLORCONV;
+    }
+    if(type)
+        return searchProgram(type, fourcc, true);
+    return NULL;
+}
+
+VBoxVHWAGlProgramVHWA * VBoxVHWAGlProgramMngr::searchProgram(uint32_t type, uint32_t fourcc, bool bCreate)
+{
+//    if(mCurrentProgram && mCurrentProgram->matches(type))
+//        return mCurrentProgram;
+
+    for (ProgramList::const_iterator it = mPrograms.begin();
+         it != mPrograms.end(); ++ it)
+    {
+        if (!(*it)->matches(type, fourcc))
+        {
+            continue;
+        }
+        return *it;
+    }
+    if(bCreate)
+    {
+        VBoxVHWAGlProgramVHWA *pProgram = createProgram(type, fourcc);
+        if(pProgram)
+        {
+            mPrograms.push_back(pProgram);
+            return pProgram;
+        }
+    }
+    return NULL;
+}
+
+int VBoxVHWASurfaceBase::setCKey(VBoxVHWAGlProgramVHWA * pProgram, const VBoxVHWAColorFormat * pFormat, const VBoxVHWAColorKey * pCKey, bool bDst)
+{
+    float r,g,b;
+//    pProgram->start();
+//    pFormat->pixel2Normalized(pCKey->upper(), &r, &g, &b);
+//    int rcU = pProgram->setCKeyUpperRange(r, g, b);
+//    Assert(RT_SUCCESS(rcU));
+    pFormat->pixel2Normalized(pCKey->lower(), &r, &g, &b);
+    int rcL = bDst ? pProgram->setDstCKeyLowerRange(r, g, b) : pProgram->setSrcCKeyLowerRange(r, g, b);
+    Assert(RT_SUCCESS(rcL));
+//    pProgram->stop();
+
+    return RT_SUCCESS(rcL) /*&& RT_SUCCESS(rcU)*/ ? VINF_SUCCESS: VERR_GENERAL_FAILURE;
+}
+
+
+
+void VBoxVHWASurfaceBase::setAddress(uchar * addr)
+{
+    Assert(addr);
+    if(!addr) return;
+    if(addr == mAddress) return;
+
+    if(mFreeAddress)
+    {
+        free(mAddress);
+    }
+
+    mAddress = addr;
+    mFreeAddress = false;
+
+    mpTex[0]->setAddress(mAddress);
+    if(fourcc() == FOURCC_YV12)
+    {
+        uchar *pTexAddr = mAddress+mpTex[0]->memSize();
+        mpTex[1]->setAddress(pTexAddr);
+        pTexAddr = pTexAddr+mpTex[1]->memSize();
+        mpTex[2]->setAddress(pTexAddr);
+    }
+
+//    makeCurrent();
+//    updateTexture(&mRect);
+    mUpdateMem2TexRect.set(mRect);
+    Assert(!mUpdateMem2TexRect.isClear());
+    Assert(mRect.contains(mUpdateMem2TexRect.rect()));
+//    mUpdateTex2FBRect.clear();
+//    Assert(mUpdateTex2FBRect.isClear());
+}
+
+void VBoxVHWASurfaceBase::globalInit()
+{
+    VBOXQGLLOG(("globalInit\n"));
+
+//    glEnable(GL_TEXTURE_2D);
+    glEnable(GL_TEXTURE_RECTANGLE);
+
+    VBOXQGL_CHECKERR(
+            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+            );
+    VBOXQGL_CHECKERR(
+            glPixelStorei(GL_PACK_ALIGNMENT, 1);
+            );
+//
+//    VBOXQGL_CHECKERR(
+//            vboxglActiveTexture(GL_TEXTURE1);
+//        );
+//    VBOXQGL_CHECKERR(
+//            glEnable(GL_TEXTURE_2D);
+//            );
+//    VBOXQGL_CHECKERR(
+//            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+//            );
+//    VBOXQGL_CHECKERR(
+//            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+//            );
+//    VBOXQGL_CHECKERR(
+//            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+//            );
+//    VBOXQGL_CHECKERR(
+//            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+//            );
+//
+//    VBOXQGL_CHECKERR(
+//            vboxglActiveTexture(GL_TEXTURE0);
+//        );
+//    VBOXQGL_CHECKERR(
+//            glEnable(GL_TEXTURE_2D);
+//            );
+//    VBOXQGL_CHECKERR(
+//            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+//            );
+//    VBOXQGL_CHECKERR(
+//            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+//            );
+//    VBOXQGL_CHECKERR(
+//            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+//            );
+//    VBOXQGL_CHECKERR(
+//            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+//            );
+}
+
+VBoxVHWASurfaceBase::VBoxVHWASurfaceBase(class VBoxGLWidget *aWidget, const QSize * aSize, const QSize * aTargSize,
+        VBoxVHWAColorFormat & aColorFormat,
+        VBoxVHWAColorKey * pSrcBltCKey, VBoxVHWAColorKey * pDstBltCKey,
+                    VBoxVHWAColorKey * pSrcOverlayCKey, VBoxVHWAColorKey * pDstOverlayCKey,
+                    bool bVGA) :
+                mRect(0,0,aSize->width(),aSize->height()),
+                mVisibleDisplayInitialized(false),
+                mAddress(NULL),
+                mColorFormat(aColorFormat),
+                mpSrcBltCKey(NULL),
+                mpDstBltCKey(NULL),
+                mpSrcOverlayCKey(NULL),
+                mpDstOverlayCKey(NULL),
+                mpDefaultDstOverlayCKey(NULL),
+                mpDefaultSrcOverlayCKey(NULL),
+                mLockCount(0),
+                mFreeAddress(false),
+                mComplexList(NULL),
+                mWidget(aWidget),
+                mHGHandle(VBOXVHWA_SURFHANDLE_INVALID)
+#ifdef DEBUG
+                ,
+                cFlipsCurr(0),
+                cFlipsTarg(0)
+#endif
+{
+    setDstBltCKey(pDstBltCKey);
+    setSrcBltCKey(pSrcBltCKey);
+
+    setDefaultDstOverlayCKey(pDstOverlayCKey);
+    resetDefaultDstOverlayCKey();
+
+    setDefaultSrcOverlayCKey(pSrcOverlayCKey);
+    resetDefaultSrcOverlayCKey();
+
+    mpTex[0] = vboxVHWATextureCreate(QRect(0,0,aSize->width(),aSize->height()), mColorFormat, bVGA);
+    if(mColorFormat.fourcc() == FOURCC_YV12)
+    {
+        QRect rect(0,0,aSize->width()/2,aSize->height()/2);
+        mpTex[1] = vboxVHWATextureCreate(rect, mColorFormat, bVGA);
+        mpTex[2] = vboxVHWATextureCreate(rect, mColorFormat, bVGA);
+    }
+
+    mSrcRect = mRect;
+    mTargRect = mRect; /* == Vis FB size */
+    mTargSize = QRect(0, 0, aTargSize->width(), aTargSize->height());
+
+//    mBytesPerPixel = calcBytesPerPixel(mColorFormat.format(), mColorFormat.type());
+//    mBytesPerLine = mRect.width() * mBytesPerPixel;
+}
+
+VBoxVHWASurfaceBase::~VBoxVHWASurfaceBase()
+{
+    uninit();
+}
+
+GLsizei VBoxVHWASurfaceBase::makePowerOf2(GLsizei val)
+{
+    int last = ASMBitLastSetS32(val);
+    if(last>1)
+    {
+        last--;
+        if((1 << last) != val)
+        {
+            Assert((1 << last) < val);
+            val = (1 << (last+1));
+        }
+    }
+    return val;
+}
+
+ulong VBoxVHWASurfaceBase::calcBytesPerPixel(GLenum format, GLenum type)
+{
+    /* we now support only common byte-aligned data */
+    int numComponents = 0;
+    switch(format)
+    {
+    case GL_COLOR_INDEX:
+    case GL_RED:
+    case GL_GREEN:
+    case GL_BLUE:
+    case GL_ALPHA:
+    case GL_LUMINANCE:
+        numComponents = 1;
+        break;
+    case GL_RGB:
+    case GL_BGR_EXT:
+        numComponents = 3;
+        break;
+    case GL_RGBA:
+    case GL_BGRA_EXT:
+        numComponents = 4;
+        break;
+    case GL_LUMINANCE_ALPHA:
+        numComponents = 2;
+        break;
+    default:
+        Assert(0);
+        break;
+    }
+
+    int componentSize = 0;
+    switch(type)
+    {
+    case GL_UNSIGNED_BYTE:
+    case GL_BYTE:
+        componentSize = 1;
+        break;
+    //case GL_BITMAP:
+    case  GL_UNSIGNED_SHORT:
+    case GL_SHORT:
+        componentSize = 2;
+        break;
+    case GL_UNSIGNED_INT:
+    case GL_INT:
+    case GL_FLOAT:
+        componentSize = 4;
+        break;
+    default:
+        Assert(0);
+        break;
+    }
+    return numComponents * componentSize;
+}
+
+void VBoxVHWASurfaceBase::uninit()
+{
+//    mState->makeCurrent(this);
+
+    deleteDisplay();
+
+    delete mpTex[0];
+    if(fourcc() == FOURCC_YV12)
+    {
+        delete mpTex[1];
+        delete mpTex[2];
+    }
+
+    if(mAddress && mFreeAddress)
+    {
+        free(mAddress);
+        mAddress = NULL;
+    }
+}
+
+ulong VBoxVHWASurfaceBase::memSize()
+{
+    ulong size = mpTex[0]->memSize();
+    if(fourcc() == FOURCC_YV12)
+    {
+        size += mpTex[1]->memSize() + mpTex[2]->memSize();
+    }
+    return size;
+}
+
+void VBoxVHWASurfaceBase::init(VBoxVHWASurfaceBase * pPrimary, uchar *pvMem)
+{
+    if(pPrimary)
+    {
+        VBOXQGL_CHECKERR(
+                vboxglActiveTexture(GL_TEXTURE1);
+            );
+    }
+
+    int size = memSize();
+    uchar * address = (uchar *)malloc(size);
+#ifdef DEBUG_misha
+    int tex0Size = mpTex[0]->memSize();
+    if(pPrimary)
+    {
+        memset(address, 0xff, tex0Size);
+        Assert(size >= tex0Size);
+        if(size > tex0Size)
+        {
+        	memset(address + tex0Size, 0x0, size - tex0Size);
+        }
+    }
+    else
+    {
+        memset(address, 0x0f, tex0Size);
+        Assert(size >= tex0Size);
+        if(size > tex0Size)
+        {
+        	memset(address + tex0Size, 0x3f, size - tex0Size);
+        }
+    }
+#else
+    memset(address, 0, size);
+#endif
+
+    mpTex[0]->init(address);
+    if(fourcc() == FOURCC_YV12)
+    {
+        mpTex[1]->init(address);
+        mpTex[2]->init(address);
+    }
+
+
+    if(pvMem)
+    {
+        mAddress = pvMem;
+        free(address);
+        mFreeAddress = false;
+
+    }
+    else
+    {
+        mAddress = address;
+        mFreeAddress = true;
+    }
+
+    mpTex[0]->setAddress(mAddress);
+    if(fourcc() == FOURCC_YV12)
+    {
+        uchar *pTexAddr = mAddress+mpTex[0]->memSize();
+        mpTex[1]->setAddress(pTexAddr);
+        pTexAddr = pTexAddr+mpTex[1]->memSize();
+        mpTex[2]->setAddress(pTexAddr);
+    }
+
+    initDisplay(pPrimary);
+
+    mUpdateMem2TexRect.set(mRect);
+    Assert(!mUpdateMem2TexRect.isClear());
+    Assert(mRect.contains(mUpdateMem2TexRect.rect()));
+
+    if(pPrimary)
+    {
+        VBOXQGLLOG(("restoring to tex 0"));
+        VBOXQGL_CHECKERR(
+                vboxglActiveTexture(GL_TEXTURE0);
+            );
+    }
+
+}
+
+#ifdef DEBUG_misha
+bool g_DbgTest = false;
+#endif
+
+void VBoxVHWATexture::doUpdate(uchar * pAddress, const QRect * pRect)
+{
+#ifdef DEBUG_misha
+	if(g_DbgTest)
+	{
+		pAddress = (uchar*)malloc(memSize());
+		uchar val = 0;
+		for(uint32_t i = 0; i < memSize(); i++)
+		{
+			pAddress[i] = val;
+			val+=64;
+		}
+	}
+#endif
+
+    GLenum tt = texTarget();
+    if(pRect)
+    {
+        Assert(mRect.contains(*pRect));
+    }
+    else
+    {
+        pRect = &mRect;
+    }
+
+    Assert(glIsTexture(mTexture));
+    VBOXQGL_CHECKERR(
+    		glBindTexture(tt, mTexture);
+    		);
+
+    int x = pRect->x()/mColorFormat.widthCompression();
+    int y = pRect->y()/mColorFormat.heightCompression();
+    int width = pRect->width()/mColorFormat.widthCompression();
+    int height = pRect->height()/mColorFormat.heightCompression();
+
+    uchar * address = pAddress + pointOffsetTex(x, y);
+
+    VBOXQGL_CHECKERR(
+            glPixelStorei(GL_UNPACK_ROW_LENGTH, mRect.width()/mColorFormat.widthCompression());
+            );
+
+    VBOXQGL_CHECKERR(
+            glTexSubImage2D(tt,
+                0,
+                x, y, width, height,
+                mColorFormat.format(),
+                mColorFormat.type(),
+                address);
+            );
+
+#ifdef DEBUG_misha
+	if(g_DbgTest)
+	{
+		free(pAddress);
+	}
+#endif
+}
+
+void VBoxVHWATexture::texCoord(int x, int y)
+{
+    glTexCoord2f(((float)x)/mTexRect.width()/mColorFormat.widthCompression(), ((float)y)/mTexRect.height()/mColorFormat.heightCompression());
+}
+
+void VBoxVHWATexture::multiTexCoord(GLenum texUnit, int x, int y)
+{
+    vboxglMultiTexCoord2f(texUnit, ((float)x)/mTexRect.width()/mColorFormat.widthCompression(), ((float)y)/mTexRect.height()/mColorFormat.heightCompression());
+}
+
+void VBoxVHWATexture::uninit()
+{
+    if(mTexture)
+    {
+        glDeleteTextures(1,&mTexture);
+    }
+}
+
+VBoxVHWATexture::VBoxVHWATexture(const QRect & aRect, const VBoxVHWAColorFormat &aFormat)
+		: mAddress(0),
+          mTexture(0)
+{
+    mColorFormat = aFormat;
+    mRect = aRect;
+    mBytesPerPixel = mColorFormat.bitsPerPixel()/8;
+    mBytesPerPixelTex = mColorFormat.bitsPerPixelTex()/8;
+    mBytesPerLine = mBytesPerPixel * mRect.width();
+    GLsizei wdt = VBoxVHWASurfaceBase::makePowerOf2(mRect.width()/mColorFormat.widthCompression());
+    GLsizei hgt = VBoxVHWASurfaceBase::makePowerOf2(mRect.height()/mColorFormat.heightCompression());
+    mTexRect = QRect(0,0,wdt,hgt);
+}
+
+void VBoxVHWATexture::initParams()
+{
+    GLenum tt = texTarget();
+
+    glTexParameteri(tt, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    VBOXQGL_ASSERTNOERR();
+    glTexParameteri(tt, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    VBOXQGL_ASSERTNOERR();
+    glTexParameteri(tt, GL_TEXTURE_WRAP_S, GL_CLAMP);
+    VBOXQGL_ASSERTNOERR();
+
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    VBOXQGL_ASSERTNOERR();
+    glPixelStorei(GL_PACK_ALIGNMENT, 1);
+    VBOXQGL_ASSERTNOERR();
+
+    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+    VBOXQGL_ASSERTNOERR();
+}
+
+void VBoxVHWATexture::load()
+{
+    VBOXQGL_CHECKERR(
+            glPixelStorei(GL_UNPACK_ROW_LENGTH, mTexRect.width());
+            );
+
+    VBOXQGL_CHECKERR(
+        glTexImage2D(texTarget(),
+                0,
+                  mColorFormat.internalFormat(),
+                  mTexRect.width(),
+                  mTexRect.height(),
+                  0,
+                  mColorFormat.format(),
+                  mColorFormat.type(),
+                  (GLvoid *)mAddress);
+        );
+}
+
+void VBoxVHWATexture::init(uchar *pvMem)
+{
+//    GLsizei wdt = mTexRect.width();
+//    GLsizei hgt = mTexRect.height();
+
+    VBOXQGL_CHECKERR(
+            glGenTextures(1, &mTexture);
+        );
+
+    VBOXQGLLOG(("tex: %d", mTexture));
+
+    bind();
+
+    initParams();
+
+    setAddress(pvMem);
+
+    load();
+}
+
+VBoxVHWATexture::~VBoxVHWATexture()
+{
+	uninit();
+}
+
+void VBoxVHWATextureNP2Rect::texCoord(int x, int y)
+{
+    glTexCoord2f(((float)x)/mColorFormat.widthCompression(), ((float)y)/mColorFormat.heightCompression());
+}
+
+void VBoxVHWATextureNP2Rect::multiTexCoord(GLenum texUnit, int x, int y)
+{
+    vboxglMultiTexCoord2f(texUnit, x/mColorFormat.widthCompression(), y/mColorFormat.heightCompression());
+}
+
+GLenum VBoxVHWATextureNP2Rect::texTarget() {return GL_TEXTURE_RECTANGLE; }
+
+void VBoxVHWASurfaceBase::synchTexMem(const QRect * pRect)
+{
+    if(pRect)
+    {
+        Assert(mRect.contains(*pRect));
+    }
+
+    if(mUpdateMem2TexRect.isClear())
+        return;
+
+    if(pRect && !mUpdateMem2TexRect.rect().intersects(*pRect))
+        return;
+
+    mpTex[0]->update(&mUpdateMem2TexRect.rect());
+    if(fourcc() == FOURCC_YV12)
+    {
+        QRect rect(mUpdateMem2TexRect.rect().x()/2, mUpdateMem2TexRect.rect().y()/2,
+                mUpdateMem2TexRect.rect().width()/2, mUpdateMem2TexRect.rect().height()/2);
+        mpTex[1]->update(&rect);
+        mpTex[2]->update(&rect);
+    }
+
+#if 0
+    mUpdateTex2FBRect.add(mUpdateMem2TexRect);
+    Assert(!mUpdateTex2FBRect.isClear());
+    Assert(mRect.contains(mUpdateTex2FBRect.rect()));
+#endif
+    mUpdateMem2TexRect.clear();
+    Assert(mUpdateMem2TexRect.isClear());
+//#ifdef DEBUG
+//    VBOXPRINTDIF(dbgTime, ("texMem:"));
+//#endif
+}
+
+void VBoxVHWATextureNP2RectPBO::init(uchar *pvMem)
+{
+	VBOXQGL_CHECKERR(
+			vboxglGenBuffers(1, &mPBO);
+			);
+	VBoxVHWATextureNP2Rect::init(pvMem);
+}
+
+void VBoxVHWATextureNP2RectPBO::doUpdate(uchar * pAddress, const QRect * pRect)
+{
+	Q_UNUSED(pAddress);
+	Q_UNUSED(pRect);
+
+	vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
+
+    GLvoid *buf = vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
+
+//    updateBuffer((uchar*)buf, pRect);
+	memcpy(buf, mAddress, memSize());
+
+	bool unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+	Assert(unmapped);
+
+    VBoxVHWATextureNP2Rect::doUpdate(0, &mRect);
+
+	vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+}
+
+VBoxVHWATextureNP2RectPBO::~VBoxVHWATextureNP2RectPBO()
+{
+	VBOXQGL_CHECKERR(
+			vboxglDeleteBuffers(1, &mPBO);
+			);
+}
+
+
+void VBoxVHWATextureNP2RectPBO::load()
+{
+	VBoxVHWATextureNP2Rect::load();
+
+	vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
+
+	vboxglBufferData(GL_PIXEL_UNPACK_BUFFER, memSize(), NULL, GL_STREAM_DRAW);
+
+	GLvoid *buf = vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
+
+//	updateBuffer((uchar*)buf, &mRect);
+	memcpy(buf, mAddress, memSize());
+
+	bool unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+	Assert(unmapped);
+
+	vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+}
+
+#if 0
+void VBoxVHWASurfaceBase::synch(const QRect * aRect)
+{
+    synchFB(aRect);
+    synchTex(aRect);
+    synchMem(aRect);
+}
+
+void VBoxVHWASurfaceBase::synchFB(const QRect * pRect)
+{
+    Assert(isYInverted());
+
+    if(pRect)
+    {
+        Assert(mRect.contains(*pRect));
+    }
+
+    synchTexMem(pRect);
+
+    if(mUpdateTex2FBRect.isClear())
+        return;
+
+    if(pRect && !mUpdateTex2FBRect.rect().intersects(*pRect))
+        return;
+
+    mState->makeCurrent(this);
+
+    VBOXQGL_CHECKERR(
+            glBindTexture(GL_TEXTURE_2D, mTexture);
+            );
+
+    VBoxVHWAGlProgramMngr * pMngr = getGlProgramMngr();
+    pMngr->stopCurrentProgram();
+
+    doTex2FB(&mUpdateTex2FBRect.rect(), &mUpdateTex2FBRect.rect());
+
+    mUpdateTex2FBRect.clear();
+    Assert(mUpdateTex2FBRect.isClear());
+}
+
+void VBoxVHWASurfaceBase::synchMem(const QRect * pRect)
+{
+    if(pRect)
+    {
+        Assert(mRect.contains(*pRect));
+    }
+
+    if(mUpdateFB2MemRect.isClear())
+        return;
+
+    if(pRect && !mUpdateFB2MemRect.rect().intersects(*pRect))
+        return;
+
+    mState->makeYInvertedCurrent(this);
+//    mState->makeCurrent(this);
+
+    uchar * address = pointAddress(mUpdateFB2MemRect.rect().x(), mUpdateFB2MemRect.rect().y());
+
+    VBOXQGL_CHECKERR(
+            glPixelStorei(GL_PACK_ROW_LENGTH, mRect.width());
+            );
+    VBOXQGL_CHECKERR(
+            glReadPixels(
+                mUpdateFB2MemRect.rect().x(),
+                mUpdateFB2MemRect.rect().y(),
+                mUpdateFB2MemRect.rect().width(),
+                mUpdateFB2MemRect.rect().height(),
+                mColorFormat.format(),
+                mColorFormat.type(),
+                address);
+            );
+
+    mUpdateFB2MemRect.clear();
+    Assert(mUpdateFB2TexRect.isClear());
+}
+
+int VBoxVHWASurfaceBase::performBlt(const QRect * pDstRect, VBoxVHWASurfaceBase * pSrcSurface, const QRect * pSrcRect, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool blt)
+{
+//    pDstCKey = NULL;
+//    pSrcCKey = NULL;
+
+    GLuint tex = pSrcSurface->textureSynched(pSrcRect);
+
+    if(pDstCKey)
+    {
+        synchTex(pDstRect);
+    }
+
+    mState->makeCurrent(this, blt);
+
+    VBoxVHWAGlProgramMngr * pMngr = getGlProgramMngr();
+    VBoxVHWAGlProgramVHWA * pProgram = pMngr->getProgram(pSrcCKey != NULL, &pSrcSurface->colorFormat(), &colorFormat());
+    if(pProgram)
+    {
+        if(pSrcCKey != NULL)
+        {
+            pProgram->start();
+            setCKey(pProgram, &pSrcSurface->colorFormat(), pSrcCKey);
+
+            vboxglActiveTexture(GL_TEXTURE0);
+        }
+    }
+    else
+    {
+        pMngr->stopCurrentProgram();
+    }
+
+//    if(blt)
+    {
+        VBOXQGL_CHECKERR(
+                glBindTexture(GL_TEXTURE_2D, tex);
+                );
+
+        //TODO: setup strething params
+        GLsizei wdt = pSrcSurface->mTexRect.width();
+        GLsizei hgt = pSrcSurface->mTexRect.height();
+
+        VBOXQGL_CHECKERR(
+                glMatrixMode(GL_TEXTURE);
+                );
+        VBOXQGL_CHECKERR(
+                glPushMatrix();
+            );
+
+        VBoxGLWidget::doSetupMatrix(QSize(wdt, hgt), true);
+        VBOXQGL_CHECKERR(
+                glMatrixMode(GL_MODELVIEW);
+                );
+
+        doTex2FB(pDstRect, pSrcRect);
+
+        VBOXQGL_CHECKERR(
+                glMatrixMode(GL_TEXTURE);
+                );
+        VBOXQGL_CHECKERR(
+                glPopMatrix();
+                );
+        VBOXQGL_CHECKERR(
+                glMatrixMode(GL_MODELVIEW);
+                );
+    }
+//    else
+//    {
+//
+//    }
+
+    /* if dst color key */
+    /* setup ckey shader */
+    if(pDstCKey)
+    {
+        VBOXQGL_CHECKERR(
+                glBindTexture(GL_TEXTURE_2D, mTexture);
+                );
+        pProgram = pMngr->getProgram(true, NULL, NULL);
+        /* setup ckey values*/
+        setCKey(pProgram, &colorFormat(), pDstCKey);
+        pProgram->start();
+        doTex2FB(pDstRect, pDstRect);
+    }
+
+    return VINF_SUCCESS;
+}
+
+int VBoxVHWASurfaceBase::overlay(VBoxVHWASurfaceBase * pOverlaySurface)
+{
+    VBOXQGLLOG(("overlay src(0x%x) ", pOverlaySurface));
+    VBOXQGLLOG_QRECT("dst: ", &pOverlaySurface->mTargRect, "\n");
+    VBOXQGLLOG_QRECT("src: ", &pOverlaySurface->mSrcRect,  "\n");
+    VBOXQGLLOG_METHODTIME("time:");
+
+    Assert(!pOverlaySurface->isHidden());
+
+    if(pOverlaySurface->isHidden())
+    {
+        VBOXQGLLOG(("!!!hidden!!!\n"));
+        return VINF_SUCCESS;
+    }
+
+    const QRect * pSrcRect = &pOverlaySurface->mSrcRect;
+    const QRect * pDstRect = &pOverlaySurface->mTargRect;
+    const VBoxVHWAColorKey * pSrcCKey = pOverlaySurface->srcOverlayCKey();
+    /* we use src (overlay) surface to maintain overridden dst ckey info
+     * to allow multiple overlays have different overridden dst keys for one primary surface */
+    /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
+     * dst ckey value in defaultDstOverlayCKey
+     * this allows the NULL to be a valid overridden value as well */
+    const VBoxVHWAColorKey * pDstCKey = pOverlaySurface->dstOverlayCKey() ? pOverlaySurface->defaultDstOverlayCKey() : dstOverlayCKey();
+
+    return performBlt(pDstRect, pOverlaySurface, pSrcRect, pDstCKey, pSrcCKey, false);
+}
+
+int VBoxVHWASurfaceBase::blt(const QRect * pDstRect, VBoxVHWASurfaceBase * pSrcSurface, const QRect * pSrcRect, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey)
+{
+    if(pDstRect)
+    {
+        Assert(mRect.contains(*pDstRect));
+    }
+    else
+    {
+        pDstRect = &mRect;
+    }
+
+    if(pSrcRect)
+    {
+        Assert(pSrcSurface->mRect.contains(*pSrcRect));
+    }
+    else
+    {
+        pSrcRect = &pSrcSurface->mRect;
+    }
+
+    if(!pSrcCKey)
+        pSrcCKey = pSrcSurface->srcBltCKey();
+    if(!pDstCKey)
+        pDstCKey = dstBltCKey();
+
+    VBOXQGLLOG(("blt dst(0x%x), src(0x%x)", this, pSrcSurface));
+    VBOXQGLLOG_QRECT("dst: ", pDstRect, "\n");
+    VBOXQGLLOG_QRECT("src: ", pSrcRect, "\n");
+    VBOXQGLLOG_METHODTIME("time:");
+    int rc = performBlt(pDstRect, pSrcSurface, pSrcRect, pDstCKey, pSrcCKey, true);
+
+    mUpdateFB2TexRect.add(*pDstRect);
+    Assert(!mUpdateFB2TexRect.isClear());
+    Assert(mRect.contains(mUpdateFB2TexRect.rect()));
+//    synchTexture(pDstRect);
+    mUpdateFB2MemRect.add(*pDstRect);
+    Assert(!mUpdateFB2MemRect.isClear());
+    Assert(mRect.contains(mUpdateFB2MemRect.rect()));
+
+    return rc;
+}
+#endif
+void VBoxVHWASurfaceBase::doTex2FB(const QRect * pDstRect, const QRect * pSrcRect)
+{
+    int tx1, ty1, tx2, ty2;
+    pSrcRect->getCoords(&tx1, &ty1, &tx2, &ty2);
+    int bx1, by1, bx2, by2;
+    pDstRect->getCoords(&bx1, &by1, &bx2, &by2);
+    tx2++; ty2++;bx2++; by2++;
+
+#if 1
+//    VBOXQGL_CHECKERR(
+            VBOXQGLLOG_QRECT("texRect: ", &mpTex[0]->texRect(), "\n");
+            glBegin(GL_QUADS);
+//            glTexCoord2d(((double)tx1)/mpTex[0]->texRect().width(), ((double)ty1)/mpTex[0]->texRect().height());
+//            glVertex2i(bx1, by1);
+//            glTexCoord2d(((double)tx1)/mpTex[0]->texRect().width(), ((double)ty2)/mpTex[0]->texRect().height());
+//            glVertex2i(bx1, by2);
+//            glTexCoord2d(((double)tx2)/mpTex[0]->texRect().width(), ((double)ty2)/mpTex[0]->texRect().height());
+//            glVertex2i(bx2, by2);
+//            glTexCoord2d(((double)tx2)/mpTex[0]->texRect().width(), ((double)ty1)/mpTex[0]->texRect().height());
+//            glVertex2i(bx2, by1);
+            mpTex[0]->texCoord(tx1, ty1);
+            glVertex2i(bx1, by1);
+            mpTex[0]->texCoord(tx1, ty2);
+            glVertex2i(bx1, by2);
+            mpTex[0]->texCoord(tx2, ty2);
+            glVertex2i(bx2, by2);
+            mpTex[0]->texCoord(tx2, ty1);
+            glVertex2i(bx2, by1);
+
+            glEnd();
+//            );
+#else
+        glBegin(GL_QUADS);
+        glTexCoord2d(0.0, 0.0);
+        glVertex2i(0, 0);
+        glTexCoord2d(0.0, 1.0);
+        glVertex2i(0, mRect.height());
+        glTexCoord2d(1.0, 1.0);
+        glVertex2i(mRect.width(), mRect.height());
+        glTexCoord2d(1.0, 0.0);
+        glVertex2i(mRect.width(), 0);
+        glEnd();
+#endif
+}
+
+
+void VBoxVHWASurfaceBase::doMultiTex2FB(const QRect * pDstRect, const QRect * pSrcRect, int cSrcTex)
+{
+    int tx1, ty1, tx2, ty2;
+    pSrcRect->getCoords(&tx1, &ty1, &tx2, &ty2);
+    int bx1, by1, bx2, by2;
+    pDstRect->getCoords(&bx1, &by1, &bx2, &by2);
+    tx2++; ty2++;bx2++; by2++;
+    uint32_t t0width = mpTex[0]->rect().width();
+    uint32_t t0height = mpTex[0]->rect().height();
+
+//    VBOXQGL_CHECKERR(
+            glBegin(GL_QUADS);
+            for(int i = 0; i < cSrcTex; i++)
+            {
+//                vboxglMultiTexCoord2d(GL_TEXTURE0 + i, ((double)tx1)/mpTex[i]->texRect().width()/(width()/mpTex[i]->rect().width()),
+//                        ((double)ty1)/mpTex[i]->texRect().height()/(height()/mpTex[i]->rect().height()));
+            	mpTex[i]->multiTexCoord(GL_TEXTURE0 + i, tx1/(t0width/mpTex[i]->texRect().width()), ty1/(t0height/mpTex[i]->rect().height()));
+            }
+            glVertex2i(bx1, by1);
+            for(int i = 0; i < cSrcTex; i++)
+            {
+//                vboxglMultiTexCoord2d(GL_TEXTURE0 + i, ((double)tx1)/mpTex[i]->texRect().width()/(width()/mpTex[i]->rect().width()),
+//                        ((double)ty2)/mpTex[i]->texRect().height()/(height()/mpTex[i]->rect().height()));
+            	mpTex[i]->multiTexCoord(GL_TEXTURE0 + i, tx1/(t0width/mpTex[i]->texRect().width()), ty2/(t0height/mpTex[i]->rect().height()));
+            }
+            glVertex2i(bx1, by2);
+            for(int i = 0; i < cSrcTex; i++)
+            {
+//                vboxglMultiTexCoord2d(GL_TEXTURE0 + i, ((double)tx2)/mpTex[i]->texRect().width()/(width()/mpTex[i]->rect().width()),
+//                        ((double)ty2)/mpTex[i]->texRect().height()/(height()/mpTex[i]->rect().height()));
+            	mpTex[i]->multiTexCoord(GL_TEXTURE0 + i, tx2/(t0width/mpTex[i]->texRect().width()), ty2/(t0height/mpTex[i]->rect().height()));
+
+            }
+            glVertex2i(bx2, by2);
+            for(int i = 0; i < cSrcTex; i++)
+            {
+//                vboxglMultiTexCoord2d(GL_TEXTURE0 + i, ((double)tx2)/mpTex[i]->texRect().width()/(width()/mpTex[i]->rect().width()),
+//                        ((double)ty1)/mpTex[i]->texRect().height()/(height()/mpTex[i]->rect().height()));
+            	mpTex[i]->multiTexCoord(GL_TEXTURE0 + i, tx2/(t0width/mpTex[i]->texRect().width()), ty1/(t0height/mpTex[i]->rect().height()));
+            }
+            glVertex2i(bx2, by1);
+            glEnd();
+//            );
+}
+
+void VBoxVHWASurfaceBase::doMultiTex2FB(const QRect * pDstRect, VBoxVHWATexture * pDstTex, const QRect * pSrcRect, int cSrcTex)
+{
+    int tx1, ty1, tx2, ty2;
+    pSrcRect->getCoords(&tx1, &ty1, &tx2, &ty2);
+    int bx1, by1, bx2, by2;
+    pDstRect->getCoords(&bx1, &by1, &bx2, &by2);
+    tx2++; ty2++;bx2++; by2++;
+    uint32_t t0width = mpTex[0]->rect().width();
+    uint32_t t0height = mpTex[0]->rect().height();
+
+//    VBOXQGL_CHECKERR(
+            glBegin(GL_QUADS);
+            pDstTex->multiTexCoord(GL_TEXTURE0, bx1, by1);
+            for(int i = 0; i < cSrcTex; i++)
+            {
+//                vboxglMultiTexCoord2d(GL_TEXTURE1 + i, ((double)tx1)/mpTex[i]->texRect().width()/(width()/mpTex[i]->rect().width()),
+//                        ((double)ty1)/mpTex[i]->texRect().height()/(height()/mpTex[i]->rect().height()));
+            	mpTex[i]->multiTexCoord(GL_TEXTURE1 + i, tx1/(t0width/mpTex[i]->rect().width()), ty1/(t0height/mpTex[i]->rect().height()));
+
+            }
+            glVertex2i(bx1, by1);
+            pDstTex->multiTexCoord(GL_TEXTURE0, bx1, by2);
+            for(int i = 0; i < cSrcTex; i++)
+            {
+//                vboxglMultiTexCoord2d(GL_TEXTURE1 + i, ((double)tx1)/mpTex[i]->texRect().width()/(width()/mpTex[i]->rect().width()),
+//                        ((double)ty2)/mpTex[i]->texRect().height()/(height()/mpTex[i]->rect().height()));
+            	mpTex[i]->multiTexCoord(GL_TEXTURE1 + i, tx1/(t0width/mpTex[i]->rect().width()), ty2/(t0height/mpTex[i]->rect().height()));
+
+            }
+            glVertex2i(bx1, by2);
+            pDstTex->multiTexCoord(GL_TEXTURE0, bx2, by2);
+            for(int i = 0; i < cSrcTex; i++)
+            {
+//                vboxglMultiTexCoord2d(GL_TEXTURE1 + i, ((double)tx2)/mpTex[i]->texRect().width()/(width()/mpTex[i]->rect().width()),
+//                        ((double)ty2)/mpTex[i]->texRect().height()/(height()/mpTex[i]->rect().height()));
+            	mpTex[i]->multiTexCoord(GL_TEXTURE1 + i, tx2/(t0width/mpTex[i]->rect().width()), ty2/(t0height/mpTex[i]->rect().height()));
+
+            }
+            glVertex2i(bx2, by2);
+            pDstTex->multiTexCoord(GL_TEXTURE0, bx2, by1);
+            for(int i = 0; i < cSrcTex; i++)
+            {
+//                vboxglMultiTexCoord2d(GL_TEXTURE1 + i, ((double)tx2)/mpTex[i]->texRect().width()/(width()/mpTex[i]->rect().width()),
+//                        ((double)ty1)/mpTex[i]->texRect().height()/(height()/mpTex[i]->rect().height()));
+            	mpTex[i]->multiTexCoord(GL_TEXTURE1 + i, tx2/(t0width/mpTex[i]->rect().width()), ty1/(t0height/mpTex[i]->rect().height()));
+
+            }
+            glVertex2i(bx2, by1);
+            glEnd();
+//            );
+
+}
+
+int VBoxVHWASurfaceBase::lock(const QRect * pRect, uint32_t flags)
+{
+	Q_UNUSED(flags);
+
+    if(pRect)
+    {
+        Assert(mRect.contains(*pRect));
+    }
+
+    Assert(mLockCount >= 0);
+    if(pRect && pRect->isEmpty())
+        return VERR_GENERAL_FAILURE;
+    if(mLockCount < 0)
+        return VERR_GENERAL_FAILURE;
+
+    VBOXQGLLOG(("lock (0x%x)", this));
+    VBOXQGLLOG_QRECT("rect: ", pRect ? pRect : &mRect, "\n");
+    VBOXQGLLOG_METHODTIME("time ");
+//    if(!(flags & VBOXVHWA_LOCK_DISCARDCONTENTS))
+//    {
+//        synchMem(pRect);
+//    }
+
+    mUpdateMem2TexRect.add(pRect ? *pRect : mRect);
+
+    Assert(!mUpdateMem2TexRect.isClear());
+    Assert(mRect.contains(mUpdateMem2TexRect.rect()));
+    return VINF_SUCCESS;
+}
+
+int VBoxVHWASurfaceBase::unlock()
+{
+    VBOXQGLLOG(("unlock (0x%x)\n", this));
+    mLockCount = 0;
+    return VINF_SUCCESS;
+}
+
+void VBoxVHWASurfaceBase::setRects(VBoxVHWASurfaceBase *pPrimary, const QRect * aTargRect, const QRect * aSrcRect)
+{
+    if(mTargRect == *aTargRect && mSrcRect == *aSrcRect)
+        return;
+
+    mTargRect = *aTargRect;
+    mSrcRect = *aSrcRect;
+
+    initDisplay(pPrimary);
+}
+
+void VBoxVHWASurfaceBase::setTargetRectPosition(VBoxVHWASurfaceBase *pPrimary, const QPoint * aPoint)
+{
+    if(mTargRect.topLeft() == *aPoint)
+        return;
+
+    mTargRect = QRect(aPoint->x(), aPoint->y(), mTargRect.width(), mTargRect.height());
+
+    initDisplay(pPrimary
+//            false
+            );
+}
+
+void VBoxVHWASurfaceBase::deleteDisplay(
+//        bool bInverted
+        )
+{
+    {
+        if(mVisibleDisplayInitialized)
+        {
+            glDeleteLists(mVisibleDisplay, 1);
+            mVisibleDisplayInitialized = false;
+        }
+    }
+}
+
+void VBoxVHWASurfaceBase::doDisplay(VBoxVHWASurfaceBase *pPrimary, VBoxVHWAGlProgramVHWA * pProgram, bool bBindDst)
+{
+    bool bInvokeMultiTex2 = false;
+
+    if(pProgram)
+    {
+        pProgram->start();
+
+//            if(pSrcCKey != NULL)
+//            {
+//                pProgram->start();
+//                setCKey(pProgram, &pSrcSurface->colorFormat(), pSrcCKey);
+
+//                vboxglActiveTexture(GL_TEXTURE0);
+//            }
+
+        if(bBindDst)
+        {
+            vboxglActiveTexture(GL_TEXTURE1);
+            mpTex[0]->bind();
+            if(fourcc() == FOURCC_YV12)
+            {
+                vboxglActiveTexture(GL_TEXTURE1+1);
+                mpTex[1]->bind();
+                vboxglActiveTexture(GL_TEXTURE1 + 2);
+                mpTex[2]->bind();
+            }
+            vboxglActiveTexture(GL_TEXTURE0);
+            pPrimary->mpTex[0]->bind();
+            bInvokeMultiTex2 = true;
+        }
+        else
+        {
+            if(fourcc() == FOURCC_YV12)
+            {
+                vboxglActiveTexture(GL_TEXTURE1);
+                mpTex[1]->bind();
+                vboxglActiveTexture(GL_TEXTURE1 + 1);
+                mpTex[2]->bind();
+                vboxglActiveTexture(GL_TEXTURE0);
+            }
+            mpTex[0]->bind();
+        }
+    }
+    else
+    {
+//        vboxglActiveTexture(GL_TEXTURE0);
+        mpTex[0]->bind();
+//        VBOXQGLLOG(("binding (primary??) texture: %d\n", mpTex[0]->texture()));
+    }
+
+    if(bInvokeMultiTex2)
+    {
+        doMultiTex2FB(&mTargRect, pPrimary->mpTex[0], &mSrcRect,
+                (fourcc() == FOURCC_YV12) ? 3 : 1);
+    }
+    else
+    {
+        if(fourcc() == FOURCC_YV12)
+        {
+            doMultiTex2FB(&mTargRect, &mSrcRect, 3 );
+        }
+        else
+        {
+            VBOXQGLLOG_QRECT("mTargRect: ", &mTargRect, "\n");
+            VBOXQGLLOG_QRECT("mSrcRect: ", &mSrcRect, "\n");
+            doTex2FB(&mTargRect, &mSrcRect);
+        }
+    }
+
+    if(pProgram)
+    {
+        pProgram->stop();
+    }
+}
+
+GLuint VBoxVHWASurfaceBase::createDisplay(VBoxVHWASurfaceBase *pPrimary)
+{
+    VBoxVHWAGlProgramVHWA * pProgram = NULL;
+    const VBoxVHWAColorKey * pSrcCKey = NULL, *pDstCKey = NULL;
+    if(pPrimary)
+    {
+        pSrcCKey = getActiveSrcOverlayCKey();
+        /* we use src (overlay) surface to maintain overridden dst ckey info
+         * to allow multiple overlays have different overridden dst keys for one primary surface */
+        /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
+         * dst ckey value in defaultDstOverlayCKey
+         * this allows the NULL to be a valid overridden value as well */
+        pDstCKey = getActiveDstOverlayCKey(pPrimary);
+//        pSrcCKey = NULL;
+//        pDstCKey = NULL;
+
+        pProgram = mWidget->vboxVHWAGetGlProgramMngr()->getProgram(pDstCKey != NULL, pSrcCKey != NULL, &colorFormat(), &pPrimary->colorFormat());
+    }
+
+    GLuint display = glGenLists(1);
+    VBOXQGL_ASSERTNOERR();
+    glNewList(display, GL_COMPILE);
+
+    doDisplay(pPrimary, pProgram, pDstCKey != NULL);
+
+    glEndList();
+    VBOXQGL_ASSERTNOERR();
+
+    return display;
+}
+
+void VBoxVHWASurfaceBase::initDisplay(VBoxVHWASurfaceBase *pPrimary)
+{
+    deleteDisplay();
+
+
+    {
+        mVisibleDisplay = createDisplay(pPrimary);
+        mVisibleDisplayInitialized = true;
+    }
+}
+
+void VBoxVHWASurfaceBase::updatedMem(const QRect *rec)
+{
+    if(rec)
+    {
+        Assert(mRect.contains(*rec));
+    }
+    mUpdateMem2TexRect.add(*rec);
+}
+
+void VBoxVHWASurfaceBase::performDisplay(VBoxVHWASurfaceBase *pPrimary)
+{
+    Assert(mVisibleDisplayInitialized);
+
+    synchTexMem(&mSrcRect);
+    if(pPrimary && getActiveDstOverlayCKey(pPrimary))
+    {
+        pPrimary->synchTexMem(&mTargRect);
+    }
+
+#ifdef DEBUG_misha
+    if(0)
+    {
+        VBoxVHWAGlProgramVHWA * pProgram = NULL;
+        const VBoxVHWAColorKey * pSrcCKey = NULL, *pDstCKey = NULL;
+        if(pPrimary)
+        {
+            pSrcCKey = getActiveSrcOverlayCKey();
+            /* we use src (overlay) surface to maintain overridden dst ckey info
+             * to allow multiple overlays have different overridden dst keys for one primary surface */
+            /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
+             * dst ckey value in defaultDstOverlayCKey
+             * this allows the NULL to be a valid overridden value as well */
+            pDstCKey = getActiveDstOverlayCKey(pPrimary);
+    //        pSrcCKey = NULL;
+    //        pDstCKey = NULL;
+
+            pProgram = mWidget->vboxVHWAGetGlProgramMngr()->getProgram(pDstCKey != NULL, pSrcCKey != NULL, &colorFormat(), &pPrimary->colorFormat());
+        }
+
+        doDisplay(pPrimary, pProgram, pDstCKey != NULL);
+
+//        doDisplay(pPrimary, NULL, false);
+    }
+    else
+#endif
+    {
+        VBOXQGL_CHECKERR(
+                glCallList(mVisibleDisplay);
+                );
+    }
+}
+
+/** @class VBoxQGLFrameBuffer
+ *
+ *  The VBoxQImageFrameBuffer class is a class that implements the IFrameBuffer
+ *  interface and uses QImage as the direct storage for VM display data. QImage
+ *  is then converted to QPixmap and blitted to the console view widget.
+ */
+
+VBoxQGLFrameBuffer::VBoxQGLFrameBuffer (VBoxConsoleView *aView) :
+    VBoxFrameBuffer (aView)
+{
+//    mWidget = new GLWidget(aView->viewport());
+#ifndef VBOXQGL_PROF_BASE
+    resizeEvent (new VBoxResizeEvent (FramebufferPixelFormat_Opaque,
+                                      NULL, 0, 0, 640, 480));
+#else
+    resizeEvent (new VBoxResizeEvent (FramebufferPixelFormat_Opaque,
+                                      NULL, 0, 0, VBOXQGL_PROF_WIDTH, VBOXQGL_PROF_HEIGHT));
+#endif
+}
+
+/** @note This method is called on EMT from under this object's lock */
+STDMETHODIMP VBoxQGLFrameBuffer::NotifyUpdate (ULONG aX, ULONG aY,
+                                                  ULONG aW, ULONG aH)
+{
+//    /* We're not on the GUI thread and update() isn't thread safe in
+//     * Qt 4.3.x on the Win, Qt 3.3.x on the Mac (4.2.x is),
+//     * on Linux (didn't check Qt 4.x there) and probably on other
+//     * non-DOS platforms, so post the event instead. */
+#ifdef VBOXQGL_PROF_BASE
+    QApplication::postEvent (mView,
+                             new VBoxRepaintEvent (aX, aY, aW, aH));
+#else
+    vboxWidget()->postCmd(VBOXVHWA_PIPECMD_PAINT, &QRect(aX, aY, aW, aH));
+#endif
+    return S_OK;
+}
+
+#ifdef VBOXQGL_PROF_BASE
+STDMETHODIMP VBoxQGLFrameBuffer::RequestResize (ULONG aScreenId, ULONG aPixelFormat,
+                              BYTE *aVRAM, ULONG aBitsPerPixel, ULONG aBytesPerLine,
+                              ULONG aWidth, ULONG aHeight,
+                              BOOL *aFinished)
+{
+	aWidth = VBOXQGL_PROF_WIDTH;
+	aHeight = VBOXQGL_PROF_HEIGHT;
+    VBoxFrameBuffer::RequestResize (aScreenId, aPixelFormat,
+            aVRAM, aBitsPerPixel, aBytesPerLine,
+            aWidth, aHeight,
+            aFinished);
+
+//    if(aVRAM)
+    {
+        for(;;)
+        {
+            ULONG aX = 0;
+            ULONG aY = 0;
+            ULONG aW = aWidth;
+            ULONG aH = aHeight;
+            NotifyUpdate (aX, aY, aW, aH);
+            RTThreadSleep(40);
+        }
+    }
+    return S_OK;
+}
+#endif
+
+VBoxGLWidget* VBoxQGLFrameBuffer::vboxWidget()
+{
+    return (VBoxGLWidget*)mView->viewport();
+}
+
+void VBoxQGLFrameBuffer::paintEvent (QPaintEvent *pe)
+{
+    vboxWidget()->vboxPaintEvent(pe);
+}
+
+void VBoxQGLFrameBuffer::resizeEvent (VBoxResizeEvent *re)
+{
+    mWdt = re->width();
+    mHgt = re->height();
+
+    vboxWidget()->vboxResizeEvent(re);
+}
+
+/* processing the VHWA command, called from the GUI thread */
+void VBoxQGLFrameBuffer::doProcessVHWACommand(QEvent * pEvent)
+{
+    vboxWidget()->vboxProcessVHWACommands((VBoxVHWACommandProcessEvent*)pEvent);
+}
+
+VBoxGLWidget::VBoxGLWidget (VBoxConsoleView *aView, QWidget *aParent)
+    : QGLWidget (VBoxGLWidget::vboxGLFormat(), aParent),
+    mPixelFormat(0),
+    mUsesGuestVRAM(false),
+    mbVGASurfCreated(false),
+    mView(aView),
+    mConstructingList(NULL),
+    mcRemaining2Contruct(0),
+    mpfnOp(NULL),
+    mSurfHandleTable(128) /* 128 should be enough */
+{
+    cmdPipeInit();
+    mpMngr = new VBoxVHWAGlProgramMngr();
+//        /* No need for background drawing */
+//        setAttribute (Qt::WA_OpaquePaintEvent);
+}
+
+const QGLFormat & VBoxGLWidget::vboxGLFormat()
+{
+    static QGLFormat vboxFormat = QGLFormat();
+    vboxFormat.setAlpha(true);
+    Assert(vboxFormat.alpha());
+    vboxFormat.setSwapInterval(0);
+    Assert(vboxFormat.swapInterval() == 0);
+    vboxFormat.setAccum(false);
+    Assert(!vboxFormat.accum());
+    vboxFormat.setDepth(false);
+    Assert(!vboxFormat.depth());
+    return vboxFormat;
+}
+
+VBoxGLWidget::~VBoxGLWidget()
+{
+    delete mpMngr;
+    cmdPipeDelete();
+}
+
+void VBoxGLWidget::cmdPipeInit()
+{
+    int rc = RTCritSectInit(&mCritSect);
+    AssertRC(rc);
+
+    mpFirstEvent = NULL;
+    mpLastEvent = NULL;
+    mbNewEvent = false;
+    for(int i = RT_ELEMENTS(mElementsBuffer) - 1; i >= 0; i--)
+    {
+        mFreeElements.push(&mElementsBuffer[i]);
+    }
+}
+
+void VBoxGLWidget::cmdPipeDelete()
+{
+    RTCritSectDelete(&mCritSect);
+}
+
+void VBoxGLWidget::doSetupMatrix(const QSize & aSize, bool bInverted)
+{
+    VBOXQGL_CHECKERR(
+            glLoadIdentity();
+            );
+    if(bInverted)
+    {
+        VBOXQGL_CHECKERR(
+                glScalef(1.0f/aSize.width(), 1.0f/aSize.height(), 1.0f);
+                );
+    }
+    else
+    {
+        /* make display coordinates be scaled to pixel coordinates */
+        VBOXQGL_CHECKERR(
+                glTranslatef(0.0f, 1.0f, 0.0f);
+                );
+        VBOXQGL_CHECKERR(
+                glScalef(1.0f/aSize.width(), 1.0f/aSize.height(), 1.0f);
+                );
+        VBOXQGL_CHECKERR(
+                glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
+                );
+    }
+}
+void VBoxGLWidget::adjustViewport(const QSize &display, const QRect &viewport)
+{
+    /* viewport:  (viewport.x;viewport.y) (viewport.width;viewport.height)*/
+    glViewport(-((int)display.width() + viewport.x()),
+                -((int)display.height() - viewport.y() + display.height() - viewport.height()),
+                2*display.width(),
+                2*display.height());
+}
+
+void VBoxGLWidget::setupMatricies(const QSize &display)
+{
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glFrustum(0., (GLdouble)display.width(), 0., (GLdouble)display.height(), 0., 0.);
+
+    glMatrixMode(GL_MODELVIEW);
+    //    doSetupMatrix(bInverted ? &mRect.size() : &mTargSize.size(), bInverted);
+    doSetupMatrix(display, false);
+}
+
+void VBoxGLWidget::postCmd(VBOXVHWA_PIPECMD_TYPE aType, void * pvData)
+{
+    /* 1. lock*/
+    RTCritSectEnter(&mCritSect);
+    VBoxVHWACommandElement * pCmd = mFreeElements.pop();
+    if(!pCmd)
+    {
+        VBOXQGLLOG(("!!!no more free elements!!!\n"));
+#ifdef VBOXQGL_PROF_BASE
+        RTCritSectLeave(&mCritSect);
+        return;
+#else
+    //TODO:
+#endif
+    }
+    pCmd->setData(aType, pvData);
+    /* 2. if can add to current*/
+    if(!mbNewEvent)
+    {
+        /* 3. if event is being processed (event != 0) */
+        if(mpLastEvent)
+        {
+            /* 3.a add cmd to event */
+            mpLastEvent->pipe().put(pCmd);
+            /* 3.b unlock and return */
+            RTCritSectLeave(&mCritSect);
+            return;
+        }
+    }
+
+    /* we're here because the cmd was NOT be added to the current event queue */
+    /* 4. unlock*/
+    RTCritSectLeave(&mCritSect);
+    /* 5. create & initialize new Event */
+    VBoxVHWACommandProcessEvent *pCurrentEvent = new VBoxVHWACommandProcessEvent(pCmd);
+    /* 6. lock */
+    RTCritSectEnter(&mCritSect);
+    /* 7. if no current event set event as current */
+    if(!mpLastEvent)
+    {
+        Assert(!mpFirstEvent);
+        mpFirstEvent = pCurrentEvent;
+        mpLastEvent = pCurrentEvent;
+        pCurrentEvent->mpNext = NULL;
+    }
+    else
+    {
+        mpLastEvent->mpNext = pCurrentEvent;
+        mpLastEvent = pCurrentEvent;
+    }
+    /* 8. reset blocking events counter */
+    mbNewEvent = false;
+    /* 9. unlock */
+    RTCritSectLeave(&mCritSect);
+    /* 10. post event */
+    QApplication::postEvent (mView, pCurrentEvent);
+}
+
+VBoxVHWACommandElement * VBoxGLWidget::detachCmdList(VBoxVHWACommandElement * pFirst2Free, VBoxVHWACommandElement * pLast2Free)
+{
+    VBoxVHWACommandElement * pList = NULL;
+    RTCritSectEnter(&mCritSect);
+    if(pFirst2Free)
+    {
+        mFreeElements.pusha(pFirst2Free, pLast2Free);
+    }
+    if(mpFirstEvent)
+    {
+        pList = mpFirstEvent->pipe().detachList();
+        if(!pList)
+        {
+            VBoxVHWACommandProcessEvent *pNext = mpFirstEvent->mpNext;
+            if(pNext)
+            {
+                mpFirstEvent = pNext;
+            }
+            else
+            {
+                mpFirstEvent = NULL;
+                mpLastEvent = NULL;
+            }
+        }
+    }
+    RTCritSectLeave(&mCritSect);
+
+    return pList;
+}
+
+VBoxVHWACommandElement * VBoxGLWidget::processCmdList(VBoxVHWACommandElement * pCmd)
+{
+    VBoxVHWACommandElement * pCur;
+    do
+    {
+        pCur = pCmd;
+        switch(pCmd->type())
+        {
+        case VBOXVHWA_PIPECMD_PAINT:
+            vboxDoUpdateRect(&pCmd->rect());
+            break;
+#ifdef VBOX_WITH_VIDEOHWACCEL
+        case VBOXVHWA_PIPECMD_VHWA:
+            vboxDoVHWACmd(pCmd->vhwaCmd());
+            break;
+        case VBOXVHWA_PIPECMD_OP:
+        {
+            const VBOXVHWACALLBACKINFO & info = pCmd->op();
+            (info.pThis->*(info.pfnCallback))(info.pContext);
+            break;
+        }
+#endif
+        default:
+            Assert(0);
+        }
+        pCmd = pCmd->mpNext;
+    } while(pCmd);
+
+    return pCur;
+}
+
+void VBoxGLWidget::vboxDoProcessVHWACommands(void *pContext)
+{
+    VBoxVHWACommandElement * pFirst = detachCmdList(NULL, NULL);
+    do
+    {
+        VBoxVHWACommandElement * pLast = processCmdList(pFirst);
+
+        pFirst = detachCmdList(pFirst, pLast);
+    } while(pFirst);
+
+    mDisplay.performDisplay();
+}
+
+#ifdef VBOX_WITH_VIDEOHWACCEL
+/* static */
+bool VBoxQGLFrameBuffer::isAcceleration2DVideoAvailable()
+{
+    vboxVHWAGlInit(NULL);
+    return vboxVHWASupportedInternal();
+}
+
+STDMETHODIMP VBoxQGLFrameBuffer::ProcessVHWACommand(BYTE *pCommand)
+{
+    VBOXVHWACMD * pCmd = (VBOXVHWACMD*)pCommand;
+//    Assert(0);
+    /* indicate that we process and complete the command asynchronously */
+    pCmd->Flags |= VBOXVHWACMD_FLAG_HG_ASYNCH;
+    /* post the command to the GUI thread for processing */
+//    QApplication::postEvent (mView,
+//                             new VBoxVHWACommandProcessEvent (pCmd));
+    vboxWidget()->postCmd(VBOXVHWA_PIPECMD_VHWA, pCmd);
+    return S_OK;
+}
+
+void VBoxGLWidget::vboxDoVHWACmd(void *cmd)
+{
+    vboxDoVHWACmdExec(cmd);
+
+    CDisplay display = mView->console().GetDisplay();
+    Assert (!display.isNull());
+
+    display.CompleteVHWACommand((BYTE*)cmd);
+}
+
+void VBoxGLWidget::vboxDoVHWACmdAndFree(void *cmd)
+{
+    vboxDoVHWACmdExec(cmd);
+
+    delete cmd;
+}
+
+void VBoxGLWidget::vboxDoVHWACmdExec(void *cmd)
+{
+    struct _VBOXVHWACMD * pCmd = (struct _VBOXVHWACMD *)cmd;
+    switch(pCmd->enmCmd)
+    {
+        case VBOXVHWACMD_TYPE_SURF_CANCREATE:
+        {
+            VBOXVHWACMD_SURF_CANCREATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CANCREATE);
+            pCmd->rc = vhwaSurfaceCanCreate(pBody);
+        } break;
+        case VBOXVHWACMD_TYPE_SURF_CREATE:
+        {
+            VBOXVHWACMD_SURF_CREATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
+            pCmd->rc = vhwaSurfaceCreate(pBody);
+        } break;
+        case VBOXVHWACMD_TYPE_SURF_DESTROY:
+        {
+            VBOXVHWACMD_SURF_DESTROY * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
+            pCmd->rc = vhwaSurfaceDestroy(pBody);
+        } break;
+        case VBOXVHWACMD_TYPE_SURF_LOCK:
+        {
+            VBOXVHWACMD_SURF_LOCK * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_LOCK);
+            pCmd->rc = vhwaSurfaceLock(pBody);
+        } break;
+        case VBOXVHWACMD_TYPE_SURF_UNLOCK:
+        {
+            VBOXVHWACMD_SURF_UNLOCK * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_UNLOCK);
+            pCmd->rc = vhwaSurfaceUnlock(pBody);
+        } break;
+        case VBOXVHWACMD_TYPE_SURF_BLT:
+        {
+            VBOXVHWACMD_SURF_BLT * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_BLT);
+            pCmd->rc = vhwaSurfaceBlt(pBody);
+        } break;
+        case VBOXVHWACMD_TYPE_SURF_FLIP:
+        {
+            VBOXVHWACMD_SURF_FLIP * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_FLIP);
+            pCmd->rc = vhwaSurfaceFlip(pBody);
+        } break;
+        case VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE:
+        {
+            VBOXVHWACMD_SURF_OVERLAY_UPDATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
+            pCmd->rc = vhwaSurfaceOverlayUpdate(pBody);
+        } break;
+        case VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION:
+        {
+            VBOXVHWACMD_SURF_OVERLAY_SETPOSITION * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_SETPOSITION);
+            pCmd->rc = vhwaSurfaceOverlaySetPosition(pBody);
+        } break;
+        case VBOXVHWACMD_TYPE_SURF_COLORKEY_SET:
+        {
+            VBOXVHWACMD_SURF_COLORKEY_SET * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_COLORKEY_SET);
+            pCmd->rc = vhwaSurfaceColorkeySet(pBody);
+        } break;
+        case VBOXVHWACMD_TYPE_QUERY_INFO1:
+        {
+            VBOXVHWACMD_QUERYINFO1 * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
+            pCmd->rc = vhwaQueryInfo1(pBody);
+        } break;
+        case VBOXVHWACMD_TYPE_QUERY_INFO2:
+        {
+            VBOXVHWACMD_QUERYINFO2 * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO2);
+            pCmd->rc = vhwaQueryInfo2(pBody);
+        } break;
+        case VBOXVHWACMD_TYPE_ENABLE:
+        case VBOXVHWACMD_TYPE_DISABLE:
+            pCmd->rc = VINF_SUCCESS;
+            break;
+        case VBOXVHWACMD_TYPE_HH_CONSTRUCT:
+        {
+            VBOXVHWACMD_HH_CONSTRUCT * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_HH_CONSTRUCT);
+            pCmd->rc = vhwaConstruct(pBody);
+        } break;
+        default:
+            Assert(0);
+            pCmd->rc = VERR_NOT_IMPLEMENTED;
+            break;
+    }
+}
+
+int VBoxGLWidget::vhwaSurfaceCanCreate(struct _VBOXVHWACMD_SURF_CANCREATE *pCmd)
+{
+    VBOXQGLLOG_ENTER(("\n"));
+
+    if(!(pCmd->SurfInfo.flags & VBOXVHWA_SD_CAPS))
+    {
+        Assert(0);
+        pCmd->u.out.ErrInfo = 1;
+        return VINF_SUCCESS;
+    }
+
+    if(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE)
+    {
+        pCmd->u.out.ErrInfo = 0;
+        return VINF_SUCCESS;
+    }
+
+    if(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN)
+    {
+        pCmd->u.out.ErrInfo = 1;
+        return VINF_SUCCESS;
+    }
+
+    Assert(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN
+            || pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY);
+
+    if(pCmd->u.in.bIsDifferentPixelFormat)
+    {
+        if(!(pCmd->SurfInfo.flags & VBOXVHWA_SD_PIXELFORMAT))
+        {
+            Assert(0);
+            pCmd->u.out.ErrInfo = 1;
+            return VINF_SUCCESS;
+        }
+
+        if(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
+        {
+            if(pCmd->SurfInfo.PixelFormat.c.rgbBitCount != 32
+                    || pCmd->SurfInfo.PixelFormat.c.rgbBitCount != 24)
+            {
+                Assert(0);
+                pCmd->u.out.ErrInfo = 1;
+                return VINF_SUCCESS;
+            }
+        }
+        else if(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
+        {
+            /* detect whether we support this format */
+            bool bFound = false;
+            for(uint32_t i = 0; i < g_vboxVHWAFourccSupportedCount; i++)
+            {
+                if(g_vboxVHWAFourccSupportedList[i] == pCmd->SurfInfo.PixelFormat.fourCC)
+                {
+                    bFound = true;
+                    break;
+                }
+            }
+            Assert(bFound);
+            if(!bFound)
+            {
+                Assert(0);
+                pCmd->u.out.ErrInfo = 1;
+                return VINF_SUCCESS;
+            }
+        }
+        else
+        {
+            Assert(0);
+            pCmd->u.out.ErrInfo = 1;
+            return VINF_SUCCESS;
+        }
+    }
+
+    pCmd->u.out.ErrInfo = 0;
+    return VINF_SUCCESS;
+}
+
+int VBoxGLWidget::vhwaSurfaceCreate(struct _VBOXVHWACMD_SURF_CREATE *pCmd)
+{
+    VBOXQGLLOG_ENTER(("\n"));
+
+    uint32_t handle = VBOXVHWA_SURFHANDLE_INVALID;
+    if(pCmd->SurfInfo.hSurf != VBOXVHWA_SURFHANDLE_INVALID)
+    {
+        handle = pCmd->SurfInfo.hSurf;
+        if(mSurfHandleTable.get(handle))
+        {
+//            do
+//            {
+//                if(!mcVGASurfCreated)
+//                {
+//                    /* check if it is a primary surface that needs handle adjusting*/
+//                    if((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE)
+//                            && handle2Surface(handle) == mDisplay.getVGA())
+//                    {
+//                        /* remove, the primary surface will be assigned to a new handle assumed by the guest */
+//                        mSurfHandleTable.remove(handle);
+//                        break;
+//                    }
+//                }
+                Assert(0);
+                return VERR_GENERAL_FAILURE;
+//            }while(0);
+        }
+    }
+
+    VBoxVHWASurfaceBase *surf = NULL;
+//    VBoxVHWAColorFormat *pFormat = NULL, Format;
+    bool bPrimary = false;
+
+    VBoxVHWAColorKey *pDstBltCKey = NULL, DstBltCKey;
+    VBoxVHWAColorKey *pSrcBltCKey = NULL, SrcBltCKey;
+    VBoxVHWAColorKey *pDstOverlayCKey = NULL, DstOverlayCKey;
+    VBoxVHWAColorKey *pSrcOverlayCKey = NULL, SrcOverlayCKey;
+    if(pCmd->SurfInfo.flags & VBOXVHWA_SD_CKDESTBLT)
+    {
+        DstBltCKey = VBoxVHWAColorKey(pCmd->SurfInfo.DstBltCK.high, pCmd->SurfInfo.DstBltCK.low);
+        pDstBltCKey = &DstBltCKey;
+    }
+    if(pCmd->SurfInfo.flags & VBOXVHWA_SD_CKSRCBLT)
+    {
+        SrcBltCKey = VBoxVHWAColorKey(pCmd->SurfInfo.SrcBltCK.high, pCmd->SurfInfo.SrcBltCK.low);
+        pSrcBltCKey = &SrcBltCKey;
+    }
+    if(pCmd->SurfInfo.flags & VBOXVHWA_SD_CKDESTOVERLAY)
+    {
+        DstOverlayCKey = VBoxVHWAColorKey(pCmd->SurfInfo.DstOverlayCK.high, pCmd->SurfInfo.DstOverlayCK.low);
+        pDstOverlayCKey = &DstOverlayCKey;
+    }
+    if(pCmd->SurfInfo.flags & VBOXVHWA_SD_CKSRCOVERLAY)
+    {
+        SrcOverlayCKey = VBoxVHWAColorKey(pCmd->SurfInfo.SrcOverlayCK.high, pCmd->SurfInfo.SrcOverlayCK.low);
+        pSrcOverlayCKey = &SrcOverlayCKey;
+    }
+
+    if(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE)
+    {
+        bPrimary = true;
+        if(!mbVGASurfCreated)
+        {
+            VBoxVHWASurfaceBase * pVga = vboxGetVGASurface();
+            if(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
+            {
+                if(pCmd->SurfInfo.width == pVga->width()
+                        && pCmd->SurfInfo.height == pVga->height())
+                {
+                    VBoxVHWAColorFormat format(pCmd->SurfInfo.PixelFormat.c.rgbBitCount,
+                                                pCmd->SurfInfo.PixelFormat.m1.rgbRBitMask,
+                                                pCmd->SurfInfo.PixelFormat.m2.rgbGBitMask,
+                                                pCmd->SurfInfo.PixelFormat.m3.rgbBBitMask);
+                    if(pVga->colorFormat().equals(format))
+                    {
+                        surf = pVga;
+
+                        surf->setDstBltCKey(pDstBltCKey);
+                        surf->setSrcBltCKey(pSrcBltCKey);
+
+                        surf->setDefaultDstOverlayCKey(pDstOverlayCKey);
+                        surf->resetDefaultDstOverlayCKey();
+
+                        surf->setDefaultSrcOverlayCKey(pDstOverlayCKey);
+                        surf->resetDefaultSrcOverlayCKey();
+                        mbVGASurfCreated = true;
+                    }
+                }
+            }
+        }
+    }
+
+    if(!surf)
+    {
+        if(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
+        {
+        	VBoxVHWAColorFormat format(pCmd->SurfInfo.PixelFormat.c.rgbBitCount,
+        	                                pCmd->SurfInfo.PixelFormat.m1.rgbRBitMask,
+        	                                pCmd->SurfInfo.PixelFormat.m2.rgbGBitMask,
+        	                                pCmd->SurfInfo.PixelFormat.m3.rgbBBitMask);
+            surf = new VBoxVHWASurfaceBase(this, &QSize(pCmd->SurfInfo.width, pCmd->SurfInfo.height),
+//                        ((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY) ? mDisplay.getPrimary()->rect().size() : &QSize(pCmd->SurfInfo.width, pCmd->SurfInfo.height)),
+                        &mDisplay.getPrimary()->rect().size(),
+                        format,
+                        pSrcBltCKey, pDstBltCKey, pSrcOverlayCKey, pDstOverlayCKey,
+                        bPrimary);
+        }
+        else if(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
+        {
+            VBoxVHWAColorFormat format(pCmd->SurfInfo.PixelFormat.fourCC);
+            surf = new VBoxVHWASurfaceBase(this, &QSize(pCmd->SurfInfo.width, pCmd->SurfInfo.height),
+            //                        ((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY) ? mDisplay.getPrimary()->rect().size() : &QSize(pCmd->SurfInfo.width, pCmd->SurfInfo.height)),
+                                    &mDisplay.getPrimary()->rect().size(),
+                                    format,
+                                    pSrcBltCKey, pDstBltCKey, pSrcOverlayCKey, pDstOverlayCKey,
+                                    bPrimary);
+        }
+        else
+        {
+            Assert(0);
+            VBOXQGLLOG_EXIT(("pSurf (0x%x)\n",surf));
+            return VERR_GENERAL_FAILURE;
+        }
+
+        uchar * addr = vboxVRAMAddressFromOffset(pCmd->SurfInfo.offSurface);
+        surf->init(mDisplay.getVGA(), addr);
+
+        if(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY)
+        {
+            Assert(!bPrimary);
+
+            if(!mConstructingList)
+            {
+                mConstructingList = new VBoxVHWASurfList();
+                mcRemaining2Contruct = pCmd->SurfInfo.cBackBuffers+1;
+                mDisplay.addOverlay(mConstructingList);
+            }
+
+            mConstructingList->add(surf);
+            mcRemaining2Contruct--;
+            if(!mcRemaining2Contruct)
+            {
+                mConstructingList = NULL;
+            }
+        }
+        else if(bPrimary)
+        {
+            Assert(mbVGASurfCreated);
+            mDisplay.getVGA()->getComplexList()->add(surf);
+            if(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_VISIBLE)
+            {
+                Assert(surf->getComplexList() == mDisplay.getVGA()->getComplexList());
+                surf->getComplexList()->setCurrentVisible(surf);
+            }
+        }
+        else if(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_COMPLEX)
+        {
+            //TODO: impl fullscreen mode support
+            Assert(0);
+        }
+        else
+        {
+            Assert(0);
+        }
+    }
+
+    /* tell the guest how we think the memory is organized */
+    VBOXQGLLOG(("bps: %d\n", surf->bitsPerPixel()));
+
+    pCmd->SurfInfo.pitch        = surf->bitsPerPixel() * surf->width() / 8;
+    pCmd->SurfInfo.sizeX = surf->memSize();
+    pCmd->SurfInfo.sizeY = 1;
+
+    if(handle != VBOXVHWA_SURFHANDLE_INVALID)
+    {
+        bool bSuccess = mSurfHandleTable.mapPut(handle, surf);
+        Assert(bSuccess);
+        if(!bSuccess)
+        {
+            /* @todo: this is very bad, should not be here */
+            return VERR_GENERAL_FAILURE;
+        }
+    }
+    else
+    {
+        /* tell the guest our handle */
+        handle = mSurfHandleTable.put(surf);
+        pCmd->SurfInfo.hSurf = (VBOXVHWA_SURFHANDLE)handle;
+    }
+
+    surf->setHandle(handle);
+
+    VBOXQGLLOG_EXIT(("pSurf (0x%x)\n",surf));
+
+    return VINF_SUCCESS;
+}
+
+int VBoxGLWidget::vhwaSurfaceDestroy(struct _VBOXVHWACMD_SURF_DESTROY *pCmd)
+{
+    VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
+    VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
+    if(pSurf != mDisplay.getVGA())
+    {
+        VBoxVHWASurfList *pList = pSurf->getComplexList();
+        if(pList)
+        {
+            pList->remove(pSurf);
+            if(pList->surfaces().empty())
+            {
+                mDisplay.removeOverlay(pList);
+//                Assert(mConstructingList != pList);
+                if(pList == mConstructingList)
+                {
+                    mConstructingList = NULL;
+                    mcRemaining2Contruct = 0;
+                }
+                delete pList;
+            }
+            else if(pList == mDisplay.getVGA()->getComplexList())
+            {
+                if(pList->current() == NULL)
+                {
+                    pList->setCurrentVisible(mDisplay.getVGA());
+                }
+            }
+        }
+
+        delete(pSurf);
+    }
+    else
+    {
+        Assert(mbVGASurfCreated);
+        mbVGASurfCreated = false;
+    }
+
+    void * test = mSurfHandleTable.remove(pCmd->u.in.hSurf);
+    Assert(test);
+
+    return VINF_SUCCESS;
+}
+
+#define VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_RB(_pr) \
+             QRect((_pr)->left,                     \
+                 (_pr)->top,                        \
+                 (_pr)->right - (_pr)->left + 1,    \
+                 (_pr)->bottom - (_pr)->top + 1)
+
+#define VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(_pr) \
+             QRect((_pr)->left,                     \
+                 (_pr)->top,                        \
+                 (_pr)->right - (_pr)->left,        \
+                 (_pr)->bottom - (_pr)->top)
+
+int VBoxGLWidget::vhwaSurfaceLock(struct _VBOXVHWACMD_SURF_LOCK *pCmd)
+{
+    VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
+    VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
+    vboxCheckUpdateAddress (pSurf, pCmd->u.in.offSurface);
+    if(pCmd->u.in.rectValid)
+    {
+        QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.rect);
+        return pSurf->lock(&r, pCmd->u.in.flags);
+    }
+    return pSurf->lock(NULL, pCmd->u.in.flags);
+}
+
+int VBoxGLWidget::vhwaSurfaceUnlock(struct _VBOXVHWACMD_SURF_UNLOCK *pCmd)
+{
+    VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
+    VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
+    if(pCmd->u.in.xUpdatedMemValid)
+    {
+        QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedMemRect);
+        pSurf->updatedMem(&r);
+    }
+    return pSurf->unlock();
+}
+
+int VBoxGLWidget::vhwaSurfaceBlt(struct _VBOXVHWACMD_SURF_BLT *pCmd)
+{
+    /**/
+    return VERR_NOT_IMPLEMENTED;
+//    VBoxVHWASurfaceBase *pDstSurf = (VBoxVHWASurfaceBase*)pCmd->u.in.hDstSurf;
+//    VBoxVHWASurfaceBase *pSrcSurf = (VBoxVHWASurfaceBase*)pCmd->u.in.hSrcSurf;
+//    VBOXQGLLOG_ENTER(("pDstSurf (0x%x), pSrcSurf (0x%x)\n",pDstSurf,pSrcSurf));
+//    QRect dstRect = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL(&pCmd->u.in.dstRect);
+//    QRect srcRect = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL(&pCmd->u.in.srcRect);
+//    vboxCheckUpdateAddress (pSrcSurf, pCmd->u.in.offSrcSurface);
+//    vboxCheckUpdateAddress (pDstSurf, pCmd->u.in.offDstSurface);
+////    pDstSurf->makeCurrent();
+////    const VBoxVHWAColorKey DstCKey, *pDstCKey = NULL;
+////    const VBoxVHWAColorKey SrcCKey, *pSrcCKey = NULL;
+////    if(pCmd->u.in.flags & VBOXVHWA_BLT_KEYSRCOVERRIDE)
+////    {
+////        pSrcCKey = &
+////    }
+////    if(pCmd->u.in.flags & VBOXVHWA_BLT_KEYDESTOVERRIDE)
+////    {
+////
+////    }
+//    if(pCmd->u.in.xUpdatedSrcMemValid)
+//    {
+//        QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL(&pCmd->u.in.xUpdatedSrcMemRect);
+//        pSrcSurf->updatedMem(&r);
+//    }
+//
+//    return pDstSurf->blt(&dstRect, pSrcSurf, &srcRect,
+//            pCmd->u.in.flags & VBOXVHWA_BLT_KEYSRCOVERRIDE ? &VBoxVHWAColorKey(pCmd->u.in.desc.SrcCK.high, pCmd->u.in.desc.SrcCK.low) : NULL,
+//            pCmd->u.in.flags & VBOXVHWA_BLT_KEYDESTOVERRIDE ? &VBoxVHWAColorKey(pCmd->u.in.desc.DstCK.high, pCmd->u.in.desc.DstCK.low) : NULL);
+}
+
+int VBoxGLWidget::vhwaSurfaceFlip(struct _VBOXVHWACMD_SURF_FLIP *pCmd)
+{
+    VBoxVHWASurfaceBase *pTargSurf = handle2Surface(pCmd->u.in.hTargSurf);
+    VBoxVHWASurfaceBase *pCurrSurf = handle2Surface(pCmd->u.in.hCurrSurf);
+    VBOXQGLLOG_ENTER(("pTargSurf (0x%x), pCurrSurf (0x%x)\n",pTargSurf,pCurrSurf));
+    vboxCheckUpdateAddress (pCurrSurf, pCmd->u.in.offCurrSurface);
+    vboxCheckUpdateAddress (pTargSurf, pCmd->u.in.offTargSurface);
+
+//    Assert(pTargSurf->isYInverted());
+//    Assert(!pCurrSurf->isYInverted());
+    if(pCmd->u.in.xUpdatedTargMemValid)
+    {
+        QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedTargMemRect);
+        pTargSurf->updatedMem(&r);
+    }
+    pTargSurf->getComplexList()->setCurrentVisible(pTargSurf);
+
+#ifdef DEBUG
+    pCurrSurf->cFlipsCurr++;
+    pTargSurf->cFlipsTarg++;
+#endif
+//    mDisplay.flip(pTargSurf, pCurrSurf);
+//    Assert(!pTargSurf->isYInverted());
+//    Assert(pCurrSurf->isYInverted());
+    return VINF_SUCCESS;
+}
+
+void VBoxGLWidget::vhwaDoSurfaceOverlayUpdate(VBoxVHWASurfaceBase *pDstSurf, VBoxVHWASurfaceBase *pSrcSurf, struct _VBOXVHWACMD_SURF_OVERLAY_UPDATE *pCmd)
+{
+    if(pCmd->u.in.flags & VBOXVHWA_OVER_KEYDEST)
+    {
+        VBOXQGLLOG((", KEYDEST"));
+        /* we use src (overlay) surface to maintain overridden dst ckey info
+         * to allow multiple overlays have different overridden dst keys for one primary surface */
+        /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
+         * dst ckey value in defaultDstOverlayCKey
+         * this allows the NULL to be a valid overridden value as well
+         *  i.e.
+         * 1. indicate the value is NUL overridden, just set NULL*/
+        pSrcSurf->setOverriddenDstOverlayCKey(NULL);
+    }
+    else if(pCmd->u.in.flags & VBOXVHWA_OVER_KEYDESTOVERRIDE)
+    {
+        VBOXQGLLOG((", KEYDESTOVERRIDE"));
+        /* we use src (overlay) surface to maintain overridden dst ckey info
+         * to allow multiple overlays have different overridden dst keys for one primary surface */
+        /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
+         * dst ckey value in defaultDstOverlayCKey
+         * this allows the NULL to be a valid overridden value as well
+         *  i.e.
+         * 1. indicate the value is overridden (no matter what we write here, bu it should be not NULL)*/
+        VBoxVHWAColorKey ckey(pCmd->u.in.desc.DstCK.high, pCmd->u.in.desc.DstCK.low);
+        VBOXQGLLOG_CKEY(" ckey: ",&ckey, "\n");
+        pSrcSurf->setOverriddenDstOverlayCKey(&ckey);
+        /* tell the ckey is enabled */
+        pSrcSurf->setDefaultDstOverlayCKey(&ckey);
+    }
+    else
+    {
+        VBOXQGLLOG((", no KEYDEST"));
+        /* we use src (overlay) surface to maintain overridden dst ckey info
+         * to allow multiple overlays have different overridden dst keys for one primary surface */
+        /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
+         * dst ckey value in defaultDstOverlayCKey
+         * this allows the NULL to be a valid overridden value as well
+         * i.e.
+         * 1. indicate the value is overridden (no matter what we write here, bu it should be not NULL)*/
+        pSrcSurf->setOverriddenDstOverlayCKey(&VBoxVHWAColorKey(0, 0));
+        /* tell the ckey is disabled */
+        pSrcSurf->setDefaultDstOverlayCKey(NULL);
+    }
+
+    if(pCmd->u.in.flags & VBOXVHWA_OVER_KEYSRC)
+    {
+        VBOXQGLLOG((", KEYSRC"));
+        pSrcSurf->resetDefaultSrcOverlayCKey();
+    }
+    else if(pCmd->u.in.flags & VBOXVHWA_OVER_KEYSRCOVERRIDE)
+    {
+        VBOXQGLLOG((", KEYSRCOVERRIDE"));
+        pSrcSurf->setOverriddenSrcOverlayCKey(&VBoxVHWAColorKey(pCmd->u.in.desc.SrcCK.high, pCmd->u.in.desc.SrcCK.low));
+    }
+    else
+    {
+        VBOXQGLLOG((", no KEYSRC"));
+        pSrcSurf->setOverriddenSrcOverlayCKey(NULL);
+    }
+    VBOXQGLLOG(("\n"));
+    if(pDstSurf)
+    {
+        QRect dstRect = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.dstRect);
+        QRect srcRect = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.srcRect);
+
+        VBOXQGLLOG(("*******overlay update*******\n"));
+        VBOXQGLLOG(("dstSurfSize: w(%d), h(%d)\n", pDstSurf->width(), pDstSurf->height()));
+        VBOXQGLLOG(("srcSurfSize: w(%d), h(%d)\n", pSrcSurf->width(), pSrcSurf->height()));
+        VBOXQGLLOG_QRECT("dstRect:", &dstRect, "\n");
+        VBOXQGLLOG_QRECT("srcRect:", &srcRect, "\n");
+
+        const VBoxVHWAColorKey *pResSrcCKey = pSrcSurf->getActiveSrcOverlayCKey();
+        const VBoxVHWAColorKey *pResDstCKey = pSrcSurf->getActiveDstOverlayCKey(pDstSurf);
+
+        VBoxVHWAGlProgramVHWA *pProgram = vboxVHWAGetGlProgramMngr()->getProgram(pResDstCKey != NULL, pResSrcCKey != NULL, &pSrcSurf->colorFormat(), &pDstSurf->colorFormat());
+
+        if(pProgram)
+        {
+            pProgram->start();
+            if(pResSrcCKey || pResDstCKey)
+            {
+                if(pResSrcCKey)
+                {
+                    VBoxVHWASurfaceBase::setCKey(pProgram, &pSrcSurf->colorFormat(), pResSrcCKey, false);
+                }
+                if(pResDstCKey)
+                {
+                    VBoxVHWASurfaceBase::setCKey(pProgram, &pDstSurf->colorFormat(), pResDstCKey, true);
+                }
+
+            }
+
+            switch(pSrcSurf->fourcc())
+            {
+                case 0:
+                case FOURCC_AYUV:
+                case FOURCC_YV12:
+                    break;
+                case FOURCC_UYVY:
+                case FOURCC_YUY2:
+                    break;
+                default:
+                    Assert(0);
+                    break;
+            }
+
+            pProgram->stop();
+        }
+
+        pSrcSurf->setRects(pDstSurf, &dstRect, &srcRect);
+    }
+}
+
+int VBoxGLWidget::vhwaSurfaceOverlayUpdate(struct _VBOXVHWACMD_SURF_OVERLAY_UPDATE *pCmd)
+{
+    VBoxVHWASurfaceBase *pSrcSurf = handle2Surface(pCmd->u.in.hSrcSurf);
+    VBoxVHWASurfList *pList = pSrcSurf->getComplexList();
+    vboxCheckUpdateAddress (pSrcSurf, pCmd->u.in.offSrcSurface);
+    VBOXQGLLOG(("OverlayUpdate: pSrcSurf (0x%x)\n",pSrcSurf));
+    VBoxVHWASurfaceBase *pDstSurf = NULL;
+
+    if(pCmd->u.in.hDstSurf)
+    {
+        pDstSurf = handle2Surface(pCmd->u.in.hDstSurf);
+        vboxCheckUpdateAddress (pDstSurf, pCmd->u.in.offDstSurface);
+        VBOXQGLLOG(("pDstSurf (0x%x)\n",pDstSurf));
+    }
+
+    const SurfList & surfaces = pList->surfaces();
+
+    for (SurfList::const_iterator it = surfaces.begin();
+             it != surfaces.end(); ++ it)
+    {
+        VBoxVHWASurfaceBase *pCurSrcSurf = (*it);
+        vhwaDoSurfaceOverlayUpdate(pDstSurf, pCurSrcSurf, pCmd);
+    }
+
+    if(pCmd->u.in.flags & VBOXVHWA_OVER_HIDE)
+    {
+        VBOXQGLLOG(("hide"));
+        pList->setCurrentVisible(NULL);
+    }
+    else if(pCmd->u.in.flags & VBOXVHWA_OVER_SHOW)
+    {
+        VBOXQGLLOG(("show"));
+        pList->setCurrentVisible(pSrcSurf);
+    }
+
+    return VINF_SUCCESS;
+}
+
+int VBoxGLWidget::vhwaSurfaceOverlaySetPosition(struct _VBOXVHWACMD_SURF_OVERLAY_SETPOSITION *pCmd)
+{
+    VBoxVHWASurfaceBase *pDstSurf = handle2Surface(pCmd->u.in.hDstSurf);
+    VBoxVHWASurfaceBase *pSrcSurf = handle2Surface(pCmd->u.in.hSrcSurf);
+
+    VBOXQGLLOG_ENTER(("pDstSurf (0x%x), pSrcSurf (0x%x)\n",pDstSurf,pSrcSurf));
+
+    vboxCheckUpdateAddress (pSrcSurf, pCmd->u.in.offSrcSurface);
+    vboxCheckUpdateAddress (pDstSurf, pCmd->u.in.offDstSurface);
+
+    VBoxVHWASurfList *pList = pSrcSurf->getComplexList();
+    const SurfList & surfaces = pList->surfaces();
+
+    for (SurfList::const_iterator it = surfaces.begin();
+             it != surfaces.end(); ++ it)
+    {
+        VBoxVHWASurfaceBase *pCurSrcSurf = (*it);
+        pCurSrcSurf->setTargetRectPosition(pDstSurf, &QPoint(pCmd->u.in.xPos, pCmd->u.in.yPos));;
+    }
+
+    return VINF_SUCCESS;
+}
+
+int VBoxGLWidget::vhwaSurfaceColorkeySet(struct _VBOXVHWACMD_SURF_COLORKEY_SET *pCmd)
+{
+    VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
+
+    VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
+
+    vboxCheckUpdateAddress (pSurf, pCmd->u.in.offSurface);
+
+//    VBOXVHWA_CKEY_COLORSPACE
+    if(pCmd->u.in.flags & VBOXVHWA_CKEY_DESTBLT)
+    {
+        pSurf->setDstBltCKey(&VBoxVHWAColorKey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low));
+    }
+    if(pCmd->u.in.flags & VBOXVHWA_CKEY_DESTOVERLAY)
+    {
+        pSurf->setDefaultDstOverlayCKey(&VBoxVHWAColorKey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low));
+    }
+    if(pCmd->u.in.flags & VBOXVHWA_CKEY_SRCBLT)
+    {
+        pSurf->setSrcBltCKey(&VBoxVHWAColorKey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low));
+    }
+    if(pCmd->u.in.flags & VBOXVHWA_CKEY_SRCOVERLAY)
+    {
+        pSurf->setDefaultSrcOverlayCKey(&VBoxVHWAColorKey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low));
+    }
+
+    return VINF_SUCCESS;
+}
+
+int VBoxGLWidget::vhwaQueryInfo1(struct _VBOXVHWACMD_QUERYINFO1 *pCmd)
+{
+    VBOXQGLLOG_ENTER(("\n"));
+    bool bEnabled = false;
+    if(vboxVHWASupportedInternal())
+    {
+        Assert(pCmd->u.in.guestVersion.maj == VBOXVHWA_VERSION_MAJ);
+        if(pCmd->u.in.guestVersion.maj == VBOXVHWA_VERSION_MAJ)
+        {
+            Assert(pCmd->u.in.guestVersion.min == VBOXVHWA_VERSION_MIN);
+            if(pCmd->u.in.guestVersion.min == VBOXVHWA_VERSION_MIN)
+            {
+                Assert(pCmd->u.in.guestVersion.bld == VBOXVHWA_VERSION_BLD);
+                if(pCmd->u.in.guestVersion.bld == VBOXVHWA_VERSION_BLD)
+                {
+                    Assert(pCmd->u.in.guestVersion.reserved == VBOXVHWA_VERSION_RSV);
+                    if(pCmd->u.in.guestVersion.reserved == VBOXVHWA_VERSION_RSV)
+                    {
+                        bEnabled = true;
+                    }
+                }
+            }
+        }
+    }
+
+    memset(pCmd, 0, sizeof(VBOXVHWACMD_QUERYINFO1));
+    if(bEnabled)
+    {
+        pCmd->u.out.cfgFlags = VBOXVHWA_CFG_ENABLED;
+
+        pCmd->u.out.caps =
+//                        VBOXVHWA_CAPS_BLT | VBOXVHWA_CAPS_BLTSTRETCH | VBOXVHWA_CAPS_BLTQUEUE
+//                                 // | VBOXVHWA_CAPS_BLTCOLORFILL not supported, although adding it is trivial
+//                                 // | VBOXVHWA_CAPS_BLTFOURCC set below if shader support is available
+                                 VBOXVHWA_CAPS_OVERLAY
+                                 | VBOXVHWA_CAPS_OVERLAYSTRETCH
+                                 | VBOXVHWA_CAPS_OVERLAYCANTCLIP
+                                 // | VBOXVHWA_CAPS_OVERLAYFOURCC set below if shader support is available
+                                 ;
+
+        pCmd->u.out.caps2 = VBOXVHWA_CAPS2_CANRENDERWINDOWED
+                                    | VBOXVHWA_CAPS2_WIDESURFACES;
+
+        //TODO: setup stretchCaps
+        pCmd->u.out.stretchCaps = 0;
+
+        pCmd->u.out.numOverlays = 1;
+        /* TODO: set curOverlays properly */
+        pCmd->u.out.curOverlays = 0;
+
+        pCmd->u.out.surfaceCaps =
+                            VBOXVHWA_SCAPS_PRIMARYSURFACE
+                    //        | VBOXVHWA_SCAPS_OFFSCREENPLAIN
+                            | VBOXVHWA_SCAPS_FLIP
+                            | VBOXVHWA_SCAPS_LOCALVIDMEM
+                            | VBOXVHWA_SCAPS_OVERLAY
+                    //        | VBOXVHWA_SCAPS_VIDEOMEMORY
+                    //        | VBOXVHWA_SCAPS_COMPLEX
+                    //        | VBOXVHWA_SCAPS_VISIBLE
+                            ;
+
+        if(g_vboxVHWAGlShaderSupported && g_vboxVHWAGlMultiTexNumSupported >= 2)
+        {
+            pCmd->u.out.caps |= VBOXVHWA_CAPS_COLORKEY
+                            | VBOXVHWA_CAPS_COLORKEYHWASSIST
+                            ;
+
+            pCmd->u.out.colorKeyCaps =
+//                          VBOXVHWA_CKEYCAPS_DESTBLT | VBOXVHWA_CKEYCAPS_DESTBLTCLRSPACE | VBOXVHWA_CKEYCAPS_SRCBLT| VBOXVHWA_CKEYCAPS_SRCBLTCLRSPACE |
+//                          VBOXVHWA_CKEYCAPS_SRCOVERLAY | VBOXVHWA_CKEYCAPS_SRCOVERLAYONEACTIVE |
+                            VBOXVHWA_CKEYCAPS_DESTOVERLAY          |
+                            VBOXVHWA_CKEYCAPS_DESTOVERLAYONEACTIVE;
+                            ;
+
+            if(g_vboxVHWAGlTextureRectangleSupported)
+            {
+                pCmd->u.out.caps |= VBOXVHWA_CAPS_OVERLAYFOURCC
+//                              | VBOXVHWA_CAPS_BLTFOURCC
+                                ;
+
+                pCmd->u.out.colorKeyCaps |=
+//                               VBOXVHWA_CKEYCAPS_SRCOVERLAYYUV |
+                                 VBOXVHWA_CKEYCAPS_DESTOVERLAYYUV;
+                                 ;
+
+//              pCmd->u.out.caps2 |= VBOXVHWA_CAPS2_COPYFOURCC;
+
+                pCmd->u.out.numFourCC = g_vboxVHWAFourccSupportedCount;
+            }
+        }
+    }
+
+    return VINF_SUCCESS;
+}
+
+int VBoxGLWidget::vhwaQueryInfo2(struct _VBOXVHWACMD_QUERYINFO2 *pCmd)
+{
+    VBOXQGLLOG_ENTER(("\n"));
+
+    Assert(pCmd->numFourCC >= g_vboxVHWAFourccSupportedCount);
+    if(pCmd->numFourCC < g_vboxVHWAFourccSupportedCount)
+        return VERR_GENERAL_FAILURE;
+
+    pCmd->numFourCC = g_vboxVHWAFourccSupportedCount;
+    for(uint32_t i = 0; i < g_vboxVHWAFourccSupportedCount; i++)
+    {
+        pCmd->FourCC[i] = g_vboxVHWAFourccSupportedList[i];
+    }
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(void) vboxQGLSaveExec(PSSMHANDLE pSSM, void *pvUser)
+{
+    VBoxGLWidget * pw = (VBoxGLWidget*)pvUser;
+    pw->vhwaSaveExec(pSSM);
+}
+
+static DECLCALLBACK(int) vboxQGLLoadExec(PSSMHANDLE pSSM, void *pvUser, uint32_t u32Version, uint32_t uPhase)
+{
+    VBoxGLWidget * pw = (VBoxGLWidget*)pvUser;
+    return pw->vhwaLoadExec(pSSM, u32Version);
+}
+
+int VBoxGLWidget::vhwaSaveSurface(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, uint32_t surfCaps)
+{
+    VBOXQGL_SAVE_SURFSTART(pSSM);
+
+    uint64_t u64 = vboxVRAMOffset(pSurf);
+    int rc;
+    rc = SSMR3PutU32(pSSM, pSurf->handle());         AssertRC(rc);
+    rc = SSMR3PutU64(pSSM, u64);         AssertRC(rc);
+    rc = SSMR3PutU32(pSSM, pSurf->width());         AssertRC(rc);
+    rc = SSMR3PutU32(pSSM, pSurf->height());         AssertRC(rc);
+    rc = SSMR3PutU32(pSSM, surfCaps);         AssertRC(rc);
+    uint32_t flags = 0;
+    const VBoxVHWAColorKey * pDstBltCKey = pSurf->dstBltCKey();
+    const VBoxVHWAColorKey * pSrcBltCKey = pSurf->srcBltCKey();
+    const VBoxVHWAColorKey * pDstOverlayCKey = pSurf->dstOverlayCKey();
+    const VBoxVHWAColorKey * pSrcOverlayCKey = pSurf->srcOverlayCKey();
+    if(pDstBltCKey)
+    {
+        flags |= VBOXVHWA_SD_CKDESTBLT;
+    }
+    if(pSrcBltCKey)
+    {
+        flags |= VBOXVHWA_SD_CKSRCBLT;
+    }
+    if(pDstOverlayCKey)
+    {
+        flags |= VBOXVHWA_SD_CKDESTOVERLAY;
+    }
+    if(pSrcOverlayCKey)
+    {
+        flags |= VBOXVHWA_SD_CKSRCOVERLAY;
+    }
+
+    rc = SSMR3PutU32(pSSM, flags);         AssertRC(rc);
+    if(pDstBltCKey)
+    {
+        rc = SSMR3PutU32(pSSM, pDstBltCKey->lower());         AssertRC(rc);
+        rc = SSMR3PutU32(pSSM, pDstBltCKey->upper());         AssertRC(rc);
+    }
+    if(pSrcBltCKey)
+    {
+        rc = SSMR3PutU32(pSSM, pSrcBltCKey->lower());         AssertRC(rc);
+        rc = SSMR3PutU32(pSSM, pSrcBltCKey->upper());         AssertRC(rc);
+    }
+    if(pDstOverlayCKey)
+    {
+        rc = SSMR3PutU32(pSSM, pDstOverlayCKey->lower());         AssertRC(rc);
+        rc = SSMR3PutU32(pSSM, pDstOverlayCKey->upper());         AssertRC(rc);
+    }
+    if(pSrcOverlayCKey)
+    {
+        rc = SSMR3PutU32(pSSM, pSrcOverlayCKey->lower());         AssertRC(rc);
+        rc = SSMR3PutU32(pSSM, pSrcOverlayCKey->upper());         AssertRC(rc);
+    }
+
+    const VBoxVHWAColorFormat & format = pSurf->colorFormat();
+    flags = 0;
+    if(format.fourcc())
+    {
+        flags |= VBOXVHWA_PF_FOURCC;
+        rc = SSMR3PutU32(pSSM, flags);         AssertRC(rc);
+        rc = SSMR3PutU32(pSSM, format.fourcc());         AssertRC(rc);
+    }
+    else
+    {
+        flags |= VBOXVHWA_PF_RGB;
+        rc = SSMR3PutU32(pSSM, flags);         AssertRC(rc);
+        rc = SSMR3PutU32(pSSM, format.bitsPerPixel());         AssertRC(rc);
+        rc = SSMR3PutU32(pSSM, format.r().mask());         AssertRC(rc);
+        rc = SSMR3PutU32(pSSM, format.g().mask());         AssertRC(rc);
+        rc = SSMR3PutU32(pSSM, format.b().mask());         AssertRC(rc);
+        rc = SSMR3PutU32(pSSM, format.a().mask());         AssertRC(rc);
+    }
+
+    VBOXQGL_SAVE_SURFSTOP(pSSM);
+
+    return rc;
+}
+
+int VBoxGLWidget::vhwaLoadSurface(struct SSMHANDLE * pSSM, uint32_t u32Version)
+{
+    VBOXQGL_LOAD_SURFSTART(pSSM);
+
+    char *buf = new char[VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE)];
+    memset(buf, 0, sizeof(buf));
+    VBOXVHWACMD * pCmd = (VBOXVHWACMD*)buf;
+    pCmd->enmCmd = VBOXVHWACMD_TYPE_SURF_CREATE;
+    pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
+
+    VBOXVHWACMD_SURF_CREATE * pCreateSurf = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
+    int rc;
+    uint32_t u32;
+    rc = SSMR3GetU32(pSSM, &u32);         AssertRC(rc);
+    pCreateSurf->SurfInfo.hSurf = (VBOXVHWA_SURFHANDLE)u32;
+    if(RT_SUCCESS(rc))
+    {
+        rc = SSMR3GetU64(pSSM, &pCreateSurf->SurfInfo.offSurface);         AssertRC(rc);
+        rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.width);         AssertRC(rc);
+        rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.height);         AssertRC(rc);
+        rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.surfCaps);         AssertRC(rc);
+        rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.flags);         AssertRC(rc);
+        if(pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKDESTBLT)
+        {
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstBltCK.low);         AssertRC(rc);
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstBltCK.high);         AssertRC(rc);
+        }
+        if(pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKSRCBLT)
+        {
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcBltCK.low);         AssertRC(rc);
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcBltCK.high);         AssertRC(rc);
+        }
+        if(pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKDESTOVERLAY)
+        {
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstOverlayCK.low);         AssertRC(rc);
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstOverlayCK.high);         AssertRC(rc);
+        }
+        if(pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKSRCOVERLAY)
+        {
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcOverlayCK.low);         AssertRC(rc);
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcOverlayCK.high);         AssertRC(rc);
+        }
+
+        rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.flags);         AssertRC(rc);
+        if(pCreateSurf->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
+        {
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.c.rgbBitCount);         AssertRC(rc);
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m1.rgbRBitMask);         AssertRC(rc);
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m2.rgbGBitMask);         AssertRC(rc);
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m3.rgbBBitMask);         AssertRC(rc);
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m4.rgbABitMask);         AssertRC(rc);
+        }
+        else if(pCreateSurf->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
+        {
+            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.fourCC);         AssertRC(rc);
+        }
+        else
+        {
+            Assert(0);
+        }
+
+        vboxExecOnResize(&VBoxGLWidget::vboxDoVHWACmdAndFree, pCmd); AssertRC(rc);
+//        if(RT_SUCCESS(rc))
+//        {
+//            rc = pCmd->rc;
+//            AssertRC(rc);
+//        }
+    }
+
+    VBOXQGL_LOAD_SURFSTOP(pSSM);
+
+    return rc;
+}
+
+int VBoxGLWidget::vhwaSaveOverlayData(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, bool bVisible)
+{
+    VBOXQGL_SAVE_OVERLAYSTART(pSSM);
+
+    uint32_t flags = 0;
+    const VBoxVHWAColorKey * dstCKey = pSurf->dstOverlayCKey();
+    const VBoxVHWAColorKey * defaultDstCKey = pSurf->defaultDstOverlayCKey();
+    const VBoxVHWAColorKey * srcCKey = pSurf->srcOverlayCKey();;
+    const VBoxVHWAColorKey * defaultSrcCKey = pSurf->defaultSrcOverlayCKey();
+    bool bSaveDstCKey = false;
+    bool bSaveSrcCKey = false;
+
+    if(bVisible)
+    {
+        flags |= VBOXVHWA_OVER_SHOW;
+    }
+    else
+    {
+        flags |= VBOXVHWA_OVER_HIDE;
+    }
+
+    if(!dstCKey)
+    {
+        flags |= VBOXVHWA_OVER_KEYDEST;
+    }
+    else if(defaultDstCKey)
+    {
+        flags |= VBOXVHWA_OVER_KEYDESTOVERRIDE;
+        bSaveDstCKey = true;
+    }
+
+    if(srcCKey == defaultSrcCKey)
+    {
+        flags |= VBOXVHWA_OVER_KEYSRC;
+    }
+    else if(srcCKey)
+    {
+        flags |= VBOXVHWA_OVER_KEYSRCOVERRIDE;
+        bSaveSrcCKey = true;
+    }
+
+    int rc = SSMR3PutU32(pSSM, flags); AssertRC(rc);
+
+    rc = SSMR3PutU32(pSSM, mDisplay.getVGA()->handle()); AssertRC(rc);
+    rc = SSMR3PutU32(pSSM, pSurf->handle()); AssertRC(rc);
+
+    if(bSaveDstCKey)
+    {
+        rc = SSMR3PutU32(pSSM, dstCKey->lower()); AssertRC(rc);
+        rc = SSMR3PutU32(pSSM, dstCKey->upper()); AssertRC(rc);
+    }
+    if(bSaveSrcCKey)
+    {
+        rc = SSMR3PutU32(pSSM, srcCKey->lower()); AssertRC(rc);
+        rc = SSMR3PutU32(pSSM, srcCKey->upper()); AssertRC(rc);
+    }
+
+    int x1, x2, y1, y2;
+    pSurf->targRect().getCoords(&x1, &y1, &x2, &y2);
+    rc = SSMR3PutS32(pSSM, x1); AssertRC(rc);
+    rc = SSMR3PutS32(pSSM, x2+1); AssertRC(rc);
+    rc = SSMR3PutS32(pSSM, y1); AssertRC(rc);
+    rc = SSMR3PutS32(pSSM, y2+1); AssertRC(rc);
+
+    pSurf->srcRect().getCoords(&x1, &y1, &x2, &y2);
+    rc = SSMR3PutS32(pSSM, x1); AssertRC(rc);
+    rc = SSMR3PutS32(pSSM, x2+1); AssertRC(rc);
+    rc = SSMR3PutS32(pSSM, y1); AssertRC(rc);
+    rc = SSMR3PutS32(pSSM, y2+1); AssertRC(rc);
+
+    VBOXQGL_SAVE_OVERLAYSTOP(pSSM);
+
+    return rc;
+}
+
+int VBoxGLWidget::vhwaLoadOverlayData(struct SSMHANDLE * pSSM, uint32_t u32Version)
+{
+    VBOXQGL_LOAD_OVERLAYSTART(pSSM);
+
+//    char buf[VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_OVERLAY_UPDATE)];
+    char *buf = new char[VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE)];
+    memset(buf, 0, sizeof(buf));
+    VBOXVHWACMD * pCmd = (VBOXVHWACMD*)buf;
+    pCmd->enmCmd = VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE;
+    pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
+
+    VBOXVHWACMD_SURF_OVERLAY_UPDATE * pUpdateOverlay = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
+    int rc;
+
+    rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.flags); AssertRC(rc);
+    uint32_t hSrc, hDst;
+    rc = SSMR3GetU32(pSSM, &hDst); AssertRC(rc);
+    rc = SSMR3GetU32(pSSM, &hSrc); AssertRC(rc);
+    pUpdateOverlay->u.in.hSrcSurf = hSrc;
+    pUpdateOverlay->u.in.hDstSurf = hDst;
+//    Assert(hDst == mDisplay.getVGA()->handle());
+//    VBoxVHWASurfaceBase *pDstSurf = handle2Surface(hDst);
+//    VBoxVHWASurfaceBase *pSrcSurf = handle2Surface(hSrc);
+//    Assert(pSrcSurf);
+//    Assert(pDstSurf);
+//    if(pSrcSurf && pDstSurf)
+    {
+        pUpdateOverlay->u.in.offDstSurface = VBOXVHWA_OFFSET64_VOID;
+//        vboxVRAMOffset(pDstSurf);
+        pUpdateOverlay->u.in.offSrcSurface = VBOXVHWA_OFFSET64_VOID;
+//        vboxVRAMOffset(pSrcSurf);
+
+        if(pUpdateOverlay->u.in.flags & VBOXVHWA_OVER_KEYDESTOVERRIDE)
+        {
+            rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.DstCK.low); AssertRC(rc);
+            rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.DstCK.high); AssertRC(rc);
+        }
+
+        if(pUpdateOverlay->u.in.flags & VBOXVHWA_OVER_KEYSRCOVERRIDE)
+        {
+            rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.SrcCK.low); AssertRC(rc);
+            rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.SrcCK.high); AssertRC(rc);
+        }
+
+        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.left); AssertRC(rc);
+        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.right); AssertRC(rc);
+        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.top); AssertRC(rc);
+        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.bottom); AssertRC(rc);
+
+        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.left); AssertRC(rc);
+        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.right); AssertRC(rc);
+        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.top); AssertRC(rc);
+        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.bottom); AssertRC(rc);
+
+        vboxExecOnResize(&VBoxGLWidget::vboxDoVHWACmdAndFree, pCmd); AssertRC(rc);
+//        if(RT_SUCCESS(rc))
+//        {
+//            rc = pCmd->rc;
+//            AssertRC(rc);
+//        }
+    }
+//    else
+//    {
+//        rc = VERR_GENERAL_FAILURE;
+//    }
+
+    VBOXQGL_LOAD_OVERLAYSTOP(pSSM);
+
+    return rc;
+}
+
+void VBoxGLWidget::vhwaSaveExec(struct SSMHANDLE * pSSM)
+{
+    VBOXQGL_SAVE_START(pSSM);
+
+    /* the mechanism of restoring data is based on generating VHWA commands that restore the surfaces state
+     * the following commands are generated:
+     * I.    CreateSurface
+     * II.   UpdateOverlay
+     *
+     * Data format is the following:
+     * I.    u32 - Num primary surfaces - (the current frontbuffer is detected in the stored surf flags which are posted to the generated CreateSurface cmd)
+     * II.   for each primary surf
+     * II.1    generate & execute CreateSurface cmd (see below on the generation logic)
+     * III.  u32 - Num overlays
+     * IV.   for each overlay
+     * IV.1    u32 - Num surfaces in overlay (the current frontbuffer is detected in the stored surf flags which are posted to the generated CreateSurface cmd)
+     * IV.2    for each surface in overlay
+     * IV.2.a    generate & execute CreateSurface cmd (see below on the generation logic)
+     * IV.2.b    generate & execute UpdateOverlay cmd (see below on the generation logic)
+     *
+     */
+    const SurfList & primaryList = mDisplay.getVGA()->getComplexList()->surfaces();
+    uint32_t cPrimary = (uint32_t)primaryList.size();
+    Assert(cPrimary >= 1);
+    if(!mbVGASurfCreated)
+    {
+        cPrimary -= 1;
+    }
+    int rc = SSMR3PutU32(pSSM, cPrimary);         AssertRC(rc);
+
+    for (SurfList::const_iterator pr = primaryList.begin();
+         pr != primaryList.end(); ++ pr)
+    {
+        VBoxVHWASurfaceBase *pSurf = *pr;
+        bool bVga = (pSurf == mDisplay.getVGA());
+        bool bVisible = (pSurf == mDisplay.getPrimary());
+        uint32_t flags = VBOXVHWA_SCAPS_PRIMARYSURFACE;
+        if(bVisible)
+            flags |= VBOXVHWA_SCAPS_VISIBLE;
+
+        if(mbVGASurfCreated || !bVga)
+        {
+            rc = vhwaSaveSurface(pSSM, *pr, flags);    AssertRC(rc);
+#ifdef DEBUG
+            --cPrimary;
+            Assert(cPrimary < UINT32_MAX / 2);
+#endif
+        }
+    }
+
+#ifdef DEBUG
+    Assert(!cPrimary);
+#endif
+
+    const OverlayList & overlays = mDisplay.overlays();
+    rc = SSMR3PutU32(pSSM, (uint32_t)overlays.size());         AssertRC(rc);
+
+    for (OverlayList::const_iterator it = overlays.begin();
+         it != overlays.end(); ++ it)
+    {
+        VBoxVHWASurfList * pSurfList = *it;
+        const SurfList & surfaces = pSurfList->surfaces();
+        uint32_t cSurfs = (uint32_t)surfaces.size();
+        uint32_t flags = VBOXVHWA_SCAPS_OVERLAY;
+        if(cSurfs > 1)
+            flags |= VBOXVHWA_SCAPS_COMPLEX;
+        rc = SSMR3PutU32(pSSM, cSurfs);         AssertRC(rc);
+        for (SurfList::const_iterator sit = surfaces.begin();
+             sit != surfaces.end(); ++ sit)
+        {
+            rc = vhwaSaveSurface(pSSM, *sit, flags);    AssertRC(rc);
+        }
+
+        bool bVisible = true;
+        VBoxVHWASurfaceBase * pOverlayData = pSurfList->current();
+        if(!pOverlayData)
+        {
+            pOverlayData = surfaces.front();
+            bVisible = false;
+        }
+
+        rc = vhwaSaveOverlayData(pSSM, pOverlayData, bVisible);    AssertRC(rc);
+    }
+
+    VBOXQGL_SAVE_STOP(pSSM);
+}
+
+int VBoxGLWidget::vhwaLoadExec(struct SSMHANDLE * pSSM, uint32_t u32Version)
+{
+    VBOXQGL_LOAD_START(pSSM);
+
+    int rc;
+    uint32_t u32;
+
+    rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
+    if(RT_SUCCESS(rc))
+    {
+        for(uint32_t i = 0; i < u32; ++i)
+        {
+            rc = vhwaLoadSurface(pSSM, u32Version);  AssertRC(rc);
+            if(RT_FAILURE(rc))
+                break;
+        }
+
+        if(RT_SUCCESS(rc))
+        {
+            rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
+            if(RT_SUCCESS(rc))
+            {
+                for(uint32_t i = 0; i < u32; ++i)
+                {
+                    uint32_t cSurfs;
+                    rc = SSMR3GetU32(pSSM, &cSurfs); AssertRC(rc);
+                    for(uint32_t j = 0; j < cSurfs; ++j)
+                    {
+                        rc = vhwaLoadSurface(pSSM, u32Version);  AssertRC(rc);
+                        if(RT_FAILURE(rc))
+                            break;
+                    }
+
+                    if(RT_SUCCESS(rc))
+                    {
+                        rc = vhwaLoadOverlayData(pSSM, u32Version);  AssertRC(rc);
+                    }
+
+                    if(RT_FAILURE(rc))
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    VBOXQGL_LOAD_STOP(pSSM);
+
+    return rc;
+}
+
+int VBoxGLWidget::vhwaConstruct(struct _VBOXVHWACMD_HH_CONSTRUCT *pCmd)
+{
+    PVM pVM = (PVM)pCmd->pVM;
+    uint32_t intsId = 0; /* @todo: set the proper id */
+
+    char nameFuf[sizeof(VBOXQGL_STATE_NAMEBASE) + 8];
+
+    char * pszName = nameFuf;
+    sprintf(pszName, "%s%d", VBOXQGL_STATE_NAMEBASE, intsId);
+    int rc = SSMR3RegisterExternal(
+            pVM,                    /* The VM handle*/
+            pszName,                /* Data unit name. */
+            intsId,                 /* The instance identifier of the data unit.
+                                     * This must together with the name be unique. */
+            VBOXQGL_STATE_VERSION,   /* Data layout version number. */
+            128,             /* The approximate amount of data in the unit.
+                              * Only for progress indicators. */
+            NULL, NULL, NULL, /* pfnLiveXxx */
+            NULL,            /* Prepare save callback, optional. */
+            vboxQGLSaveExec, /* Execute save callback, optional. */
+            NULL,            /* Done save callback, optional. */
+            NULL,            /* Prepare load callback, optional. */
+            vboxQGLLoadExec, /* Execute load callback, optional. */
+            NULL,            /* Done load callback, optional. */
+            this             /* User argument. */
+            );
+    Assert(RT_SUCCESS(rc));
+    return rc;
+}
+
+uchar * VBoxGLWidget::vboxVRAMAddressFromOffset(uint64_t offset)
+{
+    return ((offset != VBOXVHWA_OFFSET64_VOID) && vboxUsesGuestVRAM()) ? vboxAddress() + offset : NULL;
+}
+
+uint64_t VBoxGLWidget::vboxVRAMOffsetFromAddress(uchar* addr)
+{
+    return uint64_t(addr - vboxAddress());
+}
+
+uint64_t VBoxGLWidget::vboxVRAMOffset(VBoxVHWASurfaceBase * pSurf)
+{
+    return pSurf->addressAlocated() ? VBOXVHWA_OFFSET64_VOID : vboxVRAMOffsetFromAddress(pSurf->address());
+}
+
+#endif
+
+void VBoxGLWidget::initializeGL()
+{
+    vboxVHWAGlInit(context());
+    VBoxVHWASurfaceBase::globalInit();
+}
+
+#ifdef VBOXQGL_DBG_SURF
+
+int g_iCur = 0;
+VBoxVHWASurfaceBase * g_apSurf[] = {NULL, NULL, NULL};
+
+void VBoxGLWidget::vboxDoTestSurfaces(void* context)
+{
+//    uint32_t width = 103;
+//    uint32_t height = 47;
+//    uint32_t rgbBitCount = 32;
+//    uint32_t r = 0xff, g = 0xff00, b = 0xff0000;
+//    QRect dstRect(10, 50, width, height);
+//    QRect srcRect(0, 0, width, height);
+////    Assert(0);
+//    if(!pSurf1)
+//    {
+//
+////        pSurf1 = new VBoxVHWASurfaceBase(this, width, height,
+////                        VBoxVHWAColorFormat(rgbBitCount,
+////                                r,
+////                                g,
+////                                b),
+////                        NULL, NULL, NULL, NULL);
+//        pSurf1 = new VBoxVHWASurfaceBase(this, &QSize(width, height),
+////                        ((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY) ? mDisplay.getPrimary()->rect().size() : &QSize(pCmd->SurfInfo.width, pCmd->SurfInfo.height)),
+//                        &mDisplay.getPrimary()->rect().size(),
+//                        VBoxVHWAColorFormat(rgbBitCount,
+//                                r,
+//                                g,
+//                                b),
+////                        pSrcBltCKey, pDstBltCKey, pSrcOverlayCKey, pDstOverlayCKey);
+//                        NULL, NULL, NULL, NULL);
+//
+//        pSurf1->init(mDisplay.getVGA(), NULL);
+//
+//        VBoxVHWASurfList *pConstructingList = new VBoxVHWASurfList();
+//        mDisplay.addOverlay(pConstructingList);
+//        pConstructingList->add(pSurf1);
+//        pConstructingList->setCurrentVisible(pSurf1);
+////        pSurf1->performDisplay();
+//    }
+//
+////    pDisplay->blt(&dstRect, pSurf1, &srcRect, NULL, NULL);
+////    pDisplay->performDisplay();
+    if(g_iCur >= RT_ELEMENTS(g_apSurf))
+        g_iCur = 0;
+    VBoxVHWASurfaceBase * pSurf1 = g_apSurf[g_iCur];
+    if(pSurf1)
+    {
+        pSurf1->getComplexList()->setCurrentVisible(pSurf1);
+    }
+}
+#endif
+
+void VBoxGLWidget::vboxDoPaint(void *pe)
+{
+#ifdef VBOXQGL_DBG_SURF
+    vboxDoTestSurfaces(NULL);
+#endif
+    QRect vp(mView->contentsX(), mView->contentsY(), width(), height());
+
+    if(vp != mViewport)
+    {
+        adjustViewport(mDisplay.getVGA()->size(), vp);
+        mViewport = vp;
+    }
+
+//#ifdef VBOXQGL_PROF_BASE
+//    vboxDoUpdateRect(&((QPaintEvent*)pe)->rect());
+//#endif
+    mDisplay.performDisplay();
+}
+
+void VBoxGLWidget::vboxDoUpdateRect(const QRect * pRect)
+{
+    mDisplay.getVGA()->updatedMem(pRect);
+}
+
+void VBoxGLWidget::vboxDoResize(void *resize)
+{
+//    Assert(!format().accum());
+//    Assert(format().alpha());
+//    Assert(format().alphaBufferSize() == 8);
+    Assert(format().blueBufferSize() == 8);
+    Assert(format().greenBufferSize() == 8);
+    Assert(format().redBufferSize() == 8);
+
+//    Assert(!format().depth());
+    Assert(format().directRendering());
+    Assert(format().doubleBuffer());
+    Assert(format().hasOpenGL());
+    VBOXQGLLOG(("hasOpenGLOverlays(%d), hasOverlay(%d)\n", format().hasOpenGLOverlays(), format().hasOverlay()));
+//    Assert(format().hasOpenGLOverlays());
+//    Assert(format().hasOverlay());
+    Assert(format().plane() == 0);
+    Assert(format().rgba());
+    Assert(!format().sampleBuffers());
+//    Assert(!format().stencil());
+    Assert(!format().stereo());
+    VBOXQGLLOG(("swapInterval(%d)\n", format().swapInterval()));
+//    Assert(format().swapInterval() == 0);
+
+
+    VBOXQGL_CHECKERR(
+            vboxglActiveTexture(GL_TEXTURE0);
+        );
+
+    VBoxResizeEvent *re = (VBoxResizeEvent*)resize;
+    bool remind = false;
+    bool fallback = false;
+
+    VBOXQGLLOG(("resizing: fmt=%d, vram=%p, bpp=%d, bpl=%d, width=%d, height=%d\n",
+                      re->pixelFormat(), re->VRAM(),
+                      re->bitsPerPixel(), re->bytesPerLine(),
+                      re->width(), re->height()));
+
+    /* clean the old values first */
+
+    ulong bytesPerLine;
+    uint32_t bitsPerPixel;
+    uint32_t b = 0xff, g = 0xff00, r = 0xff0000;
+
+    /* check if we support the pixel format and can use the guest VRAM directly */
+    if (re->pixelFormat() == FramebufferPixelFormat_FOURCC_RGB)
+    {
+
+        bitsPerPixel = re->bitsPerPixel();
+        bytesPerLine = re->bytesPerLine();
+        ulong bitsPerLine = bytesPerLine * 8;
+
+        switch (bitsPerPixel)
+        {
+            case 32:
+//                format = VBoxVHWAColorFormat(bitsPerPixel, 0xff, 0xff00, 0xff0000);
+                break;
+            case 24:
+#ifdef DEBUG_misha
+                Assert(0);
+#endif
+//                format = VBoxVHWAColorFormat(bitsPerPixel, 0xff, 0xff00, 0xff0000);
+//                remind = true;
+                break;
+//            case 16:
+//                Assert(0);
+////                r = 0xf800;
+////                g = 0x7e0;
+////                b = 0x1f;
+//                break;
+            case 8:
+#ifdef DEBUG_misha
+                Assert(0);
+#endif
+                g = b = 0;
+                remind = true;
+                break;
+            case 1:
+#ifdef DEBUG_misha
+                Assert(0);
+#endif
+                r = 1;
+                g = b = 0;
+                remind = true;
+                break;
+            default:
+#ifdef DEBUG_misha
+                Assert(0);
+#endif
+                remind = true;
+                fallback = true;
+                break;
+        }
+
+        if (!fallback)
+        {
+            /* QImage only supports 32-bit aligned scan lines... */
+            Assert ((re->bytesPerLine() & 3) == 0);
+            fallback = ((re->bytesPerLine() & 3) != 0);
+        }
+        if (!fallback)
+        {
+            /* ...and the scan lines ought to be a whole number of pixels. */
+            Assert ((bitsPerLine & (re->bitsPerPixel() - 1)) == 0);
+            fallback = ((bitsPerLine & (re->bitsPerPixel() - 1)) != 0);
+        }
+        if (!fallback)
+        {
+            ulong virtWdt = bitsPerLine / re->bitsPerPixel();
+            mPixelFormat = FramebufferPixelFormat_FOURCC_RGB;
+            mUsesGuestVRAM = true;
+        }
+    }
+    else
+    {
+        fallback = true;
+    }
+
+    if (fallback)
+    {
+        /* we don't support either the pixel format or the color depth,
+         * fallback to a self-provided 32bpp RGB buffer */
+        bitsPerPixel = 32;
+        b = 0xff;
+        g = 0xff00;
+        r = 0xff0000;
+        bytesPerLine = re->width()*bitsPerPixel/8;
+        mPixelFormat = FramebufferPixelFormat_FOURCC_RGB;
+//        internalformat = 3;//GL_RGB;
+//        format = GL_BGRA_EXT;//GL_RGBA;
+//        type = GL_UNSIGNED_BYTE;
+        mUsesGuestVRAM = false;
+    }
+
+    ulong bytesPerPixel = bitsPerPixel/8;
+    ulong displayWidth = bytesPerLine/bytesPerPixel;
+    ulong displayHeight = re->height();
+
+#ifdef VBOXQGL_DBG_SURF
+    for(int i = 0; i < RT_ELEMENTS(g_apSurf); i++)
+    {
+        VBoxVHWASurfaceBase * pSurf1 = g_apSurf[i];
+        if(pSurf1)
+        {
+            VBoxVHWASurfList *pConstructingList = pSurf1->getComplexList();
+            delete pSurf1;
+            if(pConstructingList)
+                delete pConstructingList;
+    //
+    //            mDisplay.addOverlay(pConstructingList);
+    //            //            pConstructingList->add(pSurf1);
+    //            //            pConstructingList->setCurrentVisible(pSurf1);
+    //            ////            pConstructingList->setCurrentVisible(NULL);
+        }
+    }
+#endif
+
+    VBoxVHWASurfaceBase * pDisplay = mDisplay.setVGA(NULL);
+    if(pDisplay)
+        delete pDisplay;
+
+    VBoxVHWAColorFormat format(bitsPerPixel, r,g,b);
+    QSize dispSize(displayWidth, displayHeight);
+    pDisplay = new VBoxVHWASurfaceBase(this, &dispSize, &dispSize,
+    		format,
+            (VBoxVHWAColorKey*)NULL, (VBoxVHWAColorKey*)NULL, (VBoxVHWAColorKey*)NULL, (VBoxVHWAColorKey*)NULL, true);
+    pDisplay->init(NULL, mUsesGuestVRAM ? re->VRAM() : NULL);
+    mDisplay.setVGA(pDisplay);
+    VBOXQGLLOG(("\n\n*******\n\n     viewport size is: (%d):(%d)\n\n*******\n\n", size().width(), size().height()));
+    mViewport = QRect(0,0,displayWidth, displayHeight);
+    adjustViewport(dispSize, mViewport);
+    setupMatricies(dispSize);
+
+#ifdef VBOXQGL_DBG_SURF
+    {
+        uint32_t width = 100;
+        uint32_t height = 60;
+//        uint32_t rgbBitCount = 32;
+//        uint32_t r = 0xff, g = 0xff00, b = 0xff0000;
+//        QRect dstRect(150, 200, width, height);
+//        QRect srcRect(0, 0, 720, 480);
+    //    Assert(0);
+
+        for(int i = 0; i < RT_ELEMENTS(g_apSurf); i++)
+        {
+
+    //        pSurf1 = new VBoxVHWASurfaceBase(this, width, height,
+    //                        VBoxVHWAColorFormat(rgbBitCount,
+    //                                r,
+    //                                g,
+    //                                b),
+    //                        NULL, NULL, NULL, NULL);
+            VBoxVHWASurfaceBase *pSurf1 = new VBoxVHWASurfaceBase(this, &QSize(width, height),
+    //                        ((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY) ? mDisplay.getPrimary()->rect().size() : &QSize(pCmd->SurfInfo.width, pCmd->SurfInfo.height)),
+                            &mDisplay.getPrimary()->rect().size(),
+//                            VBoxVHWAColorFormat(rgbBitCount,
+//                                    r,
+//                                    g,
+//                                    b),
+                            VBoxVHWAColorFormat(FOURCC_YV12),
+    //                        pSrcBltCKey, pDstBltCKey, pSrcOverlayCKey, pDstOverlayCKey);
+                            NULL, NULL, NULL, &VBoxVHWAColorKey(0,0), false);
+
+            Assert(mDisplay.getVGA());
+            pSurf1->init(mDisplay.getVGA(), NULL);
+            uchar *addr = pSurf1->address();
+            uchar cur = 0;
+            for(uint32_t k = 0; k < width*height; k++)
+            {
+            	addr[k] = cur;
+            	cur+=64;
+            }
+            pSurf1->updatedMem(&QRect(0,0,width, height));
+//            VBOXQGL_CHECKERR(
+//                    vboxglActiveTexture(GL_TEXTURE0);
+//                );
+
+            VBoxVHWASurfList *pConstructingList = new VBoxVHWASurfList();
+            mDisplay.addOverlay(pConstructingList);
+            pConstructingList->add(pSurf1);
+//            pConstructingList->setCurrentVisible(pSurf1);
+//            pConstructingList->setCurrentVisible(NULL);
+            g_apSurf[i] = pSurf1;
+
+//            VBoxVHWAGlProgramVHWA * pProgram = vboxVHWAGetGlProgramMngr()->getProgram(true, false, &pSurf1->colorFormat(), &pDisplay->colorFormat());
+//            pProgram->start();
+//            pProgram->setSrcTexImgWidth(pSurf1->texRect().width());
+//            pProgram->stop();
+        }
+//        else
+//        {
+//            VBoxVHWASurfList *pConstructingList = pSurf1->getComplexList();
+//            mDisplay.addOverlay(pConstructingList);
+//            pConstructingList->add(pSurf1);
+//            pConstructingList->setCurrentVisible(pSurf1);
+////            pConstructingList->setCurrentVisible(NULL);
+//        }
+
+        VBOXVHWACMD_SURF_OVERLAY_UPDATE updateCmd;
+        memset(&updateCmd, 0, sizeof(updateCmd));
+        updateCmd.u.in.hSrcSurf = (VBOXVHWA_SURFHANDLE)g_apSurf[0];
+        updateCmd.u.in.hDstSurf = (VBOXVHWA_SURFHANDLE)pDisplay;
+        updateCmd.u.in.flags =
+        		VBOXVHWA_OVER_SHOW
+        		| VBOXVHWA_OVER_KEYDESTOVERRIDE;
+
+        updateCmd.u.in.desc.DstCK.high = 1;
+        updateCmd.u.in.desc.DstCK.low = 1;
+
+        updateCmd.u.in.dstRect.left = 0;
+        updateCmd.u.in.dstRect.right = pDisplay->width();
+        updateCmd.u.in.dstRect.top = (pDisplay->height() - height)/2;
+        updateCmd.u.in.dstRect.bottom = updateCmd.u.in.dstRect.top + height;
+
+        updateCmd.u.in.srcRect.left = 0;
+        updateCmd.u.in.srcRect.right = width;
+        updateCmd.u.in.srcRect.top = 0;
+        updateCmd.u.in.srcRect.bottom = height;
+
+        updateCmd.u.in.offDstSurface = 0xffffffffffffffffL; /* just a magic to avoid surf mem buffer change  */
+        updateCmd.u.in.offSrcSurface = 0xffffffffffffffffL; /* just a magic to avoid surf mem buffer change  */
+
+        vhwaSurfaceOverlayUpdate(&updateCmd);
+    }
+#endif
+
+    VBoxVHWACommandElement * pPpCmd = mResizePostProcessCmds.detachList();
+    if(pPpCmd)
+    {
+        processCmdList(pPpCmd);
+        while(pPpCmd)
+        {
+            VBoxVHWACommandElement * pCur = pPpCmd;
+            pPpCmd = pCur->mpNext;
+            delete pCur;
+        }
+    }
+
+
+    mDisplay.performDisplay();
+
+    if (remind)
+    {
+        class RemindEvent : public VBoxAsyncEvent
+        {
+            ulong mRealBPP;
+        public:
+            RemindEvent (ulong aRealBPP)
+                : mRealBPP (aRealBPP) {}
+            void handle()
+            {
+                vboxProblem().remindAboutWrongColorDepth (mRealBPP, 32);
+            }
+        };
+        (new RemindEvent (re->bitsPerPixel()))->post();
+    }
+}
+
+//typedef struct VBOXQGLDEFFEREDOPCONTEXT
+//{
+//    PFNVBOXQGLOP pfn;
+//    void *pContext;
+//    VBoxVHWACommandElement * pEl;
+//}VBOXQGLDEFFEREDOPCONTEXT;
+//
+//void VBoxGLWidget::vboxDefferedOpCallback(void * pContext)
+//{
+//    VBOXQGLDEFFEREDOPCONTEXT * pData = (VBOXQGLDEFFEREDOPCONTEXT*)pContext;
+//    this->*(pData->pfn)(pData->pContext);
+//    delete pEl;
+//}
+
+void VBoxGLWidget::vboxExecOnResize(PFNVBOXQGLOP pfn, void* pContext)
+{
+    VBoxVHWACommandElement *pCmd = new VBoxVHWACommandElement();
+    VBOXVHWACALLBACKINFO info;
+    info.pThis = this;
+    info.pfnCallback = pfn;
+    info.pContext = pContext;
+    pCmd->setOp(info);
+    mResizePostProcessCmds.put(pCmd);
+}
+
+//int VBoxGLWidget::vboxExecOpSynch(PFNVBOXQGLOP pfn, void* pContext)
+//{
+//    VBOXQGLOPCALLBACKCONTEXT data;
+//    data.pThis = this;
+//    data.pfn = pfn;
+//    data.pContext = pContext;
+//    int rc = RTSemEventCreate(&data.hEvent);
+//    AssertRC(rc);
+//    if(RT_SUCCESS(rc))
+//    {
+//        VBOXVHWACALLBACKINFO info;
+//        info.pContext = &data;
+//        info.pfnCallback = vboxQGLOpCallback;
+//        postCmd(VBOXVHWA_PIPECMD_OP, &info);
+//        rc = RTSemEventWaitNoResume(data.hEvent, RT_INDEFINITE_WAIT);
+//        AssertRC(rc);
+//        if(RT_SUCCESS(rc))
+//        {
+//            RTSemEventDestroy(data.hEvent);
+//        }
+//    }
+//    return rc;
+//}
+
+VBoxVHWAColorFormat::VBoxVHWAColorFormat(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b) :
+    mWidthCompression(1),
+    mHeightCompression(1)
+{
+    init(bitsPerPixel, r, g, b);
+}
+
+VBoxVHWAColorFormat::VBoxVHWAColorFormat(uint32_t fourcc) :
+    mWidthCompression(1),
+    mHeightCompression(1)
+{
+    init(fourcc);
+}
+
+void VBoxVHWAColorFormat::init(uint32_t fourcc)
+{
+    mDataFormat = fourcc;
+    mInternalFormat = GL_RGBA8;//GL_RGB;
+    mFormat = GL_BGRA_EXT;//GL_RGBA;
+    mType = GL_UNSIGNED_BYTE;
+    mR = VBoxVHWAColorComponent(0xff);
+    mG = VBoxVHWAColorComponent(0xff);
+    mB = VBoxVHWAColorComponent(0xff);
+    mA = VBoxVHWAColorComponent(0xff);
+    mBitsPerPixelTex = 32;
+
+    switch(fourcc)
+    {
+        case FOURCC_AYUV:
+            mBitsPerPixel = 32;
+            mWidthCompression = 1;
+            break;
+        case FOURCC_UYVY:
+        case FOURCC_YUY2:
+            mBitsPerPixel = 16;
+            mWidthCompression = 2;
+            break;
+        case FOURCC_YV12:
+            mBitsPerPixel = 8;
+            mWidthCompression = 4;
+            break;
+        default:
+            Assert(0);
+            mBitsPerPixel = 0;
+            mBitsPerPixelTex = 0;
+            mWidthCompression = 0;
+            break;
+    }
+}
+
+void VBoxVHWAColorFormat::init(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b)
+{
+    mBitsPerPixel = bitsPerPixel;
+    mBitsPerPixelTex = bitsPerPixel;
+    mDataFormat = 0;
+    switch (bitsPerPixel)
+    {
+        case 32:
+            mInternalFormat = GL_RGB;//3;//GL_RGB;
+            mFormat = GL_BGRA_EXT;//GL_RGBA;
+            mType = GL_UNSIGNED_BYTE;
+            mR = VBoxVHWAColorComponent(r);
+            mG = VBoxVHWAColorComponent(g);
+            mB = VBoxVHWAColorComponent(b);
+            break;
+        case 24:
+#ifdef DEBUG_misha
+            Assert(0);
+#endif
+            mInternalFormat = 3;//GL_RGB;
+            mFormat = GL_BGR_EXT;
+            mType = GL_UNSIGNED_BYTE;
+            mR = VBoxVHWAColorComponent(r);
+            mG = VBoxVHWAColorComponent(g);
+            mB = VBoxVHWAColorComponent(b);
+            break;
+        case 16:
+#ifdef DEBUG_misha
+            Assert(0);
+#endif
+            mInternalFormat = GL_RGB5;
+            mFormat = GL_BGR_EXT;
+            mType = GL_UNSIGNED_BYTE; /* TODO" ??? */
+            mR = VBoxVHWAColorComponent(r);
+            mG = VBoxVHWAColorComponent(g);
+            mB = VBoxVHWAColorComponent(b);
+            break;
+        case 8:
+#ifdef DEBUG_misha
+            Assert(0);
+#endif
+            mInternalFormat = 1;//GL_RGB;
+            mFormat = GL_RED;//GL_RGB;
+            mType = GL_UNSIGNED_BYTE;
+            mR = VBoxVHWAColorComponent(0xff);
+            break;
+        case 1:
+#ifdef DEBUG_misha
+            Assert(0);
+#endif
+            mInternalFormat = 1;
+            mFormat = GL_COLOR_INDEX;
+            mType = GL_BITMAP;
+            mR = VBoxVHWAColorComponent(0x1);
+            break;
+        default:
+#ifdef DEBUG_misha
+            Assert(0);
+#endif
+            mBitsPerPixel = 0;
+            mBitsPerPixelTex = 0;
+            break;
+    }
+}
+
+bool VBoxVHWAColorFormat::equals (const VBoxVHWAColorFormat & other) const
+{
+    if(fourcc())
+        return fourcc() == other.fourcc();
+    if(other.fourcc())
+        return false;
+
+    return bitsPerPixel() == other.bitsPerPixel();
+}
+
+VBoxVHWAColorComponent::VBoxVHWAColorComponent(uint32_t aMask)
+{
+    unsigned f = ASMBitFirstSetU32(aMask);
+    if(f)
+    {
+        mOffset = f - 1;
+        f = ASMBitFirstSetU32(~(aMask >> mOffset));
+        if(f)
+        {
+            mcBits = f - 1;
+        }
+        else
+        {
+            mcBits = 32 - mOffset;
+        }
+
+        Assert(mcBits);
+        mMask = (((uint32_t)0xffffffff) >> (32 - mcBits)) << mOffset;
+        Assert(mMask == aMask);
+
+        mRange = (mMask >> mOffset) + 1;
+    }
+    else
+    {
+        mMask = 0;
+        mRange = 0;
+        mOffset = 32;
+        mcBits = 0;
+    }
+}
+
+void VBoxVHWAColorFormat::pixel2Normalized (uint32_t pix, float *r, float *g, float *b) const
+{
+    *r = mR.colorValNorm(pix);
+    *g = mG.colorValNorm(pix);
+    *b = mB.colorValNorm(pix);
+}
+
+#endif
