Support creating a Surface from a user pointer.

Bug 21716622

Change-Id: Ifa5940c17932066b3860ff148be8b6b2bec726c0
Reviewed-on: https://swiftshader-review.googlesource.com/3444
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/Renderer/Surface.cpp b/src/Renderer/Surface.cpp
index dddaca1..9b48ebd 100644
--- a/src/Renderer/Surface.cpp
+++ b/src/Renderer/Surface.cpp
@@ -784,10 +784,61 @@
 		lock = LOCK_UNLOCKED;
 	}
 
+	Surface::Surface(int width, int height, int depth, Format format, void *pixels, int pitch, int slice) : lockable(true), renderTarget(false)
+	{
+		resource = new Resource(0);
+		hasParent = false;
+		ownExternal = false;
+		depth = max(1, depth);
+
+		external.buffer = pixels;
+		external.width = width;
+		external.height = height;
+		external.depth = depth;
+		external.format = format;
+		external.bytes = bytes(external.format);
+		external.pitchB = pitch;
+		external.pitchP = pitch / external.bytes;
+		external.sliceB = slice;
+		external.sliceP = slice / external.bytes;
+		external.lock = LOCK_UNLOCKED;
+		external.dirty = true;
+
+		internal.buffer = 0;
+		internal.width = width;
+		internal.height = height;
+		internal.depth = depth;
+		internal.format = selectInternalFormat(format);
+		internal.bytes = bytes(internal.format);
+		internal.pitchB = pitchB(internal.width, internal.format, false);
+		internal.pitchP = pitchP(internal.width, internal.format, false);
+		internal.sliceB = sliceB(internal.width, internal.height, internal.format, false);
+		internal.sliceP = sliceP(internal.width, internal.height, internal.format, false);
+		internal.lock = LOCK_UNLOCKED;
+		internal.dirty = false;
+
+		stencil.buffer = 0;
+		stencil.width = width;
+		stencil.height = height;
+		stencil.depth = depth;
+		stencil.format = FORMAT_S8;
+		stencil.bytes = bytes(stencil.format);
+		stencil.pitchB = pitchB(stencil.width, stencil.format, false);
+		stencil.pitchP = pitchP(stencil.width, stencil.format, false);
+		stencil.sliceB = sliceB(stencil.width, stencil.height, stencil.format, false);
+		stencil.sliceP = sliceP(stencil.width, stencil.height, stencil.format, false);
+		stencil.lock = LOCK_UNLOCKED;
+		stencil.dirty = false;
+
+		dirtyMipmaps = true;
+		paletteUsed = 0;
+	}
+
 	Surface::Surface(Resource *texture, int width, int height, int depth, Format format, bool lockable, bool renderTarget) : lockable(lockable), renderTarget(renderTarget)
 	{
 		resource = texture ? texture : new Resource(0);
 		hasParent = texture != 0;
+		ownExternal = true;
 		depth = max(1, depth);
 
 		external.buffer = 0;
@@ -844,7 +895,10 @@
 			resource->destruct();
 		}
 
-		deallocate(external.buffer);
+		if(ownExternal)
+		{
+			deallocate(external.buffer);
+		}
 
 		if(internal.buffer != external.buffer)
 		{
diff --git a/src/Renderer/Surface.hpp b/src/Renderer/Surface.hpp
index 72a6edf..ba2d2fe 100644
--- a/src/Renderer/Surface.hpp
+++ b/src/Renderer/Surface.hpp
@@ -172,6 +172,7 @@
 		};

 

 	public:

+		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);

 		

 		virtual ~Surface();

@@ -386,6 +387,7 @@
 		static unsigned int paletteID;

 

 		bool hasParent;

+		bool ownExternal;

 	};

 }