Implement EGL_LARGEST_PBUFFER.

Bug 23041720

Change-Id: I9f6bed0a3d239a0adde9cc4e90cc368f078f3662
Reviewed-on: https://swiftshader-review.googlesource.com/3902
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libEGL/Display.cpp b/src/OpenGL/libEGL/Display.cpp
index 7cc9c44..2ea5a9f 100644
--- a/src/OpenGL/libEGL/Display.cpp
+++ b/src/OpenGL/libEGL/Display.cpp
@@ -305,7 +305,7 @@
         return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
     }
 
-    Surface *surface = new Surface(this, configuration, window);
+    Surface *surface = new WindowSurface(this, configuration, window);
 
     if(!surface->initialize())
     {
@@ -319,61 +319,63 @@
     return success(surface);
 }
 
-EGLSurface Display::createOffscreenSurface(EGLConfig config, const EGLint *attribList)
+EGLSurface Display::createPBufferSurface(EGLConfig config, const EGLint *attribList)
 {
     EGLint width = 0, height = 0;
     EGLenum textureFormat = EGL_NO_TEXTURE;
     EGLenum textureTarget = EGL_NO_TEXTURE;
+	EGLBoolean largestPBuffer = EGL_FALSE;
     const Config *configuration = mConfigSet.get(config);
 
     if(attribList)
     {
         while(*attribList != EGL_NONE)
         {
-            switch (attribList[0])
+            switch(attribList[0])
             {
-              case EGL_WIDTH:
+            case EGL_WIDTH:
                 width = attribList[1];
                 break;
-              case EGL_HEIGHT:
+            case EGL_HEIGHT:
                 height = attribList[1];
                 break;
-              case EGL_LARGEST_PBUFFER:
-                if(attribList[1] != EGL_FALSE)
-                  UNIMPLEMENTED(); // FIXME
+            case EGL_LARGEST_PBUFFER:
+                largestPBuffer = attribList[1];
                 break;
-              case EGL_TEXTURE_FORMAT:
-                switch (attribList[1])
+            case EGL_TEXTURE_FORMAT:
+                switch(attribList[1])
                 {
-                  case EGL_NO_TEXTURE:
-                  case EGL_TEXTURE_RGB:
-                  case EGL_TEXTURE_RGBA:
+                case EGL_NO_TEXTURE:
+                case EGL_TEXTURE_RGB:
+                case EGL_TEXTURE_RGBA:
                     textureFormat = attribList[1];
                     break;
-                  default:
+                default:
                     return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
                 }
                 break;
-              case EGL_TEXTURE_TARGET:
-                switch (attribList[1])
+            case EGL_TEXTURE_TARGET:
+                switch(attribList[1])
                 {
-                  case EGL_NO_TEXTURE:
-                  case EGL_TEXTURE_2D:
+                case EGL_NO_TEXTURE:
+                case EGL_TEXTURE_2D:
                     textureTarget = attribList[1];
                     break;
-                  default:
+                default:
                     return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
                 }
                 break;
-              case EGL_MIPMAP_TEXTURE:
+            case EGL_MIPMAP_TEXTURE:
                 if(attribList[1] != EGL_FALSE)
-                  return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+				{
+					return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+				}
                 break;
-              case EGL_VG_COLORSPACE:
+            case EGL_VG_COLORSPACE:
                 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
-              case EGL_VG_ALPHA_FORMAT:
+            case EGL_VG_ALPHA_FORMAT:
                 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
-              default:
+            default:
                 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
             }
 
@@ -408,7 +410,7 @@
         return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
     }
 
-    Surface *surface = new Surface(this, configuration, width, height, textureFormat, textureTarget);
+    Surface *surface = new PBufferSurface(this, configuration, width, height, textureFormat, textureTarget, largestPBuffer);
 
     if(!surface->initialize())
     {
@@ -543,21 +545,24 @@
 {
     for(SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
     {
-        if((*surface)->getWindowHandle() == window)
-        {
-            return true;
-        }
+		if((*surface)->isWindowSurface())
+		{
+			if((*surface)->getWindowHandle() == window)
+			{
+				return true;
+			}
+		}
     }
 
     return false;
 }
 
-EGLint Display::getMinSwapInterval()
+EGLint Display::getMinSwapInterval() const
 {
     return mMinSwapInterval;
 }
 
-EGLint Display::getMaxSwapInterval()
+EGLint Display::getMaxSwapInterval() const
 {
     return mMaxSwapInterval;
 }
diff --git a/src/OpenGL/libEGL/Display.h b/src/OpenGL/libEGL/Display.h
index 3c47853..39b8ff1 100644
--- a/src/OpenGL/libEGL/Display.h
+++ b/src/OpenGL/libEGL/Display.h
@@ -39,7 +39,7 @@
 		bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);

 

 		EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList);

-		EGLSurface createOffscreenSurface(EGLConfig config, const EGLint *attribList);

+		EGLSurface createPBufferSurface(EGLConfig config, const EGLint *attribList);

 		EGLContext createContext(EGLConfig configHandle, const Context *shareContext, EGLint clientVersion);

 

 		void destroySurface(Surface *surface);

@@ -52,8 +52,8 @@
 		bool isValidWindow(EGLNativeWindowType window);

 		bool hasExistingWindowSurface(EGLNativeWindowType window);

 

-		EGLint getMinSwapInterval();

-		EGLint getMaxSwapInterval();

+		EGLint getMinSwapInterval() const;

+		EGLint getMaxSwapInterval() const;

 

 		EGLNativeDisplayType getNativeDisplay() const;

 		const char *getExtensionString() const;

diff --git a/src/OpenGL/libEGL/Surface.cpp b/src/OpenGL/libEGL/Surface.cpp
index 816f952..d36be0d 100644
--- a/src/OpenGL/libEGL/Surface.cpp
+++ b/src/OpenGL/libEGL/Surface.cpp
@@ -36,40 +36,21 @@
 namespace egl

 {

 

-Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window)

-    : mDisplay(display), mConfig(config), mWindow(window)

+Surface::Surface(const Display *display, const Config *config) : display(display), config(config)

 {

-    frameBuffer = 0;

-	backBuffer = 0;

+	backBuffer = nullptr;

+    depthStencil = nullptr;

+    texture = nullptr;

 

-    mDepthStencil = NULL;

-    mTexture = NULL;

-    mTextureFormat = EGL_NO_TEXTURE;

-    mTextureTarget = EGL_NO_TEXTURE;

-

-    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio

-    mRenderBuffer = EGL_BACK_BUFFER;

-    mSwapBehavior = EGL_BUFFER_PRESERVED;

-    mSwapInterval = -1;

-    setSwapInterval(1);

-}

-

-Surface::Surface(Display *display, const Config *config, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)

-    : mDisplay(display), mWindow(NULL), mConfig(config), mWidth(width), mHeight(height)

-{

-	frameBuffer = 0;

-	backBuffer = 0;

-

-    mDepthStencil = NULL;

-    mWindowSubclassed = false;

-    mTexture = NULL;

-    mTextureFormat = textureFormat;

-    mTextureTarget = textureType;

-

-    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio

-    mRenderBuffer = EGL_BACK_BUFFER;

-    mSwapBehavior = EGL_BUFFER_PRESERVED;

-    mSwapInterval = -1;

+	width = 0;

+	height = 0;

+	largestPBuffer = EGL_FALSE;

+    pixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio

+    renderBuffer = EGL_BACK_BUFFER;

+    swapBehavior = EGL_BUFFER_PRESERVED;

+	textureFormat = EGL_NO_TEXTURE;

+    textureTarget = EGL_NO_TEXTURE;

+    swapInterval = -1;

     setSwapInterval(1);

 }

 

@@ -80,88 +61,15 @@
 

 bool Surface::initialize()

 {

-    ASSERT(!frameBuffer && !backBuffer && !mDepthStencil);

-

-    return reset();

-}

-

-void Surface::deleteResources()

-{

-    if(mDepthStencil)

-    {

-        mDepthStencil->release();

-        mDepthStencil = NULL;

-    }

-

-    if(mTexture)

-    {

-        mTexture->releaseTexImage();

-        mTexture = NULL;

-    }

-

-	if(backBuffer)

-	{

-		backBuffer->release();

-		backBuffer = 0;

-	}

-

-	delete frameBuffer;

-	frameBuffer = 0;

-}

-

-bool Surface::reset()

-{

-    if(!mWindow)

-    {

-        return reset(mWidth, mHeight);

-    }

-

-	// FIXME: Wrap into an abstract Window class

-	#if defined(_WIN32)

-		RECT windowRect;

-		GetClientRect(mWindow, &windowRect);

-

-		return reset(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);

-	#elif defined(__ANDROID__)

-		return reset(ANativeWindow_getWidth(mWindow), ANativeWindow_getHeight(mWindow));

-	#else

-		XWindowAttributes windowAttributes;

-		libX11->XGetWindowAttributes(mDisplay->getNativeDisplay(), mWindow, &windowAttributes);

-

-		return reset(windowAttributes.width, windowAttributes.height);

-	#endif

-}

-

-bool Surface::reset(int backBufferWidth, int backBufferHeight)

-{

-    deleteResources();

-

-    if(mWindow)

-    {

-		if(libGLES_CM)

-		{

-			frameBuffer = libGLES_CM->createFrameBuffer(mDisplay->getNativeDisplay(), mWindow, backBufferWidth, backBufferHeight);

-		}

-		else if(libGLESv2)

-		{

-			frameBuffer = libGLESv2->createFrameBuffer(mDisplay->getNativeDisplay(), mWindow, backBufferWidth, backBufferHeight);

-		}

-

-		if(!frameBuffer)

-		{

-			ERR("Could not create frame buffer");

-			deleteResources();

-			return error(EGL_BAD_ALLOC, false);

-		}

-    }

+	ASSERT(!backBuffer && !depthStencil);

 

 	if(libGLES_CM)

 	{

-		backBuffer = libGLES_CM->createBackBuffer(backBufferWidth, backBufferHeight, mConfig);

+		backBuffer = libGLES_CM->createBackBuffer(width, height, config);

 	}

 	else if(libGLESv2)

 	{

-		backBuffer = libGLESv2->createBackBuffer(backBufferWidth, backBufferHeight, mConfig);

+		backBuffer = libGLESv2->createBackBuffer(width, height, config);

 	}

 

     if(!backBuffer)

@@ -171,18 +79,18 @@
         return error(EGL_BAD_ALLOC, false);

     }

 

-    if(mConfig->mDepthStencilFormat != sw::FORMAT_NULL)

+    if(config->mDepthStencilFormat != sw::FORMAT_NULL)

     {

 		if(libGLES_CM)

 		{

-			mDepthStencil = libGLES_CM->createDepthStencil(backBufferWidth, backBufferHeight, mConfig->mDepthStencilFormat, 1, false);

+			depthStencil = libGLES_CM->createDepthStencil(width, height, config->mDepthStencilFormat, 1, false);

 		}

 		else if(libGLESv2)

 		{

-			mDepthStencil = libGLESv2->createDepthStencil(backBufferWidth, backBufferHeight, mConfig->mDepthStencilFormat, 1, false);

+			depthStencil = libGLESv2->createDepthStencil(width, height, config->mDepthStencilFormat, 1, false);

 		}

 

-		if(!mDepthStencil)

+		if(!depthStencil)

 		{

 			ERR("Could not create depth/stencil buffer for surface");

 			deleteResources();

@@ -190,26 +98,27 @@
 		}

     }

 

-    mWidth = backBufferWidth;

-    mHeight = backBufferHeight;

-

-    return true;

+	return true;

 }

 

-EGLNativeWindowType Surface::getWindowHandle()

+void Surface::deleteResources()

 {

-    return mWindow;

-}

-

-void Surface::swap()

-{

-	if(backBuffer)

+    if(depthStencil)

     {

-		void *source = backBuffer->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);

-		frameBuffer->flip(source, backBuffer->Surface::getInternalFormat());

-		backBuffer->unlockInternal();

+        depthStencil->release();

+        depthStencil = nullptr;

+    }

 

-        checkForResize();

+    if(texture)

+    {

+        texture->releaseTexImage();

+        texture = nullptr;

+    }

+

+	if(backBuffer)

+	{

+		backBuffer->release();

+		backBuffer = nullptr;

 	}

 }

 

