From dfa2dc6eabaa137de1a04d09e934e435dede8ee6 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Wed, 16 Oct 2013 23:31:18 -0700 Subject: [PATCH] fix up the rest of the GL code, add glew to project, add makefiles for opengl, fix makefiles so that it can be built with gcc, update project files to automatically output to the build directory --- {vs/2010/wintest => build}/draw.effect | 0 {vs/2010/wintest => build}/test.effect | 0 libobs-d3d11/d3d11-exports.h | 10 +- libobs-d3d11/d3d11-samplerstate.cpp | 62 +++--- libobs-d3d11/d3d11-subsystem.cpp | 130 +++++++++--- libobs-d3d11/d3d11-subsystem.hpp | 16 +- libobs-d3d11/d3d11-texture2d.cpp | 10 +- libobs-opengl/gl-exports.h | 10 +- libobs-opengl/gl-helpers.c | 5 +- libobs-opengl/gl-helpers.h | 27 ++- libobs-opengl/gl-indexbuffer.c | 2 +- libobs-opengl/gl-shader.c | 69 +++++-- libobs-opengl/gl-shaderparser.c | 195 ++++++++++++------ libobs-opengl/gl-shaderparser.h | 19 +- libobs-opengl/gl-stagesurf.c | 17 +- libobs-opengl/gl-subsystem.c | 212 ++++++++++++++++---- libobs-opengl/gl-subsystem.h | 27 ++- libobs-opengl/gl-texture2d.c | 15 +- libobs-opengl/gl-texturecube.c | 13 +- libobs-opengl/gl-vertexbuffer.c | 24 ++- libobs-opengl/gl-windows.c | 92 +++++++-- libobs-opengl/makefile | 48 +++++ libobs/graphics/effect-parser.c | 18 +- libobs/graphics/graphics-imports.c | 1 - libobs/graphics/graphics-internal.h | 8 +- libobs/graphics/graphics.c | 51 ++--- libobs/graphics/graphics.h | 12 +- libobs/graphics/matrix4.c | 65 +----- libobs/graphics/matrix4.h | 7 - libobs/obs-source.c | 2 +- libobs/obs-video.c | 10 +- makefile | 2 +- test/test-input/test-random.c | 7 +- test/win/test.cpp | 17 +- vs/2010/OBS.sln | 59 ++++++ vs/2010/libobs-d3d11/libobs-d3d11.vcxproj | 12 ++ vs/2010/libobs-opengl/libobs-opengl.vcxproj | 12 ++ vs/2010/libobs/libobs.vcxproj | 12 ++ vs/2010/test-input/test-input.vcxproj | 12 ++ vs/2010/wintest/wintest.vcxproj | 16 +- 40 files changed, 937 insertions(+), 389 deletions(-) rename {vs/2010/wintest => build}/draw.effect (100%) rename {vs/2010/wintest => build}/test.effect (100%) create mode 100644 libobs-opengl/makefile diff --git a/vs/2010/wintest/draw.effect b/build/draw.effect similarity index 100% rename from vs/2010/wintest/draw.effect rename to build/draw.effect diff --git a/vs/2010/wintest/test.effect b/build/test.effect similarity index 100% rename from vs/2010/wintest/test.effect rename to build/test.effect diff --git a/libobs-d3d11/d3d11-exports.h b/libobs-d3d11/d3d11-exports.h index 9644b0df7..53e4ac277 100644 --- a/libobs-d3d11/d3d11-exports.h +++ b/libobs-d3d11/d3d11-exports.h @@ -33,14 +33,14 @@ 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, - uint32_t levels, void **data, uint32_t flags); + uint32_t levels, const void **data, uint32_t flags); EXPORT 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); + const 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, uint32_t levels, void **data, - uint32_t flags); + enum gs_color_format color_format, uint32_t levels, + const 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, @@ -124,8 +124,6 @@ EXPORT void device_ortho(device_t device, float left, float right, float top, float bottom, float znear, float zfar); EXPORT void device_frustum(device_t device, float left, float right, float top, float bottom, float znear, float zfar); -EXPORT void device_perspective(device_t device, float fovy, float aspect, - float znear, float zfar); EXPORT void device_projection_push(device_t device); EXPORT void device_projection_pop(device_t device); diff --git a/libobs-d3d11/d3d11-samplerstate.cpp b/libobs-d3d11/d3d11-samplerstate.cpp index 1746c66bc..5cc5d8fff 100644 --- a/libobs-d3d11/d3d11-samplerstate.cpp +++ b/libobs-d3d11/d3d11-samplerstate.cpp @@ -18,27 +18,43 @@ #include "d3d11-subsystem.hpp" #include "graphics/vec4.h" -const D3D11_TEXTURE_ADDRESS_MODE convertAddressMode[] = +static inline D3D11_TEXTURE_ADDRESS_MODE ConvertGSAddressMode( + gs_address_mode mode) { - D3D11_TEXTURE_ADDRESS_CLAMP, - D3D11_TEXTURE_ADDRESS_WRAP, - D3D11_TEXTURE_ADDRESS_MIRROR, - D3D11_TEXTURE_ADDRESS_BORDER, - D3D11_TEXTURE_ADDRESS_MIRROR_ONCE -}; - -const D3D11_FILTER convertFilter[] = + switch (mode) { + default: + case GS_ADDRESS_WRAP: return D3D11_TEXTURE_ADDRESS_WRAP; + case GS_ADDRESS_CLAMP: return D3D11_TEXTURE_ADDRESS_CLAMP; + case GS_ADDRESS_MIRROR: return D3D11_TEXTURE_ADDRESS_MIRROR; + case GS_ADDRESS_BORDER: return D3D11_TEXTURE_ADDRESS_BORDER; + case GS_ADDRESS_MIRRORONCE: return D3D11_TEXTURE_ADDRESS_MIRROR_ONCE; + } +} + +static inline D3D11_FILTER ConvertGSFilter( gs_sample_filter filter) { - D3D11_FILTER_MIN_MAG_MIP_LINEAR, - D3D11_FILTER_MIN_MAG_MIP_POINT, - D3D11_FILTER_ANISOTROPIC, - D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR, - D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT, - D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR, - D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT, - D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, - D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT -}; + switch (filter) { + default: + case GS_FILTER_POINT: + return D3D11_FILTER_MIN_MAG_MIP_POINT; + case GS_FILTER_LINEAR: + return D3D11_FILTER_MIN_MAG_MIP_LINEAR; + case GS_FILTER_MIN_MAG_POINT_MIP_LINEAR: + return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; + case GS_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT: + return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; + case GS_FILTER_MIN_POINT_MAG_MIP_LINEAR: + return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR; + case GS_FILTER_MIN_LINEAR_MAG_MIP_POINT: + return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT; + case GS_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR: + return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; + case GS_FILTER_MIN_MAG_LINEAR_MIP_POINT: + return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + case GS_FILTER_ANISOTROPIC: + return D3D11_FILTER_ANISOTROPIC; + } +} gs_sampler_state::gs_sampler_state(device_t device, gs_sampler_info *info) : device (device), @@ -49,11 +65,11 @@ gs_sampler_state::gs_sampler_state(device_t device, gs_sampler_info *info) vec4 v4; memset(&sd, 0, sizeof(sd)); - sd.AddressU = convertAddressMode[(uint32_t)info->address_u]; - sd.AddressV = convertAddressMode[(uint32_t)info->address_v]; - sd.AddressW = convertAddressMode[(uint32_t)info->address_w]; + sd.AddressU = ConvertGSAddressMode(info->address_u); + sd.AddressV = ConvertGSAddressMode(info->address_v); + sd.AddressW = ConvertGSAddressMode(info->address_w); sd.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - sd.Filter = convertFilter[(uint32_t)info->filter]; + sd.Filter = ConvertGSFilter(info->filter); sd.MaxAnisotropy = info->max_anisotropy; sd.MaxLOD = FLT_MAX; diff --git a/libobs-d3d11/d3d11-subsystem.cpp b/libobs-d3d11/d3d11-subsystem.cpp index 1021d29c9..b5f2e90a0 100644 --- a/libobs-d3d11/d3d11-subsystem.cpp +++ b/libobs-d3d11/d3d11-subsystem.cpp @@ -232,10 +232,12 @@ ID3D11RasterizerState *gs_device::AddRasterState() ID3D11RasterizerState *state; memset(&rd, 0, sizeof(rd)); - rd.FillMode = D3D11_FILL_SOLID; - rd.CullMode = ConvertGSCullMode(rasterState.cullMode); - rd.DepthClipEnable = true; - rd.ScissorEnable = rasterState.scissorEnabled; + /* use CCW to convert to for a right-handed coordinate system */ + rd.FrontCounterClockwise = true; + rd.FillMode = D3D11_FILL_SOLID; + rd.CullMode = ConvertGSCullMode(rasterState.cullMode); + rd.DepthClipEnable = true; + rd.ScissorEnable = rasterState.scissorEnabled; hr = device->CreateRasterizerState(&rd, savedState.state.Assign()); if (FAILED(hr)) @@ -364,6 +366,13 @@ void gs_device::UpdateViewProjMatrix() gs_matrix_get(&cur_matrix); matrix4_from_matrix3(&curViewMatrix, &cur_matrix); + + /* negate Z col of the view matrix for right-handed coordinate system */ + curViewMatrix.x.z = -curViewMatrix.x.z; + curViewMatrix.y.z = -curViewMatrix.y.z; + curViewMatrix.z.z = -curViewMatrix.z.z; + curViewMatrix.t.z = -curViewMatrix.t.z; + matrix4_mul(&curViewProjMatrix, &curViewMatrix, &curProjMatrix); matrix4_transpose(&curViewProjMatrix, &curViewProjMatrix); @@ -490,7 +499,7 @@ 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, - uint32_t levels, void **data, uint32_t flags) + uint32_t levels, const void **data, uint32_t flags) { gs_texture *texture = NULL; try { @@ -508,8 +517,8 @@ 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, uint32_t levels, void **data, - uint32_t flags) + enum gs_color_format color_format, uint32_t levels, + const void **data, uint32_t flags) { gs_texture *texture = NULL; try { @@ -531,7 +540,7 @@ 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, uint32_t levels, - void **data, uint32_t flags) + const void **data, uint32_t flags) { /* TODO */ return NULL; @@ -884,14 +893,14 @@ void device_setrendertarget(device_t device, texture_t tex, zstencil_t zstencil) if (tex->type != GS_TEXTURE_2D) { blog(LOG_ERROR, "device_setrendertarget (D3D11): " - "texture is not a 2D texture"); + "texture is not a 2D texture"); return; } gs_texture_2d *tex2d = static_cast(tex); if (!tex2d->renderTarget[0]) { blog(LOG_ERROR, "device_setrendertarget (D3D11): " - "texture is not a render target"); + "texture is not a render target"); return; } @@ -942,8 +951,6 @@ void device_setcuberendertarget(device_t device, texture_t tex, int side, inline void gs_device::CopyTex(ID3D11Texture2D *dst, texture_t src) { - if (!src) - src = curRenderTarget; if (src->type != GS_TEXTURE_2D) throw "Source texture must be a 2D texture"; @@ -954,10 +961,22 @@ inline void gs_device::CopyTex(ID3D11Texture2D *dst, texture_t src) void device_copy_texture(device_t device, texture_t dst, texture_t src) { try { + gs_texture_2d *src2d = static_cast(src); + gs_texture_2d *dst2d = static_cast(dst); + + if (!src) + throw "Source texture is NULL"; if (!dst) - throw "Failed because destination texture is NULL"; - if (dst->type != GS_TEXTURE_2D) - throw "Destination texture must be a 2D texture"; + throw "Destination texture is NULL"; + 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) + 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"; gs_texture_2d *tex2d = static_cast(dst); device->CopyTex(tex2d->texture, src); @@ -970,8 +989,20 @@ void device_copy_texture(device_t device, texture_t dst, texture_t src) void device_stage_texture(device_t device, stagesurf_t dst, texture_t src) { try { + gs_texture_2d *src2d = static_cast(src); + + if (!src) + throw "Source texture is NULL"; + if (src->type != GS_TEXTURE_2D) + throw "Source texture must be a 2D texture"; if (!dst) - throw "Failed because destination texture is NULL"; + throw "Destination surface is NULL"; + if (dst->format != src->format) + throw "Source and destination formats do not match"; + if (dst->width != src2d->width || + dst->height != src2d->height) + throw "Source and destination must have the same " + "dimensions"; device->CopyTex(dst->texture, src); @@ -1025,13 +1056,15 @@ void device_draw(device_t device, enum gs_draw_mode draw_mode, device->curToplogy = newTopology; } - if (num_verts == 0) - num_verts = (uint32_t)device->curVertexBuffer->numVerts; - - if (device->curIndexBuffer) + if (device->curIndexBuffer) { + if (num_verts == 0) + num_verts = (uint32_t)device->curIndexBuffer->num; device->context->DrawIndexed(num_verts, start_vert, 0); - else + } else { + if (num_verts == 0) + num_verts = (uint32_t)device->curVertexBuffer->numVerts; device->context->Draw(num_verts, start_vert); + } } void device_endscene(device_t device) @@ -1292,23 +1325,56 @@ void device_setscissorrect(device_t device, struct gs_rect *rect) } void device_ortho(device_t device, float left, float right, float top, - float bottom, float znear, float zfar) + float bottom, float zNear, float zFar) { - matrix4_ortho(&device->curProjMatrix, left, right, top, bottom, znear, - zfar); + matrix4 *dst = &device->curProjMatrix; + + float rml = right-left; + float bmt = bottom-top; + float fmn = zFar-zNear; + + vec4_zero(&dst->x); + vec4_zero(&dst->y); + vec4_zero(&dst->z); + vec4_zero(&dst->t); + + dst->x.x = 2.0f / rml; + dst->t.x = (left+right) / -rml; + + dst->y.y = 2.0f / -bmt; + dst->t.y = (bottom+top) / bmt; + + dst->z.z = 1.0f / fmn; + dst->t.z = zNear / -fmn; + + dst->t.w = 1.0f; } void device_frustum(device_t device, float left, float right, float top, - float bottom, float znear, float zfar) + float bottom, float zNear, float zFar) { - matrix4_frustum(&device->curProjMatrix, left, right, top, bottom, - znear, zfar); -} + matrix4 *dst = &device->curProjMatrix; -void device_perspective(device_t device, float fovy, float aspect, - float znear, float zfar) -{ - matrix4_perspective(&device->curProjMatrix, fovy, aspect, znear, zfar); + float rml = right-left; + float bmt = bottom-top; + float fmn = zFar-zNear; + float nearx2 = 2.0f*zNear; + + vec4_zero(&dst->x); + vec4_zero(&dst->y); + vec4_zero(&dst->z); + vec4_zero(&dst->t); + + dst->x.x = nearx2 / rml; + dst->z.x = (left+right) / -rml; + + dst->y.y = nearx2 / -bmt; + dst->z.y = (bottom+top) / bmt; + + dst->z.z = zFar / fmn; + dst->t.z = (zNear*zFar) / -fmn; + + dst->z.w = 1.0f; } void device_projection_push(device_t device) diff --git a/libobs-d3d11/d3d11-subsystem.hpp b/libobs-d3d11/d3d11-subsystem.hpp index d6dea75db..f7f1e49b1 100644 --- a/libobs-d3d11/d3d11-subsystem.hpp +++ b/libobs-d3d11/d3d11-subsystem.hpp @@ -221,14 +221,16 @@ struct gs_texture { gs_texture_type type; gs_device *device; uint32_t levels; + gs_color_format format; ComPtr shaderRes; inline gs_texture(gs_device *device, gs_texture_type type, - uint32_t levels) + uint32_t levels, gs_color_format format) : device (device), type (type), - levels (levels) + levels (levels), + format (format) { } @@ -241,7 +243,6 @@ struct gs_texture_2d : gs_texture { ComPtr gdiSurface; uint32_t width, height; - gs_color_format format; DXGI_FORMAT dxgiFormat; bool isRenderTarget; bool isGDICompatible; @@ -250,16 +251,15 @@ struct gs_texture_2d : gs_texture { bool genMipmaps; HANDLE sharedHandle; - void InitSRD(vector &srd, void **data); - void InitTexture(void **data); + void InitSRD(vector &srd, const void **data); + void InitTexture(const void **data); void InitResourceView(); void InitRenderTargets(); inline gs_texture_2d() - : gs_texture (NULL, GS_TEXTURE_2D, 0), + : gs_texture (NULL, GS_TEXTURE_2D, 0, GS_UNKNOWN), width (0), height (0), - format (GS_UNKNOWN), dxgiFormat (DXGI_FORMAT_UNKNOWN), isRenderTarget (false), isGDICompatible (false), @@ -272,7 +272,7 @@ struct gs_texture_2d : gs_texture { gs_texture_2d(device_t device, uint32_t width, uint32_t height, gs_color_format colorFormat, uint32_t levels, - void **data, uint32_t flags, gs_texture_type type, + const void **data, uint32_t flags, gs_texture_type type, bool gdiCompatible, bool shared); }; diff --git a/libobs-d3d11/d3d11-texture2d.cpp b/libobs-d3d11/d3d11-texture2d.cpp index 2676676ca..9ef6c2b93 100644 --- a/libobs-d3d11/d3d11-texture2d.cpp +++ b/libobs-d3d11/d3d11-texture2d.cpp @@ -18,7 +18,8 @@ #include "util/base.h" #include "d3d11-subsystem.hpp" -void gs_texture_2d::InitSRD(vector &srd, void **data) +void gs_texture_2d::InitSRD(vector &srd, + const void **data) { uint32_t rowSizeBytes = width * gs_get_format_bpp(format); uint32_t texSizeBytes = height * rowSizeBytes / 8; @@ -48,7 +49,7 @@ void gs_texture_2d::InitSRD(vector &srd, void **data) } } -void gs_texture_2d::InitTexture(void **data) +void gs_texture_2d::InitTexture(const void **data) { vector srd; D3D11_TEXTURE2D_DESC td; @@ -131,13 +132,12 @@ void gs_texture_2d::InitRenderTargets() } gs_texture_2d::gs_texture_2d(device_t device, uint32_t width, uint32_t height, - gs_color_format colorFormat, uint32_t levels, void **data, + gs_color_format colorFormat, uint32_t levels, const void **data, uint32_t flags, gs_texture_type type, bool gdiCompatible, bool shared) - : gs_texture (device, type, levels), + : gs_texture (device, type, levels, colorFormat), width (width), height (height), - format (colorFormat), dxgiFormat (ConvertGSTextureFormat(format)), isGDICompatible (gdiCompatible), isShared (shared), diff --git a/libobs-opengl/gl-exports.h b/libobs-opengl/gl-exports.h index 4e7e41181..a8a6440a1 100644 --- a/libobs-opengl/gl-exports.h +++ b/libobs-opengl/gl-exports.h @@ -31,14 +31,14 @@ 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, - uint32_t levels, void **data, uint32_t flags); + uint32_t levels, const void **data, uint32_t flags); EXPORT 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); + const 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, uint32_t levels, void **data, - uint32_t flags); + enum gs_color_format color_format, uint32_t levels, + const 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, @@ -118,8 +118,6 @@ EXPORT void device_ortho(device_t device, float left, float right, float top, float bottom, float znear, float zfar); EXPORT void device_frustum(device_t device, float left, float right, float top, float bottom, float znear, float zfar); -EXPORT void device_perspective(device_t device, float fovy, float aspect, - float znear, float zfar); EXPORT void device_projection_push(device_t device); EXPORT void device_projection_pop(device_t device); diff --git a/libobs-opengl/gl-helpers.c b/libobs-opengl/gl-helpers.c index b8b1aec48..da97f0167 100644 --- a/libobs-opengl/gl-helpers.c +++ b/libobs-opengl/gl-helpers.c @@ -19,10 +19,11 @@ bool gl_init_face(GLenum target, 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) + uint32_t width, uint32_t height, uint32_t size, + const void ***p_data) { bool success = true; - void **data = p_data ? *p_data : NULL; + const void **data = p_data ? *p_data : NULL; uint32_t i; for (i = 0; i < num_levels; i++) { diff --git a/libobs-opengl/gl-helpers.h b/libobs-opengl/gl-helpers.h index 3dba0ec37..ed4a7c920 100644 --- a/libobs-opengl/gl-helpers.h +++ b/libobs-opengl/gl-helpers.h @@ -71,6 +71,24 @@ static inline void gl_delete_buffers(GLsizei num_buffers, GLuint *buffers) gl_success("glDeleteBuffers"); } +static inline bool gl_gen_vertex_arrays(GLsizei num_arrays, GLuint *arrays) +{ + glGenVertexArrays(num_arrays, arrays); + return gl_success("glGenVertexArrays"); +} + +static inline bool gl_bind_vertex_array(GLuint array) +{ + glBindVertexArray(array); + return gl_success("glBindVertexArray"); +} + +static inline void gl_delete_vertex_arrays(GLsizei num_arrays, GLuint *arrays) +{ + glDeleteVertexArrays(num_arrays, arrays); + gl_success("glDeleteVertexArrays"); +} + static inline bool gl_bind_renderbuffer(GLenum target, GLuint buffer) { glBindRenderbuffer(target, buffer); @@ -113,9 +131,16 @@ static inline bool gl_disable(GLenum capability) return gl_success("glDisable"); } +static inline bool gl_cull_face(GLenum faces) +{ + glCullFace(faces); + return gl_success("glCullFace"); +} + extern bool gl_init_face(GLenum target, 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); + uint32_t width, uint32_t height, uint32_t size, + const void ***p_data); extern bool gl_copy_texture(struct gs_device *device, GLuint dst, GLenum dst_target, diff --git a/libobs-opengl/gl-indexbuffer.c b/libobs-opengl/gl-indexbuffer.c index 6a3d8cc55..e0bfc91ce 100644 --- a/libobs-opengl/gl-indexbuffer.c +++ b/libobs-opengl/gl-indexbuffer.c @@ -19,7 +19,7 @@ static inline bool init_ib(struct gs_index_buffer *ib) { - GLenum usage = ib->dynamic ? GL_DYNAMIC_COPY : GL_STATIC_DRAW; + GLenum usage = ib->dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW; bool success; success = gl_create_buffer(GL_ARRAY_BUFFER, &ib->buffer, ib->size, diff --git a/libobs-opengl/gl-shader.c b/libobs-opengl/gl-shader.c index 0270bb5d0..98680bfee 100644 --- a/libobs-opengl/gl-shader.c +++ b/libobs-opengl/gl-shader.c @@ -81,12 +81,21 @@ static bool gl_add_param(struct gs_shader *shader, struct shader_var *var, param.param = glGetUniformLocation(shader->program, param.name); if (!gl_success("glGetUniformLocation")) - return false; + goto fail; - if (param.type == SHADER_PARAM_TEXTURE) - glUniform1i(param.param, param.texture_id); + if (param.type == SHADER_PARAM_TEXTURE) { + glProgramUniform1i(shader->program, param.param, + param.texture_id); + if (!gl_success("glProgramUniform1i")) + goto fail; + } + da_push_back(shader->params, ¶m); return true; + +fail: + shader_param_free(¶m); + return false; } static inline bool gl_add_params(struct gs_shader *shader, @@ -99,6 +108,9 @@ static inline bool gl_add_params(struct gs_shader *shader, if (!gl_add_param(shader, glsp->parser.params.array+i, &tex_id)) return false; + shader->viewproj = shader_getparambyname(shader, "ViewProj"); + shader->world = shader_getparambyname(shader, "World"); + return true; } @@ -151,7 +163,7 @@ static void get_attrib_type(const char *mapping, enum attrib_type *type, *index = 0; } -static inline bool gl_add_attrib(struct gs_shader *shader, +static inline bool gl_process_attrib(struct gs_shader *shader, struct gl_parser_attrib *pa) { struct shader_attrib attrib = {0}; @@ -161,26 +173,21 @@ static inline bool gl_add_attrib(struct gs_shader *shader, if (!gl_success("glGetAttribLocation")) return false; + /* If the attribute is not found, it's usually just an output */ if (attrib.attrib == -1) - return false; - - if (attrib.type == ATTRIB_TARGET) { - glBindFragDataLocation(shader->program, 0, pa->name.array); - if (!gl_success("glBindFragDataLocation")) - return false; - } + return true; da_push_back(shader->attribs, &attrib); return true; } -static inline bool gl_add_attribs(struct gs_shader *shader, +static inline bool gl_process_attribs(struct gs_shader *shader, struct gl_shader_parser *glsp) { size_t i; for (i = 0; i < glsp->attribs.num; i++) { struct gl_parser_attrib *pa = glsp->attribs.array+i; - if (!gl_add_attrib(shader, pa)) + if (!gl_process_attrib(shader, pa)) return false; } @@ -196,9 +203,8 @@ static bool gl_shader_init(struct gs_shader *shader, bool success = true; shader->program = glCreateShaderProgramv(type, 1, - &glsp->gl_string.array); - gl_success("glCreateShaderProgramv"); - if (!shader->program) + (const GLchar**)&glsp->gl_string.array); + if (!gl_success("glCreateShaderProgramv") || !shader->program) return false; blog(LOG_DEBUG, "+++++++++++++++++++++++++++++++++++"); @@ -218,8 +224,9 @@ static bool gl_shader_init(struct gs_shader *shader, if (success) success = gl_add_params(shader, glsp); - if (success) - success = gl_add_attribs(shader, glsp); + /* Only vertex shaders actually require input attributes */ + if (success && shader->type == SHADER_VERTEX) + success = gl_process_attribs(shader, glsp); if (success) gl_add_samplers(shader, glsp); @@ -237,7 +244,7 @@ static struct gs_shader *shader_create(device_t device, enum shader_type type, shader->device = device; shader->type = type; - gl_shader_parser_init(&glsp); + gl_shader_parser_init(&glsp, type); if (!gl_shader_parse(&glsp, shader_str, file)) success = false; else @@ -294,6 +301,7 @@ void shader_destroy(shader_t shader) da_free(shader->samplers); da_free(shader->params); + da_free(shader->attribs); bfree(shader); } @@ -362,7 +370,7 @@ void shader_setmatrix3(shader_t shader, sparam_t param, struct matrix4 mat; matrix4_from_matrix3(&mat, val); - glProgramUniformMatrix4fv(shader->program, param->param, 1, true, + glProgramUniformMatrix4fv(shader->program, param->param, 1, false, mat.x.ptr); gl_success("glProgramUniformMatrix4fv"); } @@ -370,7 +378,7 @@ void shader_setmatrix3(shader_t shader, sparam_t param, void shader_setmatrix4(shader_t shader, sparam_t param, const struct matrix4 *val) { - glProgramUniformMatrix4fv(shader->program, param->param, 1, true, + glProgramUniformMatrix4fv(shader->program, param->param, 1, false, val->x.ptr); gl_success("glProgramUniformMatrix4fv"); } @@ -432,6 +440,18 @@ static void shader_setval_data(shader_t shader, sparam_t param, } } +void shader_update_textures(struct gs_shader *shader) +{ + size_t i; + for (i = 0; i < shader->params.num; i++) { + struct shader_param *param = shader->params.array+i; + + if (param->type == SHADER_PARAM_TEXTURE) + device_load_texture(shader->device, param->texture, + param->texture_id); + } +} + void shader_setval(shader_t shader, sparam_t param, const void *val, size_t size) { @@ -448,6 +468,8 @@ void shader_setval(shader_t shader, sparam_t param, const void *val, case SHADER_PARAM_VEC3: expected_size = sizeof(float)*3; break; case SHADER_PARAM_VEC4: expected_size = sizeof(float)*4; break; case SHADER_PARAM_MATRIX4X4: expected_size = sizeof(float)*4*4; break; + case SHADER_PARAM_TEXTURE: expected_size = sizeof(void*); break; + default: expected_size = 0; } expected_size *= count; @@ -460,7 +482,10 @@ void shader_setval(shader_t shader, sparam_t param, const void *val, return; } - shader_setval_data(shader, param, val, count); + if (param->type == SHADER_PARAM_TEXTURE) + shader_settexture(shader, param, *(texture_t*)val); + else + shader_setval_data(shader, param, val, count); } void shader_setdefault(shader_t shader, sparam_t param) diff --git a/libobs-opengl/gl-shaderparser.c b/libobs-opengl/gl-shaderparser.c index 65d693762..7e05fdc8c 100644 --- a/libobs-opengl/gl-shaderparser.c +++ b/libobs-opengl/gl-shaderparser.c @@ -112,12 +112,11 @@ static inline void gl_write_params(struct gl_shader_parser *glsp) } static void gl_write_storage_var(struct gl_shader_parser *glsp, - struct shader_var *var, const char *storage, - const char *prefix); + struct shader_var *var, bool input, const char *prefix); /* unwraps a structure that's used for input/output */ static void gl_unwrap_storage_struct(struct gl_shader_parser *glsp, - struct shader_struct *st, const char *name, const char *storage, + struct shader_struct *st, const char *name, bool input, const char *prefix) { struct dstr prefix_str; @@ -131,27 +130,23 @@ static void gl_unwrap_storage_struct(struct gl_shader_parser *glsp, for (i = 0; i < st->vars.num; i++) { struct shader_var *st_var = st->vars.array+i; - gl_write_storage_var(glsp, st_var, storage, prefix_str.array); + gl_write_storage_var(glsp, st_var, input, prefix_str.array); } dstr_free(&prefix_str); } static void gl_write_storage_var(struct gl_shader_parser *glsp, - struct shader_var *var, const char *storage, const char *prefix) + struct shader_var *var, bool input, const char *prefix) { struct shader_struct *st = shader_parser_getstruct(&glsp->parser, var->type); if (st) { - gl_unwrap_storage_struct(glsp, st, var->name, storage, prefix); + gl_unwrap_storage_struct(glsp, st, var->name, input, prefix); } else { - struct gl_parser_attrib attrib = {0}; - - if (storage) { - dstr_cat(&glsp->gl_string, storage); - dstr_cat(&glsp->gl_string, " "); - } + struct gl_parser_attrib attrib = {{0}}; + dstr_cat(&glsp->gl_string, input ? "in " : "out "); if (prefix) dstr_cat(&attrib.name, prefix); @@ -162,6 +157,7 @@ static void gl_write_storage_var(struct gl_shader_parser *glsp, dstr_cat_dstr(&glsp->gl_string, &attrib.name); dstr_cat(&glsp->gl_string, ";\n"); + attrib.input = input; attrib.mapping = var->mapping; da_push_back(glsp->attribs, &attrib); } @@ -172,7 +168,7 @@ static inline void gl_write_inputs(struct gl_shader_parser *glsp, { size_t i; for (i = 0; i < main->params.num; i++) - gl_write_storage_var(glsp, main->params.array+i, "in", + gl_write_storage_var(glsp, main->params.array+i, true, "inputval_"); dstr_cat(&glsp->gl_string, "\n"); } @@ -186,7 +182,7 @@ static void gl_write_outputs(struct gl_shader_parser *glsp, if (main->mapping) var.mapping = main->mapping; - gl_write_storage_var(glsp, &var, "out", NULL); + gl_write_storage_var(glsp, &var, false, NULL); dstr_cat(&glsp->gl_string, "\n"); } @@ -209,6 +205,14 @@ static void gl_write_struct(struct gl_shader_parser *glsp, dstr_cat(&glsp->gl_string, "};\n\n"); } +static void gl_write_interface_block(struct gl_shader_parser *glsp) +{ + if (glsp->type == SHADER_VERTEX) { + dstr_cat(&glsp->gl_string, "out gl_PerVertex {\n" + "\tvec4 gl_Position;\n};\n\n"); + } +} + static inline void gl_write_structs(struct gl_shader_parser *glsp) { size_t i; @@ -245,7 +249,6 @@ static bool gl_write_mul(struct gl_shader_parser *glsp, struct cf_token **p_token) { struct cf_parser *cfp = &glsp->parser.cfp; - bool written = false; cfp->cur_token = *p_token; if (!next_token(cfp)) return false; @@ -266,7 +269,6 @@ static bool gl_write_saturate(struct gl_shader_parser *glsp, struct cf_token **p_token) { struct cf_parser *cfp = &glsp->parser.cfp; - bool written = false; cfp->cur_token = *p_token; if (!next_token(cfp)) return false; @@ -293,6 +295,9 @@ static inline bool gl_write_texture_call(struct gl_shader_parser *glsp, sampler_id = sp_getsampler(glsp, cfp->cur_token); if (sampler_id == -1) return false; + if (!next_token(cfp)) return false; + if (!token_is(cfp, ",")) return false; + var->gl_sampler_id = sampler_id; dstr_cat(&glsp->gl_string, call); @@ -417,7 +422,7 @@ static void gl_write_function(struct gl_shader_parser *glsp, dstr_cat(&glsp->gl_string, " "); if (strcmp(func->name, "main") == 0) - dstr_cat(&glsp->gl_string, "obs_main_x"); + dstr_cat(&glsp->gl_string, "_main_wrap"); else dstr_cat(&glsp->gl_string, func->name); @@ -447,7 +452,21 @@ static inline void gl_write_functions(struct gl_shader_parser *glsp) } } -static void gl_write_main_storage_var(struct gl_shader_parser *glsp, +static inline void gl_write_main_interface_assign( + struct gl_shader_parser *glsp, struct shader_var *var, + const char *src) +{ + /* vertex shaders: write gl_Position */ + if (glsp->type == SHADER_VERTEX && + strcmp(var->mapping, "POSITION") == 0) { + dstr_cat(&glsp->gl_string, "\tgl_Position = "); + dstr_cat(&glsp->gl_string, src); + dstr_cat(&glsp->gl_string, var->name); + dstr_cat(&glsp->gl_string, ";\n"); + } +} + +static void gl_write_main_storage_assign(struct gl_shader_parser *glsp, struct shader_var *var, const char *dst, const char *src, bool input) { @@ -477,7 +496,7 @@ static void gl_write_main_storage_var(struct gl_shader_parser *glsp, for (i = 0; i < st->vars.num; i++) { struct shader_var *var = st->vars.array+i; - gl_write_main_storage_var(glsp, var, dst_copy.array, + gl_write_main_storage_assign(glsp, var, dst_copy.array, src_copy.array, input); } @@ -490,81 +509,127 @@ static void gl_write_main_storage_var(struct gl_shader_parser *glsp, dstr_cat(&glsp->gl_string, src); dstr_cat(&glsp->gl_string, var->name); dstr_cat(&glsp->gl_string, ";\n"); + + if (!input) + gl_write_main_interface_assign(glsp, var, src); } dstr_free(&dst_copy); } -static void gl_write_main_storage_output(struct gl_shader_parser *glsp, - bool input, const char *type) +static inline void gl_write_main_storage_inputs(struct gl_shader_parser *glsp, + struct shader_func *main) { - struct shader_var var = {0}; + gl_write_main_storage_assign(glsp, main->params.array, NULL, + "inputval_", true); +} - if (input) { - var.name = "inputval"; - var.type = (char*)type; - gl_write_main_storage_var(glsp, &var, NULL, NULL, true); - } else { +static inline void gl_write_main_storage_outputs(struct gl_shader_parser *glsp, + struct shader_func *main) +{ + /* we only do this *if* we're writing a struct, because otherwise + * the call to 'main' already does the assignment for us */ + if (!main->mapping) { + struct shader_var var = {0}; var.name = "outputval"; - var.type = (char*)type; - gl_write_main_storage_var(glsp, &var, NULL, NULL, false); + var.type = (char*)main->return_type; + dstr_cat(&glsp->gl_string, "\n"); + gl_write_main_storage_assign(glsp, &var, NULL, NULL, false); } } +static inline void gl_write_main_vars(struct gl_shader_parser *glsp, + struct shader_func *main_func) +{ + size_t i; + for (i = 0; i < main_func->params.num; i++) { + dstr_cat(&glsp->gl_string, "\t"); + dstr_cat(&glsp->gl_string, main_func->params.array[i].type); + dstr_cat(&glsp->gl_string, " "); + dstr_cat(&glsp->gl_string, main_func->params.array[i].name); + dstr_cat(&glsp->gl_string, ";\n"); + } + + if (!main_func->mapping) { + dstr_cat(&glsp->gl_string, "\t"); + dstr_cat(&glsp->gl_string, main_func->return_type); + dstr_cat(&glsp->gl_string, " outputval;\n\n"); + } +} + +static inline void gl_write_main_func_call(struct gl_shader_parser *glsp, + struct shader_func *main_func) +{ + size_t i; + dstr_cat(&glsp->gl_string, "\n\toutputval = _main_wrap("); + + for (i = 0; i < main_func->params.num; i++) { + if (i) + dstr_cat(&glsp->gl_string, ", "); + dstr_cat(&glsp->gl_string, main_func->params.array[i].name); + } + + dstr_cat(&glsp->gl_string, ");\n"); +} + static void gl_write_main(struct gl_shader_parser *glsp, struct shader_func *main) { - size_t i; dstr_cat(&glsp->gl_string, "void main(void)\n{\n"); - for (i = 0; i < main->params.num; i++) { - dstr_cat(&glsp->gl_string, "\t"); - dstr_cat(&glsp->gl_string, main->params.array[i].type); - dstr_cat(&glsp->gl_string, " "); - dstr_cat(&glsp->gl_string, main->params.array[i].name); - dstr_cat(&glsp->gl_string, ";\n"); - } - if (!main->mapping) { - dstr_cat(&glsp->gl_string, "\t"); - dstr_cat(&glsp->gl_string, main->return_type); - dstr_cat(&glsp->gl_string, " outputval;\n\n"); - } - - /* gl_write_main_storage(glsp, true, main->params.array[0].type); */ - gl_write_main_storage_var(glsp, main->params.array, NULL, - "inputval_", true); - - dstr_cat(&glsp->gl_string, "\n\toutputval = obs_main_x("); - for (i = 0; i < main->params.num; i++) { - if (i) - dstr_cat(&glsp->gl_string, ", "); - dstr_cat(&glsp->gl_string, main->params.array[i].name); - } - dstr_cat(&glsp->gl_string, ");\n"); - - if (!main->mapping) { - dstr_cat(&glsp->gl_string, "\n"); - gl_write_main_storage_output(glsp, false, main->return_type); - } + gl_write_main_vars(glsp, main); + gl_write_main_storage_inputs(glsp, main); + gl_write_main_func_call(glsp, main); + gl_write_main_storage_outputs(glsp, main); dstr_cat(&glsp->gl_string, "}\n"); } +/* ugh, don't ask. I'll probably get rid of the need for this function later */ +static void gl_rename_attributes(struct gl_shader_parser *glsp) +{ + size_t i = 0, input_idx = 0, output_idx = 0; + + for (i = 0; i < glsp->attribs.num; i++) { + struct gl_parser_attrib *attrib = glsp->attribs.array+i; + struct dstr new_name = {0}; + const char *prefix; + size_t val; + + if (attrib->input) { + prefix = glsp->input_prefix; + val = input_idx++; + } else { + prefix = glsp->output_prefix; + val = output_idx++; + } + + dstr_printf(&new_name, "%s%u", prefix, val); + dstr_replace(&glsp->gl_string, attrib->name.array, + new_name.array); + dstr_move(&attrib->name, &new_name); + } +} + static bool gl_shader_buildstring(struct gl_shader_parser *glsp) { - struct shader_func *main = shader_parser_getfunc(&glsp->parser, "main"); - if (!main) { + struct shader_func *main_func; + + main_func = shader_parser_getfunc(&glsp->parser, "main"); + if (!main_func) { blog(LOG_ERROR, "function 'main' not found"); return false; } - dstr_copy(&glsp->gl_string, "#version 140\n\n"); + dstr_copy(&glsp->gl_string, "#version 150\n\n"); gl_write_params(glsp); - gl_write_inputs(glsp, main); - gl_write_outputs(glsp, main); + gl_write_inputs(glsp, main_func); + gl_write_outputs(glsp, main_func); + gl_write_interface_block(glsp); gl_write_structs(glsp); gl_write_functions(glsp); - gl_write_main(glsp, main); + gl_write_main(glsp, main_func); + gl_rename_attributes(glsp); return true; } diff --git a/libobs-opengl/gl-shaderparser.h b/libobs-opengl/gl-shaderparser.h index 1a75b4adf..dc40c8361 100644 --- a/libobs-opengl/gl-shaderparser.h +++ b/libobs-opengl/gl-shaderparser.h @@ -29,14 +29,18 @@ struct gl_parser_attrib { struct dstr name; const char *mapping; + bool input; }; -static inline gl_parser_attrib_free(struct gl_parser_attrib *attr) +static inline void gl_parser_attrib_free(struct gl_parser_attrib *attr) { dstr_free(&attr->name); } struct gl_shader_parser { + enum shader_type type; + const char *input_prefix; + const char *output_prefix; struct shader_parser parser; struct dstr gl_string; @@ -44,8 +48,19 @@ struct gl_shader_parser { DARRAY(struct gl_parser_attrib) attribs; }; -static inline void gl_shader_parser_init(struct gl_shader_parser *glsp) +static inline void gl_shader_parser_init(struct gl_shader_parser *glsp, + enum shader_type type) { + glsp->type = type; + + if (type == SHADER_VERTEX) { + glsp->input_prefix = "_geom_shader_attrib"; + glsp->output_prefix = "_vertex_shader_attrib"; + } else if (type == SHADER_PIXEL) { + glsp->input_prefix = "_vertex_shader_attrib"; + glsp->output_prefix = "_pixel_shader_attrib"; + } + shader_parser_init(&glsp->parser); dstr_init(&glsp->gl_string); da_init(glsp->texture_samplers); diff --git a/libobs-opengl/gl-stagesurf.c b/libobs-opengl/gl-stagesurf.c index 379c3824e..80897ea9e 100644 --- a/libobs-opengl/gl-stagesurf.c +++ b/libobs-opengl/gl-stagesurf.c @@ -104,18 +104,29 @@ void stagesurface_destroy(stagesurf_t stagesurf) static bool can_stage(struct gs_stage_surface *dst, struct gs_texture_2d *src) { + if (!src) { + blog(LOG_ERROR, "Source texture is NULL"); + return false; + } + if (src->base.type != GS_TEXTURE_2D) { blog(LOG_ERROR, "Source texture must be a 2D texture"); return false; } - if (src->width != dst->width || src->height != dst->height) { - blog(LOG_ERROR, "Source and destination sizes do not match"); + if (!dst) { + blog(LOG_ERROR, "Destination surface is NULL"); return false; } if (src->base.format != dst->format) { - blog(LOG_ERROR, "Source and destination format do not match"); + blog(LOG_ERROR, "Source and destination formats do not match"); + return false; + } + + if (src->width != dst->width || src->height != dst->height) { + blog(LOG_ERROR, "Source and destination must have the same " + "dimensions"); return false; } diff --git a/libobs-opengl/gl-subsystem.c b/libobs-opengl/gl-subsystem.c index 723db05ec..2fec2e9f5 100644 --- a/libobs-opengl/gl-subsystem.c +++ b/libobs-opengl/gl-subsystem.c @@ -64,7 +64,11 @@ device_t device_create(struct gs_init_data *info) blog(LOG_DEBUG, "OpenGL debug information not available"); #endif + gl_enable(GL_CULL_FACE); + device_leavecontext(device); + device->cur_swap = gl_platform_getswap(device->plat); + return device; fail: @@ -132,8 +136,8 @@ uint32_t device_getheight(device_t device) 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) + enum gs_color_format color_format, uint32_t levels, + const void **data, uint32_t flags) { /* TODO */ return NULL; @@ -220,9 +224,14 @@ void device_load_texture(device_t device, texture_t tex, int unit) if (cur_tex == tex) return; + + if (!gl_active_texture(GL_TEXTURE0 + unit)) + goto fail; + if (cur_tex && cur_tex->gl_target != tex->gl_target) gl_bind_texture(cur_tex->gl_target, 0); + device->cur_textures[unit] = tex; param = get_texture_param(device, unit); if (!param) @@ -235,8 +244,6 @@ void device_load_texture(device_t device, texture_t tex, int unit) sampler = device->cur_samplers[param->sampler_id]; - if (!gl_active_texture(GL_TEXTURE0 + unit)) - goto fail; if (!gl_bind_texture(tex->gl_target, tex->texture)) goto fail; if (sampler && !load_texture_sampler(tex, sampler)) @@ -298,7 +305,7 @@ void device_load_vertexshader(device_t device, shader_t vertshader) if (device->cur_vertex_shader == vertshader) return; - if (vertshader->type != SHADER_VERTEX) { + if (vertshader && vertshader->type != SHADER_VERTEX) { blog(LOG_ERROR, "Specified shader is not a vertex shader"); goto fail; } @@ -313,7 +320,7 @@ void device_load_vertexshader(device_t device, shader_t vertshader) if (vertshader) program = vertshader->program; - glUseProgramStages(device->pipeline, GL_VERTEX_SHADER, program); + glUseProgramStages(device->pipeline, GL_VERTEX_SHADER_BIT, program); if (!gl_success("glUseProgramStages")) goto fail; @@ -326,13 +333,29 @@ fail: blog(LOG_ERROR, "device_load_vertexshader (GL) failed"); } +static void load_default_pixelshader_samplers(struct gs_device *device, + struct gs_shader *ps) +{ + size_t i; + if (!ps) + return; + + for (i = 0; i < ps->samplers.num; i++) { + struct gs_sampler_state *ss = ps->samplers.array[i]; + device->cur_samplers[i] = ss; + } + + for (; i < GS_MAX_TEXTURES; i++) + device->cur_samplers[i] = NULL; +} + void device_load_pixelshader(device_t device, shader_t pixelshader) { GLuint program = 0; if (device->cur_pixel_shader == pixelshader) return; - if (pixelshader->type != SHADER_PIXEL) { + if (pixelshader && pixelshader->type != SHADER_PIXEL) { blog(LOG_ERROR, "Specified shader is not a pixel shader"); goto fail; } @@ -342,12 +365,14 @@ void device_load_pixelshader(device_t device, shader_t pixelshader) if (pixelshader) program = pixelshader->program; - glUseProgramStages(device->pipeline, GL_FRAGMENT_SHADER, - pixelshader->program); + glUseProgramStages(device->pipeline, GL_FRAGMENT_SHADER_BIT, program); if (!gl_success("glUseProgramStages")) goto fail; clear_textures(device); + + if (pixelshader) + load_default_pixelshader_samplers(device, pixelshader); return; fail: @@ -529,14 +554,16 @@ static bool set_target(device_t device, texture_t tex, int side, zstencil_t zs) void device_setrendertarget(device_t device, texture_t tex, zstencil_t zstencil) { - if (tex->type != GS_TEXTURE_2D) { - blog(LOG_ERROR, "Texture is not a 2D texture"); - goto fail; - } + if (tex) { + if (tex->type != GS_TEXTURE_2D) { + blog(LOG_ERROR, "Texture is not a 2D texture"); + goto fail; + } - if (!tex->is_render_target) { - blog(LOG_ERROR, "Texture is not a render target"); - goto fail; + if (!tex->is_render_target) { + blog(LOG_ERROR, "Texture is not a render target"); + goto fail; + } } if (!set_target(device, tex, 0, zstencil)) @@ -551,14 +578,16 @@ fail: void device_setcuberendertarget(device_t device, texture_t cubetex, int side, zstencil_t zstencil) { - if (cubetex->type != GS_TEXTURE_CUBE) { - blog(LOG_ERROR, "Texture is not a cube texture"); - goto fail; - } + if (cubetex) { + if (cubetex->type != GS_TEXTURE_CUBE) { + blog(LOG_ERROR, "Texture is not a cube texture"); + goto fail; + } - if (!cubetex->is_render_target) { - blog(LOG_ERROR, "Texture is not a render target"); - goto fail; + if (!cubetex->is_render_target) { + blog(LOG_ERROR, "Texture is not a render target"); + goto fail; + } } if (!set_target(device, cubetex, side, zstencil)) @@ -575,9 +604,13 @@ void device_copy_texture(device_t device, texture_t dst, texture_t src) struct gs_texture_2d *src2d = (struct gs_texture_2d*)src; struct gs_texture_2d *dst2d = (struct gs_texture_2d*)dst; - if (dst->format != src->format) { - blog(LOG_ERROR, "Source and destination texture formats do " - "not match"); + if (!src) { + blog(LOG_ERROR, "Source texture is NULL"); + goto fail; + } + + if (!dst) { + blog(LOG_ERROR, "Destination texture is NULL"); goto fail; } @@ -587,8 +620,13 @@ void device_copy_texture(device_t device, texture_t dst, texture_t src) goto fail; } + if (dst->format != src->format) { + blog(LOG_ERROR, "Source and destination formats do not match"); + goto fail; + } + if (dst2d->width != src2d->width || dst2d->height != src2d->height) { - blog(LOG_ERROR, "Source and destination textures must have " + blog(LOG_ERROR, "Source and destination must have " "the same dimensions"); goto fail; } @@ -644,24 +682,58 @@ static void update_viewproj_matrix(struct gs_device *device) shader_setmatrix4(vs, vs->viewproj, &device->cur_viewproj); } +static inline bool check_shader_pipeline_validity(device_t device) +{ + int valid = false; + + glValidateProgramPipeline(device->pipeline); + if (!gl_success("glValidateProgramPipeline")) + return false; + + glGetProgramPipelineiv(device->pipeline, GL_VALIDATE_STATUS, &valid); + if (!gl_success("glGetProgramPipelineiv")) + return false; + + if (!valid) + blog(LOG_ERROR, "Shader pipeline appears to be invalid"); + + return valid != 0; +} + void device_draw(device_t device, enum gs_draw_mode draw_mode, uint32_t start_vert, uint32_t num_verts) { struct gs_index_buffer *ib = device->cur_index_buffer; GLenum topology = convert_gs_topology(draw_mode); + effect_t effect = gs_geteffect(); if (!can_render(device)) goto fail; + if (effect) + effect_updateparams(effect); + + shader_update_textures(device->cur_pixel_shader); + update_viewproj_matrix(device); + +#ifdef _DEBUG + if (!check_shader_pipeline_validity(device)) + goto fail; +#endif + if (ib) { + if (num_verts == 0) + num_verts = (uint32_t)device->cur_index_buffer->num; glDrawElements(topology, num_verts, ib->gl_type, (const GLvoid*)(start_vert * ib->width)); if (!gl_success("glDrawElements")) goto fail; } else { + if (num_verts == 0) + num_verts = (uint32_t)device->cur_vertex_buffer->num; glDrawArrays(topology, start_vert, num_verts); if (!gl_success("glDrawArrays")) goto fail; @@ -684,7 +756,7 @@ void device_clear(device_t device, uint32_t clear_flags, GLbitfield gl_flags = 0; if (clear_flags & GS_CLEAR_COLOR) { - glClearColor(color->x, color->y, color->x, color->w); + glClearColor(color->x, color->y, color->z, color->w); gl_flags |= GL_COLOR_BUFFER_BIT; } @@ -698,7 +770,7 @@ void device_clear(device_t device, uint32_t clear_flags, gl_flags |= GL_STENCIL_BUFFER_BIT; } - glClear(clear_flags); + glClear(gl_flags); if (!gl_success("glClear")) blog(LOG_ERROR, "device_clear (GL) failed"); } @@ -712,10 +784,11 @@ void device_setcullmode(device_t device, enum gs_cull_mode mode) gl_enable(GL_CULL_FACE); device->cur_cull_mode = mode; + if (mode == GS_BACK) - glCullFace(GL_BACK); + gl_cull_face(GL_BACK); else if (mode == GS_FRONT) - glCullFace(GL_FRONT); + gl_cull_face(GL_FRONT); else gl_disable(GL_CULL_FACE); } @@ -837,10 +910,31 @@ void device_setcolorramp(device_t device, float gamma, float brightness, /* TODO */ } +static inline uint32_t get_target_height(struct gs_device *device) +{ + if (!device->cur_render_target) + return device_getheight(device); + + if (device->cur_render_target->type == GS_TEXTURE_2D) + return texture_getheight(device->cur_render_target); + else /* cube map */ + return cubetexture_getsize(device->cur_render_target); +} + void device_setviewport(device_t device, int x, int y, int width, int height) { - glViewport(x, y, width, height); + uint32_t base_height; + + /* GL uses bottom-up coordinates for viewports. We want top-down */ + if (device->cur_render_target) { + base_height = get_target_height(device); + } else { + uint32_t dw; + gl_getclientsize(device->cur_swap, &dw, &base_height); + } + + glViewport(x, base_height - y - height, width, height); if (!gl_success("glViewport")) blog(LOG_ERROR, "device_setviewport (GL) failed"); @@ -863,22 +957,56 @@ void device_setscissorrect(device_t device, struct gs_rect *rect) } void device_ortho(device_t device, float left, float right, - float top, float bottom, float znear, float zfar) + float top, float bottom, float near, float far) { - matrix4_ortho(&device->cur_proj, left, right, top, bottom, znear, zfar); + struct matrix4 *dst = &device->cur_proj; + + float rml = right-left; + float bmt = bottom-top; + float fmn = far-near; + + vec4_zero(&dst->x); + vec4_zero(&dst->y); + vec4_zero(&dst->z); + vec4_zero(&dst->t); + + dst->x.x = 2.0f / rml; + dst->t.x = (left+right) / -rml; + + dst->y.y = 2.0f / -bmt; + dst->t.y = (bottom+top) / bmt; + + dst->z.z = -2.0f / fmn; + dst->t.z = (far+near) / -fmn; + + dst->t.w = 1.0f; } void device_frustum(device_t device, float left, float right, - float top, float bottom, float znear, float zfar) + float top, float bottom, float near, float far) { - matrix4_frustum(&device->cur_proj, left, right, top, bottom, - znear, zfar); -} + struct matrix4 *dst = &device->cur_proj; -void device_perspective(device_t device, float fovy, float aspect, - float znear, float zfar) -{ - matrix4_perspective(&device->cur_proj, fovy, aspect, znear, zfar); + float rml = right-left; + float tmb = top-bottom; + float nmf = near-far; + float nearx2 = 2.0f*near; + + vec4_zero(&dst->x); + vec4_zero(&dst->y); + vec4_zero(&dst->z); + vec4_zero(&dst->t); + + dst->x.x = nearx2 / rml; + dst->z.x = (left+right) / rml; + + dst->y.y = nearx2 / tmb; + dst->z.y = (bottom+top) / tmb; + + dst->z.z = (far+near) / nmf; + dst->t.z = 2.0f * (near*far) / nmf; + + dst->z.w = -1.0f; } void device_projection_push(device_t device) diff --git a/libobs-opengl/gl-subsystem.h b/libobs-opengl/gl-subsystem.h index a60da0f34..2aaab8128 100644 --- a/libobs-opengl/gl-subsystem.h +++ b/libobs-opengl/gl-subsystem.h @@ -81,7 +81,7 @@ static inline GLint convert_gs_internal_format(enum gs_color_format format) } } -static inline GLenum get_gl_format_type(enum color_format format) +static inline GLenum get_gl_format_type(enum gs_color_format format) { switch (format) { case GS_A8: return GL_UNSIGNED_BYTE; @@ -185,10 +185,6 @@ static inline void convert_filter(enum gs_sample_filter filter, GLint *min_filter, GLint *mag_filter) { switch (filter) { - case GS_FILTER_ANISOTROPIC: - *min_filter = GL_LINEAR_MIPMAP_LINEAR; - *mag_filter = GL_LINEAR; - break; default: case GS_FILTER_POINT: *min_filter = GL_NEAREST_MIPMAP_NEAREST; @@ -222,6 +218,10 @@ static inline void convert_filter(enum gs_sample_filter filter, *min_filter = GL_LINEAR_MIPMAP_NEAREST; *mag_filter = GL_LINEAR; break; + case GS_FILTER_ANISOTROPIC: + *min_filter = GL_LINEAR_MIPMAP_LINEAR; + *mag_filter = GL_LINEAR; + break; } } @@ -230,7 +230,7 @@ static inline GLint convert_address_mode(enum gs_address_mode mode) switch (mode) { default: case GS_ADDRESS_WRAP: return GL_REPEAT; - case GS_ADDRESS_CLAMP: return GL_CLAMP; + case GS_ADDRESS_CLAMP: return GL_CLAMP_TO_EDGE; case GS_ADDRESS_MIRROR: return GL_MIRRORED_REPEAT; case GS_ADDRESS_BORDER: return GL_CLAMP_TO_BORDER; case GS_ADDRESS_MIRRORONCE: return GL_MIRROR_CLAMP_EXT; @@ -319,6 +319,8 @@ struct gs_shader { DARRAY(samplerstate_t) samplers; }; +extern void shader_update_textures(struct gs_shader *shader); + struct gs_vertex_buffer { GLuint vertex_buffer; GLuint normal_buffer; @@ -328,6 +330,7 @@ struct gs_vertex_buffer { DARRAY(size_t) uv_sizes; device_t device; + size_t num; bool dynamic; struct vb_data *data; }; @@ -418,8 +421,12 @@ struct fbo_info { static inline void fbo_info_destroy(struct fbo_info *fbo) { - glDeleteFramebuffers(1, &fbo->fbo); - gl_success("glDeleteFramebuffers"); + if (fbo) { + glDeleteFramebuffers(1, &fbo->fbo); + gl_success("glDeleteFramebuffers"); + + bfree(fbo); + } } struct gs_device { @@ -458,3 +465,7 @@ extern void gl_platform_destroy(struct gl_platform *platform); extern struct gl_windowinfo *gl_windowinfo_create(struct gs_init_data *info); extern void gl_windowinfo_destroy(struct gl_windowinfo *wi); + +extern void gl_getclientsize(struct gs_swap_chain *swap, + uint32_t *width, + uint32_t *height); diff --git a/libobs-opengl/gl-texture2d.c b/libobs-opengl/gl-texture2d.c index 10fe1e516..4c7544b40 100644 --- a/libobs-opengl/gl-texture2d.c +++ b/libobs-opengl/gl-texture2d.c @@ -17,7 +17,7 @@ #include "gl-subsystem.h" -static bool upload_texture_2d(struct gs_texture_2d *tex, void **data) +static bool upload_texture_2d(struct gs_texture_2d *tex, const void **data) { uint32_t row_size = tex->width * gs_get_format_bpp(tex->base.format); uint32_t tex_size = tex->height * row_size / 8; @@ -35,6 +35,8 @@ static bool upload_texture_2d(struct gs_texture_2d *tex, void **data) tex->base.gl_format, tex->base.gl_internal_format, compressed, tex->width, tex->height, tex_size, &data); + if (!gl_tex_param_i(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels-1)) + success = false; if (!gl_bind_texture(GL_TEXTURE_2D, 0)) success = false; @@ -74,7 +76,7 @@ static bool create_pixel_unpack_buffer(struct gs_texture_2d *tex) 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) + uint32_t levels, const void **data, uint32_t flags) { struct gs_texture_2d *tex = bmalloc(sizeof(struct gs_texture_2d)); memset(tex, 0, sizeof(struct gs_texture_2d)); @@ -87,9 +89,9 @@ texture_t device_create_texture(device_t device, uint32_t width, tex->base.gl_internal_format = convert_gs_internal_format(color_format); tex->base.gl_type = get_gl_format_type(color_format); tex->base.gl_target = GL_TEXTURE_2D; - tex->base.is_dynamic = flags & GS_DYNAMIC; - tex->base.is_render_target = flags & GS_RENDERTARGET; - tex->base.gen_mipmaps = flags & GS_BUILDMIPMAPS; + tex->base.is_dynamic = (flags & GS_DYNAMIC) != 0; + tex->base.is_render_target = (flags & GS_RENDERTARGET) != 0; + tex->base.gen_mipmaps = (flags & GS_BUILDMIPMAPS) != 0; tex->width = width; tex->height = height; @@ -125,6 +127,9 @@ void texture_destroy(texture_t tex) if (!is_texture_2d(tex, "texture_destroy")) return; + if (tex->cur_sampler) + samplerstate_destroy(tex->cur_sampler); + if (tex->is_dynamic && tex2d->unpack_buffer) gl_delete_buffers(1, &tex2d->unpack_buffer); diff --git a/libobs-opengl/gl-texturecube.c b/libobs-opengl/gl-texturecube.c index 7c9968a44..3469e9944 100644 --- a/libobs-opengl/gl-texturecube.c +++ b/libobs-opengl/gl-texturecube.c @@ -17,7 +17,8 @@ #include "gl-subsystem.h" -static inline bool upload_texture_cube(struct gs_texture_cube *tex, void **data) +static inline bool upload_texture_cube(struct gs_texture_cube *tex, + const void **data) { uint32_t row_size = tex->size * gs_get_format_bpp(tex->base.format); uint32_t tex_size = tex->size * row_size / 8; @@ -50,12 +51,16 @@ static inline bool upload_texture_cube(struct gs_texture_cube *tex, void **data) data++; } + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, num_levels); + if (!gl_success("glTexParameteri")) + success = false; + 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) + const void **data, uint32_t flags) { struct gs_texture_cube *tex = bmalloc(sizeof(struct gs_texture_cube)); memset(tex, 0, sizeof(struct gs_texture_2d)); @@ -67,8 +72,8 @@ texture_t device_create_cubetexture(device_t device, uint32_t size, tex->base.gl_format = convert_gs_format(color_format); tex->base.gl_internal_format = convert_gs_internal_format(color_format); tex->base.gl_target = GL_TEXTURE_CUBE_MAP; - tex->base.is_render_target = flags & GS_RENDERTARGET; - tex->base.gen_mipmaps = flags & GS_BUILDMIPMAPS; + tex->base.is_render_target = (flags & GS_RENDERTARGET) != 0; + tex->base.gen_mipmaps = (flags & GS_BUILDMIPMAPS) != 0; tex->size = size; if (!gl_gen_textures(1, &tex->base.texture)) diff --git a/libobs-opengl/gl-vertexbuffer.c b/libobs-opengl/gl-vertexbuffer.c index 2a60b4f6d..1fafacd24 100644 --- a/libobs-opengl/gl-vertexbuffer.c +++ b/libobs-opengl/gl-vertexbuffer.c @@ -18,9 +18,9 @@ #include "graphics/vec3.h" #include "gl-subsystem.h" -static bool init_vb(struct gs_vertex_buffer *vb) +static bool create_buffers(struct gs_vertex_buffer *vb) { - GLenum usage = vb->dynamic ? GL_DYNAMIC_COPY : GL_STATIC_DRAW; + GLenum usage = vb->dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW; size_t i; if (!gl_create_buffer(GL_ARRAY_BUFFER, &vb->vertex_buffer, @@ -81,9 +81,10 @@ vertbuffer_t device_create_vertexbuffer(device_t device, vb->device = device; vb->data = data; + vb->num = data->num; vb->dynamic = flags & GS_DYNAMIC; - if (!init_vb(vb)) { + if (!create_buffers(vb)) { blog(LOG_ERROR, "device_create_vertexbuffer (GL) failed"); vertexbuffer_destroy(vb); return NULL; @@ -97,16 +98,12 @@ void vertexbuffer_destroy(vertbuffer_t vb) if (vb) { if (vb->vertex_buffer) gl_delete_buffers(1, &vb->vertex_buffer); - if (vb->normal_buffer) gl_delete_buffers(1, &vb->normal_buffer); - if (vb->tangent_buffer) gl_delete_buffers(1, &vb->tangent_buffer); - if (vb->color_buffer) gl_delete_buffers(1, &vb->color_buffer); - if (vb->uv_buffers.num) gl_delete_buffers((GLsizei)vb->uv_buffers.num, vb->uv_buffers.array); @@ -220,11 +217,14 @@ static bool load_vb_buffer(struct gs_shader *shader, if (!gl_bind_buffer(GL_ARRAY_BUFFER, buffer)) return false; - glVertexAttribPointer(attrib->attrib, width, type, GL_TRUE, 0, 0); + glVertexAttribPointer(attrib->attrib, width, type, GL_FALSE, 0, 0); if (!gl_success("glVertexAttribPointer")) success = false; - gl_bind_buffer(GL_ARRAY_BUFFER, 0); + glEnableVertexAttribArray(attrib->attrib); + if (!gl_success("glEnableVertexAttribArray")) + success = false; + return success; } @@ -247,8 +247,10 @@ bool vertexbuffer_load(device_t device, vertbuffer_t vb) return true; device->cur_vertex_buffer = vb; - if (!device->cur_vertex_shader || !vb) + if (!device->cur_vertex_shader || !vb) { + gl_bind_vertex_array(0); return true; + } if (!load_vb_buffers(device->cur_vertex_shader, vb)) return false; @@ -258,6 +260,6 @@ bool vertexbuffer_load(device_t device, vertbuffer_t vb) void device_load_vertexbuffer(device_t device, vertbuffer_t vb) { - if (vertexbuffer_load(device, vb)) + if (!vertexbuffer_load(device, vb)) blog(LOG_ERROR, "device_load_vertexbuffer (GL) failed"); } diff --git a/libobs-opengl/gl-windows.c b/libobs-opengl/gl-windows.c index d76498d09..3aaf80ff3 100644 --- a/libobs-opengl/gl-windows.c +++ b/libobs-opengl/gl-windows.c @@ -72,7 +72,7 @@ static inline int get_stencil_format_bits(enum gs_zstencil_format zsformat) /* would use designated initializers but microsoft sort of sucks */ static inline void init_dummy_pixel_format(PIXELFORMATDESCRIPTOR *pfd) { - memset(pfd, 0, sizeof(pfd)); + memset(pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); pfd->nSize = sizeof(pfd); pfd->nVersion = 1; pfd->iPixelType = PFD_TYPE_RGBA; @@ -137,7 +137,7 @@ static inline bool wgl_make_current(HDC hdc, HGLRC hglrc) return success; } -static inline HGLRC gl_init_context(HDC hdc) +static inline HGLRC gl_init_basic_context(HDC hdc) { HGLRC hglrc = wglCreateContext(hdc); if (!hglrc) { @@ -153,6 +153,39 @@ static inline HGLRC gl_init_context(HDC hdc) return hglrc; } +static const int attribs[] = +{ + WGL_CONTEXT_MAJOR_VERSION_ARB, 3, + WGL_CONTEXT_MINOR_VERSION_ARB, 2, + WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB | + WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, + 0, 0 +}; + +static inline HGLRC gl_init_context(HDC hdc) +{ +#ifdef _DEBUG + if (WGLEW_ARB_create_context) { + HGLRC hglrc = wglCreateContextAttribsARB(hdc, 0, attribs); + if (!hglrc) { + blog(LOG_ERROR, "wglCreateContextAttribsARB failed, %u", + GetLastError()); + return NULL; + } + + if (!wgl_make_current(hdc, hglrc)) { + wglDeleteContext(hglrc); + return NULL; + } + + return hglrc; + } +#endif + + return gl_init_basic_context(hdc); +} + static bool gl_dummy_context_init(struct dummy_context *dummy) { PIXELFORMATDESCRIPTOR pfd; @@ -181,7 +214,7 @@ static bool gl_dummy_context_init(struct dummy_context *dummy) return false; } - dummy->hrc = gl_init_context(dummy->hdc); + dummy->hrc = gl_init_basic_context(dummy->hdc); if (!dummy->hrc) { blog(LOG_ERROR, "Failed to initialize dummy context"); return false; @@ -284,7 +317,7 @@ static int gl_choose_pixel_format(HDC hdc, struct gs_init_data *info) return format; } -static inline bool gl_get_pixel_format(HDC hdc, struct gs_init_data *info, +static inline bool gl_getpixelformat(HDC hdc, struct gs_init_data *info, int *format, PIXELFORMATDESCRIPTOR *pfd) { *format = gl_choose_pixel_format(hdc, info); @@ -301,7 +334,7 @@ static inline bool gl_get_pixel_format(HDC hdc, struct gs_init_data *info, return true; } -static inline bool gl_set_pixel_format(HDC hdc, int format, +static inline bool gl_setpixelformat(HDC hdc, int format, PIXELFORMATDESCRIPTOR *pfd) { if (!SetPixelFormat(hdc, format, pfd)) { @@ -338,12 +371,25 @@ static bool init_default_swap(struct gl_platform *plat, device_t device, if (!plat->swap.wi) return false; - if (!gl_set_pixel_format(plat->swap.wi->hdc, pixel_format, pfd)) + if (!gl_setpixelformat(plat->swap.wi->hdc, pixel_format, pfd)) return false; return true; } +#ifdef _DEBUG +static void APIENTRY gl_debug_message_amd(GLuint id, + GLenum category, + GLenum severity, + GLsizei length, + const GLchar *msg, + void *param) +{ + OutputDebugStringA(msg); + OutputDebugStringA("\n"); +} +#endif + struct gl_platform *gl_platform_create(device_t device, struct gs_init_data *info) { @@ -362,7 +408,7 @@ struct gl_platform *gl_platform_create(device_t device, /* you have to have a dummy context open before you can actually * use wglChoosePixelFormatARB */ - if (!gl_get_pixel_format(dummy.hdc, info, &pixel_format, &pfd)) + if (!gl_getpixelformat(dummy.hdc, info, &pixel_format, &pfd)) goto fail; gl_dummy_context_free(&dummy); @@ -379,6 +425,14 @@ struct gl_platform *gl_platform_create(device_t device, gl_success("GL_TEXTURE_CUBE_MAP_SEAMLESS"); } +#ifdef _DEBUG + if (GLEW_AMD_debug_output) { + glDebugMessageEnableAMD(0, 0, 0, NULL, true); + glDebugMessageCallbackAMD(gl_debug_message_amd, device); + gl_success("glDebugMessageCallback"); + } +#endif + return plat; fail: @@ -415,9 +469,9 @@ struct gl_windowinfo *gl_windowinfo_create(struct gs_init_data *info) if (!wi) return NULL; - if (!gl_get_pixel_format(wi->hdc, info, &pixel_format, &pfd)) + if (!gl_getpixelformat(wi->hdc, info, &pixel_format, &pfd)) goto fail; - if (!gl_set_pixel_format(wi->hdc, pixel_format, &pfd)) + if (!gl_setpixelformat(wi->hdc, pixel_format, &pfd)) goto fail; return wi; @@ -454,7 +508,10 @@ void device_leavecontext(device_t device) void device_load_swapchain(device_t device, swapchain_t swap) { - HDC hdc = device->plat->swap.wi->hdc; + HDC hdc; + if (!swap) + swap = &device->plat->swap; + if (device->cur_swap == swap) return; @@ -469,13 +526,18 @@ void device_load_swapchain(device_t device, swapchain_t swap) void device_present(device_t device) { - HDC hdc = device->plat->swap.wi->hdc; - if (device->cur_swap) - hdc = device->cur_swap->wi->hdc; - - if (!SwapBuffers(hdc)) { + if (!SwapBuffers(device->cur_swap->wi->hdc)) { blog(LOG_ERROR, "SwapBuffers failed, GetLastError " "returned %u", GetLastError()); blog(LOG_ERROR, "device_present (GL) failed"); } } + +extern void gl_getclientsize(struct gs_swap_chain *swap, + uint32_t *width, uint32_t *height) +{ + RECT rc; + GetClientRect(swap->wi->hwnd, &rc); + *width = rc.right; + *height = rc.bottom; +} diff --git a/libobs-opengl/makefile b/libobs-opengl/makefile new file mode 100644 index 000000000..d99866be1 --- /dev/null +++ b/libobs-opengl/makefile @@ -0,0 +1,48 @@ +include ../config.mak + +.PHONY: all default clean + +all: default + +SRCFILES=gl-subsystem.c \ + gl-windows.c \ + gl-vertexbuffer.c \ + gl-texturecube.c \ + gl-texture2d.c \ + gl-stagesurf.c \ + gl-shaderparser.c \ + gl-shader.c \ + gl-indexbuffer.c \ + gl-zstencil.c \ + gl-helpers.c + +SONAME=../build/libobs-opengl.$(SOEXT) + +OBJS += $(SRCFILES:%.c=%.$(OBJ)) + +CPPFLAGS += -iquote../libobs -DGLEW_STATIC +LDFLAGS += -Lglew/lib -Wl,-Bstatic -lglew32 -Wl,-Bdynamic -lopengl32 \ + -Wl,--subsystem,windows -mwindows -L../build -lobs -lpthread + +default: makeglew $(SONAME) + +makeglew: glew + make -C glew glew.lib + +.depend: + @rm -f .depend + @$(foreach SRC, $(addprefix $(SRCPATH)/, $(SRCFILES)), $(CCDEP) \ + $(CPPFLAGS) $(SRC) \ + -MT $(SRC:$(SRCPATH)/%.c=%.$(OBJ)) -MM 1>> .depend;) + +$(SONAME): .depend $(OBJS) + $(LD)$@ $(OBJS) $(LDFLAGS) + +depend: .depend +ifneq ($(wildcard .depend),) +include .depend +endif + +clean: + rm -f $(OBJS) $(SONAME) *.a *.lib *.exp *.pdb .depend + make clean -C glew diff --git a/libobs/graphics/effect-parser.c b/libobs/graphics/effect-parser.c index 15de014de..52e3aa577 100644 --- a/libobs/graphics/effect-parser.c +++ b/libobs/graphics/effect-parser.c @@ -1299,7 +1299,7 @@ static void ep_compile_param(struct effect_parser *ep, size_t idx) ep->effect->world = param; } -static inline void ep_compile_pass_shaderparams(struct effect_parser *ep, +static bool ep_compile_pass_shaderparams(struct effect_parser *ep, struct darray *pass_params, struct darray *used_params, shader_t shader) { @@ -1319,7 +1319,14 @@ static inline void ep_compile_pass_shaderparams(struct effect_parser *ep, param_name->array); param->sparam = shader_getparambyname(shader, param_name->array); + + if (!param->sparam) { + blog(LOG_ERROR, "Effect shader parameter not found"); + return false; + } } + + return true; } static inline bool ep_compile_pass_shader(struct effect_parser *ep, @@ -1332,6 +1339,7 @@ static inline bool ep_compile_pass_shader(struct effect_parser *ep, struct darray used_params; /* struct dstr */ struct darray *pass_params; /* struct pass_shaderparam */ shader_t shader; + bool success = true; dstr_init(&shader_str); darray_init(&used_params); @@ -1375,15 +1383,17 @@ static inline bool ep_compile_pass_shader(struct effect_parser *ep, blog(LOG_DEBUG, "+++++++++++++++++++++++++++++++++++"); if (shader) - ep_compile_pass_shaderparams(ep, pass_params, &used_params, - shader); + success = ep_compile_pass_shaderparams(ep, pass_params, + &used_params, shader); + else + success = false; dstr_free(&location); dstr_array_free(used_params.array, used_params.num); darray_free(&used_params); dstr_free(&shader_str); - return shader != NULL; + return success; } static bool ep_compile_pass(struct effect_parser *ep, diff --git a/libobs/graphics/graphics-imports.c b/libobs/graphics/graphics-imports.c index 1458191ab..fa27ace25 100644 --- a/libobs/graphics/graphics-imports.c +++ b/libobs/graphics/graphics-imports.c @@ -97,7 +97,6 @@ bool load_graphics_imports(struct gs_exports *exports, void *module, GRAPHICS_IMPORT(device_setscissorrect); GRAPHICS_IMPORT(device_ortho); GRAPHICS_IMPORT(device_frustum); - GRAPHICS_IMPORT(device_perspective); GRAPHICS_IMPORT(device_projection_push); GRAPHICS_IMPORT(device_projection_pop); diff --git a/libobs/graphics/graphics-internal.h b/libobs/graphics/graphics-internal.h index 5b1b9a75b..7b91688d7 100644 --- a/libobs/graphics/graphics-internal.h +++ b/libobs/graphics/graphics-internal.h @@ -36,14 +36,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, - uint32_t levels, void **data, uint32_t flags); + uint32_t levels, const void **data, uint32_t flags); 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); + const 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); + const void **data, uint32_t flags); zstencil_t (*device_create_zstencil)(device_t device, uint32_t width, uint32_t height, enum gs_zstencil_format format); @@ -128,8 +128,6 @@ struct gs_exports { float top, float bottom, float znear, float zfar); void (*device_frustum)(device_t device, float left, float right, float top, float bottom, float znear, float zfar); - void (*device_perspective)(device_t device, float fovy, float aspect, - float znear, float zfar); void (*device_projection_push)(device_t device); void (*device_projection_pop)(device_t device); diff --git a/libobs/graphics/graphics.c b/libobs/graphics/graphics.c index ce0fbbe29..c84eccfab 100644 --- a/libobs/graphics/graphics.c +++ b/libobs/graphics/graphics.c @@ -149,17 +149,13 @@ void gs_destroy(graphics_t graphics) while (thread_graphics) gs_leavecontext(); - graphics->exports.device_entercontext(graphics->device); - - if (graphics->sprite_buffer) + if (graphics->device) { + graphics->exports.device_entercontext(graphics->device); graphics->exports.vertexbuffer_destroy(graphics->sprite_buffer); - - if (graphics->immediate_vertbuffer) graphics->exports.vertexbuffer_destroy( graphics->immediate_vertbuffer); - - if (graphics->device) graphics->exports.device_destroy(graphics->device); + } pthread_mutex_destroy(&graphics->mutex); da_free(graphics->matrix_stack); @@ -596,8 +592,7 @@ effect_t gs_create_effect(const char *effect_string, const char *filename, return effect; } -shader_t gs_create_vertexshader_from_file(const char *file, - char **error_string) +shader_t gs_create_vertexshader_from_file(const char *file, char **error_string) { char *file_string; shader_t shader = NULL; @@ -615,8 +610,7 @@ shader_t gs_create_vertexshader_from_file(const char *file, return shader; } -shader_t gs_create_pixelshader_from_file(const char *file, - char **error_string) +shader_t gs_create_pixelshader_from_file(const char *file, char **error_string) { char *file_string; shader_t shader = NULL; @@ -640,13 +634,13 @@ texture_t gs_create_texture_from_file(const char *file, uint32_t flags) return NULL; } -texture_t gs_create_cubetexture_from_file(const char *flie, uint32_t flags) +texture_t gs_create_cubetexture_from_file(const char *file, uint32_t flags) { /* TODO */ return NULL; } -texture_t gs_create_volumetexture_from_file(const char *flie, uint32_t flags) +texture_t gs_create_volumetexture_from_file(const char *file, uint32_t flags) { /* TODO */ return NULL; @@ -681,6 +675,7 @@ void gs_draw_sprite(texture_t tex) vec2_set(tvarray+3, 1.0f, 1.0f); vertexbuffer_flush(graphics->sprite_buffer, false); gs_load_vertexbuffer(graphics->sprite_buffer); + gs_load_indexbuffer(NULL); gs_draw(GS_TRISTRIP, 0, 0); } @@ -740,6 +735,21 @@ void cubetexture_setimage(texture_t cubetex, uint32_t side, const void *data, /* TODO */ } +void gs_perspective(float angle, float aspect, float near, float far) +{ + graphics_t graphics = thread_graphics; + float xmin, xmax, ymin, ymax; + + ymax = near * tanf(RAD(angle)*0.5f); + ymin = -ymax; + + xmin = ymin * aspect; + xmax = ymax * aspect; + + graphics->exports.device_frustum(graphics->device, xmin, xmax, + ymin, ymax, near, far); +} + /* ------------------------------------------------------------------------- */ swapchain_t gs_create_swapchain(struct gs_init_data *data) @@ -779,8 +789,8 @@ static inline bool is_pow2(uint32_t size) } texture_t gs_create_texture(uint32_t width, uint32_t height, - enum gs_color_format color_format, uint32_t levels, void **data, - uint32_t flags) + enum gs_color_format color_format, uint32_t levels, + const void **data, uint32_t flags) { graphics_t graphics = thread_graphics; bool pow2tex = is_pow2(width) && is_pow2(height); @@ -809,7 +819,7 @@ texture_t gs_create_texture(uint32_t width, uint32_t height, texture_t gs_create_cubetexture(uint32_t size, enum gs_color_format color_format, uint32_t levels, - void **data, uint32_t flags) + const void **data, uint32_t flags) { graphics_t graphics = thread_graphics; bool pow2tex = is_pow2(size); @@ -839,7 +849,7 @@ texture_t gs_create_cubetexture(uint32_t size, texture_t gs_create_volumetexture(uint32_t width, uint32_t height, uint32_t depth, enum gs_color_format color_format, - uint32_t levels, void **data, uint32_t flags) + uint32_t levels, const void **data, uint32_t flags) { graphics_t graphics = thread_graphics; return graphics->exports.device_create_volumetexture(graphics->device, @@ -1182,13 +1192,6 @@ void gs_frustum(float left, float right, float top, float bottom, float znear, bottom, znear, zfar); } -void gs_perspective(float fovy, float aspect, float znear, float zfar) -{ - graphics_t graphics = thread_graphics; - graphics->exports.device_perspective(graphics->device, fovy, aspect, - znear, zfar); -} - void gs_projection_push(void) { graphics_t graphics = thread_graphics; diff --git a/libobs/graphics/graphics.h b/libobs/graphics/graphics.h index e103e3133..5f394ea5d 100644 --- a/libobs/graphics/graphics.h +++ b/libobs/graphics/graphics.h @@ -503,6 +503,8 @@ EXPORT void texture_setimage(texture_t tex, const void *data, EXPORT void cubetexture_setimage(texture_t cubetex, uint32_t side, const void *data, uint32_t byte_width); +EXPORT void gs_perspective(float fovy, float aspect, float znear, float zfar); + /* -------------------------- */ /* library-specific functions */ @@ -514,14 +516,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, uint32_t levels, void **data, - uint32_t flags); + enum gs_color_format color_format, uint32_t levels, + const void **data, uint32_t flags); EXPORT texture_t gs_create_cubetexture(uint32_t size, enum gs_color_format color_format, uint32_t levels, - void **data, uint32_t flags); + const 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, - uint32_t levels, void **data, uint32_t flags); + uint32_t levels, const void **data, uint32_t flags); EXPORT zstencil_t gs_create_zstencil(uint32_t width, uint32_t height, enum gs_zstencil_format format); @@ -612,8 +614,6 @@ EXPORT void gs_ortho(float left, float right, float top, float bottom, float znear, float zfar); EXPORT void gs_frustum(float left, float right, float top, float bottom, float znear, float zfar); -EXPORT void gs_perspective(float fovy, float aspect, float znear, - float zfar); EXPORT void gs_projection_push(void); EXPORT void gs_projection_pop(void); diff --git a/libobs/graphics/matrix4.c b/libobs/graphics/matrix4.c index 3cbd235ce..9013800d9 100644 --- a/libobs/graphics/matrix4.c +++ b/libobs/graphics/matrix4.c @@ -124,7 +124,7 @@ void matrix4_transpose(struct matrix4 *dst, const struct matrix4 *m) { struct matrix4 temp; - /* TODO: Use SSE */ + /* TODO: Add SSE */ temp.x.x = m->x.x; temp.x.y = m->y.x; temp.x.z = m->z.x; @@ -144,66 +144,3 @@ void matrix4_transpose(struct matrix4 *dst, const struct matrix4 *m) matrix4_copy(dst, &temp); } - -void matrix4_ortho(struct matrix4 *dst, float left, float right, - float top, float bottom, float near, float far) -{ - float rml = right-left; - float bmt = bottom-top; - float fmn = far-near; - - vec4_zero(&dst->x); - vec4_zero(&dst->y); - vec4_zero(&dst->z); - vec4_zero(&dst->t); - - dst->x.x = 2.0f / rml; - dst->t.x = (left+right) / -rml; - - dst->y.y = 2.0f / -bmt; - dst->t.y = (bottom+top) / bmt; - - dst->z.z = 1.0f / fmn; - dst->t.z = near / -fmn; - - dst->t.w = 1.0f; -} - -void matrix4_frustum(struct matrix4 *dst, float left, float right, - float top, float bottom, float near, float far) -{ - float rml = right-left; - float bmt = bottom-top; - float fmn = far-near; - float nearx2 = 2.0f*near; - - vec4_zero(&dst->x); - vec4_zero(&dst->y); - vec4_zero(&dst->z); - vec4_zero(&dst->t); - - dst->x.x = nearx2 / rml; - dst->z.x = (left+right) / -rml; - - dst->y.y = nearx2 / -bmt; - dst->z.y = (bottom+top) / bmt; - - dst->z.z = far / fmn; - dst->t.z = (near*far) / -fmn; - - dst->z.w = 1.0f; -} - -void matrix4_perspective(struct matrix4 *dst, float angle, - float aspect, float near, float far) -{ - float xmin, xmax, ymin, ymax; - - ymax = near * tanf(RAD(angle)*0.5f); - ymin = -ymax; - - xmin = ymin * aspect; - xmax = ymax * aspect; - - matrix4_frustum(dst, xmin, xmax, ymin, ymax, near, far); -} diff --git a/libobs/graphics/matrix4.h b/libobs/graphics/matrix4.h index 9b0f9bf19..19fdb30dd 100644 --- a/libobs/graphics/matrix4.h +++ b/libobs/graphics/matrix4.h @@ -61,13 +61,6 @@ EXPORT float matrix4_determinant(const struct matrix4 *m); EXPORT bool matrix4_inv(struct matrix4 *dst, const struct matrix4 *m); EXPORT void matrix4_transpose(struct matrix4 *dst, const struct matrix4 *m); -EXPORT void matrix4_ortho(struct matrix4 *dst, float left, float right, - float top, float bottom, float near, float far); -EXPORT void matrix4_frustum(struct matrix4 *dst, float left, float right, - float top, float bottom, float near, float far); -EXPORT void matrix4_perspective(struct matrix4 *dst, float angle, - float aspect, float near, float far); - #ifdef __cplusplus } #endif diff --git a/libobs/obs-source.c b/libobs/obs-source.c index afa9b8d8e..2b4d5e77d 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -87,7 +87,7 @@ void obs_source_init(struct obs_source *source) da_push_back(obs->sources, &source); } -obs_source_t obs_source_create(enum source_type type, const char *name, +obs_source_t obs_source_create(enum obs_source_type type, const char *name, const char *settings) { const struct source_info *info = NULL; diff --git a/libobs/obs-video.c b/libobs/obs-video.c index cb359a8f6..dff25e8f9 100644 --- a/libobs/obs-video.c +++ b/libobs/obs-video.c @@ -42,8 +42,6 @@ static inline void render_displays(void) struct vec4 clear_color; vec4_set(&clear_color, 0.3f, 0.0f, 0.0f, 1.0f); - //gs_enable_depthtest(false); - gs_ortho(0.0f, (float)obs->output_width, 0.0f, (float)obs->output_height, -100.0f, 100.0f); @@ -66,9 +64,13 @@ static inline void render_displays(void) gs_load_swapchain(NULL); gs_beginscene(); - gs_clear(GS_CLEAR_COLOR|GS_CLEAR_DEPTH|GS_CLEAR_STENCIL, + gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH | GS_CLEAR_STENCIL, &clear_color, 1.0f, 0); + gs_enable_depthtest(false); + gs_enable_blending(false); + gs_setcullmode(GS_NEITHER); + gs_setviewport(0, 0, gs_getwidth(), gs_getheight()); if (obs->primary_source) @@ -90,7 +92,7 @@ static bool swap_frame(uint64_t timestamp) } obs->textures_copied[obs->cur_texture] = true; - gs_stage_texture(last_surface, NULL); + //gs_stage_texture(last_surface, NULL); if (++obs->cur_texture == NUM_TEXTURES) obs->cur_texture = 0; diff --git a/makefile b/makefile index 94a63b871..9d4ff477c 100644 --- a/makefile +++ b/makefile @@ -2,7 +2,7 @@ include config.mak all: default -PROJECTS=libobs test +PROJECTS=libobs test libobs-opengl .PHONY: all default clean diff --git a/test/test-input/test-random.c b/test/test-input/test-random.c index f71a5d30b..7c3c7423f 100644 --- a/test/test-input/test-random.c +++ b/test/test-input/test-random.c @@ -15,13 +15,15 @@ struct random_tex *random_create(const char *settings, obs_source_t source) pixel |= (rand()%256); pixel |= (rand()%256) << 8; pixel |= (rand()%256) << 16; + //pixel |= 0xFFFFFFFF; pixels[y*20 + x] = pixel; } } gs_entercontext(obs_graphics()); - rt->texture = gs_create_texture(20, 20, GS_RGBA, 1, &pixels, 0); + rt->texture = gs_create_texture(20, 20, GS_RGBA, 1, + (const void**)&pixels, 0); bfree(pixels); if (!rt->texture) { @@ -61,7 +63,8 @@ uint32_t random_get_output_flags(struct random_tex *rt) void random_video_render(struct random_tex *rt, obs_source_t filter_target) { technique_t tech = effect_gettechnique(rt->whatever, "Default"); - effect_settexture(rt->whatever, effect_getparambyidx(rt->whatever, 1), rt->texture); + effect_settexture(rt->whatever, effect_getparambyidx(rt->whatever, 1), + rt->texture); technique_begin(tech); technique_beginpass(tech, 0); diff --git a/test/win/test.cpp b/test/win/test.cpp index c25a0f8ae..10cf60567 100644 --- a/test/win/test.cpp +++ b/test/win/test.cpp @@ -58,30 +58,33 @@ static void do_log(enum log_type type, const char *msg, va_list args) OutputDebugStringA(bla); OutputDebugStringA("\n"); - if (type >= LOG_WARNING) - __debugbreak(); + /*if (type >= LOG_WARNING) + __debugbreak();*/ } static void CreateOBS(HWND hwnd) { + RECT rc; + GetClientRect(hwnd, &rc); + struct video_info vi; memset(&vi, 0, sizeof(struct video_info)); vi.format = "RGBA"; vi.fps_num = 30000; vi.fps_den = 1001; - vi.width = cx; - vi.height = cy; + vi.width = rc.right; + vi.height = rc.bottom; vi.name = "video"; struct gs_init_data gsid; memset(&gsid, 0, sizeof(gsid)); gsid.hwnd = hwnd; - gsid.cx = cx; - gsid.cy = cy; + gsid.cx = rc.right; + gsid.cy = rc.bottom; gsid.num_backbuffers = 2; gsid.format = GS_RGBA; - if (!obs_startup("libobs-d3d11.dll", &gsid, &vi, NULL)) + if (!obs_startup("libobs-opengl.dll", &gsid, &vi, NULL)) throw "Couldn't create OBS"; } diff --git a/vs/2010/OBS.sln b/vs/2010/OBS.sln index 912da38cc..4b774f801 100644 --- a/vs/2010/OBS.sln +++ b/vs/2010/OBS.sln @@ -25,65 +25,124 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test-input", "test-input\te EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libobs-opengl", "libobs-opengl\libobs-opengl.vcxproj", "{B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}" ProjectSection(ProjectDependencies) = postProject + {664E6F0D-6784-4760-9565-D54F8EB1EDF4} = {664E6F0D-6784-4760-9565-D54F8EB1EDF4} {6F1AC2AE-6424-401A-AF9F-A771E6BEE026} = {6F1AC2AE-6424-401A-AF9F-A771E6BEE026} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glew_static", "..\..\libobs-opengl\glew\build\vc10\glew_static.vcxproj", "{664E6F0D-6784-4760-9565-D54F8EB1EDF4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug MX|Win32 = Debug MX|Win32 + Debug MX|x64 = Debug MX|x64 Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + Release MX|Win32 = Release MX|Win32 + Release MX|x64 = Release MX|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug MX|Win32.ActiveCfg = Debug|x64 + {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug MX|x64.ActiveCfg = Debug|x64 + {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug MX|x64.Build.0 = Debug|x64 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug|Win32.ActiveCfg = Debug|Win32 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug|Win32.Build.0 = Debug|Win32 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug|x64.ActiveCfg = Debug|x64 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug|x64.Build.0 = Debug|x64 + {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release MX|Win32.ActiveCfg = Release|x64 + {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release MX|x64.ActiveCfg = Release|x64 + {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release MX|x64.Build.0 = Release|x64 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release|Win32.ActiveCfg = Release|Win32 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release|Win32.Build.0 = Release|Win32 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release|x64.ActiveCfg = Release|x64 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release|x64.Build.0 = Release|x64 + {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug MX|Win32.ActiveCfg = Debug|x64 + {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug MX|x64.ActiveCfg = Debug|x64 + {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug MX|x64.Build.0 = Debug|x64 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug|Win32.ActiveCfg = Debug|Win32 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug|Win32.Build.0 = Debug|Win32 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug|x64.ActiveCfg = Debug|x64 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug|x64.Build.0 = Debug|x64 + {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release MX|Win32.ActiveCfg = Release|x64 + {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release MX|x64.ActiveCfg = Release|x64 + {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release MX|x64.Build.0 = Release|x64 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release|Win32.ActiveCfg = Release|Win32 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release|Win32.Build.0 = Release|Win32 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release|x64.ActiveCfg = Release|x64 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release|x64.Build.0 = Release|x64 + {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug MX|Win32.ActiveCfg = Debug|x64 + {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug MX|x64.ActiveCfg = Debug|x64 + {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug MX|x64.Build.0 = Debug|x64 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug|Win32.ActiveCfg = Debug|Win32 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug|Win32.Build.0 = Debug|Win32 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug|x64.ActiveCfg = Debug|x64 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug|x64.Build.0 = Debug|x64 + {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release MX|Win32.ActiveCfg = Release|x64 + {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release MX|x64.ActiveCfg = Release|x64 + {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release MX|x64.Build.0 = Release|x64 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release|Win32.ActiveCfg = Release|Win32 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release|Win32.Build.0 = Release|Win32 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release|x64.ActiveCfg = Release|x64 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release|x64.Build.0 = Release|x64 + {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug MX|Win32.ActiveCfg = Debug|x64 + {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug MX|x64.ActiveCfg = Debug|x64 + {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug MX|x64.Build.0 = Debug|x64 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug|Win32.ActiveCfg = Debug|Win32 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug|Win32.Build.0 = Debug|Win32 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug|x64.ActiveCfg = Debug|x64 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug|x64.Build.0 = Debug|x64 + {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release MX|Win32.ActiveCfg = Release|x64 + {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release MX|x64.ActiveCfg = Release|x64 + {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release MX|x64.Build.0 = Release|x64 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release|Win32.ActiveCfg = Release|Win32 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release|Win32.Build.0 = Release|Win32 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release|x64.ActiveCfg = Release|x64 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release|x64.Build.0 = Release|x64 + {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug MX|Win32.ActiveCfg = Debug|x64 + {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug MX|x64.ActiveCfg = Debug|x64 + {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug MX|x64.Build.0 = Debug|x64 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug|Win32.ActiveCfg = Debug|Win32 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug|Win32.Build.0 = Debug|Win32 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug|x64.ActiveCfg = Debug|x64 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug|x64.Build.0 = Debug|x64 + {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release MX|Win32.ActiveCfg = Release|x64 + {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release MX|x64.ActiveCfg = Release|x64 + {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release MX|x64.Build.0 = Release|x64 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release|Win32.ActiveCfg = Release|Win32 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release|Win32.Build.0 = Release|Win32 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release|x64.ActiveCfg = Release|x64 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release|x64.Build.0 = Release|x64 + {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug MX|Win32.ActiveCfg = Debug|x64 + {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug MX|x64.ActiveCfg = Debug|x64 + {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug MX|x64.Build.0 = Debug|x64 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug|Win32.ActiveCfg = Debug|Win32 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug|Win32.Build.0 = Debug|Win32 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug|x64.ActiveCfg = Debug|x64 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug|x64.Build.0 = Debug|x64 + {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release MX|Win32.ActiveCfg = Release|x64 + {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release MX|x64.ActiveCfg = Release|x64 + {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release MX|x64.Build.0 = Release|x64 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release|Win32.ActiveCfg = Release|Win32 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release|Win32.Build.0 = Release|Win32 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release|x64.ActiveCfg = Release|x64 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release|x64.Build.0 = Release|x64 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Debug MX|Win32.ActiveCfg = Debug MX|Win32 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Debug MX|Win32.Build.0 = Debug MX|Win32 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Debug MX|x64.ActiveCfg = Debug MX|x64 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Debug MX|x64.Build.0 = Debug MX|x64 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Debug|Win32.ActiveCfg = Debug|Win32 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Debug|Win32.Build.0 = Debug|Win32 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Debug|x64.ActiveCfg = Debug|x64 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Debug|x64.Build.0 = Debug|x64 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Release MX|Win32.ActiveCfg = Release MX|Win32 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Release MX|Win32.Build.0 = Release MX|Win32 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Release MX|x64.ActiveCfg = Release MX|x64 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Release MX|x64.Build.0 = Release MX|x64 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Release|Win32.ActiveCfg = Release|Win32 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Release|Win32.Build.0 = Release|Win32 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Release|x64.ActiveCfg = Release|x64 + {664E6F0D-6784-4760-9565-D54F8EB1EDF4}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vs/2010/libobs-d3d11/libobs-d3d11.vcxproj b/vs/2010/libobs-d3d11/libobs-d3d11.vcxproj index 138fe45ba..6edb78e82 100644 --- a/vs/2010/libobs-d3d11/libobs-d3d11.vcxproj +++ b/vs/2010/libobs-d3d11/libobs-d3d11.vcxproj @@ -114,6 +114,9 @@ $(OutDir);%(AdditionalLibraryDirectories) d3d11.lib;dxgi.lib;d3dcompiler.lib;libobs.lib;%(AdditionalDependencies) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -131,6 +134,9 @@ $(OutDir);%(AdditionalLibraryDirectories) d3d11.lib;dxgi.lib;d3dcompiler.lib;libobs.lib;%(AdditionalDependencies) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -152,6 +158,9 @@ $(OutDir);%(AdditionalLibraryDirectories) d3d11.lib;dxgi.lib;d3dcompiler.lib;libobs.lib;%(AdditionalDependencies) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -173,6 +182,9 @@ $(OutDir);%(AdditionalLibraryDirectories) d3d11.lib;dxgi.lib;d3dcompiler.lib;libobs.lib;%(AdditionalDependencies) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + diff --git a/vs/2010/libobs-opengl/libobs-opengl.vcxproj b/vs/2010/libobs-opengl/libobs-opengl.vcxproj index 2c9ec5ee1..87964442d 100644 --- a/vs/2010/libobs-opengl/libobs-opengl.vcxproj +++ b/vs/2010/libobs-opengl/libobs-opengl.vcxproj @@ -91,6 +91,9 @@ ../../../libobs-opengl/glew/lib/Debug/Win32/;$(OutDir);%(AdditionalLibraryDirectories) glew32sd.lib;opengl32.lib;libobs.lib;%(AdditionalDependencies) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -109,6 +112,9 @@ ../../../libobs-opengl/glew/lib/Debug/x64/;$(OutDir);%(AdditionalLibraryDirectories) glew32sd.lib;opengl32.lib;libobs.lib;%(AdditionalDependencies) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -131,6 +137,9 @@ ../../../libobs-opengl/glew/lib/Release/Win32/;$(OutDir);%(AdditionalLibraryDirectories) glew32s.lib;opengl32.lib;libobs.lib;%(AdditionalDependencies) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -153,6 +162,9 @@ ../../../libobs-opengl/glew/lib/Release/x64/;$(OutDir);%(AdditionalLibraryDirectories) glew32s.lib;opengl32.lib;libobs.lib;%(AdditionalDependencies) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + diff --git a/vs/2010/libobs/libobs.vcxproj b/vs/2010/libobs/libobs.vcxproj index 234c4608f..bcc9a4efe 100644 --- a/vs/2010/libobs/libobs.vcxproj +++ b/vs/2010/libobs/libobs.vcxproj @@ -173,6 +173,9 @@ pthreads.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -190,6 +193,9 @@ pthreads.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -211,6 +217,9 @@ pthreads.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -232,6 +241,9 @@ pthreads.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + diff --git a/vs/2010/test-input/test-input.vcxproj b/vs/2010/test-input/test-input.vcxproj index 7dcca62f1..fac191091 100644 --- a/vs/2010/test-input/test-input.vcxproj +++ b/vs/2010/test-input/test-input.vcxproj @@ -100,6 +100,9 @@ $(OutDir);%(AdditionalLibraryDirectories) libobs.lib;%(AdditionalDependencies) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -117,6 +120,9 @@ $(OutDir);%(AdditionalLibraryDirectories) libobs.lib;%(AdditionalDependencies) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -138,6 +144,9 @@ $(OutDir);%(AdditionalLibraryDirectories) libobs.lib;%(AdditionalDependencies) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -159,6 +168,9 @@ $(OutDir);%(AdditionalLibraryDirectories) libobs.lib;%(AdditionalDependencies) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + diff --git a/vs/2010/wintest/wintest.vcxproj b/vs/2010/wintest/wintest.vcxproj index 5abec706d..262c5ce2b 100644 --- a/vs/2010/wintest/wintest.vcxproj +++ b/vs/2010/wintest/wintest.vcxproj @@ -93,6 +93,9 @@ libobs.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -100,16 +103,19 @@ Level3 Disabled - WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;GLEW_STATIC;%(PreprocessorDefinitions) ../../../libobs MultiThreadedDebug Windows true - libobs.lib;%(AdditionalDependencies) + opengl32.lib;D:\OBS2\libobs-opengl\glew\lib\Debug\x64/glew32sd.lib;libobs.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -131,6 +137,9 @@ libobs.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" + @@ -152,6 +161,9 @@ libobs.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) + + copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/$(TargetName)$(TargetExt)" +