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