@@ -225,96 +134,143 @@
 

 egl::Image *Surface::getDepthStencil()

 {

-    if(mDepthStencil)

+    if(depthStencil)

     {

-        mDepthStencil->addRef();

+        depthStencil->addRef();

     }

 

-    return mDepthStencil;

+    return depthStencil;

 }

 

 void Surface::setSwapBehavior(EGLenum swapBehavior)

 {

-	mSwapBehavior = swapBehavior;

+	swapBehavior = swapBehavior;

 }

 

 void Surface::setSwapInterval(EGLint interval)

 {

-    if(mSwapInterval == interval)

+    if(swapInterval == interval)

     {

         return;

     }

 

-    mSwapInterval = interval;

-    mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval());

-    mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval());

+    swapInterval = interval;

+    swapInterval = std::max(swapInterval, display->getMinSwapInterval());

+    swapInterval = std::min(swapInterval, display->getMaxSwapInterval());

 }

 

 EGLint Surface::getConfigID() const

 {

-    return mConfig->mConfigID;

+    return config->mConfigID;

 }

 

 EGLenum Surface::getSurfaceType() const

 {

-    return mConfig->mSurfaceType;

+    return config->mSurfaceType;

 }

 

 sw::Format Surface::getInternalFormat() const

 {

-    return mConfig->mRenderTargetFormat;

+    return config->mRenderTargetFormat;

 }

 

 EGLint Surface::getWidth() const

 {

-    return mWidth;

+    return width;

 }

 

 EGLint Surface::getHeight() const

 {

-    return mHeight;

+    return height;

 }

 

 EGLint Surface::getPixelAspectRatio() const

 {

-    return mPixelAspectRatio;

+    return pixelAspectRatio;

 }

 

 EGLenum Surface::getRenderBuffer() const

 {

-    return mRenderBuffer;

+    return renderBuffer;

 }

 

 EGLenum Surface::getSwapBehavior() const

 {

-    return mSwapBehavior;

+    return swapBehavior;

 }

 

 EGLenum Surface::getTextureFormat() const

 {

-    return mTextureFormat;

+    return textureFormat;

 }

 

 EGLenum Surface::getTextureTarget() const

 {

-    return mTextureTarget;

+    return textureTarget;

+}

