diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 5 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 52 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 11 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 24 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 23 | ||||
-rw-r--r-- | drivers/gles3/shader_gles3.cpp | 6 | ||||
-rw-r--r-- | drivers/gles3/shaders/scene.glsl | 6 | ||||
-rw-r--r-- | drivers/unix/rw_lock_posix.cpp | 2 | ||||
-rw-r--r-- | drivers/unix/stream_peer_tcp_posix.cpp | 4 | ||||
-rw-r--r-- | drivers/wasapi/audio_driver_wasapi.cpp | 84 | ||||
-rw-r--r-- | drivers/wasapi/audio_driver_wasapi.h | 2 |
11 files changed, 151 insertions, 68 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 5b3e43fc43..0839f930c9 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -208,6 +208,8 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con } else { + texture = texture->get_ptr(); + if (texture->render_target) texture->render_target->used_in_frame = true; @@ -243,6 +245,7 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con } else { + normal_map = normal_map->get_ptr(); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, normal_map->tex_id); state.current_normal = p_normal_map; @@ -1115,6 +1118,8 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons continue; } + t = t->get_ptr(); + if (storage->config.srgb_decode_supported && t->using_srgb) { //no srgb in 2D glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 02df170da1..3031b70f70 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1235,6 +1235,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m } else { + t = t->get_ptr(); //resolve for proxies #ifdef TOOLS_ENABLED if (t->detect_3d) { t->detect_3d(t->detect_3d_ud); @@ -2164,7 +2165,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ state.scene_shader.set_conditional(SceneShaderGLES3::USE_OPAQUE_PREPASS, false); } -void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass) { +void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass) { RasterizerStorageGLES3::Material *m = NULL; RID m_src = p_instance->material_override.is_valid() ? p_instance->material_override : (p_material >= 0 ? p_instance->materials[p_material] : p_geometry->material); @@ -2196,17 +2197,17 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo ERR_FAIL_COND(!m); - _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass); + _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass, p_shadow_pass); while (m->next_pass.is_valid()) { m = storage->material_owner.getornull(m->next_pass); if (!m || !m->shader || !m->shader->valid) break; - _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass); + _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass, p_shadow_pass); } } -void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass) { +void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_shadow_pass) { bool has_base_alpha = (p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.uses_screen_texture; bool has_blend_alpha = p_material->shader->spatial.blend_mode != RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX; @@ -2238,11 +2239,11 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G if (!p_material->shader->spatial.uses_alpha_scissor && !p_material->shader->spatial.writes_modelview_or_projection && !p_material->shader->spatial.uses_vertex && !p_material->shader->spatial.uses_discard && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { //shader does not use discard and does not write a vertex position, use generic material if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) { - p_material = storage->material_owner.getptr(default_material_twosided); + p_material = storage->material_owner.getptr(!p_shadow_pass && p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material_twosided : default_material_twosided); no_cull = true; mirror = false; } else { - p_material = storage->material_owner.getptr(default_material); + p_material = storage->material_owner.getptr(!p_shadow_pass && p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material : default_material); } } @@ -2280,13 +2281,15 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G } e->sort_key |= uint64_t(e->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT; - e->sort_key |= uint64_t(e->instance->depth_layer) << RenderList::SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT; if (e->instance->gi_probe_instances.size()) { e->sort_key |= SORT_KEY_GI_PROBES_FLAG; } e->sort_key |= uint64_t(p_material->render_priority + 128) << RenderList::SORT_KEY_PRIORITY_SHIFT; + } else { + e->sort_key |= uint64_t(e->instance->depth_layer) << RenderList::SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT; + e->sort_key |= uint64_t(e->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT; } /* @@ -3060,7 +3063,7 @@ void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) { storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); } -void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass) { +void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass) { current_geometry_index = 0; current_material_index = 0; @@ -3085,7 +3088,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p int mat_idx = inst->materials[i].is_valid() ? i : -1; RasterizerStorageGLES3::Surface *s = mesh->surfaces[i]; - _add_geometry(s, inst, NULL, mat_idx, p_depth_pass); + _add_geometry(s, inst, NULL, mat_idx, p_depth_pass, p_shadow_pass); } //mesh->last_pass=frame; @@ -3108,7 +3111,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p for (int i = 0; i < ssize; i++) { RasterizerStorageGLES3::Surface *s = mesh->surfaces[i]; - _add_geometry(s, inst, multi_mesh, -1, p_depth_pass); + _add_geometry(s, inst, multi_mesh, -1, p_depth_pass, p_shadow_pass); } } break; @@ -3117,7 +3120,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getptr(inst->base); ERR_CONTINUE(!immediate); - _add_geometry(immediate, inst, NULL, -1, p_depth_pass); + _add_geometry(immediate, inst, NULL, -1, p_depth_pass, p_shadow_pass); } break; case VS::INSTANCE_PARTICLES: { @@ -3139,7 +3142,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p for (int j = 0; j < ssize; j++) { RasterizerStorageGLES3::Surface *s = mesh->surfaces[j]; - _add_geometry(s, inst, particles, -1, p_depth_pass); + _add_geometry(s, inst, particles, -1, p_depth_pass, p_shadow_pass); } } @@ -4055,8 +4058,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); render_list.clear(); - _fill_render_list(p_cull_result, p_cull_count, true); - render_list.sort_by_depth(false); + _fill_render_list(p_cull_result, p_cull_count, true, false); + render_list.sort_by_key(false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, true); _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, 0, false, false, true, false, false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, false); @@ -4086,11 +4089,10 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_cam_projection, p_shadow_atlas); _setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_cam_projection, p_reflection_atlas, env); - render_list.clear(); - bool use_mrt = false; - _fill_render_list(p_cull_result, p_cull_count, false); + render_list.clear(); + _fill_render_list(p_cull_result, p_cull_count, false, false); // glEnable(GL_BLEND); @@ -4593,10 +4595,8 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ } } - //todo hacer que se redibuje cuando corresponde - render_list.clear(); - _fill_render_list(p_cull_result, p_cull_count, true); + _fill_render_list(p_cull_result, p_cull_count, true, true); render_list.sort_by_depth(false); //shadow is front to back for performance @@ -4760,6 +4760,18 @@ void RasterizerSceneGLES3::initialize() { default_material_twosided = storage->material_create(); storage->shader_set_code(default_shader_twosided, "shader_type spatial; render_mode cull_disabled;\n"); storage->material_set_shader(default_material_twosided, default_shader_twosided); + + //default for shaders using world coordinates (typical for triplanar) + + default_worldcoord_shader = storage->shader_create(); + storage->shader_set_code(default_worldcoord_shader, "shader_type spatial; render_mode world_vertex_coords;\n"); + default_worldcoord_material = storage->material_create(); + storage->material_set_shader(default_worldcoord_material, default_worldcoord_shader); + + default_worldcoord_shader_twosided = storage->shader_create(); + default_worldcoord_material_twosided = storage->material_create(); + storage->shader_set_code(default_worldcoord_shader_twosided, "shader_type spatial; render_mode cull_disabled,world_vertex_coords;\n"); + storage->material_set_shader(default_worldcoord_material_twosided, default_worldcoord_shader_twosided); } { diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 69b43c7813..99c8044e2f 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -78,6 +78,11 @@ public: RID default_shader; RID default_shader_twosided; + RID default_worldcoord_material; + RID default_worldcoord_material_twosided; + RID default_worldcoord_shader; + RID default_worldcoord_shader_twosided; + RID default_overdraw_material; RID default_overdraw_shader; @@ -812,9 +817,9 @@ public: void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows); - _FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass); + _FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass,bool p_shadow_pass); - _FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass); + _FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_shadow_pass); void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy); @@ -827,7 +832,7 @@ public: void _copy_to_front_buffer(Environment *env); void _copy_texture_to_front_buffer(GLuint p_texture); //used for debug - void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass); + void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass); void _blur_effect_buffer(); void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index fc9150ecdc..cba9f08537 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1232,6 +1232,25 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_ return texture_owner.make_rid(ctex); } +void RasterizerStorageGLES3::texture_set_proxy(RID p_texture, RID p_proxy) { + + Texture *texture = texture_owner.get(p_texture); + ERR_FAIL_COND(!texture); + + if (texture->proxy) { + texture->proxy->proxy_owners.erase(texture); + texture->proxy = NULL; + } + + if (p_proxy.is_valid()) { + Texture *proxy = texture_owner.get(p_proxy); + ERR_FAIL_COND(!proxy); + ERR_FAIL_COND(proxy == texture); + proxy->proxy_owners.insert(texture); + texture->proxy = proxy; + } +} + RID RasterizerStorageGLES3::sky_create() { Sky *sky = memnew(Sky); @@ -1601,6 +1620,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { p_shader->spatial.uses_screen_texture = false; p_shader->spatial.uses_vertex = false; p_shader->spatial.writes_modelview_or_projection = false; + p_shader->spatial.uses_world_coordinates = false; shaders.actions_scene.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_ADD); shaders.actions_scene.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MIX); @@ -1621,9 +1641,10 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { shaders.actions_scene.render_mode_flags["vertex_lighting"] = &p_shader->spatial.uses_vertex_lighting; + shaders.actions_scene.render_mode_flags["world_vertex_coords"] = &p_shader->spatial.uses_world_coordinates; + shaders.actions_scene.usage_flag_pointers["ALPHA"] = &p_shader->spatial.uses_alpha; shaders.actions_scene.usage_flag_pointers["ALPHA_SCISSOR"] = &p_shader->spatial.uses_alpha_scissor; - shaders.actions_scene.usage_flag_pointers["VERTEX"] = &p_shader->spatial.uses_vertex; shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"] = &p_shader->spatial.uses_sss; shaders.actions_scene.usage_flag_pointers["DISCARD"] = &p_shader->spatial.uses_discard; @@ -1632,6 +1653,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection; shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection; + shaders.actions_scene.write_flag_pointers["VERTEX"] = &p_shader->spatial.uses_vertex; actions = &shaders.actions_scene; actions->uniforms = &p_shader->uniforms; diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 0ec110ab87..d5efd5307c 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -242,6 +242,9 @@ public: struct Texture : public RID_Data { + Texture *proxy; + Set<Texture *> proxy_owners; + String path; uint32_t flags; int width, height; @@ -301,6 +304,15 @@ public: detect_srgb_ud = NULL; detect_normal = NULL; detect_normal_ud = NULL; + proxy = NULL; + } + + _ALWAYS_INLINE_ Texture *get_ptr() { + if (proxy) { + return proxy; //->get_ptr(); only one level of indirection, else not inlining possible. + } else { + return this; + } } ~Texture() { @@ -309,6 +321,14 @@ public: glDeleteTextures(1, &tex_id); } + + for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) { + E->get()->proxy = NULL; + } + + if (proxy) { + proxy->proxy_owners.erase(this); + } } }; @@ -343,6 +363,8 @@ public: virtual void texture_set_detect_srgb_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); virtual void texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); + virtual void texture_set_proxy(RID p_texture, RID p_proxy); + /* SKY API */ struct Sky : public RID_Data { @@ -453,6 +475,7 @@ public: bool uses_time; bool writes_modelview_or_projection; bool uses_vertex_lighting; + bool uses_world_coordinates; } spatial; diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index d4ef256a33..9e234f5005 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -343,7 +343,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteProgram(v.id); v.id = 0; - ERR_PRINT("NO LOG, WTF"); + ERR_PRINT("Vertex shader compilation failed with empty log"); } else { if (iloglen == 0) { @@ -451,7 +451,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.vert_id); glDeleteProgram(v.id); v.id = 0; - ERR_PRINT("NO LOG, WTF"); + ERR_PRINT("Fragment shader compilation failed with empty log"); } else { if (iloglen == 0) { @@ -624,7 +624,7 @@ void ShaderGLES3::setup(const char **p_conditional_defines, int p_conditional_co feedbacks = p_feedback; feedback_count = p_feedback_count; - //split vertex and shader code (thank you, retarded shader compiler programmers from you know what company). + //split vertex and shader code (thank you, shader compiler programmers from you know what company). { String globals_tag = "\nVERTEX_SHADER_GLOBALS"; String material_tag = "\nMATERIAL_UNIFORMS"; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index b2b10fdb11..676541649c 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -263,6 +263,10 @@ uniform highp sampler2D skeleton_texture; //texunit:-1 out highp vec4 position_interp; +// FIXME: This triggers a Mesa bug that breaks rendering, so disabled for now. +// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316 +//invariant gl_Position; + void main() { highp vec4 vertex = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0); @@ -1026,7 +1030,7 @@ LIGHT_SHADER_CODE #if defined(LIGHT_USE_RIM) - float rim_light = pow(1.0-cNdotV, (1.0-roughness)*16.0); + float rim_light = pow(max(0.0,1.0-cNdotV), max(0.0,(1.0-roughness)*16.0)); diffuse_light += rim_light * rim * mix(vec3(1.0),diffuse_color,rim_tint) * light_color; #endif } diff --git a/drivers/unix/rw_lock_posix.cpp b/drivers/unix/rw_lock_posix.cpp index ab2d6495bd..00125809c0 100644 --- a/drivers/unix/rw_lock_posix.cpp +++ b/drivers/unix/rw_lock_posix.cpp @@ -39,7 +39,7 @@ void RWLockPosix::read_lock() { int err = pthread_rwlock_rdlock(&rwlock); if (err != 0) { - perror("wtf: "); + perror("Acquiring lock failed"); } ERR_FAIL_COND(err != 0); } diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 3bc2397e6f..e88a7d7de1 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -213,7 +213,7 @@ Error StreamPeerTCPPosix::write(const uint8_t *p_data, int p_bytes, int &r_sent, if (errno != EAGAIN) { - perror("shit?"); + perror("Nothing sent"); disconnect_from_host(); ERR_PRINT("Server disconnected!\n"); return FAILED; @@ -270,7 +270,7 @@ Error StreamPeerTCPPosix::read(uint8_t *p_buffer, int p_bytes, int &r_received, if (errno != EAGAIN) { - perror("shit?"); + perror("Nothing read"); disconnect_from_host(); ERR_PRINT("Server disconnected!\n"); return FAILED; diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index 2c87fb58db..10b6a61b2d 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -74,21 +74,22 @@ Error AudioDriverWASAPI::init_device(bool reinit) { ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); // Since we're using WASAPI Shared Mode we can't control any of these, we just tag along - channels = pwfex->nChannels; + wasapi_channels = pwfex->nChannels; mix_rate = pwfex->nSamplesPerSec; format_tag = pwfex->wFormatTag; bits_per_sample = pwfex->wBitsPerSample; - switch (channels) { + switch (wasapi_channels) { case 2: // Stereo case 4: // Surround 3.1 case 6: // Surround 5.1 case 8: // Surround 7.1 + channels = wasapi_channels; break; default: - ERR_PRINTS("WASAPI: Unsupported number of channels: " + itos(channels)); - ERR_FAIL_V(ERR_CANT_OPEN); + WARN_PRINTS("WASAPI: Unsupported number of channels: " + itos(wasapi_channels)); + channels = 2; break; } @@ -206,6 +207,35 @@ AudioDriver::SpeakerMode AudioDriverWASAPI::get_speaker_mode() const { return get_speaker_mode_by_total_channels(channels); } +void AudioDriverWASAPI::write_sample(AudioDriverWASAPI *ad, BYTE *buffer, int i, int32_t sample) { + if (ad->format_tag == WAVE_FORMAT_PCM) { + switch (ad->bits_per_sample) { + case 8: + ((int8_t *)buffer)[i] = sample >> 24; + break; + + case 16: + ((int16_t *)buffer)[i] = sample >> 16; + break; + + case 24: + ((int8_t *)buffer)[i * 3 + 2] = sample >> 24; + ((int8_t *)buffer)[i * 3 + 1] = sample >> 16; + ((int8_t *)buffer)[i * 3 + 0] = sample >> 8; + break; + + case 32: + ((int32_t *)buffer)[i] = sample; + break; + } + } else if (ad->format_tag == WAVE_FORMAT_IEEE_FLOAT) { + ((float *)buffer)[i] = (sample >> 16) / 32768.f; + } else { + ERR_PRINT("WASAPI: Unknown format tag"); + ad->exit_thread = true; + } +} + void AudioDriverWASAPI::thread_func(void *p_udata) { AudioDriverWASAPI *ad = (AudioDriverWASAPI *)p_udata; @@ -240,42 +270,21 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { if (hr == S_OK) { // We're using WASAPI Shared Mode so we must convert the buffer - if (ad->format_tag == WAVE_FORMAT_PCM) { - switch (ad->bits_per_sample) { - case 8: - for (unsigned int i = 0; i < write_frames * ad->channels; i++) { - ((int8_t *)buffer)[i] = ad->samples_in[buffer_idx++] >> 24; - } - break; - - case 16: - for (unsigned int i = 0; i < write_frames * ad->channels; i++) { - ((int16_t *)buffer)[i] = ad->samples_in[buffer_idx++] >> 16; - } - break; - - case 24: - for (unsigned int i = 0; i < write_frames * ad->channels; i++) { - int32_t sample = ad->samples_in[buffer_idx++]; - ((int8_t *)buffer)[i * 3 + 2] = sample >> 24; - ((int8_t *)buffer)[i * 3 + 1] = sample >> 16; - ((int8_t *)buffer)[i * 3 + 0] = sample >> 8; - } - break; - - case 32: - for (unsigned int i = 0; i < write_frames * ad->channels; i++) { - ((int32_t *)buffer)[i] = ad->samples_in[buffer_idx++]; - } - break; - } - } else if (ad->format_tag == WAVE_FORMAT_IEEE_FLOAT) { + if (ad->channels == ad->wasapi_channels) { for (unsigned int i = 0; i < write_frames * ad->channels; i++) { - ((float *)buffer)[i] = (ad->samples_in[buffer_idx++] >> 16) / 32768.f; + ad->write_sample(ad, buffer, i, ad->samples_in[buffer_idx++]); } } else { - ERR_PRINT("WASAPI: Unknown format tag"); - ad->exit_thread = true; + for (unsigned int i = 0; i < write_frames; i++) { + for (unsigned int j = 0; j < MIN(ad->channels, ad->wasapi_channels); j++) { + ad->write_sample(ad, buffer, i * ad->wasapi_channels + j, ad->samples_in[buffer_idx++]); + } + if (ad->wasapi_channels > ad->channels) { + for (unsigned int j = ad->channels; j < ad->wasapi_channels; j++) { + ad->write_sample(ad, buffer, i * ad->wasapi_channels + j, 0); + } + } + } } hr = ad->render_client->ReleaseBuffer(write_frames, 0); @@ -380,6 +389,7 @@ AudioDriverWASAPI::AudioDriverWASAPI() { buffer_size = 0; channels = 0; + wasapi_channels = 0; mix_rate = 0; buffer_frames = 0; diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h index 87a2db724c..5921645f6e 100644 --- a/drivers/wasapi/audio_driver_wasapi.h +++ b/drivers/wasapi/audio_driver_wasapi.h @@ -55,6 +55,7 @@ class AudioDriverWASAPI : public AudioDriver { unsigned int buffer_size; unsigned int channels; + unsigned int wasapi_channels; int mix_rate; int buffer_frames; @@ -62,6 +63,7 @@ class AudioDriverWASAPI : public AudioDriver { mutable bool exit_thread; bool active; + _FORCE_INLINE_ void write_sample(AudioDriverWASAPI *ad, BYTE *buffer, int i, int32_t sample); static void thread_func(void *p_udata); Error init_device(bool reinit = false); |