egl/egltest/endpointtestsuite/automated/tsrc/egltest_surface.cpp
changeset 152 9f1c3fea0f87
parent 98 bf7481649c98
--- a/egl/egltest/endpointtestsuite/automated/tsrc/egltest_surface.cpp	Tue Jul 06 15:45:57 2010 +0300
+++ b/egl/egltest/endpointtestsuite/automated/tsrc/egltest_surface.cpp	Wed Aug 18 11:05:09 2010 +0300
@@ -23,6 +23,10 @@
 #include "egltest_surface.h"
 #include "egltest_endpoint_images.h"
 #include <graphics/surfaceconfiguration.h>
+#include <e32std.h>
+#include <e32math.h>
+#include <VG/vgu.h>
+
 
 #define SURF_ASSERT(x) { if (!(x)) { RDebug::Printf("ASSERT(%s) failed at %s:%d", #x, __FILE__, __LINE__); User::Panic(_L("ASSERT SURF"), __LINE__); }}
 
@@ -38,6 +42,8 @@
 #define WindowPos(x, y)  x, y
 #define WindowMode(m) m
 
+#define LARGEST_POSSIBLE_FLAG 0x80000000
+
 static const TSurfaceParamsCommon KSurfaceParams[] =
 {
     {
@@ -131,10 +137,123 @@
         WindowPos(0, 0),
         WindowMode(EColor16MAP)
     },
+    {
+        ELargestPossibleSurface,
+        SIZE(LARGEST_POSSIBLE_FLAG, LARGEST_POSSIBLE_FLAG),
+        Buffers(2),
+        DefaultAlignment,
+        DefaultStride,
+        Offset(0),
+        EUidPixelFormatARGB_8888_PRE,
+        EFalse,
+        { 0 },
+        WindowPos(0, 0),
+        WindowMode(EColor16MAP)
+    },    
+    {
+        ESmallSurface,
+        SIZE(16, 16),
+        Buffers(1),
+        DefaultAlignment,
+        DefaultStride,
+        Offset(0),
+        EUidPixelFormatARGB_8888_PRE,
+        EFalse,
+        { 0 },
+        WindowPos(0, 0),
+        WindowMode(EColor16MAP)
+    },
+    {
+        ETinySurface,
+        SIZE(8, 8),
+        Buffers(1),
+        DefaultAlignment,
+        DefaultStride,
+        Offset(0),
+        EUidPixelFormatARGB_8888_PRE,
+        EFalse,
+        { 0 },
+        WindowPos(0, 0),
+        WindowMode(EColor16MAP)
+    },
 };
 
+const TInt KSurfaceMaxIndex = sizeof(KSurfaceParams) / sizeof(KSurfaceParams[0]);
 
-TInt KSurfaceMaxIndex = sizeof(KSurfaceParams) / sizeof(KSurfaceParams[0]);
+struct TSurfaceSize
+    {
+    TInt iWidth;
+    TInt iHeight;
+    };
+
+static const TSurfaceSize KSurfaceSizes[] =
+    {
+        {  320,  240 },
+        {  640,  480 },
+        {  720,  480 },
+        {  854,  480 },
+        {  720,  576 },
+        {  854,  576 },
+        { 1280,  720 },
+        { 1024,  768 },
+        { 1280, 1024 },
+        { 1920, 1080 },
+        { 1600, 1200 },
+#if 0
+        { 2048, 1536 },
+        { 2560, 1920 },
+        { 3648, 2736 },
+        { 4216, 2638 },
+        { 4000, 3000 },
+        { 4616, 2600 },
+#endif
+    };
+
+const TInt KMaxSurfaceSizes =  sizeof(KSurfaceSizes) / sizeof(KSurfaceSizes[0]);
+
+LOCAL_C TUint RandomNumberInRange(TUint aLow, TUint aHigh)
+    {
+    TReal32 rand = Math::Random();
+    rand /= KMaxTUint;
+    rand *= aHigh - aLow;
+    rand += aLow;
+    return TUint(rand);
+    }
+
+
+void CSurface::CreateL(TInt aIndex)
+    {
+    CreateL(aIndex, TPoint(0, 0));
+    }
+
+
+TSize CSurface::Size()
+    {
+    return iActualSize;
+    }
+
+
+TInt CSurface::SizeInBytes() const
+    {
+    RSurfaceManager::TInfoBuf infoBuf;
+    RSurfaceManager surfMgr;
+    TInt err = surfMgr.Open();
+    if (err != KErrNone)
+        {
+        RDebug::Printf("Error opening surface manager... Err=%d", err);
+        return 0;
+        }
+    err = surfMgr.SurfaceInfo(SurfaceId(), infoBuf);
+    if (err != KErrNone)
+        {
+        RDebug::Printf("Could not get surface info - err = %d", err);
+        return 0;
+        }
+    TInt size = infoBuf().iBuffers * infoBuf().iSize.iHeight * infoBuf().iStride;
+    surfMgr.Close();
+    return size;
+    }
+
 
 CRawSurface* CRawSurface::NewL()
     {
@@ -146,6 +265,7 @@
     }
 
 
