1
0
Эх сурвалжийг харах

Add copy_texture_region function

BtbN 11 жил өмнө
parent
commit
97c94b183a

+ 63 - 16
libobs-d3d11/d3d11-subsystem.cpp

@@ -959,43 +959,90 @@ void device_setcuberendertarget(device_t device, texture_t tex, int side,
 	device->context->OMSetRenderTargets(1, &rt, zstencil->view);
 }
 
-inline void gs_device::CopyTex(ID3D11Texture2D *dst, texture_t src)
+inline void gs_device::CopyTex(ID3D11Texture2D *dst, uint32_t dst_x, uint32_t dst_y,
+		texture_t src, uint32_t src_x, uint32_t src_y,
+		uint32_t src_w, uint32_t src_h)
 {
 	if (src->type != GS_TEXTURE_2D)
 		throw "Source texture must be a 2D texture";
 
 	gs_texture_2d *tex2d = static_cast<gs_texture_2d*>(src);
-	context->CopyResource(dst, tex2d->texture);
+
+	if(dst_x == 0 && dst_y == 0 && src_x == 0 && src_y == 0 && src_w == 0 && src_h == 0)
+	{
+		context->CopyResource(dst, tex2d->texture);
+	}
+	else
+	{
+		D3D11_BOX sbox;
+
+		sbox.left = src_x;
+		if(src_w > 0)
+			sbox.right = src_x + src_w;
+		else
+			sbox.right = tex2d->width - 1;
+
+		sbox.top = src_y;
+		if(src_h > 0)
+			sbox.bottom = src_y + src_h;
+		else
+			sbox.bottom = tex2d->height - 1;
+
+		sbox.front = 0;
+		sbox.back = 1;
+
+		context->CopySubresourceRegion(dst, 0, dst_x, dst_y, 0, tex2d->texture, 0, &sbox);
+	}
 }
 
