diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/dummy/rasterizer_dummy.h | 2 | ||||
| -rw-r--r-- | drivers/gles2/rasterizer_canvas_gles2.cpp | 2 | ||||
| -rw-r--r-- | drivers/gles2/rasterizer_scene_gles2.cpp | 96 | ||||
| -rw-r--r-- | drivers/gles2/rasterizer_scene_gles2.h | 4 | ||||
| -rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.cpp | 22 | ||||
| -rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.h | 1 | ||||
| -rw-r--r-- | drivers/gles2/shader_compiler_gles2.cpp | 15 | ||||
| -rw-r--r-- | drivers/gles2/shader_gles2.h | 2 | ||||
| -rw-r--r-- | drivers/gles2/shaders/canvas.glsl | 5 | ||||
| -rw-r--r-- | drivers/gles2/shaders/copy.glsl | 29 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 85 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 4 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 47 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 1 | ||||
| -rw-r--r-- | drivers/gles3/shader_compiler_gles3.cpp | 13 | ||||
| -rw-r--r-- | drivers/gles3/shaders/canvas.glsl | 5 | ||||
| -rw-r--r-- | drivers/gles3/shaders/copy.glsl | 36 | ||||
| -rw-r--r-- | drivers/unix/net_socket_posix.cpp | 6 | ||||
| -rw-r--r-- | drivers/wasapi/audio_driver_wasapi.cpp | 16 | ||||
| -rw-r--r-- | drivers/windows/file_access_windows.cpp | 8 |
20 files changed, 342 insertions, 57 deletions
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index 253936ca34..6f91fc4949 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -61,6 +61,7 @@ public: void environment_set_bg_energy(RID p_env, float p_energy) {} void environment_set_canvas_max_layer(RID p_env, int p_max_layer) {} void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0) {} + void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id){}; void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {} void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {} @@ -216,6 +217,7 @@ public: uint32_t texture_get_height(RID p_texture) const { return 0; } uint32_t texture_get_depth(RID p_texture) const { return 0; } void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth_3d) {} + void texture_bind(RID p_texture, uint32_t p_texture_no) {} void texture_set_path(RID p_texture, const String &p_path) { DummyTexture *t = texture_owner.getornull(p_texture); diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index ee722e9d6c..b82186162d 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -1081,6 +1081,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur } else { glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 3, buffer + color_ofs); } + } else { + glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 3, 1.0, 1.0, 1.0, 1.0); } if (multi_mesh->custom_data_floats) { diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index 50cb39b13f..a07c6832dc 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -36,6 +36,7 @@ #include "core/project_settings.h" #include "core/vmap.h" #include "rasterizer_canvas_gles2.h" +#include "servers/camera/camera_feed.h" #include "servers/visual/visual_server_raster.h" #ifndef GLES_OVER_GL @@ -769,6 +770,13 @@ void RasterizerSceneGLES2::environment_set_ambient_light(RID p_env, const Color env->ambient_sky_contribution = p_sky_contribution; } +void RasterizerSceneGLES2::environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) { + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->camera_feed_id = p_camera_feed_id; +} + void RasterizerSceneGLES2::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -2261,7 +2269,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, bool rebind_reflection = false; bool rebind_lightmap = false; - if (!p_shadow) { + if (!p_shadow && material->shader) { bool unshaded = material->shader->spatial.unshaded; @@ -2281,7 +2289,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, bool depth_prepass = false; - if (!p_alpha_pass && material->shader && material->shader->spatial.depth_draw_mode == RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { + if (!p_alpha_pass && material->shader->spatial.depth_draw_mode == RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { depth_prepass = true; } @@ -2843,6 +2851,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const // clear color Color clear_color(0, 0, 0, 1); + Ref<CameraFeed> feed; if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { clear_color = Color(0, 0, 0, 0); @@ -2855,6 +2864,9 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const } else if (env->bg_mode == VS::ENV_BG_CANVAS || env->bg_mode == VS::ENV_BG_COLOR || env->bg_mode == VS::ENV_BG_COLOR_SKY) { clear_color = env->bg_color; storage->frame.clear_request = false; + } else if (env->bg_mode == VS::ENV_BG_CAMERA_FEED) { + feed = CameraServer::get_singleton()->get_feed_by_id(env->camera_feed_id); + storage->frame.clear_request = false; } else { storage->frame.clear_request = false; } @@ -2891,7 +2903,66 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const env_radiance_tex = sky->radiance; } } break; + case VS::ENV_BG_CAMERA_FEED: { + if (feed.is_valid() && (feed->get_base_width() > 0) && (feed->get_base_height() > 0)) { + // copy our camera feed to our background + + glDisable(GL_BLEND); + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, true); + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_DISPLAY_TRANSFORM, true); + + if (feed->get_datatype() == CameraFeed::FEED_RGB) { + RID camera_RGBA = feed->get_texture(CameraServer::FEED_RGBA_IMAGE); + + VS::get_singleton()->texture_bind(camera_RGBA, 0); + + } else if (feed->get_datatype() == CameraFeed::FEED_YCbCr) { + RID camera_YCbCr = feed->get_texture(CameraServer::FEED_YCbCr_IMAGE); + + VS::get_singleton()->texture_bind(camera_YCbCr, 0); + + storage->shaders.copy.set_conditional(CopyShaderGLES2::YCBCR_TO_RGB, true); + + } else if (feed->get_datatype() == CameraFeed::FEED_YCbCr_Sep) { + RID camera_Y = feed->get_texture(CameraServer::FEED_Y_IMAGE); + RID camera_CbCr = feed->get_texture(CameraServer::FEED_CbCr_IMAGE); + + VS::get_singleton()->texture_bind(camera_Y, 0); + VS::get_singleton()->texture_bind(camera_CbCr, 1); + + storage->shaders.copy.set_conditional(CopyShaderGLES2::SEP_CBCR_TEXTURE, true); + storage->shaders.copy.set_conditional(CopyShaderGLES2::YCBCR_TO_RGB, true); + }; + + storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES2::DISPLAY_TRANSFORM, feed->get_transform()); + + storage->bind_quad_array(); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisableVertexAttribArray(VS::ARRAY_VERTEX); + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + // turn off everything used + storage->shaders.copy.set_conditional(CopyShaderGLES2::SEP_CBCR_TEXTURE, false); + storage->shaders.copy.set_conditional(CopyShaderGLES2::YCBCR_TO_RGB, false); + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, false); + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_DISPLAY_TRANSFORM, false); + //restore + glEnable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + } else { + // don't have a feed, just show greenscreen :) + clear_color = Color(0.0, 1.0, 0.0, 1.0); + } + } break; default: { // FIXME: implement other background modes } break; @@ -2919,7 +2990,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const if (storage->frame.current_rt && state.used_screen_texture) { //copy screen texture - if (storage->frame.current_rt && storage->frame.current_rt->multisample_active) { + if (storage->frame.current_rt->multisample_active) { // Resolve framebuffer to front buffer before copying #ifdef GLES_OVER_GL @@ -2931,14 +3002,16 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); #elif IPHONE_ENABLED + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); glResolveMultisampleFramebufferAPPLE(); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); -#else - // In GLES2 Blit is not available, so just copy color texture manually +#elif ANDROID_ENABLED + + // In GLES2 AndroidBlit is not available, so just copy color texture manually _copy_texture_to_front_buffer(storage->frame.current_rt->multisample_color); #endif } @@ -2972,8 +3045,17 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); -#else - // In GLES2 Blit is not available, so just copy color texture manually +#elif IPHONE_ENABLED + + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); + glResolveMultisampleFramebufferAPPLE(); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +#elif ANDROID_ENABLED + + // In GLES2 Android Blit is not available, so just copy color texture manually _copy_texture_to_front_buffer(storage->frame.current_rt->multisample_color); #endif } diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h index d5a691d0b9..c95385eb24 100644 --- a/drivers/gles2/rasterizer_scene_gles2.h +++ b/drivers/gles2/rasterizer_scene_gles2.h @@ -354,6 +354,8 @@ public: float bg_energy; float sky_ambient; + int camera_feed_id; + Color ambient_color; float ambient_energy; float ambient_sky_contribution; @@ -381,6 +383,7 @@ public: sky_custom_fov(0.0), bg_energy(1.0), sky_ambient(0), + camera_feed_id(0), ambient_energy(1.0), ambient_sky_contribution(0.0), canvas_max_layer(0), @@ -413,6 +416,7 @@ public: virtual void environment_set_bg_energy(RID p_env, float p_energy); virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer); virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0); + virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id); virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index c610f31bc1..70f1173a7d 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -91,7 +91,7 @@ GLuint RasterizerStorageGLES2::system_fbo = 0; //void *glRenderbufferStorageMultisampleAPPLE; //void *glResolveMultisampleFramebufferAPPLE; #define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleAPPLE -#else +#elif ANDROID_ENABLED #include <GLES2/gl2ext.h> PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; @@ -968,6 +968,15 @@ uint32_t RasterizerStorageGLES2::texture_get_texid(RID p_texture) const { return texture->tex_id; } +void RasterizerStorageGLES2::texture_bind(RID p_texture, uint32_t p_texture_no) { + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND(!texture); + + glActiveTexture(GL_TEXTURE0 + p_texture_no); + glBindTexture(texture->target, texture->tex_id); +} + uint32_t RasterizerStorageGLES2::texture_get_width(RID p_texture) const { Texture *texture = texture_owner.getornull(p_texture); @@ -4688,6 +4697,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { /* BACK FBO */ /* For MSAA */ +#ifndef JAVASCRIPT_ENABLED if (rt->msaa != VS::VIEWPORT_MSAA_DISABLED && config.multisample_supported) { rt->multisample_active = true; @@ -4719,7 +4729,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->multisample_color); -#else +#elif ANDROID_ENABLED // Render to a texture in android glGenTextures(1, &rt->multisample_color); glBindTexture(GL_TEXTURE_2D, rt->multisample_color); @@ -4743,7 +4753,9 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glBindRenderbuffer(GL_RENDERBUFFER, 0); - } else { + } else +#endif + { rt->multisample_active = false; } @@ -5602,11 +5614,11 @@ void RasterizerStorageGLES2::initialize() { //Manually load extensions for android and ios #ifdef IPHONE_ENABLED - + // appears that IPhone doesn't need to dlopen TODO: test this rigorously before removing //void *gles2_lib = dlopen(NULL, RTLD_LAZY); //glRenderbufferStorageMultisampleAPPLE = dlsym(gles2_lib, "glRenderbufferStorageMultisampleAPPLE"); //glResolveMultisampleFramebufferAPPLE = dlsym(gles2_lib, "glResolveMultisampleFramebufferAPPLE"); -#else +#elif ANDROID_ENABLED void *gles2_lib = dlopen("libGLESv2.so", RTLD_LAZY); glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glRenderbufferStorageMultisampleEXT"); diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index af57aa3d9b..d139697b86 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -350,6 +350,7 @@ public: virtual uint32_t texture_get_height(RID p_texture) const; virtual uint32_t texture_get_depth(RID p_texture) const; virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth); + virtual void texture_bind(RID p_texture, uint32_t p_texture_no); virtual void texture_set_path(RID p_texture, const String &p_path); virtual String texture_get_path(RID p_texture) const; diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 9778d39a21..b48b93944c 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -361,6 +361,21 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener fragment_global += final_code; } + // constants + + for (Map<StringName, SL::ShaderNode::Constant>::Element *E = snode->constants.front(); E; E = E->next()) { + String gcode; + gcode += "const "; + gcode += _prestr(E->get().precision); + gcode += _typestr(E->get().type); + gcode += " " + _mkid(E->key()); + gcode += "="; + gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + gcode += ";\n"; + vertex_global += gcode; + fragment_global += gcode; + } + // functions Map<StringName, String> function_code; diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h index ebea40e10e..2456a83d35 100644 --- a/drivers/gles2/shader_gles2.h +++ b/drivers/gles2/shader_gles2.h @@ -1,4 +1,4 @@ -/*************************************************************************/ +/*************************************************************************/ /* shader_gles2.h */ /*************************************************************************/ /* This file is part of: */ diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 7dce784f52..0818942b0a 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -112,7 +112,12 @@ void main() { #ifdef USE_INSTANCING mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0))); color *= instance_color; + +#ifdef USE_INSTANCE_CUSTOM vec4 instance_custom = instance_custom_data; +#else + vec4 instance_custom = vec4(0.0); +#endif #else mat4 extra_matrix_instance = extra_matrix; diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index 931b3f3708..195db7c45f 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -28,8 +28,15 @@ varying vec2 uv_interp; #endif varying vec2 uv2_interp; +// These definitions are here because the shader-wrapper builder does +// not understand `#elif defined()` +#ifdef USE_DISPLAY_TRANSFORM +#endif + #ifdef USE_COPY_SECTION uniform highp vec4 copy_section; +#elif defined(USE_DISPLAY_TRANSFORM) +uniform highp mat4 display_transform; #endif void main() { @@ -48,6 +55,8 @@ void main() { #ifdef USE_COPY_SECTION uv_interp = copy_section.xy + uv_interp * copy_section.zw; gl_Position.xy = (copy_section.xy + (gl_Position.xy * 0.5 + 0.5) * copy_section.zw) * 2.0 - 1.0; +#elif defined(USE_DISPLAY_TRANSFORM) + uv_interp = (display_transform * vec4(uv_in, 1.0, 1.0)).xy; #endif } @@ -88,6 +97,10 @@ uniform samplerCube source_cube; // texunit:0 uniform sampler2D source; // texunit:0 #endif +#ifdef SEP_CBCR_TEXTURE +uniform sampler2D CbCr; //texunit:1 +#endif + varying vec2 uv2_interp; #ifdef USE_MULTIPLIER @@ -145,10 +158,26 @@ void main() { #elif defined(USE_CUBEMAP) vec4 color = textureCube(source_cube, normalize(cube_interp)); +#elif defined(SEP_CBCR_TEXTURE) + vec4 color; + color.r = texture2D(source, uv_interp).r; + color.gb = texture2D(CbCr, uv_interp).rg - vec2(0.5, 0.5); + color.a = 1.0; #else vec4 color = texture2D(source, uv_interp); #endif +#ifdef YCBCR_TO_RGB + // YCbCr -> RGB conversion + + // Using BT.601, which is the standard for SDTV is provided as a reference + color.rgb = mat3( + vec3(1.00000, 1.00000, 1.00000), + vec3(0.00000, -0.34413, 1.77200), + vec3(1.40200, -0.71414, 0.00000)) * + color.rgb; +#endif + #ifdef USE_NO_ALPHA color.a = 1.0; #endif diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 4552fddfe8..7acb8a22bc 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -34,6 +34,7 @@ #include "core/os/os.h" #include "core/project_settings.h" #include "rasterizer_canvas_gles3.h" +#include "servers/camera/camera_feed.h" #include "servers/visual/visual_server_raster.h" #ifndef GLES_OVER_GL @@ -830,6 +831,12 @@ void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color env->ambient_energy = p_energy; env->ambient_sky_contribution = p_sky_contribution; } +void RasterizerSceneGLES3::environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) { + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->camera_feed_id = p_camera_feed_id; +} void RasterizerSceneGLES3::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) { @@ -3304,7 +3311,7 @@ void RasterizerSceneGLES3::_prepare_depth_texture() { void RasterizerSceneGLES3::_bind_depth_texture() { if (!state.bound_depth_texture) { - ERR_FAIL_COND(!state.prepared_depth_texture) + ERR_FAIL_COND(!state.prepared_depth_texture); //bind depth for read glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 8); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); @@ -4342,6 +4349,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const Color clear_color(0, 0, 0, 0); RasterizerStorageGLES3::Sky *sky = NULL; + Ref<CameraFeed> feed; GLuint env_radiance_tex = 0; if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { @@ -4376,6 +4384,9 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const clear_color = env->bg_color.to_linear(); storage->frame.clear_request = false; + } else if (env->bg_mode == VS::ENV_BG_CAMERA_FEED) { + feed = CameraServer::get_singleton()->get_feed_by_id(env->camera_feed_id); + storage->frame.clear_request = false; } else { storage->frame.clear_request = false; } @@ -4426,6 +4437,63 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); break; + case VS::ENV_BG_CAMERA_FEED: + if (feed.is_valid() && (feed->get_base_width() > 0) && (feed->get_base_height() > 0)) { + // copy our camera feed to our background + + glDisable(GL_BLEND); + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_DISPLAY_TRANSFORM, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, true); + + if (feed->get_datatype() == CameraFeed::FEED_RGB) { + RID camera_RGBA = feed->get_texture(CameraServer::FEED_RGBA_IMAGE); + + VS::get_singleton()->texture_bind(camera_RGBA, 0); + } else if (feed->get_datatype() == CameraFeed::FEED_YCbCr) { + RID camera_YCbCr = feed->get_texture(CameraServer::FEED_YCbCr_IMAGE); + + VS::get_singleton()->texture_bind(camera_YCbCr, 0); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, true); + + } else if (feed->get_datatype() == CameraFeed::FEED_YCbCr_Sep) { + RID camera_Y = feed->get_texture(CameraServer::FEED_Y_IMAGE); + RID camera_CbCr = feed->get_texture(CameraServer::FEED_CbCr_IMAGE); + + VS::get_singleton()->texture_bind(camera_Y, 0); + VS::get_singleton()->texture_bind(camera_CbCr, 1); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::SEP_CBCR_TEXTURE, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, true); + }; + + storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES3::DISPLAY_TRANSFORM, feed->get_transform()); + + _copy_screen(true, true); + + //turn off everything used + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_DISPLAY_TRANSFORM, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::SEP_CBCR_TEXTURE, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, false); + + //restore + glEnable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + } else { + // don't have a feed, just show greenscreen :) + clear_color = Color(0.0, 1.0, 0.0, 1.0); + } + break; default: { } } @@ -4552,8 +4620,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const } _post_process(env, p_cam_projection); - - if (false && shadow_atlas) { + // Needed only for debugging + /* if (shadow_atlas && storage->frame.current_rt) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -4563,7 +4631,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); } - if (false && storage->frame.current_rt) { + if (storage->frame.current_rt) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -4573,7 +4641,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 16, storage->frame.current_rt->height / 16), Rect2(0, 0, 1, 1)); } - if (false && reflection_atlas && storage->frame.current_rt) { + if (reflection_atlas && storage->frame.current_rt) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -4582,7 +4650,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); } - if (false && directional_shadow.fbo) { + if (directional_shadow.fbo) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -4592,7 +4660,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); } - if (false && env_radiance_tex) { + if ( env_radiance_tex) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -4603,8 +4671,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - + }*/ //disable all stuff } diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 59e23e5ac9..910f90edc2 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -376,6 +376,8 @@ public: float bg_energy; float sky_ambient; + int camera_feed_id; + Color ambient_color; float ambient_energy; float ambient_sky_contribution; @@ -461,6 +463,7 @@ public: sky_custom_fov(0.0), bg_energy(1.0), sky_ambient(0), + camera_feed_id(0), ambient_energy(1.0), ambient_sky_contribution(0.0), canvas_max_layer(0), @@ -542,6 +545,7 @@ public: virtual void environment_set_bg_energy(RID p_env, float p_energy); virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer); virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0); + virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id); virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 8311d0de84..f8a3283869 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1437,6 +1437,15 @@ uint32_t RasterizerStorageGLES3::texture_get_texid(RID p_texture) const { return texture->tex_id; } +void RasterizerStorageGLES3::texture_bind(RID p_texture, uint32_t p_texture_no) { + + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND(!texture); + + glActiveTexture(GL_TEXTURE0 + p_texture_no); + glBindTexture(texture->target, texture->tex_id); +} uint32_t RasterizerStorageGLES3::texture_get_width(RID p_texture) const { Texture *texture = texture_owner.get(p_texture); @@ -3501,7 +3510,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: if (p_vertex_count < (1 << 16)) { //read 16 bit indices const uint16_t *src_idx = (const uint16_t *)ir.ptr(); - for (int i = 0; i < index_count; i += 6) { + for (int i = 0; i + 5 < index_count; i += 6) { wr[i + 0] = src_idx[i / 2]; wr[i + 1] = src_idx[i / 2 + 1]; @@ -3515,7 +3524,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: //read 16 bit indices const uint32_t *src_idx = (const uint32_t *)ir.ptr(); - for (int i = 0; i < index_count; i += 6) { + for (int i = 0; i + 5 < index_count; i += 6) { wr[i + 0] = src_idx[i / 2]; wr[i + 1] = src_idx[i / 2 + 1]; @@ -3531,7 +3540,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: index_count = p_vertex_count * 2; wf_indices.resize(index_count); PoolVector<uint32_t>::Write wr = wf_indices.write(); - for (int i = 0; i < index_count; i += 6) { + for (int i = 0; i + 5 < index_count; i += 6) { wr[i + 0] = i / 2; wr[i + 1] = i / 2 + 1; @@ -3772,28 +3781,30 @@ PoolVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_m Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V(surface->index_array_len == 0, PoolVector<uint8_t>()); - PoolVector<uint8_t> ret; ret.resize(surface->index_array_byte_size); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id); + + if (surface->index_array_byte_size > 0) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id); #if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) - { - PoolVector<uint8_t>::Write w = ret.write(); - glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, w.ptr()); - } + { + PoolVector<uint8_t>::Write w = ret.write(); + glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, w.ptr()); + } #else - void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT); - ERR_FAIL_NULL_V(data, PoolVector<uint8_t>()); - { - PoolVector<uint8_t>::Write w = ret.write(); - copymem(w.ptr(), data, surface->index_array_byte_size); - } - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT); + ERR_FAIL_NULL_V(data, PoolVector<uint8_t>()); + { + PoolVector<uint8_t>::Write w = ret.write(); + copymem(w.ptr(), data, surface->index_array_byte_size); + } + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); #endif - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + return ret; } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 3d86558407..badb656e96 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -358,6 +358,7 @@ public: virtual uint32_t texture_get_height(RID p_texture) const; virtual uint32_t texture_get_depth(RID p_texture) const; virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth); + virtual void texture_bind(RID p_texture, uint32_t p_texture_no); virtual void texture_set_path(RID p_texture, const String &p_path); virtual String texture_get_path(RID p_texture) const; diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index e8417900ea..b0f0a71d56 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -472,6 +472,19 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener r_gen_code.fragment_global += interp_mode + "in " + vcode; } + for (Map<StringName, SL::ShaderNode::Constant>::Element *E = pnode->constants.front(); E; E = E->next()) { + String gcode; + gcode += "const "; + gcode += _prestr(E->get().precision); + gcode += _typestr(E->get().type); + gcode += " " + _mkid(E->key()); + gcode += "="; + gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + gcode += ";\n"; + r_gen_code.vertex_global += gcode; + r_gen_code.fragment_global += gcode; + } + Map<StringName, String> function_code; //code for functions diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 0d1e7ee4a1..a46b31c92e 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -117,7 +117,12 @@ void main() { #ifdef USE_INSTANCING mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0))); color *= instance_color; + +#ifdef USE_INSTANCE_CUSTOM vec4 instance_custom = instance_custom_data; +#else + vec4 instance_custom = vec4(0.0); +#endif #else mat4 extra_matrix_instance = extra_matrix; diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index e1a0813efc..232b9ce7c0 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -18,10 +18,19 @@ out vec2 uv_interp; out vec2 uv2_interp; +// These definitions are here because the shader-wrapper builder does +// not understand `#elif defined()` +#ifdef USE_DISPLAY_TRANSFORM +#endif + #ifdef USE_COPY_SECTION uniform vec4 copy_section; +#elif defined(USE_DISPLAY_TRANSFORM) + +uniform highp mat4 display_transform; + #endif void main() { @@ -44,6 +53,9 @@ void main() { uv_interp = copy_section.xy + uv_interp * copy_section.zw; gl_Position.xy = (copy_section.xy + (gl_Position.xy * 0.5 + 0.5) * copy_section.zw) * 2.0 - 1.0; +#elif defined(USE_DISPLAY_TRANSFORM) + + uv_interp = (display_transform * vec4(uv_in, 1.0, 1.0)).xy; #endif } @@ -73,6 +85,8 @@ uniform highp vec4 asym_proj; #endif #ifdef USE_TEXTURE2DARRAY #endif +#ifdef YCBCR_TO_SRGB +#endif #ifdef USE_CUBEMAP uniform samplerCube source_cube; //texunit:0 @@ -84,6 +98,10 @@ uniform sampler2DArray source_2d_array; //texunit:0 uniform sampler2D source; //texunit:0 #endif +#ifdef SEP_CBCR_TEXTURE +uniform sampler2D CbCr; //texunit:1 +#endif + /* clang-format on */ #if defined(USE_TEXTURE3D) || defined(USE_TEXTURE2DARRAY) @@ -166,14 +184,30 @@ void main() { vec4 color = textureLod(source_3d, vec3(uv_interp, layer), 0.0); #elif defined(USE_TEXTURE2DARRAY) vec4 color = textureLod(source_2d_array, vec3(uv_interp, layer), 0.0); +#elif defined(SEP_CBCR_TEXTURE) + vec4 color; + color.r = textureLod(source, uv_interp, 0.0).r; + color.gb = textureLod(CbCr, uv_interp, 0.0).rg - vec2(0.5, 0.5); + color.a = 1.0; #else vec4 color = textureLod(source, uv_interp, 0.0); #endif #ifdef LINEAR_TO_SRGB - //regular Linear -> SRGB conversion + // regular Linear -> SRGB conversion vec3 a = vec3(0.055); color.rgb = mix((vec3(1.0) + a) * pow(color.rgb, vec3(1.0 / 2.4)) - a, 12.92 * color.rgb, lessThan(color.rgb, vec3(0.0031308))); + +#elif defined(YCBCR_TO_SRGB) + + // YCbCr -> SRGB conversion + // Using BT.709 which is the standard for HDTV + color.rgb = mat3( + vec3(1.00000, 1.00000, 1.00000), + vec3(0.00000, -0.18732, 1.85560), + vec3(1.57481, -0.46813, 0.00000)) * + color.rgb; + #endif #ifdef SRGB_TO_LINEAR diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index 37abccbe27..75d51c8503 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -306,7 +306,7 @@ Error NetSocketPosix::bind(IP_Address p_addr, uint16_t p_port) { sockaddr_storage addr; size_t addr_size = _set_addr_storage(&addr, p_addr, p_port, _ip_type); - if (::bind(_sock, (struct sockaddr *)&addr, addr_size) == SOCK_EMPTY) { + if (::bind(_sock, (struct sockaddr *)&addr, addr_size) != 0) { close(); ERR_FAIL_V(ERR_UNAVAILABLE); } @@ -317,7 +317,7 @@ Error NetSocketPosix::bind(IP_Address p_addr, uint16_t p_port) { Error NetSocketPosix::listen(int p_max_pending) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); - if (::listen(_sock, p_max_pending) == SOCK_EMPTY) { + if (::listen(_sock, p_max_pending) != 0) { close(); ERR_FAIL_V(FAILED); @@ -334,7 +334,7 @@ Error NetSocketPosix::connect_to_host(IP_Address p_host, uint16_t p_port) { struct sockaddr_storage addr; size_t addr_size = _set_addr_storage(&addr, p_host, p_port, _ip_type); - if (::connect(_sock, (struct sockaddr *)&addr, addr_size) == SOCK_EMPTY) { + if (::connect(_sock, (struct sockaddr *)&addr, addr_size) != 0) { NetError err = _get_socket_error(); diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index c97849ef07..fea38ee95d 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -167,13 +167,13 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); for (ULONG i = 0; i < count && !found; i++) { - IMMDevice *device = NULL; + IMMDevice *tmp_device = NULL; - hr = devices->Item(i, &device); + hr = devices->Item(i, &tmp_device); ERR_BREAK(hr != S_OK); IPropertyStore *props = NULL; - hr = device->OpenPropertyStore(STGM_READ, &props); + hr = tmp_device->OpenPropertyStore(STGM_READ, &props); ERR_BREAK(hr != S_OK); PROPVARIANT propvar; @@ -183,7 +183,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c ERR_BREAK(hr != S_OK); if (p_device->device_name == String(propvar.pwszVal)) { - hr = device->GetId(&strId); + hr = tmp_device->GetId(&strId); ERR_BREAK(hr != S_OK); found = true; @@ -191,7 +191,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c PropVariantClear(&propvar); props->Release(); - device->Release(); + tmp_device->Release(); } if (found) { @@ -289,7 +289,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c } DWORD streamflags = 0; - if (mix_rate != pwfex->nSamplesPerSec) { + if ((DWORD)mix_rate != pwfex->nSamplesPerSec) { streamflags |= AUDCLNT_STREAMFLAGS_RATEADJUST; pwfex->nSamplesPerSec = mix_rate; pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nChannels * (pwfex->wBitsPerSample / 8); @@ -571,7 +571,7 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { if (ad->audio_output.active) { ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptrw()); } else { - for (unsigned int i = 0; i < ad->samples_in.size(); i++) { + for (int i = 0; i < ad->samples_in.size(); i++) { ad->samples_in.write[i] = 0; } } @@ -699,7 +699,7 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { ERR_BREAK(hr != S_OK); // fixme: Only works for floating point atm - for (int j = 0; j < num_frames_available; j++) { + for (UINT32 j = 0; j < num_frames_available; j++) { int32_t l, r; if (flags & AUDCLNT_BUFFERFLAGS_SILENT) { diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index c13300d09f..646e744248 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -93,7 +93,7 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { // a file using the wrong case (which *works* on Windows, but won't on other // platforms). if (p_mode_flags == READ) { - WIN32_FIND_DATAW d = { 0 }; + WIN32_FIND_DATAW d; HANDLE f = FindFirstFileW(path.c_str(), &d); if (f) { String fname = d.cFileName; @@ -302,7 +302,7 @@ void FileAccessWindows::store_buffer(const uint8_t *p_src, int p_length) { } prev_op = WRITE; } - ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != p_length); + ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != (size_t)p_length); } bool FileAccessWindows::file_exists(const String &p_name) { @@ -340,13 +340,11 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) { } uint32_t FileAccessWindows::_get_unix_permissions(const String &p_file) { - ERR_PRINT("Windows does not support unix permissions"); return 0; } Error FileAccessWindows::_set_unix_permissions(const String &p_file, uint32_t p_permissions) { - ERR_PRINT("Windows does not support unix permissions"); - return FAILED; + return ERR_UNAVAILABLE; } FileAccessWindows::FileAccessWindows() : |