+
 CRawSurface::CRawSurface() : iDrawBuffer(0), iBuffers(0)
     {
     }
@@ -155,7 +275,7 @@
     {
     iSurfaceId = TSurfaceId::CreateNullId();
     User::LeaveIfError(iSurfaceManager.Open());
-    User::LeaveIfError(iSurfaceUpdate.Connect(5));
+    User::LeaveIfError(iSurfaceUpdate.Connect());
     }
 
 
@@ -192,19 +312,30 @@
     }
 
 
-void CRawSurface::GetSurfAttribs(RSurfaceManager::TSurfaceCreationAttributesBuf &aSurfaceAttribs, TInt aIndex)
+void CRawSurface::GetSurfAttribs(RSurfaceManager::TSurfaceCreationAttributesBuf &aSurfaceAttribs, 
+        TInt aIndex, TInt aSizeIndex)
     {
     SURF_ASSERT(aIndex < KSurfaceMaxIndex);
     SURF_ASSERT(aIndex == KSurfaceParams[aIndex].iIndex);
     iParamIndex = aIndex;
-    aSurfaceAttribs().iSize = TSize(KSurfaceParams[aIndex].iXSize, KSurfaceParams[aIndex].iYSize);
+    if (KSurfaceParams[aIndex].iXSize & LARGEST_POSSIBLE_FLAG)
+        {
+        
+        aSurfaceAttribs().iSize = 
+                TSize(KSurfaceSizes[aSizeIndex].iWidth, KSurfaceSizes[aSizeIndex].iHeight);
+        }
+    else
+        {
+        aSurfaceAttribs().iSize = 
+                TSize(KSurfaceParams[aIndex].iXSize, KSurfaceParams[aIndex].iYSize);
+        }
     iBuffers = KSurfaceParams[aIndex].iBuffers;
     aSurfaceAttribs().iBuffers = iBuffers;
     aSurfaceAttribs().iPixelFormat = KSurfaceParams[aIndex].iPixelFormat;
     TInt stride = KSurfaceParams[aIndex].iStrideInBytes;
     if (stride == 0)
         {
-        stride = KSurfaceParams[aIndex].iXSize * PixelSize(KSurfaceParams[aIndex].iPixelFormat);
+        stride = aSurfaceAttribs().iSize.iWidth * PixelSize(KSurfaceParams[aIndex].iPixelFormat);
         }
     aSurfaceAttribs().iStride = stride;
     aSurfaceAttribs().iOffsetToFirstBuffer = KSurfaceParams[aIndex].iOffsetToFirstBuffer;
@@ -218,13 +349,25 @@
     }
 
 
-//From CSurface.
-void CRawSurface::CreateL(TInt aIndex)
+void CRawSurface::CreateL(TInt aIndex, const TPoint &/* aPoint */)
     {
     RSurfaceManager::TSurfaceCreationAttributesBuf surfaceAttribs;
-
-    GetSurfAttribs(surfaceAttribs, aIndex);
-    TInt err = iSurfaceManager.CreateSurface(surfaceAttribs, iSurfaceId);
+    SURF_ASSERT(aIndex < KSurfaceMaxIndex);
+    TInt sizeIndex = 0;
+    if (KSurfaceParams[aIndex].iXSize & LARGEST_POSSIBLE_FLAG)
+        {
+        sizeIndex = KMaxSurfaceSizes-1;
+        
+        }
+    TInt err = KErrNone;
+    do
+        {
+        GetSurfAttribs(surfaceAttribs, aIndex, sizeIndex);
+        err = iSurfaceManager.CreateSurface(surfaceAttribs, iSurfaceId);
+        iActualSize = surfaceAttribs().iSize;
+        sizeIndex--;
+        }
+    while(err != KErrNone && sizeIndex >= 0);
     User::LeaveIfError(err);
     }
 
@@ -239,6 +382,7 @@
     aInfo = infoBuf();
     TInt offset = -1000;  // So we hopefully detect when it goes horribly wrong.
     User::LeaveIfError(iSurfaceManager.GetBufferOffset(iSurfaceId, iDrawBuffer, offset));
