diff --git a/libobs-d3d11/GS_D3D11Exports.h b/libobs-d3d11/GS_D3D11Exports.h index 03777b957..8993728a3 100644 --- a/libobs-d3d11/GS_D3D11Exports.h +++ b/libobs-d3d11/GS_D3D11Exports.h @@ -31,14 +31,15 @@ EXPORT void device_getsize(device_t device, uint32_t *x, uint32_t *y); EXPORT uint32_t device_getwidth(device_t device); EXPORT uint32_t device_getheight(device_t device); EXPORT texture_t device_create_texture(device_t device, uint32_t width, - uint32_t height, enum gs_color_format color_format, void *data, - uint32_t flags); + uint32_t height, enum gs_color_format color_format, + uint32_t levels, void **data, uint32_t flags); EXPORT texture_t device_create_cubetexture(device_t device, uint32_t size, - enum gs_color_format color_format, void *data[6], - uint32_t flags); + enum gs_color_format color_format, uint32_t levels, + void **data, uint32_t flags); EXPORT texture_t device_create_volumetexture(device_t device, uint32_t width, uint32_t height, uint32_t depth, - enum gs_color_format color_format, void *data, uint32_t flags); + enum gs_color_format color_format, uint32_t levels, void **data, + uint32_t flags); EXPORT zstencil_t device_create_zstencil(device_t device, uint32_t width, uint32_t height, enum gs_zstencil_format format); EXPORT stagesurf_t device_create_stagesurface(device_t device, uint32_t width, diff --git a/libobs-d3d11/GS_D3D11SubSystem.cpp b/libobs-d3d11/GS_D3D11SubSystem.cpp index 123ce543e..62b6e8442 100644 --- a/libobs-d3d11/GS_D3D11SubSystem.cpp +++ b/libobs-d3d11/GS_D3D11SubSystem.cpp @@ -479,13 +479,14 @@ uint32_t device_getheight(device_t device) } texture_t device_create_texture(device_t device, uint32_t width, - uint32_t height, enum gs_color_format color_format, void *data, - uint32_t flags) + uint32_t height, enum gs_color_format color_format, + uint32_t levels, void **data, uint32_t flags) { gs_texture *texture = NULL; try { texture = new gs_texture_2d(device, width, height, color_format, - data, flags, false, false, false); + levels, data, flags, GS_TEXTURE_2D, false, + false); } catch (HRError error) { blog(LOG_ERROR, "device_create_texture (D3D11): %s (%08lX)", error.str, error.hr); @@ -497,13 +498,14 @@ texture_t device_create_texture(device_t device, uint32_t width, } texture_t device_create_cubetexture(device_t device, uint32_t size, - enum gs_color_format color_format, void *data[6], + enum gs_color_format color_format, uint32_t levels, void **data, uint32_t flags) { gs_texture *texture = NULL; try { texture = new gs_texture_2d(device, size, size, color_format, - data, flags, true, false, false); + levels, data, flags, GS_TEXTURE_CUBE, false, + false); } catch (HRError error) { blog(LOG_ERROR, "device_create_cubetexture (D3D11): %s " "(%08lX)", @@ -518,7 +520,8 @@ texture_t device_create_cubetexture(device_t device, uint32_t size, texture_t device_create_volumetexture(device_t device, uint32_t width, uint32_t height, uint32_t depth, - enum gs_color_format color_format, void *data, uint32_t flags) + enum gs_color_format color_format, uint32_t levels, + void **data, uint32_t flags) { /* TODO */ return NULL; diff --git a/libobs-d3d11/GS_D3D11SubSystem.hpp b/libobs-d3d11/GS_D3D11SubSystem.hpp index 1fe034ae8..5410dcdeb 100644 --- a/libobs-d3d11/GS_D3D11SubSystem.hpp +++ b/libobs-d3d11/GS_D3D11SubSystem.hpp @@ -245,12 +245,16 @@ struct gs_index_buffer { struct gs_texture { gs_texture_type type; - ComPtr shaderRes; - gs_device *device; + gs_device *device; + uint32_t levels; - inline gs_texture(gs_device *device, gs_texture_type type) + ComPtr shaderRes; + + inline gs_texture(gs_device *device, gs_texture_type type, + uint32_t levels) : device (device), - type (type) + type (type), + levels (levels) { } @@ -272,13 +276,13 @@ struct gs_texture_2d : gs_texture { bool genMipmaps; HANDLE sharedHandle; - void InitSRD(D3D11_SUBRESOURCE_DATA *srd, void *data); - void InitTexture(void *data); + void InitSRD(vector &srd, void **data); + void InitTexture(void **data); void InitResourceView(); void InitRenderTargets(); inline gs_texture_2d() - : gs_texture (NULL, GS_TEXTURE_2D), + : gs_texture (NULL, GS_TEXTURE_2D, 0), width (0), height (0), format (GS_UNKNOWN), @@ -293,9 +297,9 @@ struct gs_texture_2d : gs_texture { } gs_texture_2d(device_t device, uint32_t width, uint32_t height, - gs_color_format colorFormat, void *data, - uint32_t flags, bool isCubeMap, bool gdiCompatible, - bool shared); + gs_color_format colorFormat, uint32_t levels, + void **data, uint32_t flags, gs_texture_type type, + bool gdiCompatible, bool shared); }; struct gs_zstencil_buffer { diff --git a/libobs-d3d11/GS_D3D11Texture2D.cpp b/libobs-d3d11/GS_D3D11Texture2D.cpp index 374c5c259..2ae5e54ed 100644 --- a/libobs-d3d11/GS_D3D11Texture2D.cpp +++ b/libobs-d3d11/GS_D3D11Texture2D.cpp @@ -23,36 +23,58 @@ static inline bool IsPow2(uint32_t num) return num >= 2 && (num & (num-1)) == 0; } -void gs_texture_2d::InitSRD(D3D11_SUBRESOURCE_DATA *srd, void *data) +static inline uint32_t numActualLevels(uint32_t levels, uint32_t width, + uint32_t height) { - uint32_t rowSizeBytes = width * GetFormatBPP(format); - uint32_t texSizeBytes = rowSizeBytes * height; + if (levels > 0) + return levels; - if (type == GS_TEXTURE_2D) { - srd->pSysMem = (uint8_t*)data; - srd->SysMemPitch = rowSizeBytes; - srd->SysMemSlicePitch = texSizeBytes; + uint32_t size = max(width, height); + uint32_t numLevels = 0; - } else { /* GS_TEXTURE_CUBE */ - void **buffers = (void**)data; - for (size_t i = 0; i < 6; i++) { - srd[i].pSysMem = buffers[i]; - srd[i].SysMemPitch = rowSizeBytes; - srd[i].SysMemSlicePitch = texSizeBytes; + while (size > 1) { + size /= 2; + numLevels++; + } + + return numLevels; +} + +void gs_texture_2d::InitSRD(vector &srd, void **data) +{ + uint32_t rowSizeBytes = width * GetFormatBPP(format); + uint32_t texSizeBytes = height * rowSizeBytes; + size_t textures = type == GS_TEXTURE_2D ? 1 : 6; + uint32_t actual_levels = numActualLevels(levels, width, height); + + for (size_t i = 0; i < textures; i++) { + uint32_t newRowSize = rowSizeBytes; + uint32_t newTexSize = texSizeBytes; + + for (size_t j = 0; j < actual_levels; j++) { + D3D11_SUBRESOURCE_DATA newSRD; + newSRD.pSysMem = data; + newSRD.SysMemPitch = newRowSize; + newSRD.SysMemSlicePitch = newTexSize; + srd.push_back(newSRD); + + newRowSize /= 2; + newTexSize /= 4; + data++; } } } -void gs_texture_2d::InitTexture(void *data) +void gs_texture_2d::InitTexture(void **data) { + vector srd; D3D11_TEXTURE2D_DESC td; - D3D11_SUBRESOURCE_DATA srd[6]; HRESULT hr; memset(&td, 0, sizeof(td)); td.Width = width; td.Height = height; - td.MipLevels = genMipmaps ? 0 : 1; + td.MipLevels = genMipmaps ? 0 : levels; td.ArraySize = type == GS_TEXTURE_CUBE ? 6 : 1; td.Format = dxgiFormat; td.BindFlags = D3D10_BIND_SHADER_RESOURCE; @@ -70,7 +92,7 @@ void gs_texture_2d::InitTexture(void *data) if (data) InitSRD(srd, data); - hr = device->device->CreateTexture2D(&td, data ? srd : NULL, + hr = device->device->CreateTexture2D(&td, data ? srd.data() : NULL, texture.Assign()); if (FAILED(hr)) throw HRError("Failed to create 2D texture", hr); @@ -126,9 +148,10 @@ void gs_texture_2d::InitRenderTargets() } gs_texture_2d::gs_texture_2d(device_t device, uint32_t width, uint32_t height, - gs_color_format colorFormat, void *data, uint32_t flags, - bool isCubeMap, bool gdiCompatible, bool shared) - : gs_texture (device, isCubeMap ? GS_TEXTURE_CUBE : GS_TEXTURE_2D), + gs_color_format colorFormat, uint32_t levels, void **data, + uint32_t flags, gs_texture_type type, bool gdiCompatible, + bool shared) + : gs_texture (device, type, levels), width (width), height (height), format (colorFormat), @@ -139,11 +162,13 @@ gs_texture_2d::gs_texture_2d(device_t device, uint32_t width, uint32_t height, isRenderTarget ((flags & GS_RENDERTARGET) != 0), genMipmaps ((flags & GS_BUILDMIPMAPS) != 0) { - if (genMipmaps && (!IsPow2(width) || !IsPow2(height))) { - blog(LOG_WARNING, "Cannot generate mipmaps for a " + bool hasMips = genMipmaps || levels != 1; + if (hasMips && (!IsPow2(width) || !IsPow2(height))) { + blog(LOG_WARNING, "Cannot use mipmaps with a " "non-power-of-two texture. Disabling " "mipmaps for this texture."); - genMipmaps = false; + genMipmaps = false; + this->levels = 1; } InitTexture(data); diff --git a/libobs-opengl/gl-exports.h b/libobs-opengl/gl-exports.h index 100e9868d..0b67c7ecd 100644 --- a/libobs-opengl/gl-exports.h +++ b/libobs-opengl/gl-exports.h @@ -12,14 +12,15 @@ EXPORT void device_getsize(device_t device, uint32_t *x, uint32_t *y); EXPORT uint32_t device_getwidth(device_t device); EXPORT uint32_t device_getheight(device_t device); EXPORT texture_t device_create_texture(device_t device, uint32_t width, - uint32_t height, enum gs_color_format color_format, void *data, - uint32_t flags); + uint32_t height, enum gs_color_format color_format, + uint32_t levels, void **data, uint32_t flags); EXPORT texture_t device_create_cubetexture(device_t device, uint32_t size, - enum gs_color_format color_format, void *data[6], - uint32_t flags); + enum gs_color_format color_format, uint32_t levels, + void **data, uint32_t flags); EXPORT texture_t device_create_volumetexture(device_t device, uint32_t width, uint32_t height, uint32_t depth, - enum gs_color_format color_format, void *data, uint32_t flags); + enum gs_color_format color_format, uint32_t levels, void **data, + uint32_t flags); EXPORT zstencil_t device_create_zstencil(device_t device, uint32_t width, uint32_t height, enum gs_zstencil_format format); EXPORT stagesurf_t device_create_stagesurface(device_t device, uint32_t width, diff --git a/libobs-opengl/gl-helpers.h b/libobs-opengl/gl-helpers.h new file mode 100644 index 000000000..325f1d534 --- /dev/null +++ b/libobs-opengl/gl-helpers.h @@ -0,0 +1,34 @@ +#ifndef GL_HELPERS_H +#define GL_HELPERS_H + +/* + * Okay, so GL error handling is.. unclean to work with. I don't want + * to have to keep typing out the same stuff over and over again do I'll just + * make a bunch of helper functions to make it a bit easier to handle errors + */ + +static inline bool gl_error_occurred(const char *funcname) +{ + GLenum errorcode = glGetError(); + if (errorcode != GL_NO_ERROR) { + blog(LOG_ERROR, "%s failed, glGetError returned %u", + funcname, errorcode); + return false; + } + + return true; +} + +static inline bool gl_gen_textures(GLsizei num_texture, GLuint *textures) +{ + glGenTextures(num_texture, textures); + return gl_error_occurred("glGenTextures"); +} + +static inline bool gl_bind_texture(GLenum target, GLuint texture) +{ + glBindTexture(target, texture); + return gl_error_occurred("glBindTexture"); +} + +#endif diff --git a/libobs-opengl/gl-subsystem.c b/libobs-opengl/gl-subsystem.c index 400bddf0e..90d4588d5 100644 --- a/libobs-opengl/gl-subsystem.c +++ b/libobs-opengl/gl-subsystem.c @@ -41,37 +41,39 @@ swapchain_t device_create_swapchain(device_t device, struct gs_init_data *info) return swap; } -void device_resize(device_t device, uint32_t x, uint32_t y) +void device_resize(device_t device, uint32_t cx, uint32_t cy) { + /* GL automatically resizes the device, so it doesn't do much */ + device->cur_swap->info.cx = cx; + device->cur_swap->info.cy = cy; } -void device_getsize(device_t device, uint32_t *x, uint32_t *y) +void device_getsize(device_t device, uint32_t *cx, uint32_t *cy) { + *cx = device->cur_swap->info.cx; + *cy = device->cur_swap->info.cy; } uint32_t device_getwidth(device_t device) { + return device->cur_swap->info.cx; } uint32_t device_getheight(device_t device) { -} - -texture_t device_create_texture(device_t device, uint32_t width, - uint32_t height, enum gs_color_format color_format, void *data, - uint32_t flags) -{ + return device->cur_swap->info.cy; } texture_t device_create_cubetexture(device_t device, uint32_t size, - enum gs_color_format color_format, void *data[6], - uint32_t flags) + 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, void *data, uint32_t flags) + enum gs_color_format color_format, uint32_t levels, void **data, + uint32_t flags) { } @@ -335,10 +337,6 @@ void swapchain_destroy(swapchain_t swapchain) { } -void texture_destroy(texture_t tex) -{ -} - uint32_t texture_getwidth(texture_t tex) { } diff --git a/libobs-opengl/gl-subsystem.h b/libobs-opengl/gl-subsystem.h index 01f962bac..8716de7d4 100644 --- a/libobs-opengl/gl-subsystem.h +++ b/libobs-opengl/gl-subsystem.h @@ -20,10 +20,97 @@ #include "graphics/graphics.h" #include "glew/include/GL/glew.h" +#include "gl-helpers.h" struct gl_platform; struct gl_windowinfo; +static inline GLint convert_gs_format(enum gs_color_format format) +{ + switch (format) { + case GS_A8: return GL_RGBA; + case GS_R8: return GL_RED; + case GS_RGBA: return GL_RGBA; + case GS_BGRX: return GL_BGR; + case GS_BGRA: return GL_BGRA; + case GS_R10G10B10A2: return GL_RGBA; + case GS_RGBA16: return GL_RGBA; + case GS_R16: return GL_RED; + case GS_RGBA16F: return GL_RGBA; + case GS_RGBA32F: return GL_RGBA; + case GS_RG16F: return GL_RG; + case GS_RG32F: return GL_RG; + case GS_R16F: return GL_RED; + case GS_R32F: return GL_RED; + case GS_DXT1: return GL_RGB; + case GS_DXT3: return GL_RGBA; + case GS_DXT5: return GL_RGBA; + default: return 0; + } +} + +static inline GLint convert_gs_internal_format(enum gs_color_format format) +{ + switch (format) { + case GS_A8: return GL_R8; /* NOTE: use GL_TEXTURE_SWIZZLE_x */ + case GS_R8: return GL_R8; + case GS_RGBA: return GL_RGBA; + case GS_BGRX: return GL_RGBA; + case GS_BGRA: return GL_RGBA; + case GS_R10G10B10A2: return GL_RGB10_A2; + case GS_RGBA16: return GL_RGBA16; + case GS_R16: return GL_R16; + case GS_RGBA16F: return GL_RGBA16F; + case GS_RGBA32F: return GL_RGBA32F; + case GS_RG16F: return GL_RG16F; + case GS_RG32F: return GL_RG32F; + case GS_R16F: return GL_R16F; + case GS_R32F: return GL_R32F; + case GS_DXT1: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + case GS_DXT3: return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + case GS_DXT5: return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + default: return 0; + } +} + +static inline bool is_compressed_format(enum gs_color_format format) +{ + return (format == GS_DXT1 || format == GS_DXT3 || format == GS_DXT5); +} + +static inline GLint convert_zstencil_format(enum gs_zstencil_format format) +{ + switch (format) { + case GS_Z16: return GL_DEPTH_COMPONENT16; + case GS_Z24_S8: return GL_DEPTH24_STENCIL8; + case GS_Z32F: return GL_DEPTH_COMPONENT32F; + case GS_Z32F_S8X24: return GL_DEPTH32F_STENCIL8; + default: return 0; + } +} + +struct gs_texture { + device_t device; + enum gs_texture_type type; + enum gs_color_format format; + GLenum gl_format; + GLint gl_internal_format; + GLuint texture; +}; + +struct gs_texture_2d { + struct gs_texture base; + + uint32_t width; + uint32_t height; +}; + +struct gs_texture_cube { + struct gs_texture base; + + uint32_t size; +}; + struct gs_swap_chain { device_t device; struct gl_windowinfo *wi; @@ -34,6 +121,8 @@ struct gs_device { struct gl_platform *plat; struct gs_swap_chain *cur_swap; + int cur_render_side; + struct gs_texture *cur_render_texture; }; extern struct gl_platform *gl_platform_create(device_t device, diff --git a/libobs-opengl/gl-texture2d.c b/libobs-opengl/gl-texture2d.c new file mode 100644 index 000000000..559eef5bf --- /dev/null +++ b/libobs-opengl/gl-texture2d.c @@ -0,0 +1,45 @@ +#include "gl-subsystem.h" + +static inline bool upload_texture_data(struct gs_texture_2d *tex, void **data) +{ + if (!gl_bind_texture(GL_TEXTURE_2D, tex->base.texture)) + return false; + + //if (is_compressed_format(tex->base.format)) + + if (!gl_bind_texture(GL_TEXTURE_2D, 0)) + return false; + + return true; +} + +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) +{ + struct gs_texture_2d *tex = bmalloc(sizeof(struct gs_texture_2d)); + memset(tex, 0, sizeof(struct gs_texture_2d)); + + 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->width = width; + tex->height = height; + + if (!gl_gen_textures(1, &tex->base.texture)) + goto fail; + if (data && !upload_texture_data(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 texture_destroy(texture_t tex) +{ +} diff --git a/libobs/graphics/graphics-internal.h b/libobs/graphics/graphics-internal.h index 95c9a3fa6..9a0fa7949 100644 --- a/libobs/graphics/graphics-internal.h +++ b/libobs/graphics/graphics-internal.h @@ -34,14 +34,14 @@ struct gs_exports { uint32_t (*device_getheight)(device_t device); texture_t (*device_create_texture)(device_t device, uint32_t width, uint32_t height, enum gs_color_format color_format, - void *data, uint32_t flags); + uint32_t levels, void **data, uint32_t flags); texture_t (*device_create_cubetexture)(device_t device, uint32_t size, - enum gs_color_format color_format, void *data[6], - uint32_t flags); + 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, void *data, - uint32_t flags); + enum gs_color_format color_format, uint32_t levels, + void **data, uint32_t flags); zstencil_t (*device_create_zstencil)(device_t device, uint32_t width, uint32_t height, enum gs_zstencil_format format); diff --git a/libobs/graphics/graphics.c b/libobs/graphics/graphics.c index 6025cd03f..4d5971f66 100644 --- a/libobs/graphics/graphics.c +++ b/libobs/graphics/graphics.c @@ -726,29 +726,31 @@ uint32_t gs_getheight(void) } texture_t gs_create_texture(uint32_t width, uint32_t height, - enum gs_color_format color_format, void *data, uint32_t flags) + enum gs_color_format color_format, uint32_t levels, void **data, + uint32_t flags) { graphics_t graphics = thread_graphics; return graphics->exports.device_create_texture(graphics->device, - width, height, color_format, data, flags); + width, height, color_format, levels, data, flags); } texture_t gs_create_cubetexture(uint32_t size, - enum gs_color_format color_format, void *data[6], - uint32_t flags) + enum gs_color_format color_format, uint32_t levels, + void **data, uint32_t flags) { graphics_t graphics = thread_graphics; return graphics->exports.device_create_cubetexture(graphics->device, - size, color_format, data, flags); + size, color_format, levels, data, flags); } texture_t gs_create_volumetexture(uint32_t width, uint32_t height, - uint32_t depth, enum gs_color_format color_format, void *data, - uint32_t flags) + uint32_t depth, enum gs_color_format color_format, + uint32_t levels, void **data, uint32_t flags) { graphics_t graphics = thread_graphics; return graphics->exports.device_create_volumetexture(graphics->device, - width, height, depth, color_format, data, flags); + width, height, depth, color_format, levels, data, + flags); } zstencil_t gs_create_zstencil(uint32_t width, uint32_t height, diff --git a/libobs/graphics/graphics.h b/libobs/graphics/graphics.h index 1c72d0a66..8ea4acb68 100644 --- a/libobs/graphics/graphics.h +++ b/libobs/graphics/graphics.h @@ -513,13 +513,14 @@ EXPORT uint32_t gs_getwidth(void); EXPORT uint32_t gs_getheight(void); EXPORT texture_t gs_create_texture(uint32_t width, uint32_t height, - enum gs_color_format color_format, void *data, uint32_t flags); + enum gs_color_format color_format, uint32_t levels, void **data, + uint32_t flags); EXPORT texture_t gs_create_cubetexture(uint32_t size, - enum gs_color_format color_format, void *data[6], - uint32_t flags); + enum gs_color_format color_format, uint32_t levels, + void **data, uint32_t flags); EXPORT texture_t gs_create_volumetexture(uint32_t width, uint32_t height, - uint32_t depth, enum gs_color_format color_format, void *data, - uint32_t flags); + uint32_t depth, enum gs_color_format color_format, + uint32_t levels, void **data, uint32_t flags); EXPORT zstencil_t gs_create_zstencil(uint32_t width, uint32_t height, enum gs_zstencil_format format); diff --git a/vs/2010/libobs-opengl/libobs-opengl.vcxproj b/vs/2010/libobs-opengl/libobs-opengl.vcxproj index 6497bfa7e..5e436fa6f 100644 --- a/vs/2010/libobs-opengl/libobs-opengl.vcxproj +++ b/vs/2010/libobs-opengl/libobs-opengl.vcxproj @@ -156,10 +156,12 @@ + + diff --git a/vs/2010/libobs-opengl/libobs-opengl.vcxproj.filters b/vs/2010/libobs-opengl/libobs-opengl.vcxproj.filters index d8ef5c379..8aef33291 100644 --- a/vs/2010/libobs-opengl/libobs-opengl.vcxproj.filters +++ b/vs/2010/libobs-opengl/libobs-opengl.vcxproj.filters @@ -21,6 +21,9 @@ Header Files + + Header Files + @@ -29,5 +32,8 @@ Source Files + + Source Files + \ No newline at end of file