+

+EGLBoolean Surface::getLargestPBuffer() const

+{

+	return largestPBuffer;

 }

 

 void Surface::setBoundTexture(egl::Texture *texture)

 {

-    mTexture = texture;

+    this->texture = texture;

 }

 

 egl::Texture *Surface::getBoundTexture() const

 {

-    return mTexture;

+    return texture;

 }

 

-bool Surface::checkForResize()

+WindowSurface::WindowSurface(Display *display, const Config *config, EGLNativeWindowType window)

+    : Surface(display, config), window(window)

+{

+    frameBuffer = nullptr;

+}

+

+bool WindowSurface::initialize()

+{

+    ASSERT(!frameBuffer && !backBuffer && !depthStencil);

+

+	#if defined(_WIN32)

+		RECT windowRect;

+		GetClientRect(window, &windowRect);

+

+		return reset(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);

+	#elif defined(__ANDROID__)

+		return reset(ANativeWindow_getWidth(window), ANativeWindow_getHeight(window));

+	#else

+		XWindowAttributes windowAttributes;

+		libX11->XGetWindowAttributes(display->getNativeDisplay(), window, &windowAttributes);

+

+		return reset(windowAttributes.width, windowAttributes.height);

+	#endif

+}

+

+void WindowSurface::swap()