+    SURF_ASSERT(offset >= 0);
     return iSurfaceChunk.Base() + offset;
     }
 
@@ -266,7 +410,6 @@
     CleanupStack::PopAndDestroy(2, image);
     }
 
-
 void CRawSurface::DrawContentL(const TRgb& aColour)
     {
     //Map the surface and get its info.
@@ -298,7 +441,13 @@
     }
 
 
-void CRawSurface::SubmitContentL(TBool aShouldWaitForDisplay, TInt /* aRectsIndex */)
+void CRawSurface::DrawComplexL(const TRgb& aColour)
+    {
+    DrawContentL(aColour);
+    }
+
+
+TInt CRawSurface::SubmitContent(TBool aShouldWaitForDisplay, TInt /* aRectsIndex */)
     {
     TRequestStatus displayNotify = KRequestPending;
     TTimeStamp timeStamp;
@@ -309,19 +458,27 @@
         }
 
     TInt err = iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurfaceId, iDrawBuffer, NULL);
-    User::LeaveIfError(err);
+    if (err != KErrNone)
+        {
+        if (err != KErrNone)
+            {
+            RDebug::Printf("%s:%d: SubmitUpdate gave unexpected error %d", __FILE__, __LINE__, err);
+            }
+        return err;
+        }
     iDrawBuffer = (iDrawBuffer + 1) % iBuffers;
 
     if(aShouldWaitForDisplay)
         {
         TUint32 dummy;
-        TInt err = WaitFor(ENotifyWhenDisplayed, displayNotify, 100 * 1000, dummy);
+        err = WaitFor(ENotifyWhenDisplayed, displayNotify, 100 * 1000, dummy);
         if (err != KErrNone && err != KErrNotVisible && err != KErrOverflow)
             {
-            RDebug::Printf("%s:%d: NotifyWhenDisplayed gave unexpected error %d", __FILE__, __LINE__, err);
-            User::Leave(err);
+//            RDebug::Printf("%s:%d: NotifyWhenDisplayed gave unexpected error %d", __FILE__, __LINE__, err);
+            return err;
             }
         }
+    return KErrNone;
     }
 
 
@@ -372,6 +529,7 @@
     TInt err = timer.CreateLocal();
     if (err != KErrNone)
         {
+        RDebug::Printf("%s:%d: Could not create timer... err= %d", __FILE__, __LINE__, err);
         return err;
         }
     TRequestStatus timerStatus = KRequestPending;
@@ -403,8 +561,6 @@
     return result;
     }
 
-
-
 const TText *CRawSingleBufferSurface::GetSurfaceTypeStr() const
     {
     return _S("CRawSingleBufferedSurface");
@@ -420,31 +576,283 @@
     }
 
 
-void CRawSingleBufferSurface::CreateL(TInt aIndex)
+void CRawSingleBufferSurface::CreateL(TInt aIndex, const TPoint & /*aPoint */)
     {
     RSurfaceManager::TSurfaceCreationAttributesBuf surfaceAttribs;
 
-    GetSurfAttribs(surfaceAttribs, aIndex);
-
-    iBuffers = 1;
-    surfaceAttribs().iBuffers = 1;
-
-    TInt err = iSurfaceManager.CreateSurface(surfaceAttribs, iSurfaceId);
-    User::LeaveIfError(err);
+    TInt sizeIndex = 0;
+    if (KSurfaceParams[aIndex].iXSize & LARGEST_POSSIBLE_FLAG)
+        {
+        sizeIndex = KMaxSurfaceSizes-1;
+        }
+    TInt err = KErrNone;
+    do
+        {
+        GetSurfAttribs(surfaceAttribs, aIndex, sizeIndex);
+        iBuffers = 1;
+        surfaceAttribs().iBuffers = 1;
+        err = iSurfaceManager.CreateSurface(surfaceAttribs, iSurfaceId);
+        iActualSize = surfaceAttribs().iSize;
+        sizeIndex--;
+        }
+    while(err != KErrNone && sizeIndex >= 0);
     }
 
 CRawSingleBufferSurface::~CRawSingleBufferSurface()
     {
     }
 
