Browse Source

rearrange/cleanup GL texture stuff, and fill out GL cubemap texture functions (still need FBOs)

jp9000 12 years ago
parent
commit
3243bfbaa3

+ 50 - 0
libobs-opengl/gl-helpers.c

@@ -0,0 +1,50 @@
+/******************************************************************************
+    Copyright (C) 2013 by Hugh Bailey <[email protected]>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+#include "gl-subsystem.h"
+
+bool upload_face(GLenum type, uint32_t num_levels,
+		GLenum format, GLint internal_format, bool compressed,
+		uint32_t width, uint32_t height, uint32_t size, void ***p_data)
+{
+	bool success = true;
+	void **data = *p_data;
+	uint32_t i;
+
+	for (i = 0; i < num_levels; i++) {
+		if (compressed) {
+			glCompressedTexImage2D(type, i, internal_format,
+					width, height, 0, size, *data);
+			if (!gl_success("glCompressedTexImage2D"))
+				success = false;
+
+		} else {
+			glTexImage2D(type, i, internal_format, width, height, 0,
+					format, GL_UNSIGNED_BYTE, *data);
+			if (!gl_success("glTexImage2D"))
+				success = false;
+		}
+
+		data++;
+		size   /= 4;
+		width  /= 2;
+		height /= 2;
+	}
+
+	*p_data = data;
+	return success;
+}

+ 16 - 0
libobs-opengl/gl-helpers.h

@@ -48,4 +48,20 @@ static inline bool gl_bind_texture(GLenum target, GLuint texture)
 	return gl_success("glBindTexture");
 }
 
+static inline bool gl_gen_buffers(GLsizei num_buffers, GLuint *buffers)
+{
+	glGenBuffers(num_buffers, buffers);
+	return gl_success("glGenBuffers");
+}
+
+static inline bool gl_bind_buffer(GLenum target, GLuint buffer)
+{
+	glBindBuffer(target, buffer);
+	return gl_success("glBindBuffer");
+}
+
+extern bool upload_face(GLenum type, uint32_t num_levels,
+		GLenum format, GLint internal_format, bool compressed,
+		uint32_t width, uint32_t height, uint32_t size, void ***p_data);
+
 #endif

+ 2 - 39
libobs-opengl/gl-subsystem.c

@@ -16,7 +16,6 @@
 ******************************************************************************/
 
 #include "gl-subsystem.h"
-#include "gl-exports.h"
 
 device_t device_create(struct gs_init_data *info)
 {
@@ -81,17 +80,13 @@ uint32_t device_getheight(device_t device)
 	return device->cur_swap->info.cy;
 }
 