+{

+	if(backBuffer && frameBuffer)

+    {

+		void *source = backBuffer->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);

+		frameBuffer->flip(source, backBuffer->Surface::getInternalFormat());

+		backBuffer->unlockInternal();

+

+        checkForResize();

+	}

+}

+

+EGLNativeWindowType WindowSurface::getWindowHandle() const

+{

+    return window;

+}

+

+bool WindowSurface::checkForResize()

 {

     #if defined(_WIN32)

 		RECT client;

-		if(!GetClientRect(mWindow, &client))

+		if(!GetClientRect(window, &client))

 		{

 			ASSERT(false);

 			return false;

@@ -323,17 +279,17 @@
 		int clientWidth = client.right - client.left;

 		int clientHeight = client.bottom - client.top;

 	#elif defined(__ANDROID__)

-		int clientWidth = ANativeWindow_getWidth(mWindow);

-		int clientHeight = ANativeWindow_getHeight(mWindow);

+		int clientWidth = ANativeWindow_getWidth(window);

+		int clientHeight = ANativeWindow_getHeight(window);

 	#else

 		XWindowAttributes windowAttributes;

-		libX11->XGetWindowAttributes(mDisplay->getNativeDisplay(), mWindow, &windowAttributes);

+		libX11->XGetWindowAttributes(display->getNativeDisplay(), window, &windowAttributes);

 

 		int clientWidth = windowAttributes.width;

 		int clientHeight = windowAttributes.height;

 	#endif

 

-	bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();

+	bool sizeDirty = (clientWidth != width) || (clientHeight != height);

 

     if(sizeDirty)

     {

@@ -349,4 +305,62 @@
 

     return false;

 }

+

+void WindowSurface::deleteResources()

+{

+	delete frameBuffer;

+	frameBuffer = nullptr;

+

+	Surface::deleteResources();

+}

+

+bool WindowSurface::reset(int backBufferWidth, int backBufferHeight)

+{

+	width = backBufferWidth;

+    height = backBufferHeight;

+

+    deleteResources();

+

+    if(window)

+    {

+		if(libGLES_CM)

+		{

+			frameBuffer = libGLES_CM->createFrameBuffer(display->getNativeDisplay(), window, width, height);

+		}

+		else if(libGLESv2)

+		{

+			frameBuffer = libGLESv2->createFrameBuffer(display->getNativeDisplay(), window, width, height);

+		}

+

+		if(!frameBuffer)

+		{

+			ERR("Could not create frame buffer");

+			deleteResources();

+			return error(EGL_BAD_ALLOC, false);

+		}

+    }

+

+	return Surface::initialize();

+}

+

+PBufferSurface::PBufferSurface(Display *display, const Config *config, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType, EGLBoolean largestPBuffer)

+    : Surface(display, config)

+{

+	this->width = width;

+	this->height = height;

+	this->largestPBuffer = largestPBuffer;

+}

+

+void PBufferSurface::swap()

+{

+	// No effect

+}

+

+EGLNativeWindowType PBufferSurface::getWindowHandle() const

+{

+	UNREACHABLE(-1);   // Should not be called. Only WindowSurface has a window handle.

+

+    return 0;

+}

+

 }

diff --git a/src/OpenGL/libEGL/Surface.h b/src/OpenGL/libEGL/Surface.h
index 4d6d2e4..ca734c4 100644
--- a/src/OpenGL/libEGL/Surface.h
+++ b/src/OpenGL/libEGL/Surface.h
@@ -31,13 +31,8 @@
 class Surface : public gl::Object

 {

 public:

-    Surface(Display *display, const egl::Config *config, EGLNativeWindowType window);

-    Surface(Display *display, const egl::Config *config, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget);

-

-	bool initialize();

-    void swap();

-

-	EGLNativeWindowType getWindowHandle();

+	virtual bool initialize();

+    virtual void swap() = 0;

     

     virtual egl::Image *getRenderTarget();

     virtual egl::Image *getDepthStencil();

@@ -56,45 +51,78 @@
     virtual EGLenum getSwapBehavior() const;

     virtual EGLenum getTextureFormat() const;

     virtual EGLenum getTextureTarget() const;

+	virtual EGLBoolean getLargestPBuffer() const;

+	virtual EGLNativeWindowType getWindowHandle() const = 0;

 

     virtual void setBoundTexture(egl::Texture *texture);

     virtual egl::Texture *getBoundTexture() const;

 

-	bool checkForResize();   // Returns true if surface changed due to resize

+	virtual bool isWindowSurface() const { return false; }

+	virtual bool isPBufferSurface() const { return false; }

 

-private:

+protected:

+	Surface(const Display *display, const Config *config);

+

 	virtual ~Surface();

 

-    void deleteResources();

-    bool reset();

+    virtual void deleteResources();

 

-    Display *const mDisplay;

-    egl::Image *mDepthStencil;

-	sw::FrameBuffer *frameBuffer;

-	egl::Image *backBuffer;

-	egl::Texture *mTexture;

+    const Display *const display;

+    Image *depthStencil;

+	Image *backBuffer;

+	Texture *texture;

 

 	bool reset(int backbufferWidth, int backbufferHeight);

-    

-    const EGLNativeWindowType mWindow;   // Window that the surface is created for.

-    bool mWindowSubclassed;              // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking

-    const egl::Config *mConfig;          // EGL config surface was created with

-    EGLint mHeight;                      // Height of surface

-    EGLint mWidth;                       // Width of surface

-//  EGLint horizontalResolution;         // Horizontal dot pitch

-//  EGLint verticalResolution;           // Vertical dot pitch

-//  EGLBoolean largestPBuffer;           // If true, create largest pbuffer possible

-//  EGLBoolean mipmapTexture;            // True if texture has mipmaps

-//  EGLint mipmapLevel;                  // Mipmap level to render to

-//  EGLenum multisampleResolve;          // Multisample resolve behavior

-    EGLint mPixelAspectRatio;            // Display aspect ratio

-    EGLenum mRenderBuffer;               // Render buffer

-    EGLenum mSwapBehavior;               // Buffer swap behavior

-    EGLenum mTextureFormat;              // Format of texture: RGB, RGBA, or no texture

-    EGLenum mTextureTarget;              // Type of texture: 2D or no texture

-//  EGLenum vgAlphaFormat;               // Alpha format for OpenVG

-//  EGLenum vgColorSpace;                // Color space for OpenVG

-    EGLint mSwapInterval;

+   

+	const Config *const config;    // EGL config surface was created with

+	EGLint height;                      // Height of surface

+	EGLint width;                       // Width of surface

+//  EGLint horizontalResolution;        // Horizontal dot pitch

+//  EGLint verticalResolution;          // Vertical dot pitch

+	EGLBoolean largestPBuffer;          // If true, create largest pbuffer possible

+//  EGLBoolean mipmapTexture;           // True if texture has mipmaps

+//  EGLint mipmapLevel;                 // Mipmap level to render to

+//  EGLenum multisampleResolve;         // Multisample resolve behavior

+	EGLint pixelAspectRatio;            // Display aspect ratio

+	EGLenum renderBuffer;               // Render buffer

+	EGLenum swapBehavior;               // Buffer swap behavior

+	EGLenum textureFormat;              // Format of texture: RGB, RGBA, or no texture

+	EGLenum textureTarget;              // Type of texture: 2D or no texture

+//  EGLenum vgAlphaFormat;              // Alpha format for OpenVG

+//  EGLenum vgColorSpace;               // Color space for OpenVG

+	EGLint swapInterval;

+};

+

+class WindowSurface : public Surface

+{

+public:

+	WindowSurface(Display *display, const egl::Config *config, EGLNativeWindowType window);

+

+	bool initialize() override;

+

+	bool isWindowSurface() const override { return true; }

+	void swap() override;

+

+	EGLNativeWindowType getWindowHandle() const override;

+

+private:

+	void deleteResources() override;

+	bool checkForResize();

+	bool reset(int backBufferWidth, int backBufferHeight);

+

+	const EGLNativeWindowType window;

+	sw::FrameBuffer *frameBuffer;

+};

+

+class PBufferSurface : public Surface

+{

+public:

+	PBufferSurface(Display *display, const egl::Config *config, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget, EGLBoolean largestPBuffer);

+

+	bool isPBufferSurface() const override { return true; }

+	void swap() override;

+

+	EGLNativeWindowType getWindowHandle() const override;

 };

 }

 