+
+TInt CEglSurfaceBase::Activate()
+    {
+    if (!eglMakeCurrent(iDisplay, iSurface, iSurface, iContext))
+        {
+        EGLint err = eglGetError();
+        RDebug::Printf("%s:%d: eglMakeCurrent gave error 0x%x", __FILE__, __LINE__, err);
+        return KErrBadHandle;
+        }
+    return KErrNone;
+    }
+
+void CEglSurfaceBase::ActivateL()
+    {
+    User::LeaveIfError(Activate());
+    }
+
+void CEglSurfaceBase::DrawComplexL(const TRgb& aColour)
+    {
+    ActivateL();
+
+    TSize size;
+    eglQuerySurface(iDisplay, iSurface, EGL_WIDTH, &size.iWidth);
+    eglQuerySurface(iDisplay, iSurface, EGL_HEIGHT, &size.iHeight);
+    
+    //Paint lots of random circles to keep the GPU busy.
+    for(TInt i=0; i < 300; i++)
+        {
+        VGPaint paint = vgCreatePaint();
+        VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_APPEND_TO);
+        
+        TInt minDim = Min(size.iWidth, size.iHeight);
+        VGfloat cx = RandomNumberInRange(0, size.iWidth);
+        VGfloat cy = RandomNumberInRange(0, size.iHeight);
+        VGfloat diameter = RandomNumberInRange(minDim / 20, minDim / 3);
+        TRgb fillColour(RandomNumberInRange(0, 255), RandomNumberInRange(0, 255), RandomNumberInRange(0, 255), RandomNumberInRange(0, 255));
+        
+        vguEllipse(path, cx, cy, diameter, diameter);
+        vgSetPaint(paint, VG_FILL_PATH);
+        vgSetColor(paint, fillColour.Value());
+        vgDrawPath(path, VG_FILL_PATH);
+        
+        vgDestroyPath(path);
+        vgDestroyPaint(paint);
+        }
+    
+    //Paint the top corner with aColour so we can identify the drawing.
+    VGfloat fillColour[4];
+    fillColour[0] = (VGfloat)aColour.Red() / 255.0f;
+    fillColour[1] = (VGfloat)aColour.Green() / 255.0f;
+    fillColour[2] = (VGfloat)aColour.Blue() / 255.0f;
+    fillColour[3] = (VGfloat)aColour.Alpha() / 255.0f;
+    
+    vgSetfv(VG_CLEAR_COLOR, 4, fillColour);
+    vgClear(0, 0, 20, size.iHeight);
+    }
+
+void CEglSurfaceBase::DrawContentL(const TRgb& aColour)
+    {
+    ActivateL();
+
+    TSize size;
+    eglQuerySurface(iDisplay, iSurface, EGL_WIDTH, &size.iWidth);
+    eglQuerySurface(iDisplay, iSurface, EGL_HEIGHT, &size.iHeight);
+
+    VGfloat fillColour[4];
+    fillColour[0] = (VGfloat)aColour.Red() / 255.0f;
+    fillColour[1] = (VGfloat)aColour.Green() / 255.0f;
+    fillColour[2] = (VGfloat)aColour.Blue() / 255.0f;
+    fillColour[3] = (VGfloat)aColour.Alpha() / 255.0f;
+
+    vgSetfv(VG_CLEAR_COLOR, 4, fillColour);
+    vgClear(0, 0, size.iWidth, size.iHeight);
+    }
+
+void CEglSurfaceBase::CreateL(TInt aIndex, const TPoint &aOffset)
+    {
+    SURF_ASSERT(aIndex < KSurfaceMaxIndex);
+    SURF_ASSERT(aIndex == KSurfaceParams[aIndex].iIndex);
+
+    TInt sizeIndex = 0;
+    if (KSurfaceParams[aIndex].iXSize & LARGEST_POSSIBLE_FLAG)
+        {
+        sizeIndex = KMaxSurfaceSizes-1;
+        }
+    TInt err = KErrNone;
+    do
+        {
+        TRAP(err, DoCreateL(aIndex, aOffset, sizeIndex));
+        sizeIndex--;
+        }
+    while(err != KErrNone && sizeIndex >= 0);
+    if (err != KErrNone)
+        {
+//        RDebug::Printf("%s:%d: err=%d (%d x %d)", __FILE__, __LINE__, err, iActualSize.iWidth, iActualSize.iHeight);
+        User::Leave(err);
+        }
+    }
+
+TInt CEglSurfaceBase::SubmitContent(TBool aShouldWaitForDisplay, TInt /* aRectsIndex */)
+    {
+    TInt err = Activate();
+    if (err != KErrNone)
+        {
+        return err;
+        }
+    if (!eglSwapBuffers(iDisplay, iSurface))
+        {
+        EGLint err = eglGetError();
+        RDebug::Printf("%s:%d: eglSwapBuffers gave error 0x%x", __FILE__, __LINE__, err);
+        return KErrBadHandle;
+        }
+    if (aShouldWaitForDisplay)
+        {
+        // We are cheating: We just wait for a bit to ensure that the swapbuffer is actually finished.
+        // There is no way to determine how long this takes, so we just grab a number that should be
+        // large enough...
+        User::After(100 * 1000);  // Wait 100ms.
+        }
+    return KErrNone;
+    }
+
+void CEglSurfaceBase::DrawContentL(TInt aIndex)
+    {
+    ActivateL();
+    CTestVgImage *vgImage = CTestVgImage::NewL(aIndex);
+    CleanupStack::PushL(vgImage);
+    vgDrawImage(vgImage->VGImage());
+    CleanupStack::PopAndDestroy(vgImage);
+    }
+
+void CEglSurfaceBase::GetSurfaceParamsL(TSurfaceParamsRemote &aParams)
+    {
+    RSurfaceManager surfaceManager;
+    User::LeaveIfError(surfaceManager.Open());
+    RSurfaceManager::TInfoBuf infoBuf;
+    TInt err = surfaceManager.SurfaceInfo(SurfaceId(), infoBuf);
+    User::LeaveIfError(err);
+    surfaceManager.Close();
+    RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
+    aParams.iSurfaceId = SurfaceId();
+    aParams.iCommonParams.iAlignment = -1;  // N/A
+    aParams.iCommonParams.iBuffers = info.iBuffers;
+    aParams.iCommonParams.iOffsetToFirstBuffer = -1;
+    aParams.iCommonParams.iPixelFormat = info.iPixelFormat;
+    aParams.iCommonParams.iStrideInBytes = info.iStride;
+    aParams.iCommonParams.iXSize = info.iSize.iWidth;
+    aParams.iCommonParams.iYSize = info.iSize.iHeight;
+    aParams.iCommonParams.iUseAttribList = KSurfaceParams[iParamIndex].iUseAttribList;
+    for(TInt i = 0; i < KNumAttribs; i++)
+        {
+        aParams.iCommonParams.iAttribs[i] = KSurfaceParams[iParamIndex].iAttribs[i];
+        }
+    }
+
+
+TInt CEglSurfaceBase::Notify(TNotification /*aWhen*/, TRequestStatus& /*aStatus*/, TUint32 /*aXTImes*/)
+    {
+    return KErrNotSupported;
+    }
+
+TInt CEglSurfaceBase::WaitFor(TNotification /*aWhen*/, TRequestStatus& /*aStatus*/,
+        TInt /*aTimeoutinMicroseconds*/, TUint32 & /*aTimeStamp*/)
+    {
+    return KErrNotSupported;
+    }
+
+void CEglSurfaceBase::BaseCreateL(TInt aIndex, EGLint aSurfaceType)
+    {
+    iParamIndex = aIndex;
+    iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    
+    EGLint err;
+    if (iDisplay == EGL_NO_DISPLAY)
+        {
+        err = eglGetError();
+        RDebug::Printf("%s:%d: err = 0x%x", __FILE__, __LINE__, err);
+        User::Leave(KErrNotSupported);
+        }
+    
+    EGLint nConfigs = 0;
+    
+    // TODO: Need to use differnet config attribs based on aIndex.
+    EGLint configAttribs[] =
+    {
+        EGL_BUFFER_SIZE,    32,
+        EGL_RED_SIZE,       8,
+        EGL_GREEN_SIZE,     8,
+        EGL_BLUE_SIZE,      8,
+        EGL_ALPHA_SIZE,     8,
+        EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
+        EGL_RENDERABLE_TYPE,EGL_OPENVG_BIT,
+        EGL_NONE
+    };
+    
+    // Update surfacetype type to match 
+    for(TInt i = 0; configAttribs[i] != EGL_NONE; i += 2)
+        {
+        if (configAttribs[i] == EGL_SURFACE_TYPE)
+            {
+            configAttribs[i+1] = aSurfaceType;
+            }
+        }
+    // Need some way to configure the attribs ...
+    eglChooseConfig(iDisplay, configAttribs, &iConfig, 1, &nConfigs);
+    if (!nConfigs)
+        {
+        err = eglGetError();
+        RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err);
+        User::Leave(KErrNotSupported);
+        }
+    
+    if (!eglBindAPI(EGL_OPENVG_API))
+        {
+        err = eglGetError();
+        RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err);
+        User::Leave(KErrNotSupported);
+        }
+    iContext = eglCreateContext(iDisplay, iConfig, 0, NULL);
+    if (iContext == EGL_NO_CONTEXT)
+        {
+        err = eglGetError();
+        //RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err);
+        User::Leave(KErrNotSupported);
+        }
+    }
+
+void CEglSurfaceBase::Destroy()
+    {
+    eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    if (iSurface != EGL_NO_SURFACE)
+        {
+        eglDestroySurface(iDisplay, iSurface);
+        iSurface = EGL_NO_SURFACE;
+        }
+
+    if (iDisplay != EGL_NO_DISPLAY)
+        {
+        eglDestroyContext(iDisplay, iContext);
+        }
+    }
+
+
 class CWindow: public CBase
     {
 public:
-    static CWindow *NewL(TInt aIndex);
+    static CWindow *NewL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex);
     RWindow& Window();
     ~CWindow();
 private:
-    void ConstructL(TInt aIndex);
+    void ConstructL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex);
     CWindow();
 
 private:
@@ -454,17 +862,17 @@
     };
 
 
-CWindow* CWindow::NewL(TInt aIndex)
+CWindow* CWindow::NewL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex)
     {
     CWindow *self = new (ELeave) CWindow;
     CleanupStack::PushL(self);
-    self->ConstructL(aIndex);
+    self->ConstructL(aIndex, aOffset, aSizeIndex);
     CleanupStack::Pop(self);
     return self;
     }
 
 
-void CWindow::ConstructL(TInt aIndex)
+void CWindow::ConstructL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex)
     {
     RFbsSession::Connect();
     if (aIndex >= KSurfaceMaxIndex)
@@ -476,8 +884,17 @@
     User::LeaveIfError(iWindowGroup.Construct((TUint32)this));
     iWindow = RWindow(iWsSession);
     User::LeaveIfError(iWindow.Construct(iWindowGroup, -1U));
-    const TSurfaceParamsCommon& winAttrib = KSurfaceParams[aIndex];
-    iWindow.SetExtent(TPoint(winAttrib.iXPos, winAttrib.iYPos), TSize(winAttrib.iXSize, winAttrib.iYSize));
+    TSurfaceParamsCommon winAttrib = KSurfaceParams[aIndex];
+    TSize winSize;
+    if (winAttrib.iXSize & LARGEST_POSSIBLE_FLAG)
+        {
+        winSize = TSize(KSurfaceSizes[aSizeIndex].iWidth, KSurfaceSizes[aSizeIndex].iHeight);
+        }
+    else
+        {
+        winSize = TSize(winAttrib.iXSize, winAttrib.iYSize);
+        }
+    iWindow.SetExtent(TPoint(winAttrib.iXPos + aOffset.iX, winAttrib.iYPos + aOffset.iY), winSize);
     iWindow.SetRequiredDisplayMode(winAttrib.iDisplayMode);
     iWindow.Activate();
     }
