Avoid dummy key methods by using pure abstract classes.

Sanitizer tools desire having the vtables of any class with non-pure
virtual methods, even when none of them are called in the current
linkage unit. Work around this by making the affected classes pure
abstract and implementing them in a derived class in the respective
library responsible for creating them.

Bug swiftshader:31

Change-Id: I40046f605731eb1cc3825c1ede2d8d9b5826d0f5
Reviewed-on: https://swiftshader-review.googlesource.com/9914
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2b0a2bb..54c658d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -739,9 +739,6 @@
     ${OPENGL_DIR}/common/debug.h
     ${CMAKE_SOURCE_DIR}/include/*.h
 )
-# Key method definitions are only required to appease the gold linker,
-# and cause vtable linking issues with other linkers.
-list(REMOVE_ITEM EGL_LIST ${OPENGL_DIR}/libEGL/TypeInfo.cpp)
 
 file(GLOB_RECURSE GL32_LIST
     ${OPENGL_DIR}/libGL/*.cpp
@@ -764,9 +761,6 @@
     ${CMAKE_SOURCE_DIR}/include/GLES2/*.h
     ${CMAKE_SOURCE_DIR}/include/GLES3/*.h
 )
-# Key method definitions are only required to appease the gold linker,
-# and cause vtable linking issues with other linkers.
-list(REMOVE_ITEM GLES2_LIST ${OPENGL_DIR}/libGLESv2/TypeInfo.cpp)
 
 file(GLOB_RECURSE GLES_CM_LIST
     ${OPENGL_DIR}/libGLES_CM/*.cpp
diff --git a/src/OpenGL/common/Image.cpp b/src/OpenGL/common/Image.cpp
index 02f7f0f..cfed057 100644
--- a/src/OpenGL/common/Image.cpp
+++ b/src/OpenGL/common/Image.cpp
@@ -1178,7 +1178,54 @@
 		}
 	}
 
-	void Image::typeinfo() {}
+	class ImageImplementation : public Image
+	{
+	public:
+		ImageImplementation(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type)
+			: Image(parentTexture, width, height, format, type) {}
+		ImageImplementation(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type)
+			: Image(parentTexture, width, height, depth, format, type) {}
+		ImageImplementation(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP)
+			: Image(width, height, format, type, pitchP) {}
+		ImageImplementation(GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable)
+			: Image(width, height, internalFormat, multiSampleDepth, lockable) {}
+		~ImageImplementation() override {}
+
+		void *lockInternal(int x, int y, int z, sw::Lock lock, sw::Accessor client) override
+		{
+			return Image::lockInternal(x, y, z, lock, client);
+		}
+
+		void unlockInternal() override
+		{
+			return Image::unlockInternal();
+		}
+
+		void release() override
+		{
+			return Image::release();
+		}
+	};
+
+	Image *Image::create(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type)
+	{
+		return new ImageImplementation(parentTexture, width, height, format, type);
+	}
+
+	Image *Image::create(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type)
+	{
+		return new ImageImplementation(parentTexture, width, height, depth, format, type);
+	}
+
+	Image *Image::create(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP)
+	{
+		return new ImageImplementation(width, height, format, type, pitchP);
+	}
+
+	Image *Image::create(GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable)
+	{
+		return new ImageImplementation(width, height, internalFormat, multiSampleDepth, lockable);
+	}
 
 	Image::~Image()
 	{
@@ -1192,6 +1239,16 @@
 		ASSERT(!shared);
 	}
 
+	void *Image::lockInternal(int x, int y, int z, sw::Lock lock, sw::Accessor client)
+	{
+		return Surface::lockInternal(x, y, z, lock, client);
+	}
+
+	void Image::unlockInternal()
+	{
+		Surface::unlockInternal();
+	}
+
 	void Image::release()
 	{
 		int refs = dereference();
@@ -1620,10 +1677,11 @@
 		}
 		else
 		{
-			sw::Surface source(width, height, depth, ConvertFormatType(format, type), const_cast<void*>(input), inputPitch, inputPitch * inputHeight);
+			sw::Surface *source = sw::Surface::create(width, height, depth, ConvertFormatType(format, type), const_cast<void*>(input), inputPitch, inputPitch * inputHeight);
 			sw::Rect sourceRect(0, 0, width, height);
 			sw::Rect destRect(xoffset, yoffset, xoffset + width, yoffset + height);
-			sw::blitter.blit(&source, sourceRect, this, destRect, false);
+			sw::blitter.blit(source, sourceRect, this, destRect, false);
+			delete source;
 		}
 	}
 
diff --git a/src/OpenGL/common/Image.hpp b/src/OpenGL/common/Image.hpp
index 6cf0a59..c783b21 100644
--- a/src/OpenGL/common/Image.hpp
+++ b/src/OpenGL/common/Image.hpp
@@ -48,9 +48,7 @@
 
 class [[clang::lto_visibility_public]] Image : public sw::Surface, public gl::Object
 {
-	virtual void typeinfo();   // Dummy key method (https://gcc.gnu.org/onlinedocs/gcc/Vague-Linkage.html)
-
-public:
+protected:
 	// 2D texture image
 	Image(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type)
 		: sw::Surface(parentTexture->getResource(), width, height, 1, SelectInternalFormat(format, type), true, true),
@@ -93,6 +91,19 @@
 		Object::addRef();
 	}
 
+public:
+	// 2D texture image
+	static Image *create(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type);
+
+	// 3D texture image
+	static Image *create(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type);
+
+	// Native EGL image
+	static Image *create(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP);
+
+	// Render target
+	static Image *create(GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable);
+
 	GLsizei getWidth() const
 	{
 		return width;
@@ -150,6 +161,9 @@
 		unlockExternal();
 	}
 
+	void *lockInternal(int x, int y, int z, sw::Lock lock, sw::Accessor client) override = 0;
+	void unlockInternal() override = 0;
+
 	struct UnpackInfo
 	{
 		UnpackInfo() : alignment(4), rowLength(0), imageHeight(0), skipPixels(0), skipRows(0), skipImages(0) {}
@@ -165,7 +179,7 @@
 	void loadImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const UnpackInfo& unpackInfo, const void *input);
 	void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
 
-	void release() override;
+	void release() override = 0;
 	void unbind(const Texture *parent);   // Break parent ownership and release
 	bool isChildOf(const Texture *parent) const;
 
@@ -188,7 +202,7 @@
 
 	egl::Texture *parentTexture;
 
-	virtual ~Image();
+	~Image() override = 0;
 
 	void loadD24S8ImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, const void *input, void *buffer);
 	void loadD32FS8ImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, const void *input, void *buffer);
@@ -252,14 +266,14 @@
 private:
 	ANativeWindowBuffer *nativeBuffer;
 
-	virtual ~AndroidNativeImage()
+	~AndroidNativeImage() override
 	{
 		sync();   // Wait for any threads that use this image to finish.
 
 		nativeBuffer->common.decRef(&nativeBuffer->common);
 	}
 
-	virtual void *lockInternal(int x, int y, int z, sw::Lock lock, sw::Accessor client)
+	void *lockInternal(int x, int y, int z, sw::Lock lock, sw::Accessor client) override
 	{
 		LOGLOCK("image=%p op=%s.swsurface lock=%d", this, __FUNCTION__, lock);
 
@@ -289,7 +303,7 @@
 		return data;
 	}
 
-	virtual void unlockInternal()
+	void unlockInternal() override
 	{
 		if(nativeBuffer)   // Unlock the buffer from ANativeWindowBuffer
 		{
@@ -301,7 +315,7 @@
 		sw::Surface::unlockInternal();
 	}
 
-	virtual void *lock(unsigned int left, unsigned int top, sw::Lock lock)
+	void *lock(unsigned int left, unsigned int top, sw::Lock lock) override
 	{
 		LOGLOCK("image=%p op=%s lock=%d", this, __FUNCTION__, lock);
 		(void)sw::Surface::lockExternal(left, top, 0, lock, sw::PUBLIC);
@@ -309,7 +323,7 @@
 		return lockNativeBuffer(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
 	}
 
-	virtual void unlock()
+	void unlock() override
 	{
 		LOGLOCK("image=%p op=%s.ani", this, __FUNCTION__);
 		unlockNativeBuffer();
@@ -318,7 +332,7 @@
 		sw::Surface::unlockExternal();
 	}
 
-	void* lockNativeBuffer(int usage)
+	void *lockNativeBuffer(int usage)
 	{
 		void *buffer = nullptr;
 		GrallocModule::getInstance()->lock(nativeBuffer->handle, usage, 0, 0, nativeBuffer->width, nativeBuffer->height, &buffer);
@@ -330,6 +344,11 @@
 	{
 		GrallocModule::getInstance()->unlock(nativeBuffer->handle);
 	}
+
+	void release() override
+	{
+		Image::release();
+	}
 };
 
 #endif  // __ANDROID__
diff --git a/src/OpenGL/libEGL/BUILD.gn b/src/OpenGL/libEGL/BUILD.gn
index 6286070..c9ab8ac 100644
--- a/src/OpenGL/libEGL/BUILD.gn
+++ b/src/OpenGL/libEGL/BUILD.gn
@@ -79,7 +79,6 @@
   } else if (is_linux) {
     sources += [
       "../../Main/libX11.cpp",
-      "TypeInfo.cpp",
     ]
     ldflags =
         [ "-Wl,--version-script=" + rebase_path("exports.map", root_build_dir) ]
diff --git a/src/OpenGL/libEGL/Display.cpp b/src/OpenGL/libEGL/Display.cpp
index b5097ac..6a5dffe 100644
--- a/src/OpenGL/libEGL/Display.cpp
+++ b/src/OpenGL/libEGL/Display.cpp
@@ -42,7 +42,18 @@
 
 namespace egl
 {
-void Display::typeinfo() {}
+
+class DisplayImplementation : public Display
+{
+public:
+	DisplayImplementation(void *nativeDisplay) : Display(nativeDisplay) {}
+	~DisplayImplementation() override {}
+
+	Image *getSharedImage(EGLImageKHR name) override
+	{
+		return Display::getSharedImage(name);
+	}
+};
 
 Display *Display::get(EGLDisplay dpy)
 {
@@ -61,7 +72,7 @@
 		}
 	#endif
 
-	static Display display(nativeDisplay);
+	static DisplayImplementation display(nativeDisplay);
 
 	return &display;
 }
diff --git a/src/OpenGL/libEGL/Display.h b/src/OpenGL/libEGL/Display.h
index 3fba9e7..ba6b92c 100644
--- a/src/OpenGL/libEGL/Display.h
+++ b/src/OpenGL/libEGL/Display.h
@@ -37,7 +37,9 @@
 
 	class [[clang::lto_visibility_public]] Display
 	{
-		virtual void typeinfo();   // Dummy key method (https://gcc.gnu.org/onlinedocs/gcc/Vague-Linkage.html)
+	protected:
+		explicit Display(void *nativeDisplay);
+		virtual ~Display() = 0;
 
 	public:
 		static Display *get(EGLDisplay dpy);
@@ -72,12 +74,9 @@
 
 		EGLImageKHR createSharedImage(Image *image);
 		bool destroySharedImage(EGLImageKHR);
-		virtual Image *getSharedImage(EGLImageKHR name);
+		virtual Image *getSharedImage(EGLImageKHR name) = 0;
 
 	private:
-		explicit Display(void *nativeDisplay);
-		~Display();
-
 		sw::Format getDisplayFormat() const;
 
 		void *const nativeDisplay;
diff --git a/src/OpenGL/libEGL/EGLSurface.cpp b/src/OpenGL/libEGL/EGLSurface.cpp
index 1939431..f47cacb 100644
--- a/src/OpenGL/libEGL/EGLSurface.cpp
+++ b/src/OpenGL/libEGL/EGLSurface.cpp
@@ -38,7 +38,6 @@
 
 namespace egl
 {
-void Surface::typeinfo() {}
 
 Surface::Surface(const Display *display, const Config *config) : display(display), config(config)
 {
diff --git a/src/OpenGL/libEGL/EGLSurface.h b/src/OpenGL/libEGL/EGLSurface.h
index 3ebc2e4..c5026e2 100644
--- a/src/OpenGL/libEGL/EGLSurface.h
+++ b/src/OpenGL/libEGL/EGLSurface.h
@@ -33,8 +33,6 @@
 
 class [[clang::lto_visibility_public]] Surface : public gl::Object
 {
-	virtual void typeinfo();   // Dummy key method (https://gcc.gnu.org/onlinedocs/gcc/Vague-Linkage.html)
-
 public:
 	virtual bool initialize();
 	virtual void swap() = 0;
diff --git a/src/OpenGL/libEGL/TypeInfo.cpp b/src/OpenGL/libEGL/TypeInfo.cpp
deleted file mode 100644
index 370c865..0000000
--- a/src/OpenGL/libEGL/TypeInfo.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2017 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "common/Image.hpp"
-#include "Main/FrameBuffer.hpp"
-#include "Renderer/Surface.hpp"
-
-namespace sw
-{
-void Surface::typeinfo() {}
-}
-
-namespace egl
-{
-void Image::typeinfo() {}
-}
diff --git a/src/OpenGL/libGLES_CM/Device.cpp b/src/OpenGL/libGLES_CM/Device.cpp
index 0f9d3e5..cb95d0c 100644
--- a/src/OpenGL/libGLES_CM/Device.cpp
+++ b/src/OpenGL/libGLES_CM/Device.cpp
@@ -250,7 +250,7 @@
 			UNREACHABLE(format);
 		}
 
-		egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable);
+		egl::Image *surface = egl::Image::create(width, height, format, multiSampleDepth, lockable);
 
 		if(!surface)
 		{
@@ -269,7 +269,7 @@
 			return nullptr;
 		}
 
-		egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable);
+		egl::Image *surface = egl::Image::create(width, height, format, multiSampleDepth, lockable);
 
 		if(!surface)
 		{
diff --git a/src/OpenGL/libGLES_CM/Texture.cpp b/src/OpenGL/libGLES_CM/Texture.cpp
index a5c86a7..d54885c 100644
--- a/src/OpenGL/libGLES_CM/Texture.cpp
+++ b/src/OpenGL/libGLES_CM/Texture.cpp
@@ -464,7 +464,7 @@
 		image[level]->release();
 	}
 
-	image[level] = new egl::Image(this, width, height, format, type);
+	image[level] = egl::Image::create(this, width, height, format, type);
 
 	if(!image[level])
 	{
@@ -529,7 +529,7 @@
 		image[level]->release();
 	}
 
-	image[level] = new egl::Image(this, width, height, format, GL_UNSIGNED_BYTE);
+	image[level] = egl::Image::create(this, width, height, format, GL_UNSIGNED_BYTE);
 
 	if(!image[level])
 	{
@@ -564,7 +564,7 @@
 		image[level]->release();
 	}
 
-	image[level] = new egl::Image(this, width, height, format, GL_UNSIGNED_BYTE);
+	image[level] = egl::Image::create(this, width, height, format, GL_UNSIGNED_BYTE);
 
 	if(!image[level])
 	{
@@ -714,7 +714,7 @@
 			image[i]->release();
 		}
 
-		image[i] = new egl::Image(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), image[0]->getFormat(), image[0]->getType());
+		image[i] = egl::Image::create(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), image[0]->getFormat(), image[0]->getType());
 
 		if(!image[i])
 		{
@@ -808,7 +808,7 @@
 {
 	if(config)
 	{
-		return new egl::Image(width, height, config->mRenderTargetFormat, config->mSamples, false);
+		return egl::Image::create(width, height, config->mRenderTargetFormat, config->mSamples, false);
 	}
 
 	return nullptr;
@@ -847,7 +847,7 @@
 		UNREACHABLE(format);
 	}
 
-	egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable);
+	egl::Image *surface = egl::Image::create(width, height, format, multiSampleDepth, lockable);
 
 	if(!surface)
 	{
diff --git a/src/OpenGL/libGLESv2/BUILD.gn b/src/OpenGL/libGLESv2/BUILD.gn
index 59f4f6d..e7c58f6 100644
--- a/src/OpenGL/libGLESv2/BUILD.gn
+++ b/src/OpenGL/libGLESv2/BUILD.gn
@@ -100,7 +100,6 @@
     configs -= [ "//build/config/win:unicode" ]
     ldflags = [ "/DEF:" + rebase_path("libGLESv2.def", root_build_dir) ]
   } else if (is_linux) {
-    sources += [ "TypeInfo.cpp" ]
     ldflags =
         [ "-Wl,--version-script=" + rebase_path("exports.map", root_build_dir) ]
   }
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index f617835..445973b 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -3241,10 +3241,11 @@
 	sw::Rect dstRect = { 0, 0, width, height };
 	rect.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight());
 
-	sw::Surface externalSurface(width, height, 1, egl::ConvertFormatType(format, type), pixels, outputPitch, outputPitch * outputHeight);
+	sw::Surface *externalSurface = sw::Surface::create(width, height, 1, egl::ConvertFormatType(format, type), pixels, outputPitch, outputPitch * outputHeight);
 	sw::SliceRect sliceRect(rect);
 	sw::SliceRect dstSliceRect(dstRect);
-	device->blit(renderTarget, sliceRect, &externalSurface, dstSliceRect, false);
+	device->blit(renderTarget, sliceRect, externalSurface, dstSliceRect, false);
+	delete externalSurface;
 
 	renderTarget->release();
 }
diff --git a/src/OpenGL/libGLESv2/Device.cpp b/src/OpenGL/libGLESv2/Device.cpp
index da1583f..8b8f016 100644
--- a/src/OpenGL/libGLESv2/Device.cpp
+++ b/src/OpenGL/libGLESv2/Device.cpp
@@ -290,7 +290,7 @@
 			UNREACHABLE(format);
 		}
 
-		egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable);
+		egl::Image *surface = egl::Image::create(width, height, format, multiSampleDepth, lockable);
 
 		if(!surface)
 		{
@@ -309,7 +309,7 @@
 			return nullptr;
 		}
 
-		egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable);
+		egl::Image *surface = egl::Image::create(width, height, format, multiSampleDepth, lockable);
 
 		if(!surface)
 		{
diff --git a/src/OpenGL/libGLESv2/Texture.cpp b/src/OpenGL/libGLESv2/Texture.cpp
index 48bd363..40c8ed4 100644
--- a/src/OpenGL/libGLESv2/Texture.cpp
+++ b/src/OpenGL/libGLESv2/Texture.cpp
@@ -640,7 +640,7 @@
 		image[level]->release();
 	}
 
-	image[level] = new egl::Image(this, width, height, format, type);
+	image[level] = egl::Image::create(this, width, height, format, type);
 
 	if(!image[level])
 	{
@@ -708,7 +708,7 @@
 	}
 
 	GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
-	image[level] = new egl::Image(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
+	image[level] = egl::Image::create(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
 
 	if(!image[level])
 	{
@@ -744,7 +744,7 @@
 	}
 
 	GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
-	image[level] = new egl::Image(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
+	image[level] = egl::Image::create(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
 
 	if(!image[level])
 	{
@@ -915,7 +915,7 @@
 			image[i]->release();
 		}
 
-		image[i] = new egl::Image(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), image[0]->getFormat(), image[0]->getType());
+		image[i] = egl::Image::create(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), image[0]->getFormat(), image[0]->getType());
 
 		if(!image[i])
 		{
@@ -1137,7 +1137,7 @@
 	}
 
 	GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
-	image[face][level] = new egl::Image(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
+	image[face][level] = egl::Image::create(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
 
 	if(!image[face][level])
 	{
@@ -1278,7 +1278,7 @@
 		image[face][level]->release();
 	}
 
-	image[face][level] = new egl::Image(this, width, height, format, type);
+	image[face][level] = egl::Image::create(this, width, height, format, type);
 
 	if(!image[face][level])
 	{
@@ -1306,7 +1306,7 @@
 	}
 
 	GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
-	image[face][level] = new egl::Image(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
+	image[face][level] = egl::Image::create(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
 
 	if(!image[face][level])
 	{
@@ -1400,7 +1400,7 @@
 				image[f][i]->release();
 			}
 
-			image[f][i] = new egl::Image(this, std::max(image[0][0]->getWidth() >> i, 1), std::max(image[0][0]->getHeight() >> i, 1), image[0][0]->getFormat(), image[0][0]->getType());
+			image[f][i] = egl::Image::create(this, std::max(image[0][0]->getWidth() >> i, 1), std::max(image[0][0]->getHeight() >> i, 1), image[0][0]->getFormat(), image[0][0]->getType());
 
 			if(!image[f][i])
 			{
@@ -1601,7 +1601,7 @@
 		image[level]->release();
 	}
 
-	image[level] = new egl::Image(this, width, height, depth, format, type);
+	image[level] = egl::Image::create(this, width, height, depth, format, type);
 
 	if(!image[level])
 	{
@@ -1663,7 +1663,7 @@
 	}
 
 	GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
-	image[level] = new egl::Image(this, width, height, depth, sizedInternalFormat, GL_UNSIGNED_BYTE);
+	image[level] = egl::Image::create(this, width, height, depth, sizedInternalFormat, GL_UNSIGNED_BYTE);
 
 	if(!image[level])
 	{
@@ -1699,7 +1699,7 @@
 	}
 
 	GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
-	image[level] = new egl::Image(this, width, height, depth, sizedInternalFormat, GL_UNSIGNED_BYTE);
+	image[level] = egl::Image::create(this, width, height, depth, sizedInternalFormat, GL_UNSIGNED_BYTE);
 
 	if(!image[level])
 	{
@@ -1877,7 +1877,7 @@
 			image[i]->release();
 		}
 
-		image[i] = new egl::Image(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), std::max(image[0]->getDepth() >> i, 1), image[0]->getFormat(), image[0]->getType());
+		image[i] = egl::Image::create(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), std::max(image[0]->getDepth() >> i, 1), image[0]->getFormat(), image[0]->getType());
 
 		if(!image[i])
 		{
@@ -1976,7 +1976,7 @@
 
 		GLsizei w = std::max(image[0]->getWidth() >> i, 1);
 		GLsizei h = std::max(image[0]->getHeight() >> i, 1);
-		image[i] = new egl::Image(this, w, h, depth, image[0]->getFormat(), image[0]->getType());
+		image[i] = egl::Image::create(this, w, h, depth, image[0]->getFormat(), image[0]->getType());
 
 		if(!image[i])
 		{
@@ -2018,7 +2018,7 @@
 {
 	if(config)
 	{
-		return new egl::Image(width, height, config->mRenderTargetFormat, config->mSamples, false);
+		return egl::Image::create(width, height, config->mRenderTargetFormat, config->mSamples, false);
 	}
 
 	return nullptr;
@@ -2057,7 +2057,7 @@
 		UNREACHABLE(format);
 	}
 
-	egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable);
+	egl::Image *surface = egl::Image::create(width, height, format, multiSampleDepth, lockable);
 
 	if(!surface)
 	{
diff --git a/src/OpenGL/libGLESv2/TypeInfo.cpp b/src/OpenGL/libGLESv2/TypeInfo.cpp
deleted file mode 100644
index 8fb91d3..0000000
--- a/src/OpenGL/libGLESv2/TypeInfo.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2017 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "libEGL/Display.h"
-#include "libEGL/EGLSurface.h"
-
-namespace egl
-{
-void Surface::typeinfo() {}
-void Display::typeinfo() {}
-}
diff --git a/src/Renderer/Blitter.cpp b/src/Renderer/Blitter.cpp
index 4eea852..e10f783 100644
--- a/src/Renderer/Blitter.cpp
+++ b/src/Renderer/Blitter.cpp
@@ -39,11 +39,12 @@
 			return;
 		}
 
-		sw::Surface color(1, 1, 1, format, pixel, sw::Surface::bytes(format), sw::Surface::bytes(format));
+		sw::Surface *color = sw::Surface::create(1, 1, 1, format, pixel, sw::Surface::bytes(format), sw::Surface::bytes(format));
 		Blitter::Options clearOptions = static_cast<sw::Blitter::Options>((rgbaMask & 0xF) | CLEAR_OPERATION);
 		SliceRect sRect(dRect);
 		sRect.slice = 0;
-		blit(&color, sRect, dest, dRect, clearOptions);
+		blit(color, sRect, dest, dRect, clearOptions);
+		delete color;
 	}
 
 	bool Blitter::fastClear(void* pixel, sw::Format format, Surface *dest, const SliceRect &dRect, unsigned int rgbaMask)
diff --git a/src/Renderer/Surface.cpp b/src/Renderer/Surface.cpp
index c7ca71a..f29aaae 100644
--- a/src/Renderer/Surface.cpp
+++ b/src/Renderer/Surface.cpp
@@ -41,7 +41,6 @@
 
 	unsigned int *Surface::palette = 0;
 	unsigned int Surface::paletteID = 0;
-	void Surface::typeinfo() {}
 
 	void Rect::clip(int minX, int minY, int maxX, int maxY)
 	{
@@ -1168,6 +1167,36 @@
 		lock = LOCK_UNLOCKED;
 	}
 
+	class SurfaceImplementation : public Surface
+	{
+	public:
+		SurfaceImplementation(int width, int height, int depth, Format format, void *pixels, int pitch, int slice)
+			: Surface(width, height, depth, format, pixels, pitch, slice) {}
+		SurfaceImplementation(Resource *texture, int width, int height, int depth, Format format, bool lockable, bool renderTarget, int pitchP = 0)
+			: Surface(texture, width, height, depth, format, lockable, renderTarget, pitchP) {}
+		~SurfaceImplementation() override {};
+
+		void *lockInternal(int x, int y, int z, Lock lock, Accessor client) override
+		{
+			return Surface::lockInternal(x, y, z, lock, client);
+		}
+
+		void unlockInternal() override
+		{
+			Surface::unlockInternal();
+		}
+	};
+
+	Surface *Surface::create(int width, int height, int depth, Format format, void *pixels, int pitch, int slice)
+	{
+		return new SurfaceImplementation(width, height, depth, format, pixels, pitch, slice);
+	}
+
+	Surface *Surface::create(Resource *texture, int width, int height, int depth, Format format, bool lockable, bool renderTarget, int pitchPprovided)
+	{
+		return new SurfaceImplementation(texture, width, height, depth, format, lockable, renderTarget, pitchPprovided);
+	}
+
 	Surface::Surface(int width, int height, int depth, Format format, void *pixels, int pitch, int slice) : lockable(true), renderTarget(false)
 	{
 		resource = new Resource(0);
diff --git a/src/Renderer/Surface.hpp b/src/Renderer/Surface.hpp
index ae37df5..16ff78c 100644
--- a/src/Renderer/Surface.hpp
+++ b/src/Renderer/Surface.hpp
@@ -250,13 +250,15 @@
 			bool dirty;
 		};
 
-		virtual void typeinfo();   // Dummy key method (https://gcc.gnu.org/onlinedocs/gcc/Vague-Linkage.html)
-
-	public:
+	protected:
 		Surface(int width, int height, int depth, Format format, void *pixels, int pitch, int slice);
 		Surface(Resource *texture, int width, int height, int depth, Format format, bool lockable, bool renderTarget, int pitchP = 0);
 
-		virtual ~Surface();
+	public:
+		static Surface *create(int width, int height, int depth, Format format, void *pixels, int pitch, int slice);
+		static Surface *create(Resource *texture, int width, int height, int depth, Format format, bool lockable, bool renderTarget, int pitchP = 0);
+
+		virtual ~Surface() = 0;
 
 		inline void *lock(int x, int y, int z, Lock lock, Accessor client, bool internal = false);
 		inline void unlock(bool internal = false);
@@ -277,8 +279,8 @@
 		inline int getExternalSliceB() const;
 		inline int getExternalSliceP() const;
 
-		virtual void *lockInternal(int x, int y, int z, Lock lock, Accessor client);
-		virtual void unlockInternal();
+		virtual void *lockInternal(int x, int y, int z, Lock lock, Accessor client) = 0;
+		virtual void unlockInternal() = 0;
 		inline Format getInternalFormat() const;
 		inline int getInternalPitchB() const;
 		inline int getInternalPitchP() const;