diff --git a/src/OpenGL/libEGL/libEGL.cpp b/src/OpenGL/libEGL/libEGL.cpp
index 0999edb..491da27 100644
--- a/src/OpenGL/libEGL/libEGL.cpp
+++ b/src/OpenGL/libEGL/libEGL.cpp
@@ -302,7 +302,7 @@
 		return EGL_NO_SURFACE;

 	}

 

-	return display->createOffscreenSurface(config, attrib_list);

+	return display->createPBufferSurface(config, attrib_list);

 }

 

 EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)

@@ -380,7 +380,10 @@
 		UNIMPLEMENTED();   // FIXME

 		break;

 	case EGL_LARGEST_PBUFFER:

-		UNIMPLEMENTED();   // FIXME

+		if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.

+		{

+			*value = eglSurface->getLargestPBuffer();	

+		}

 		break;

 	case EGL_MIPMAP_TEXTURE:

 		UNIMPLEMENTED();   // FIXME

@@ -530,7 +533,7 @@
 		return error(EGL_BAD_PARAMETER, EGL_FALSE);

 	}

 

-	if(surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())

+	if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())

 	{

 		return error(EGL_BAD_SURFACE, EGL_FALSE);

 	}

@@ -572,7 +575,7 @@
 		return error(EGL_BAD_PARAMETER, EGL_FALSE);

 	}

 