@@ -523,110 +940,32 @@
     }
 
 
-void CEglWindowSurface::CreateL(TInt aIndex)
-    {
-    SURF_ASSERT(aIndex < KSurfaceMaxIndex);
-    SURF_ASSERT(aIndex == KSurfaceParams[aIndex].iIndex);
-    iParamIndex = aIndex;
-    iWindow = CWindow::NewL(aIndex);
-    iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    EGLint err;
-    if (iDisplay == EGL_NO_DISPLAY)
-        {
-        err = eglGetError();
-        RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err);
-        User::Leave(KErrNotSupported);
-        }
-
-    EGLConfig config;
-    EGLint nConfigs = 0;
-
-    // TODO: Need to use differnet config attribs based on aIndex.
-    static const EGLint KConfigAttribs[] =
+void CEglWindowSurface::DoCreateL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex)
     {
-        EGL_BUFFER_SIZE,    32,
-        EGL_RED_SIZE,       8,
-        EGL_GREEN_SIZE,     8,
-        EGL_BLUE_SIZE,      8,
-        EGL_ALPHA_SIZE,     8,
-        EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
-        EGL_RENDERABLE_TYPE,EGL_OPENVG_BIT,
-        EGL_NONE
-    };
-
-    // Need some way to configure the attribs ...
-    eglChooseConfig(iDisplay, KConfigAttribs, &config, 1, &nConfigs);
-    if (!nConfigs)
-        {
-        err = eglGetError();
-        RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err);
-        User::Leave(KErrNotSupported);
-        }
-
-    if (!eglBindAPI(EGL_OPENVG_API))
-        {
-        err = eglGetError();
-        RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err);
-        User::Leave(KErrNotSupported);
-        }
-    iContext = eglCreateContext(iDisplay, config, 0, NULL);
-    if (iContext == EGL_NO_CONTEXT)
-        {
-        err = eglGetError();
-        RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err);
-        User::Leave(KErrNotSupported);
-        }
-
-    iSurface = eglCreateWindowSurface(iDisplay, config, &iWindow->Window(), NULL);
+    iParamIndex = aIndex;
+    iWindow = CWindow::NewL(aIndex, aOffset, aSizeIndex);
+    iActualSize = iWindow->Window().Size();
+    
+    CEglSurfaceBase::BaseCreateL(aIndex, EGL_WINDOW_BIT);
+    
+    iSurface = eglCreateWindowSurface(iDisplay, iConfig, &iWindow->Window(), NULL);
     if (iSurface == EGL_NO_SURFACE)
         {
-        err = eglGetError();
-        RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err);
+        EGLint err = eglGetError();
+        RDebug::Printf("%s:%d: err = %x (%d x %d)", __FILE__, __LINE__, err, iActualSize.iWidth, iActualSize.iHeight);
         User::Leave(KErrNotSupported);
         }
     }
 