-void device_copy_texture(device_t device, texture_t dst, texture_t src)
+void device_copy_texture_region(device_t device,
+	texture_t dst, uint32_t dst_x, uint32_t dst_y,
+	texture_t src, uint32_t src_x, uint32_t src_y,
+	uint32_t src_w, uint32_t src_h)
 {
-	try {
+	try
+	{
 		gs_texture_2d *src2d = static_cast<gs_texture_2d*>(src);
 		gs_texture_2d *dst2d = static_cast<gs_texture_2d*>(dst);
 
-		if (!src)
+		if(!src)
 			throw "Source texture is NULL";
-		if (!dst)
+		if(!dst)
 			throw "Destination texture is NULL";
-		if (src->type != GS_TEXTURE_2D || dst->type != GS_TEXTURE_2D)
+		if(src->type != GS_TEXTURE_2D || dst->type != GS_TEXTURE_2D)
 			throw "Source and destination textures must be a 2D "
-			      "textures";
-		if (dst->format != src->format)
+			"textures";
+		if(dst->format != src->format)
 			throw "Source and destination formats do not match";
-		if (dst2d->width  != src2d->width ||
-		    dst2d->height != src2d->height)
-			throw "Source and destination must have the same "
-			      "dimensions";
+
+		uint32_t nw = (uint32_t)src_w ? (uint32_t)src_w : (src2d->width - src_x);
+		uint32_t nh = (uint32_t)src_h ? (uint32_t)src_h : (src2d->height - src_y);
+
+		if(dst2d->width - dst_x < nw || dst2d->height - dst_y < nh)
+			throw "Destination texture region is not big "
+			      "enough to hold the source region";
+
+		if(dst_x == 0 && dst_y == 0 && src_x == 0 && src_y == 0 && src_w == 0 && src_h == 0)
+		{
+			nw = 0;
+			nh = 0;
+		}
 
 		gs_texture_2d *tex2d = static_cast<gs_texture_2d*>(dst);
-		device->CopyTex(tex2d->texture, src);
+		device->CopyTex(tex2d->texture, dst_x, dst_y, src, src_x, src_y, nw, nh);
 
-	} catch (const char *error) {
+	}
+	catch(const char *error)
+	{
 		blog(LOG_ERROR, "device_copy_texture (D3D11): %s", error);
 	}
 }
 
+void device_copy_texture(device_t device, texture_t dst, texture_t src)
+{
+	device_copy_texture_region(device, dst, 0, 0, src, 0, 0, 0, 0);
+}
+
 void device_stage_texture(device_t device, stagesurf_t dst, texture_t src)
 {
 	try {
@@ -1014,7 +1061,7 @@ void device_stage_texture(device_t device, stagesurf_t dst, texture_t src)
 			throw "Source and destination must have the same "
 			      "dimensions";
 
-		device->CopyTex(dst->texture, src);
+		device->CopyTex(dst->texture, 0, 0, src, 0, 0, 0, 0);
 
 	} catch (const char *error) {
 		blog(LOG_ERROR, "device_copy_texture (D3D11): %s", error);

+ 3 - 1
libobs-d3d11/d3d11-subsystem.hpp

@@ -618,7 +618,9 @@ struct gs_device {
 	void UpdateRasterState();
 	void UpdateBlendState();
 
-	inline void CopyTex(ID3D11Texture2D *dst, texture_t src);
+	inline void CopyTex(ID3D11Texture2D *dst, uint32_t dst_x, uint32_t dst_y,
+		texture_t src, uint32_t src_x, uint32_t src_y,
+		uint32_t src_w, uint32_t src_h);
 
 	void UpdateViewProjMatrix();
 

+ 11 - 10
libobs-opengl/gl-helpers.c

@@ -57,8 +57,8 @@ bool gl_init_face(GLenum target, GLenum type, uint32_t num_levels,
 }
 
 static bool gl_copy_fbo(struct gs_device *device,
-		GLuint dst, GLenum dst_target,
-		GLuint src, GLenum src_target,
+		GLuint dst, GLenum dst_target, uint32_t dst_x, uint32_t dst_y,
+		GLuint src, GLenum src_target, uint32_t src_x, uint32_t src_y,
 		uint32_t width, uint32_t height,
 		enum gs_color_format format)
 {
@@ -85,7 +85,7 @@ static bool gl_copy_fbo(struct gs_device *device,
 	if (!gl_success("glReadBuffer"))
 		goto fail;
 
-	glCopyTexSubImage2D(dst_target, 0, 0, 0, 0, 0, width, height);
+	glCopyTexSubImage2D(dst_target, 0, dst_x, dst_y, src_x, src_y, width, height);
 	if (!gl_success("glCopyTexSubImage2D"))
 		goto fail;
 
@@ -101,27 +101,28 @@ fail:
 }
 
 bool gl_copy_texture(struct gs_device *device,
-                     GLuint dst, GLenum dst_target,
-                     GLuint src, GLenum src_target,
+					 GLuint dst, GLenum dst_target, uint32_t dst_x, uint32_t dst_y,
+					 GLuint src, GLenum src_target, uint32_t src_x, uint32_t src_y,
                      uint32_t width, uint32_t height,
                      enum gs_color_format format)
 {
 	bool success = false;
 
 	if (device->copy_type == COPY_TYPE_ARB) {
-		glCopyImageSubData(src, src_target, 0, 0, 0, 0,
-		                   dst, dst_target, 0, 0, 0, 0,
+		glCopyImageSubData(src, src_target, 0, src_x, src_y, 0,
+						   dst, dst_target, 0, dst_x, dst_y, 0,
 		                   width, height, 1);
 		success = gl_success("glCopyImageSubData");
 
 	} else if (device->copy_type == COPY_TYPE_NV) {
-		glCopyImageSubDataNV(src, src_target, 0, 0, 0, 0,
-		                     dst, dst_target, 0, 0, 0, 0,
+		glCopyImageSubDataNV(src, src_target, 0, src_x, src_y, 0,
+							 dst, dst_target, 0, dst_x, dst_y, 0,
 		                     width, height, 1);
 		success = gl_success("glCopyImageSubDataNV");
 
 	} else if (device->copy_type == COPY_TYPE_FBO_BLIT) {
-		if (gl_copy_fbo(device, dst, dst_target, src,  src_target,
+		if (gl_copy_fbo(device, dst, dst_target, dst_x, dst_y,
+					src, src_target, src_x, src_y,
 					width, height, format))
 			success = true;
 		else

+ 2 - 2
libobs-opengl/gl-helpers.h

@@ -149,8 +149,8 @@ extern bool gl_init_face(GLenum target, GLenum type, uint32_t num_levels,
 		const void ***p_data);
 
 extern bool gl_copy_texture(struct gs_device *device,
-                            GLuint dst, GLenum dst_target,
-                            GLuint src, GLenum src_target,
+							GLuint dst, GLenum dst_target, uint32_t dst_x, uint32_t dst_y,
+							GLuint src, GLenum src_target, uint32_t src_x, uint32_t src_y,
                             uint32_t width, uint32_t height,
 			    enum gs_color_format format);
 

+ 21 - 8
libobs-opengl/gl-subsystem.c

@@ -59,6 +59,9 @@ static void APIENTRY gl_debug_proc(
 	GLenum source, GLenum type, GLuint id, GLenum severity, 
 	GLsizei length, const GLchar *message, const GLvoid *data )
 {
+	UNUSED_PARAMETER(id);
+	UNUSED_PARAMETER(data);
+
 	blog(	LOG_DEBUG,
 		"[%s][%s]{%s}: %.*s",
 		debug_source_table[GL_DEBUG_SOURCE_OFFSET(source)],
@@ -785,7 +788,9 @@ fail:
 	blog(LOG_ERROR, "device_setcuberendertarget (GL) failed");
 }
 
-void device_copy_texture(device_t device, texture_t dst, texture_t src)
+void device_copy_texture_region(device_t device,
+		texture_t dst, uint32_t dst_x, uint32_t dst_y,
+		texture_t src, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h)
 {
 	struct gs_texture_2d *src2d = (struct gs_texture_2d*)src;
 	struct gs_texture_2d *dst2d = (struct gs_texture_2d*)dst;
@@ -802,7 +807,7 @@ void device_copy_texture(device_t device, texture_t dst, texture_t src)
 
 	if (dst->type != GS_TEXTURE_2D || src->type != GS_TEXTURE_2D) {
 		blog(LOG_ERROR, "Source and destination textures must be 2D "
-		                "textures");
+						"textures");
 		goto fail;
 	}
 
@@ -811,15 +816,18 @@ void device_copy_texture(device_t device, texture_t dst, texture_t src)
 		goto fail;
 	}
 
-	if (dst2d->width != src2d->width || dst2d->height != src2d->height) {
-		blog(LOG_ERROR, "Source and destination must have "
-		                "the same dimensions");
+	uint32_t nw = (uint32_t)src_w ? (uint32_t)src_w : (src2d->width - src_x);
+	uint32_t nh = (uint32_t)src_h ? (uint32_t)src_h : (src2d->height - src_y);
+
+	if (dst2d->width - dst_x < nw || dst2d->height - dst_y < nh) {
+		blog(LOG_ERROR, "Destination texture region is not big "
+						"enough to hold the source region");
 		goto fail;
 	}
 
-	if (!gl_copy_texture(device, dst->texture, dst->gl_target,
-				src->texture, src->gl_target,
-				src2d->width, src2d->height, src->format))
+	if (!gl_copy_texture(device, dst->texture, dst->gl_target, dst_x, dst_y,
+				src->texture, src->gl_target, src_x, src_y,
+				nw, nh, src->format))
 		goto fail;
 
 	return;
@@ -828,6 +836,11 @@ fail:
 	blog(LOG_ERROR, "device_copy_texture (GL) failed");
 }
 
+void device_copy_texture(device_t device, texture_t dst, texture_t src)
+{
+	device_copy_texture_region(device, dst, 0, 0, src, 0, 0, 0, 0);
+}
+
 void device_beginscene(device_t device)
 {
 	clear_textures(device);

+ 3 - 0
libobs/graphics/device-exports.h

@@ -80,6 +80,9 @@ EXPORT void device_setrendertarget(device_t device, texture_t tex,
 EXPORT void device_setcuberendertarget(device_t device, texture_t cubetex,
 		int side, zstencil_t zstencil);
 EXPORT void device_copy_texture(device_t device, texture_t dst, texture_t src);
+EXPORT void device_copy_texture_region(device_t device,
+		texture_t dst, uint32_t dst_x, uint32_t dst_y,
+		texture_t src, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h);
 EXPORT void device_stage_texture(device_t device, stagesurf_t dst,
 		texture_t src);
 EXPORT void device_beginscene(device_t device);

+ 1 - 0
libobs/graphics/graphics-imports.c

@@ -74,6 +74,7 @@ bool load_graphics_imports(struct gs_exports *exports, void *module,
 	GRAPHICS_IMPORT(device_getzstenciltarget);
 	GRAPHICS_IMPORT(device_setrendertarget);
 	GRAPHICS_IMPORT(device_setcuberendertarget);
+	GRAPHICS_IMPORT(device_copy_texture_region);
 	GRAPHICS_IMPORT(device_copy_texture);
 	GRAPHICS_IMPORT(device_stage_texture);
 	GRAPHICS_IMPORT(device_beginscene);

+ 4 - 0
libobs/graphics/graphics-internal.h

@@ -86,6 +86,10 @@ struct gs_exports {
 			int side, zstencil_t zstencil);
 	void (*device_copy_texture)(device_t device, texture_t dst,
 			texture_t src);
+	void (*device_copy_texture_region)(device_t device,
+			texture_t dst, uint32_t dst_x, uint32_t dst_y,
+			texture_t src, uint32_t src_x, uint32_t src_y,
+			uint32_t src_w, uint32_t src_h);
 	void (*device_stage_texture)(device_t device, stagesurf_t dst,
 			texture_t src);
 	void (*device_beginscene)(device_t device);

+ 12 - 0
libobs/graphics/graphics.c

@@ -1243,6 +1243,18 @@ void gs_copy_texture(texture_t dst, texture_t src)
 	graphics->exports.device_copy_texture(graphics->device, dst, src);
 }
 
+void gs_copy_texture_region(texture_t dst, uint32_t dst_x, uint32_t dst_y,
+		texture_t src, uint32_t src_x, uint32_t src_y,
+		uint32_t src_w, uint32_t src_h)
+{
+	graphics_t graphics = thread_graphics;
+	if (!graphics) return;
+
+	graphics->exports.device_copy_texture_region(graphics->device,
+			dst, dst_x, dst_y,
+			src, src_x, src_y, src_w, src_h);
+}
+
 void gs_stage_texture(stagesurf_t dst, texture_t src)
 {
 	graphics_t graphics = thread_graphics;

+ 4 - 0
libobs/graphics/graphics.h

@@ -580,6 +580,10 @@ EXPORT void gs_setcuberendertarget(texture_t cubetex, int side,
 		zstencil_t zstencil);
 
 EXPORT void gs_copy_texture(texture_t dst, texture_t src);
+EXPORT void gs_copy_texture_region(
+		texture_t dst, uint32_t dst_x, uint32_t dst_y,
+		texture_t src, uint32_t src_x, uint32_t src_y,
+		uint32_t src_w, uint32_t src_h);
 EXPORT void gs_stage_texture(stagesurf_t dst, texture_t src);
 
 EXPORT void gs_beginscene(void);