-	if(surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())

+	if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())

 	{

 		return error(EGL_BAD_SURFACE, EGL_FALSE);

 	}

diff --git a/src/OpenGL/libGL/Context.cpp b/src/OpenGL/libGL/Context.cpp
index 4ea7b6b..8a3847e 100644
--- a/src/OpenGL/libGL/Context.cpp
+++ b/src/OpenGL/libGL/Context.cpp
@@ -2129,7 +2129,7 @@
             }

             else

             {

-                applyTexture(samplerType, samplerIndex, 0);

+                applyTexture(samplerType, samplerIndex, nullptr);

 

                 device->setStageOperation(samplerIndex, sw::TextureStage::STAGE_SELECTARG1);

                 device->setFirstArgument(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

@@ -2144,7 +2144,7 @@
         }

         else

         {

-            applyTexture(samplerType, samplerIndex, NULL);

+            applyTexture(samplerType, samplerIndex, nullptr);

         }

     }

 }

diff --git a/src/OpenGL/libGLES_CM/Context.cpp b/src/OpenGL/libGLES_CM/Context.cpp
index 32c0cb5..22940bb 100644
--- a/src/OpenGL/libGLES_CM/Context.cpp
+++ b/src/OpenGL/libGLES_CM/Context.cpp
@@ -2238,7 +2238,7 @@
         }

         else

         {

-            applyTexture(unit, 0);

+            applyTexture(unit, nullptr);

 

 			device->setFirstArgument(unit, sw::TextureStage::SOURCE_CURRENT);

 			device->setFirstModifier(unit, sw::TextureStage::MODIFIER_COLOR);

diff --git a/src/OpenGL/libGLES_CM/IndexDataManager.cpp b/src/OpenGL/libGLES_CM/IndexDataManager.cpp
index 0de5ebf..d284efe 100644
--- a/src/OpenGL/libGLES_CM/IndexDataManager.cpp
+++ b/src/OpenGL/libGLES_CM/IndexDataManager.cpp
@@ -90,17 +90,9 @@
     }

 

     intptr_t offset = reinterpret_cast<intptr_t>(indices);