-void CEglWindowSurface::SubmitContentL(TBool aShouldWaitForDisplay, TInt /* aRectsIndex */)
-    {
-    ActivateL();
-    if (!eglSwapBuffers(iDisplay, iSurface))
-        {
-        User::Leave(KErrBadHandle);
-        }
-    if (aShouldWaitForDisplay)
-        {
-        // We are cheating: We just wait for a bit to ensure that the swapbuffer is actually finished.
-        // There is no way to determine how long this takes, so we just grab a number that should be
-        // large enough...
-        User::After(100 * 1000);  // Wait 100ms.
-        }
-    }
-
-void CEglWindowSurface::ActivateL()
-    {
-    if (!eglMakeCurrent(iDisplay, iSurface, iSurface, iContext))
-        {
-        User::Leave(KErrBadHandle);
-        }
-    }
 
 CEglWindowSurface::~CEglWindowSurface()
     {
-    eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    if (iSurface != EGL_NO_SURFACE)
-        {
-        eglDestroySurface(iDisplay, iSurface);
-        iSurface = EGL_NO_SURFACE;
-        }
-
-    if (iDisplay != EGL_NO_DISPLAY)
-        {
-        eglDestroyContext(iDisplay, iContext);
-        }
-
+    Destroy();
+	eglReleaseThread();
     delete iWindow;
     }
 
+
 TSurfaceId CEglWindowSurface::SurfaceId() const
     {
     // Default constructor for id sets it to a NULL-value, so if no window is created, we get
@@ -642,72 +981,104 @@
     }
 
 
-void CEglWindowSurface::DrawContentL(const TRgb& aColour)
-    {
-    ActivateL();
-
-    TSize size;
-    eglQuerySurface(iDisplay, iSurface, EGL_WIDTH, &size.iWidth);
-    eglQuerySurface(iDisplay, iSurface, EGL_HEIGHT, &size.iHeight);
-
-    VGfloat fillColour[4];
-    fillColour[0] = (VGfloat)aColour.Red() / 255.0f;
-    fillColour[1] = (VGfloat)aColour.Green() / 255.0f;
-    fillColour[2] = (VGfloat)aColour.Blue() / 255.0f;
-    fillColour[3] = (VGfloat)aColour.Alpha() / 255.0f;
-
-    vgSetfv(VG_CLEAR_COLOR, 4, fillColour);
-    vgClear(0, 0, size.iWidth, size.iHeight);
-    }
-
-
-void CEglWindowSurface::DrawContentL(TInt aIndex)
-    {
-    ActivateL();
-    CTestVgImage *vgImage = CTestVgImage::NewL(aIndex);
-    CleanupStack::PushL(vgImage);
-    vgDrawImage(vgImage->VGImage());
-    CleanupStack::PopAndDestroy(vgImage);
-    }
-
-void CEglWindowSurface::GetSurfaceParamsL(TSurfaceParamsRemote &aParams)
-    {
-    RSurfaceManager surfaceManager;
-    User::LeaveIfError(surfaceManager.Open());
-    RSurfaceManager::TInfoBuf infoBuf;
-    TInt err = surfaceManager.SurfaceInfo(SurfaceId(), infoBuf);
-    User::LeaveIfError(err);
-    surfaceManager.Close();
-    RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
-    aParams.iSurfaceId = SurfaceId();
-    aParams.iCommonParams.iAlignment = -1;  // N/A
-    aParams.iCommonParams.iBuffers = info.iBuffers;
-    aParams.iCommonParams.iOffsetToFirstBuffer = -1;
-    aParams.iCommonParams.iPixelFormat = info.iPixelFormat;
-    aParams.iCommonParams.iStrideInBytes = info.iStride;
-    aParams.iCommonParams.iXSize = info.iSize.iWidth;
-    aParams.iCommonParams.iYSize = info.iSize.iHeight;
-    aParams.iCommonParams.iUseAttribList = KSurfaceParams[iParamIndex].iUseAttribList;
-    for(TInt i = 0; i < KNumAttribs; i++)
-        {
-        aParams.iCommonParams.iAttribs[i] = KSurfaceParams[iParamIndex].iAttribs[i];
-        }
-    }
-
 const TText *CEglWindowSurface::GetSurfaceTypeStr() const
     {
     return _S("CEglWindowSurface");
     }
 