-texture_t device_create_cubetexture(device_t device, uint32_t size,
-		enum gs_color_format color_format, uint32_t levels,
-		void **data, uint32_t flags)
-{
-}
-
 texture_t device_create_volumetexture(device_t device, uint32_t width,
 		uint32_t height, uint32_t depth,
 		enum gs_color_format color_format, uint32_t levels, void **data,
 		uint32_t flags)
 {
+	/* TODO */
+	return NULL;
 }
 
 zstencil_t device_create_zstencil(device_t device, uint32_t width,
@@ -354,38 +349,6 @@ void swapchain_destroy(swapchain_t swapchain)
 {
 }
 
-uint32_t texture_getwidth(texture_t tex)
-{
-}
-
-uint32_t texture_getheight(texture_t tex)
-{
-}
-
-enum gs_color_format texture_getcolorformat(texture_t tex)
-{
-}
-
-bool texture_map(texture_t tex, void **ptr, uint32_t *byte_width)
-{
-}
-
-void texture_unmap(texture_t tex)
-{
-}
-
-void cubetexture_destroy(texture_t cubetex)
-{
-}
-
-uint32_t cubetexture_getsize(texture_t cubetex)
-{
-}
-
-enum gs_color_format cubetexture_getcolorformat(texture_t cubetex)
-{
-}
-
 void volumetexture_destroy(texture_t voltex)
 {
 }

+ 5 - 0
libobs-opengl/gl-subsystem.h

@@ -21,6 +21,7 @@
 #include "graphics/graphics.h"
 #include "glew/include/GL/glew.h"
 #include "gl-helpers.h"
+#include "gl-exports.h"
 
 struct gl_platform;
 struct gl_windowinfo;
@@ -92,6 +93,9 @@ struct gs_texture {
 	GLint                gl_internal_format;
 	GLuint               texture;
 	uint32_t             levels;
+	bool                 is_dynamic;
+	bool                 is_render_target;
+	bool                 gen_mipmaps;
 };
 
 struct gs_texture_2d {
@@ -100,6 +104,7 @@ struct gs_texture_2d {
 	uint32_t             width;
 	uint32_t             height;
 	bool                 gen_mipmaps;
+	GLuint               unpack_buffer;
 };
 
 struct gs_texture_cube {

+ 111 - 28
libobs-opengl/gl-texture2d.c

@@ -17,7 +17,7 @@
 
 #include "gl-subsystem.h"
 
-static inline uint32_t num_actual_levels(struct gs_texture_2d *tex)
+static uint32_t num_actual_levels(struct gs_texture_2d *tex)
 {
 	uint32_t num_levels;
 	uint32_t size;
@@ -36,41 +36,20 @@ static inline uint32_t num_actual_levels(struct gs_texture_2d *tex)
 	return num_levels;
 }
 
-static inline bool upload_texture_data(struct gs_texture_2d *tex, void **data)
+static bool upload_texture_2d(struct gs_texture_2d *tex, void **data)
 {
 	uint32_t row_size   = tex->width  * get_format_bpp(tex->base.format);
 	uint32_t tex_size   = tex->height * row_size / 8;
 	uint32_t num_levels = num_actual_levels(tex);
-	bool     success = true;
 	bool     compressed = is_compressed_format(tex->base.format);
-	uint32_t i;
+	bool     success;
 
 	if (!gl_bind_texture(GL_TEXTURE_2D, tex->base.texture))
 		return false;
 
-	for (i = 0; i < num_levels; i++) {
-		uint32_t size = tex_size;
-
-		if (compressed) {
-			glCompressedTexImage2D(GL_TEXTURE_2D, i,
-					tex->base.gl_internal_format,
-					tex->width, tex->height, 0,
-					size, *data);
-			if (!gl_success("glCompressedTexImage2D"))
-				success = false;
-
-		} else {
-			glTexImage2D(GL_TEXTURE_2D, i,
-					tex->base.gl_internal_format,
-					tex->width, tex->height, 0,
-					tex->base.gl_format, GL_UNSIGNED_BYTE,
-					*data);
-			if (!gl_success("glTexImage2D"))
-				success = false;
-		}
-
-		data++;
-	}
+	success = upload_face(GL_TEXTURE_2D, num_levels,
+			tex->base.gl_format, tex->base.gl_internal_format,
+			compressed, tex->width, tex->height, tex_size, &data);
 
 	if (!gl_bind_texture(GL_TEXTURE_2D, 0))
 		success = false;
@@ -78,6 +57,29 @@ static inline bool upload_texture_data(struct gs_texture_2d *tex, void **data)
 	return success;
 }
 
+static bool create_pixel_unpack_buffer(struct gs_texture_2d *tex)
+{
+	GLsizeiptr size;
+	bool success = true;
+
+	if (!gl_gen_buffers(1, &tex->unpack_buffer))
+		return false;
+
+	if (!gl_bind_buffer(GL_PIXEL_UNPACK_BUFFER, tex->unpack_buffer))
+		return false;
+
+	size = tex->width * tex->height * get_format_bpp(tex->base.format) / 8;
+
+	glBufferData(GL_PIXEL_UNPACK_BUFFER, size, 0, GL_DYNAMIC_DRAW);
+	if (!gl_success("glBufferData"))
+		success = false;
+
+	if (!gl_bind_buffer(GL_PIXEL_UNPACK_BUFFER, 0))
+		success = false;
+
+	return success;
+}
+
 texture_t device_create_texture(device_t device, uint32_t width,
 		uint32_t height, enum gs_color_format color_format,
 		uint32_t levels, void **data, uint32_t flags)
@@ -90,12 +92,17 @@ texture_t device_create_texture(device_t device, uint32_t width,
 	tex->base.format             = color_format;
 	tex->base.gl_format          = convert_gs_format(color_format);
 	tex->base.gl_internal_format = convert_gs_internal_format(color_format);
+	tex->base.is_dynamic         = flags & GS_DYNAMIC;
+	tex->base.is_render_target   = flags & GS_RENDERTARGET;
+	tex->base.gen_mipmaps        = flags & GS_BUILDMIPMAPS;
 	tex->width                   = width;
 	tex->height                  = height;
 
 	if (!gl_gen_textures(1, &tex->base.texture))
 		goto fail;
-	if (data && !upload_texture_data(tex, data))
+	if (tex->base.is_dynamic && !create_pixel_unpack_buffer(tex))
+		goto fail;
+	if (data && !upload_texture_2d(tex, data))
 		goto fail;
 
 	return (texture_t)tex;
@@ -114,3 +121,79 @@ void texture_destroy(texture_t tex)
 	glDeleteTextures(1, &tex->texture);
 	bfree(tex);
 }
+
+static inline bool is_texture_2d(texture_t tex, const char *func)
+{
+	bool is_tex2d = tex->type == GS_TEXTURE_2D;
+	if (!is_tex2d)
+		blog(LOG_ERROR, "%s (GL) failed:  Not a 2D texture", func);
+	return is_tex2d;
+}
+
+uint32_t texture_getwidth(texture_t tex)
+{
+	struct gs_texture_2d *tex2d = (struct gs_texture_2d*)tex;
+	if (!is_texture_2d(tex, "texture_getwidth"))
+		return 0;
+
+	return tex2d->width;
+}
+
+uint32_t texture_getheight(texture_t tex)
+{
+	struct gs_texture_2d *tex2d = (struct gs_texture_2d*)tex;
+	if (!is_texture_2d(tex, "texture_getheight"))
+		return 0;
+
+	return tex2d->height;
+}
+
+enum gs_color_format texture_getcolorformat(texture_t tex)
+{
+	return tex->format;
+}
+
+bool texture_map(texture_t tex, void **ptr, uint32_t *byte_width)
+{
+	struct gs_texture_2d *tex2d = (struct gs_texture_2d*)tex;
+
+	if (!is_texture_2d(tex, "texture_map"))
+		goto fail;
+
+	if (!tex2d->base.is_dynamic) {
+		blog(LOG_ERROR, "Texture is not dynamic");
+		goto fail;
+	}
+
+	if (!gl_bind_buffer(GL_PIXEL_UNPACK_BUFFER, tex2d->unpack_buffer))
+		goto fail;
+
+	*ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
+	if (!*ptr) {
+		gl_success("glMapBuffer");
+		goto fail;
+	}
+
+	gl_bind_buffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+	*byte_width = tex2d->width * get_format_bpp(tex->format) / 8;
+	return true;
+
+fail:
+	blog(LOG_ERROR, "texture_map (GL) failed");
+	return false;
+}
+
+void texture_unmap(texture_t tex)
+{
+	struct gs_texture_2d *tex2d = (struct gs_texture_2d*)tex;
+	if (!is_texture_2d(tex, "texture_unmap"))
+		return;
+
+	if (!gl_bind_buffer(GL_PIXEL_UNPACK_BUFFER, tex2d->unpack_buffer))
+		return;
+	glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+	gl_success("glUnmapBuffer");
+
+	gl_bind_buffer(GL_PIXEL_UNPACK_BUFFER, 0);
+}

+ 125 - 0
libobs-opengl/gl-texturecube.c

@@ -0,0 +1,125 @@
+/******************************************************************************
+    Copyright (C) 2013 by Hugh Bailey <[email protected]>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+#include "gl-subsystem.h"
+
+static inline uint32_t num_actual_levels(struct gs_texture_cube *tex)
+{
+	uint32_t num_levels;
+	uint32_t size;
+
+	if (tex->base.levels > 0)
+		return tex->base.levels;
+
+	size = tex->size;
+	num_levels = 0;
+
+	while (size  > 1) {
+		size /= 2;
+		num_levels++;
+	}
+
+	return num_levels;
+}
+
+static inline bool upload_texture_cube(struct gs_texture_cube *tex, void **data)
+{
+	uint32_t row_size   = tex->size * get_format_bpp(tex->base.format);
+	uint32_t tex_size   = tex->size * row_size / 8;
+	uint32_t num_levels = num_actual_levels(tex);
+	bool     compressed = is_compressed_format(tex->base.format);
+	bool     success    = true;
+	uint32_t i;
+
+	for (i = 0; i < 6; i++) {
+		GLenum type = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
+
+		if (!gl_bind_texture(type, tex->base.texture))
+			success = false;
+
+		if (!upload_face(type, num_levels, tex->base.gl_format,
+					tex->base.gl_internal_format,
+					compressed, tex->size, tex->size,
+					tex_size, &data))
+			success = false;
+
+		if (!gl_bind_texture(type, 0))
+			success = false;
+
+		data++;
+	}
+
+	return success;
+}
+
+texture_t device_create_cubetexture(device_t device, uint32_t size,
+		enum gs_color_format color_format, uint32_t levels,
+		void **data, uint32_t flags)
+{
+	struct gs_texture_cube *tex = bmalloc(sizeof(struct gs_texture_cube));
+	memset(tex, 0, sizeof(struct gs_texture_2d));
+
+	tex->base.device             = device;
+	tex->base.type               = GS_TEXTURE_2D;
+	tex->base.format             = color_format;
+	tex->base.gl_format          = convert_gs_format(color_format);
+	tex->base.gl_internal_format = convert_gs_internal_format(color_format);
+	tex->size                    = size;
+
+	if (!gl_gen_textures(1, &tex->base.texture))
+		goto fail;
+	if (data && !upload_texture_cube(tex, data))
+		goto fail;
+
+	return (texture_t)tex;
+
+fail:
+	texture_destroy((texture_t)tex);
+	blog(LOG_ERROR, "device_create_texture (GL) failed");
+	return NULL;
+}
+
+void cubetexture_destroy(texture_t tex)
+{
+	if (!tex)
+		return;
+
+	glDeleteTextures(1, &tex->texture);
+	bfree(tex);
+}
+
+static inline bool is_texture_cube(texture_t tex, const char *func)
+{
+	bool is_texcube = tex->type == GS_TEXTURE_CUBE;
+	if (!is_texcube)
+		blog(LOG_ERROR, "%s (GL) failed:  Not a cubemap texture", func);
+	return is_texcube;
+}
+
+uint32_t cubetexture_getsize(texture_t cubetex)
+{
+	struct gs_texture_cube *cube = (struct gs_texture_cube*)cubetex;
+	if (!is_texture_cube(cubetex, "cubetexture_getsize"))
+		return 0;
+
+	return cube->size;
+}
+
+enum gs_color_format cubetexture_getcolorformat(texture_t cubetex)
+{
+	return cubetex->format;
+}

+ 5 - 1
libobs-opengl/gl-windows.c

@@ -341,7 +341,6 @@ struct gl_platform *gl_platform_create(device_t device,
 
 	if (!gl_dummy_context_init(&dummy))
 		goto fail;
-
 	if (!gl_init_extensions())
 		goto fail;
 
@@ -359,6 +358,11 @@ struct gl_platform *gl_platform_create(device_t device,
 	if (!plat->hrc)
 		goto fail;
 
+	if (GLEW_ARB_seamless_cube_map) {
+		glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+		gl_success("GL_TEXTURE_CUBE_MAP_SEAMLESS");
+	}
+
 	return plat;
 
 fail:

+ 2 - 0
vs/2010/libobs-opengl/libobs-opengl.vcxproj

@@ -160,8 +160,10 @@
     <ClInclude Include="..\..\..\libobs-opengl\gl-subsystem.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="..\..\..\libobs-opengl\gl-helpers.c" />
     <ClCompile Include="..\..\..\libobs-opengl\gl-subsystem.c" />
     <ClCompile Include="..\..\..\libobs-opengl\gl-texture2d.c" />
+    <ClCompile Include="..\..\..\libobs-opengl\gl-texturecube.c" />
     <ClCompile Include="..\..\..\libobs-opengl\gl-windows.c" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+ 6 - 0
vs/2010/libobs-opengl/libobs-opengl.vcxproj.filters

@@ -35,5 +35,11 @@
     <ClCompile Include="..\..\..\libobs-opengl\gl-texture2d.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\libobs-opengl\gl-helpers.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\libobs-opengl\gl-texturecube.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>