-    bool alignedOffset = false;

 

     if(buffer != NULL)

     {

-        switch(type)

-        {

-        case GL_UNSIGNED_BYTE:  alignedOffset = (offset % sizeof(GLubyte) == 0);  break;

-        case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;

-        default: UNREACHABLE(type); alignedOffset = false;

-        }

-

         if(typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))

         {

             return GL_INVALID_OPERATION;

diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 079c157..7776ddc 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -3083,12 +3083,12 @@
             }

             else

             {

-                applyTexture(samplerType, samplerIndex, 0);

+                applyTexture(samplerType, samplerIndex, nullptr);

             }

         }

         else

         {

-            applyTexture(samplerType, samplerIndex, NULL);

+            applyTexture(samplerType, samplerIndex, nullptr);

         }

     }

 }

diff --git a/src/OpenGL/libGLESv2/IndexDataManager.cpp b/src/OpenGL/libGLESv2/IndexDataManager.cpp
index f0da7be..f7ac6fd 100644
--- a/src/OpenGL/libGLESv2/IndexDataManager.cpp
+++ b/src/OpenGL/libGLESv2/IndexDataManager.cpp
@@ -98,18 +98,9 @@
     }

 

     intptr_t offset = reinterpret_cast<intptr_t>(indices);

-    bool alignedOffset = false;

 

     if(buffer != NULL)

     {

-        switch(type)

-        {

-          case GL_UNSIGNED_BYTE:  alignedOffset = (offset % sizeof(GLubyte) == 0);  break;

-          case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;

-          case GL_UNSIGNED_INT:   alignedOffset = (offset % sizeof(GLuint) == 0);   break;

-          default: UNREACHABLE(type); alignedOffset = false;

-        }

-

         if(typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))

         {

             return GL_INVALID_OPERATION;

diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index 08d3c0a..2aea581 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -77,14 +77,14 @@
 	if(compressed)

 	{

 		if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||

-			(height % 4 != 0 && height != texture->getHeight(target, 0)))

+		   (height % 4 != 0 && height != texture->getHeight(target, 0)))

 		{

 			return error(GL_INVALID_OPERATION, false);

 		}

 	}

 

 	if(xoffset + width > texture->getWidth(target, level) ||

-		yoffset + height > texture->getHeight(target, level))