-TInt CEglWindowSurface::Notify(TNotification /*aWhen*/, TRequestStatus& /*aStatus*/, TUint32 /*aXTImes*/)
+
+CEglPBufferSurface::CEglPBufferSurface()
+    {
+    }
+
+
+CEglPBufferSurface::~CEglPBufferSurface()
+    {
+    Destroy();
+	eglReleaseThread();
+    }
+    
+
+CEglPBufferSurface* CEglPBufferSurface::NewL()
     {
-    return KErrNotSupported;
+    CEglPBufferSurface* self = new (ELeave) CEglPBufferSurface;
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+
+void CEglPBufferSurface::ConstructL()
+    {
+    }
+    
+
+const TText *CEglPBufferSurface::GetSurfaceTypeStr() const
+    {
+    return _S("CEglPBufferSurface");
     }
 
-TInt CEglWindowSurface::WaitFor(TNotification /*aWhen*/, TRequestStatus& /*aStatus*/,
-        TInt /*aTimeoutinMicroseconds*/, TUint32 & /*aTimeStamp*/)
+
+void CEglPBufferSurface::DoCreateL(TInt aIndex, const TPoint &/*aOffset*/, TInt aSizeIndex)
     {
-    return KErrNotSupported;
+    CEglSurfaceBase::BaseCreateL(aIndex, EGL_PBUFFER_BIT);
+
+    EGLint attribs[] = 
+            {
+                EGL_WIDTH, 0,
+                EGL_HEIGHT, 0,
+                EGL_NONE,
+            };
+    if (KSurfaceParams[aIndex].iXSize & ELargestPossibleSurface)
+        {
+        iActualSize.iWidth = KSurfaceSizes[aSizeIndex].iWidth;
+        iActualSize.iHeight = KSurfaceSizes[aSizeIndex].iHeight;
+        }
+    else
+        {
+        iActualSize.iWidth = KSurfaceParams[aIndex].iXSize;
+        iActualSize.iHeight = KSurfaceParams[aIndex].iYSize;
+        }
+    for(TInt i = 0; attribs[i] != EGL_NONE; i += 2)
+        {
+        switch(attribs[i])
+            {
+            case EGL_HEIGHT:
+                attribs[i+1] = iActualSize.iHeight;
+                break;
+            case EGL_WIDTH:
+                attribs[i+1] = iActualSize.iWidth;
+                break;
+            }
+        }
+    
+    iSurface = eglCreatePbufferSurface(iDisplay, iConfig, attribs);
+    if (iSurface == EGL_NO_SURFACE)
+        {
+        EGLint err = eglGetError();
+        User::Leave(KErrNotSupported);
+        }
+    }
+
+
+TSurfaceId CEglPBufferSurface::SurfaceId() const
+    {
+    SURF_ASSERT(0);  // We shouldn't call this!
+    return TSurfaceId::CreateNullId();
+    }
+
+TInt CEglPBufferSurface::SizeInBytes() const
+    {
+    // size of a pixel in bits. 
+    EGLint size;
+    if (!eglGetConfigAttrib(iDisplay, iConfig, EGL_BUFFER_SIZE, &size))
+        {
+        RDebug::Printf("Unable to get EGL_BUFFER_SIZE from config %d, err = %04x", iConfig, eglGetError());
+        return 0;
+        }
+    
+    return (KSurfaceParams[iParamIndex].iXSize * KSurfaceParams[iParamIndex].iYSize * size) / 8;
     }
 
 
@@ -718,13 +1089,18 @@
         {
         case ESurfTypeRaw:
             return CRawSurface::NewL();
+            
         case ESurfTypeEglWindow:
             return CEglWindowSurface::NewL();
+            
         case ESurfTypeRawSingleBuffered:
             return CRawSingleBufferSurface::NewL();
+            
+        case ESurfTypePBuffer:
+            return CEglPBufferSurface::NewL();
+            
         default:
             SURF_ASSERT(0);
             return NULL;
         }
     }
-