+	   yoffset + height > texture->getHeight(target, level))

 	{

 		return error(GL_INVALID_VALUE, false);

 	}

diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index 6faa76f..9d807fc 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -73,7 +73,7 @@
 	}

 

 	if(xoffset + width > texture->getWidth(target, level) ||

-		yoffset + height > texture->getHeight(target, level))

+	   yoffset + height > texture->getHeight(target, level))

 	{

 		return error(GL_INVALID_VALUE, false);

 	}

@@ -101,8 +101,8 @@
 	if(compressed)

 	{

 		if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||

-			(height % 4 != 0 && height != texture->getHeight(target, 0)) ||

-			(depth % 4 != 0 && depth != texture->getDepth(target, 0)))

+		   (height % 4 != 0 && height != texture->getHeight(target, 0)) ||

+		   (depth % 4 != 0 && depth != texture->getDepth(target, 0)))

 		{

 			return error(GL_INVALID_OPERATION, false);

 		}

@@ -124,10 +124,10 @@
 	{

 	case GL_ALPHA:

 		if(colorbufferFormat != GL_ALPHA &&

-			colorbufferFormat != GL_RGBA &&

-			colorbufferFormat != GL_RGBA4 &&

-			colorbufferFormat != GL_RGB5_A1 &&

-			colorbufferFormat != GL_RGBA8)

+		   colorbufferFormat != GL_RGBA &&

+		   colorbufferFormat != GL_RGBA4 &&

+		   colorbufferFormat != GL_RGB5_A1 &&

+		   colorbufferFormat != GL_RGBA8)

 		{

 			return error(GL_INVALID_OPERATION, false);

 		}

@@ -135,12 +135,12 @@
 	case GL_LUMINANCE:

 	case GL_RGB:

 		if(colorbufferFormat != GL_RGB &&

-			colorbufferFormat != GL_RGB565 &&

-			colorbufferFormat != GL_RGB8 &&

-			colorbufferFormat != GL_RGBA &&

-			colorbufferFormat != GL_RGBA4 &&

-			colorbufferFormat != GL_RGB5_A1 &&

-			colorbufferFormat != GL_RGBA8)

+		   colorbufferFormat != GL_RGB565 &&

+		   colorbufferFormat != GL_RGB8 &&

+		   colorbufferFormat != GL_RGBA &&

+		   colorbufferFormat != GL_RGBA4 &&

+		   colorbufferFormat != GL_RGB5_A1 &&

+		   colorbufferFormat != GL_RGBA8)

 		{

 			return error(GL_INVALID_OPERATION, false);

 		}

@@ -148,9 +148,9 @@
 	case GL_LUMINANCE_ALPHA:

 	case GL_RGBA:

 		if(colorbufferFormat != GL_RGBA &&

-			colorbufferFormat != GL_RGBA4 &&

-			colorbufferFormat != GL_RGB5_A1 &&

-			colorbufferFormat != GL_RGBA8)

+		   colorbufferFormat != GL_RGBA4 &&

+		   colorbufferFormat != GL_RGB5_A1 &&

+		   colorbufferFormat != GL_RGBA8)

 		{

 			return error(GL_INVALID_OPERATION, false);

 		}