summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.cpp13
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.h1
-rw-r--r--drivers/dummy/rasterizer_dummy.h170
-rw-r--r--drivers/dummy/texture_loader_dummy.cpp87
-rw-r--r--drivers/dummy/texture_loader_dummy.h47
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp49
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp9
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h2
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp113
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h7
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp50
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp7
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp67
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h4
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp1
-rw-r--r--drivers/gles3/shaders/canvas.glsl58
-rw-r--r--drivers/gles3/shaders/scene.glsl6
-rw-r--r--drivers/gles3/shaders/tonemap.glsl4
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp13
-rw-r--r--drivers/rtaudio/audio_driver_rtaudio.cpp2
-rw-r--r--drivers/unix/file_access_unix.cpp8
-rw-r--r--drivers/unix/ip_unix.cpp4
-rw-r--r--drivers/unix/os_unix.cpp25
-rw-r--r--drivers/unix/os_unix.h1
-rw-r--r--drivers/unix/stream_peer_tcp_posix.cpp21
-rw-r--r--drivers/unix/tcp_server_posix.cpp17
-rw-r--r--drivers/windows/file_access_windows.cpp4
-rw-r--r--drivers/windows/stream_peer_tcp_winsock.cpp4
-rw-r--r--drivers/windows/tcp_server_winsock.cpp1
29 files changed, 732 insertions, 63 deletions
diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp
index c84469f26f..6e451eabcd 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.cpp
+++ b/drivers/coreaudio/audio_driver_coreaudio.cpp
@@ -217,13 +217,24 @@ void AudioDriverCoreAudio::start() {
if (!active) {
OSStatus result = AudioOutputUnitStart(audio_unit);
if (result != noErr) {
- ERR_PRINT("AudioOutputUnitStart failed");
+ ERR_PRINT(("AudioOutputUnitStart failed, code: " + itos(result)).utf8().get_data());
} else {
active = true;
}
}
};
+void AudioDriverCoreAudio::stop() {
+ if (active) {
+ OSStatus result = AudioOutputUnitStop(audio_unit);
+ if (result != noErr) {
+ ERR_PRINT(("AudioOutputUnitStop failed, code: " + itos(result)).utf8().get_data());
+ } else {
+ active = false;
+ }
+ }
+}
+
int AudioDriverCoreAudio::get_mix_rate() const {
return mix_rate;
};
diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h
index 9891920263..c44e225521 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.h
+++ b/drivers/coreaudio/audio_driver_coreaudio.h
@@ -90,6 +90,7 @@ public:
virtual void finish();
bool try_lock();
+ void stop();
AudioDriverCoreAudio();
~AudioDriverCoreAudio();
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h
index ea0d3ec706..312d5aa378 100644
--- a/drivers/dummy/rasterizer_dummy.h
+++ b/drivers/dummy/rasterizer_dummy.h
@@ -127,7 +127,26 @@ public:
String path;
};
+ struct DummySurface {
+ uint32_t format;
+ VS::PrimitiveType primitive;
+ PoolVector<uint8_t> array;
+ int vertex_count;
+ PoolVector<uint8_t> index_array;
+ int index_count;
+ AABB aabb;
+ Vector<PoolVector<uint8_t> > blend_shapes;
+ Vector<AABB> bone_aabbs;
+ };
+
+ struct DummyMesh : public RID_Data {
+ Vector<DummySurface> surfaces;
+ int blend_shape_count;
+ VS::BlendShapeMode blend_shape_mode;
+ };
+
mutable RID_Owner<DummyTexture> texture_owner;
+ mutable RID_Owner<DummyMesh> mesh_owner;
RID texture_create() {
@@ -154,6 +173,19 @@ public:
t->image->create(t->width, t->height, false, t->format, p_image->get_data());
}
+ void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side) {
+ DummyTexture *t = texture_owner.get(p_texture);
+
+ ERR_FAIL_COND(!t);
+ ERR_FAIL_COND(t->format != p_image->get_format());
+ ERR_FAIL_COND(p_image.is_null());
+ ERR_FAIL_COND(src_w <= 0 || src_h <= 0);
+ ERR_FAIL_COND(src_x < 0 || src_y < 0 || src_x + src_w > p_image->get_width() || src_y + src_h > p_image->get_height());
+ ERR_FAIL_COND(dst_x < 0 || dst_y < 0 || dst_x + src_w > t->width || dst_y + src_h > t->height);
+
+ t->image->blit_rect(p_image, Rect2(src_x, src_y, src_w, src_h), Vector2(dst_x, dst_y));
+ }
+
Ref<Image> texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const {
DummyTexture *t = texture_owner.getornull(p_texture);
ERR_FAIL_COND_V(!t, Ref<Image>());
@@ -243,46 +275,128 @@ public:
/* MESH API */
- RID mesh_create() { return RID(); }
-
- void mesh_add_surface_from_arrays(RID p_mesh, VS::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), uint32_t p_compress_format = Mesh::ARRAY_COMPRESS_DEFAULT) {}
- void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()) {}
+ RID mesh_create() {
+ DummyMesh *mesh = memnew(DummyMesh);
+ ERR_FAIL_COND_V(!mesh, RID());
+ mesh->blend_shape_count = 0;
+ mesh->blend_shape_mode = VS::BLEND_SHAPE_MODE_NORMALIZED;
+ return mesh_owner.make_rid(mesh);
+ }
- void mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry::MeshData &p_mesh_data) {}
- void mesh_add_surface_from_planes(RID p_mesh, const PoolVector<Plane> &p_planes) {}
+ void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()) {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!m);
+
+ m->surfaces.push_back(DummySurface());
+ DummySurface *s = &m->surfaces[m->surfaces.size() - 1];
+ s->format = p_format;
+ s->primitive = p_primitive;
+ s->array = p_array;
+ s->vertex_count = p_vertex_count;
+ s->index_array = p_index_array;
+ s->index_count = p_index_count;
+ s->aabb = p_aabb;
+ s->blend_shapes = p_blend_shapes;
+ s->bone_aabbs = p_bone_aabbs;
+ }
- void mesh_set_blend_shape_count(RID p_mesh, int p_amount) {}
- int mesh_get_blend_shape_count(RID p_mesh) const { return 0; }
+ void mesh_set_blend_shape_count(RID p_mesh, int p_amount) {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!m);
+ m->blend_shape_count = p_amount;
+ }
+ int mesh_get_blend_shape_count(RID p_mesh) const {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!m, 0);
+ return m->blend_shape_count;
+ }
- void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) {}
- VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const { return VS::BLEND_SHAPE_MODE_NORMALIZED; }
+ void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!m);
+ m->blend_shape_mode = p_mode;
+ }
+ VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!m, VS::BLEND_SHAPE_MODE_NORMALIZED);
+ return m->blend_shape_mode;
+ }
void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data) {}
void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {}
RID mesh_surface_get_material(RID p_mesh, int p_surface) const { return RID(); }
- int mesh_surface_get_array_len(RID p_mesh, int p_surface) const { return 0; }
- int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const { return 0; }
+ int mesh_surface_get_array_len(RID p_mesh, int p_surface) const {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!m, 0);
+
+ return m->surfaces[p_surface].vertex_count;
+ }
+ int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!m, 0);
+
+ return m->surfaces[p_surface].index_count;
+ }
PoolVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const {
- PoolVector<uint8_t> p;
- return p;
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!m, PoolVector<uint8_t>());
+
+ return m->surfaces[p_surface].array;
}
PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const {
- PoolVector<uint8_t> p;
- return p;
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!m, PoolVector<uint8_t>());
+
+ return m->surfaces[p_surface].index_array;
+ }
+
+ uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!m, 0);
+
+ return m->surfaces[p_surface].format;
+ }
+ VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!m, VS::PRIMITIVE_POINTS);
+
+ return m->surfaces[p_surface].primitive;
+ }
+
+ AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!m, AABB());
+
+ return m->surfaces[p_surface].aabb;
}
+ Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!m, Vector<PoolVector<uint8_t> >());
- uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const { return 0; }
- VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { return VS::PRIMITIVE_POINTS; }
+ return m->surfaces[p_surface].blend_shapes;
+ }
+ Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!m, Vector<AABB>());
- AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const { return AABB(); }
- Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const { return Vector<PoolVector<uint8_t> >(); }
- Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const { return Vector<AABB>(); }
+ return m->surfaces[p_surface].bone_aabbs;
+ }
- void mesh_remove_surface(RID p_mesh, int p_index) {}
- int mesh_get_surface_count(RID p_mesh) const { return 0; }
+ void mesh_remove_surface(RID p_mesh, int p_index) {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!m);
+ ERR_FAIL_COND(p_index >= m->surfaces.size());
+
+ m->surfaces.remove(p_index);
+ }
+ int mesh_get_surface_count(RID p_mesh) const {
+ DummyMesh *m = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!m, 0);
+ return m->surfaces.size();
+ }
void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {}
AABB mesh_get_custom_aabb(RID p_mesh) const { return AABB(); }
@@ -333,6 +447,7 @@ public:
RID skeleton_create() { return RID(); }
void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) {}
+ void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {}
int skeleton_get_bone_count(RID p_skeleton) const { return 0; }
void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) {}
Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { return Transform(); }
@@ -584,7 +699,14 @@ public:
RID canvas_light_occluder_create() { return RID(); }
void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) {}
- VS::InstanceType get_base_type(RID p_rid) const { return VS::INSTANCE_NONE; }
+ VS::InstanceType get_base_type(RID p_rid) const {
+ if (mesh_owner.owns(p_rid)) {
+ return VS::INSTANCE_MESH;
+ }
+
+ return VS::INSTANCE_NONE;
+ }
+
bool free(RID p_rid) {
if (texture_owner.owns(p_rid)) {
diff --git a/drivers/dummy/texture_loader_dummy.cpp b/drivers/dummy/texture_loader_dummy.cpp
new file mode 100644
index 0000000000..6d3e176bbb
--- /dev/null
+++ b/drivers/dummy/texture_loader_dummy.cpp
@@ -0,0 +1,87 @@
+/*************************************************************************/
+/* texture_loader_dummy.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "texture_loader_dummy.h"
+#include "core/os/file_access.h"
+#include "print_string.h"
+#include <string.h>
+
+RES ResourceFormatDummyTexture::load(const String &p_path, const String &p_original_path, Error *r_error) {
+ unsigned int width = 8;
+ unsigned int height = 8;
+
+ //We just use some format
+ Image::Format fmt = Image::FORMAT_RGB8;
+ int rowsize = 3 * width;
+
+ PoolVector<uint8_t> dstbuff;
+
+ dstbuff.resize(rowsize * height);
+
+ PoolVector<uint8_t>::Write dstbuff_write = dstbuff.write();
+
+ uint8_t *data = dstbuff_write.ptr();
+
+ uint8_t **row_p = memnew_arr(uint8_t *, height);
+
+ for (unsigned int i = 0; i < height; i++) {
+ row_p[i] = 0; //No colors any more, I want them to turn black
+ }
+
+ memdelete_arr(row_p);
+
+ Ref<Image> img = memnew(Image(width, height, 0, fmt, dstbuff));
+
+ Ref<ImageTexture> texture = memnew(ImageTexture);
+ texture->create_from_image(img);
+
+ if (r_error)
+ *r_error = OK;
+
+ return texture;
+}
+
+void ResourceFormatDummyTexture::get_recognized_extensions(List<String> *p_extensions) const {
+ p_extensions->push_back("png");
+ p_extensions->push_back("hdr");
+ p_extensions->push_back("jpg");
+ p_extensions->push_back("tga");
+}
+
+bool ResourceFormatDummyTexture::handles_type(const String &p_type) const {
+ return ClassDB::is_parent_class(p_type, "Texture");
+}
+
+String ResourceFormatDummyTexture::get_resource_type(const String &p_path) const {
+ String extension = p_path.get_extension().to_lower();
+ if (extension == "png" || extension == "hdr" || extension == "jpg" || extension == "tga")
+ return "ImageTexture";
+ return "";
+}
diff --git a/drivers/dummy/texture_loader_dummy.h b/drivers/dummy/texture_loader_dummy.h
new file mode 100644
index 0000000000..f0a355ec12
--- /dev/null
+++ b/drivers/dummy/texture_loader_dummy.h
@@ -0,0 +1,47 @@
+/*************************************************************************/
+/* texture_loader_dummy.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TEXTURE_LOADER_DUMMY_H
+#define TEXTURE_LOADER_DUMMY_H
+
+#include "core/io/resource_loader.h"
+#include "scene/resources/texture.h"
+
+class ResourceFormatDummyTexture : public ResourceFormatLoader {
+public:
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String &p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+
+ virtual ~ResourceFormatDummyTexture() {}
+};
+
+#endif // TEXTURE_LOADER_DUMMY_H
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index 9339167c8e..ab48e682d6 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -316,7 +316,11 @@ void RasterizerGLES2::set_boot_image(const Ref<Image> &p_image, const Color &p_c
glViewport(0, 0, window_w, window_h);
glDisable(GL_BLEND);
glDepthMask(GL_FALSE);
- glClearColor(p_color.r, p_color.g, p_color.b, p_color.a);
+ if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ } else {
+ glClearColor(p_color.r, p_color.g, p_color.b, 1.0);
+ }
glClear(GL_COLOR_BUFFER_BIT);
canvas->canvas_begin();
@@ -340,6 +344,27 @@ void RasterizerGLES2::set_boot_image(const Ref<Image> &p_image, const Color &p_c
storage->free(texture);
+ if (OS::get_singleton()->is_layered_allowed()) {
+ if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
+#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED)
+ Size2 wndsize = OS::get_singleton()->get_layered_buffer_size();
+ uint8_t *data = OS::get_singleton()->get_layered_buffer_data();
+ if (data) {
+ glReadPixels(0, 0, wndsize.x, wndsize.y, GL_BGRA, GL_UNSIGNED_BYTE, data);
+ OS::get_singleton()->swap_layered_buffer();
+
+ return;
+ }
+#endif
+ } else {
+ //clear alpha
+ glColorMask(false, false, false, true);
+ glClearColor(0, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColorMask(true, true, true, true);
+ }
+ }
+
OS::get_singleton()->swap_buffers();
}
@@ -373,6 +398,28 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
}
void RasterizerGLES2::end_frame(bool p_swap_buffers) {
+
+ if (OS::get_singleton()->is_layered_allowed()) {
+ if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
+#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED)
+ Size2 wndsize = OS::get_singleton()->get_layered_buffer_size();
+ uint8_t *data = OS::get_singleton()->get_layered_buffer_data();
+ if (data) {
+ glReadPixels(0, 0, wndsize.x, wndsize.y, GL_BGRA, GL_UNSIGNED_BYTE, data);
+ OS::get_singleton()->swap_layered_buffer();
+
+ return;
+ }
+#endif
+ } else {
+ //clear alpha
+ glColorMask(false, false, false, true);
+ glClearColor(0, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColorMask(true, true, true, true);
+ }
+ }
+
if (p_swap_buffers)
OS::get_singleton()->swap_buffers();
else
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 5bca3ee548..6e7e1793e1 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -452,6 +452,11 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
texture->mipmaps = mipmaps;
}
+void RasterizerStorageGLES2::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side) {
+ // TODO
+ ERR_PRINT("Not implemented (ask Karroffel to do it :p)");
+}
+
Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side) const {
Texture *texture = texture_owner.getornull(p_texture);
@@ -1297,6 +1302,10 @@ Transform2D RasterizerStorageGLES2::skeleton_bone_get_transform_2d(RID p_skeleto
return Transform2D();
}
+void RasterizerStorageGLES2::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
+
+}
+
void RasterizerStorageGLES2::update_dirty_skeletons() {
}
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 9f8d8d100b..b735f2e148 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -237,6 +237,7 @@ public:
virtual RID texture_create();
virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT);
+ virtual void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT);
virtual Ref<Image> texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const;
virtual void texture_set_flags(RID p_texture, uint32_t p_flags);
virtual uint32_t texture_get_flags(RID p_texture) const;
@@ -555,6 +556,7 @@ public:
virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const;
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
+ virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
/* Light API */
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index c33fdaa355..bb4c8ab4d7 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -160,6 +160,7 @@ void RasterizerCanvasGLES3::canvas_begin() {
state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, false);
state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false);
state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_NINEPATCH, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, false);
state.canvas_shader.set_custom_shader(0);
state.canvas_shader.bind();
@@ -180,6 +181,7 @@ void RasterizerCanvasGLES3::canvas_begin() {
glBindVertexArray(data.canvas_quad_array);
state.using_texture_rect = true;
state.using_ninepatch = false;
+ state.using_skeleton = false;
}
void RasterizerCanvasGLES3::canvas_end() {
@@ -191,11 +193,11 @@ void RasterizerCanvasGLES3::canvas_end() {
state.using_ninepatch = false;
}
-RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map) {
+RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map, bool p_force) {
RasterizerStorageGLES3::Texture *tex_return = NULL;
- if (p_texture == state.current_tex) {
+ if (p_texture == state.current_tex && !p_force) {
tex_return = state.current_tex_ptr;
} else if (p_texture.is_valid()) {
@@ -230,7 +232,7 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con
state.current_tex_ptr = NULL;
}
- if (p_normal_map == state.current_normal) {
+ if (p_normal_map == state.current_normal && !p_force) {
//do none
state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, state.current_normal.is_valid());
@@ -284,6 +286,10 @@ void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable, bool p_ninepat
state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate);
state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform);
state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix);
+ if (state.using_skeleton) {
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform);
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse);
+ }
if (storage->frame.current_rt) {
state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height));
} else {
@@ -293,7 +299,7 @@ void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable, bool p_ninepat
state.using_ninepatch = p_ninepatch;
}
-void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) {
+void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const int *p_bones, const float *p_weights) {
glBindVertexArray(data.polygon_buffer_pointer_array);
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
@@ -301,11 +307,17 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun
uint32_t buffer_ofs = 0;
//vertex
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size);
+#endif
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices);
glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs);
buffer_ofs += sizeof(Vector2) * p_vertex_count;
//color
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size);
+#endif
if (p_singlecolor) {
glDisableVertexAttribArray(VS::ARRAY_COLOR);
@@ -322,6 +334,10 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun
buffer_ofs += sizeof(Color) * p_vertex_count;
}
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size);
+#endif
+
if (p_uvs) {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
@@ -333,6 +349,32 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun
glDisableVertexAttribArray(VS::ARRAY_TEX_UV);
}
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size);
+#endif
+
+ if (p_bones && p_weights) {
+
+ glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones);
+ glEnableVertexAttribArray(VS::ARRAY_BONES);
+ //glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, false, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs);
+ glVertexAttribIPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs);
+ buffer_ofs += sizeof(int) * 4 * p_vertex_count;
+
+ glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights);
+ glEnableVertexAttribArray(VS::ARRAY_WEIGHTS);
+ glVertexAttribPointer(VS::ARRAY_WEIGHTS, 4, GL_FLOAT, false, sizeof(float) * 4, ((uint8_t *)0) + buffer_ofs);
+ buffer_ofs += sizeof(float) * 4 * p_vertex_count;
+
+ } else if (state.using_skeleton) {
+ glVertexAttribI4ui(VS::ARRAY_BONES, 0, 0, 0, 0);
+ glVertexAttrib4f(VS::ARRAY_WEIGHTS, 0, 0, 0, 0);
+ }
+
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size);
+#endif
+
//bind the indices buffer.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices);
@@ -342,6 +384,12 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun
storage->frame.canvas_draw_commands++;
+ if (p_bones && p_weights) {
+ //not used so often, so disable when used
+ glDisableVertexAttribArray(VS::ARRAY_BONES);
+ glDisableVertexAttribArray(VS::ARRAY_WEIGHTS);
+ }
+
glBindVertexArray(0);
}
@@ -735,7 +783,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size);
}
- _draw_polygon(polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
+
+ _draw_polygon(polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1, polygon->bones.ptr(), polygon->weights.ptr());
#ifdef GLES_OVER_GL
if (polygon->antialiased) {
glEnable(GL_LINE_SMOOTH);
@@ -921,7 +970,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
}
_bind_canvas_texture(RID(), RID());
- _draw_polygon(indices, numpoints * 3, numpoints + 1, points, NULL, &circle->color, true);
+ _draw_polygon(indices, numpoints * 3, numpoints + 1, points, NULL, &circle->color, true, NULL, NULL);
//_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true);
//canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1);
@@ -1037,7 +1086,7 @@ void RasterizerCanvasGLES3::_copy_texscreen(const Rect2 &p_rect) {
state.using_texture_rect = true;
_set_texture_rect_mode(false);
- _bind_canvas_texture(state.current_tex, state.current_normal);
+ _bind_canvas_texture(state.current_tex, state.current_normal, true);
glEnable(GL_BLEND);
}
@@ -1068,6 +1117,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
RID canvas_last_material;
bool prev_distance_field = false;
+ bool prev_use_skeleton = false;
while (p_item_list) {
@@ -1106,6 +1156,36 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
}
}
+ RasterizerStorageGLES3::Skeleton *skeleton = NULL;
+
+ {
+ //skeleton handling
+ if (ci->skeleton.is_valid()) {
+ skeleton = storage->skeleton_owner.getornull(ci->skeleton);
+ if (!skeleton->use_2d) {
+ skeleton = NULL;
+ } else {
+ state.skeleton_transform = p_transform * skeleton->base_transform_2d;
+ state.skeleton_transform_inverse = state.skeleton_transform.affine_inverse();
+ }
+ }
+
+ bool use_skeleton = skeleton != NULL;
+ if (prev_use_skeleton != use_skeleton) {
+ rebind_shader = true;
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, use_skeleton);
+ prev_use_skeleton = use_skeleton;
+ }
+
+ if (skeleton) {
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
+ glBindTexture(GL_TEXTURE_2D, skeleton->texture);
+ state.using_skeleton = true;
+ } else {
+ state.using_skeleton = false;
+ }
+ }
+
//begin rect
Item *material_owner = ci->material_owner ? ci->material_owner : ci;
@@ -1130,6 +1210,9 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
if (shader_ptr->canvas_item.uses_screen_texture && !state.canvas_texscreen_used) {
//copy if not copied before
_copy_texscreen(Rect2());
+
+ // blend mode will have been enabled so make sure we disable it again later on
+ last_blend_mode = last_blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1;
}
if (shader_ptr != shader_cache) {
@@ -1201,14 +1284,30 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
}
int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX;
+ if (blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) {
+ blend_mode = RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX;
+ }
bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode == RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX);
bool reclip = false;
if (last_blend_mode != blend_mode) {
+ if (last_blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED) {
+ // re-enable it
+ glEnable(GL_BLEND);
+ } else if (blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED) {
+ // disable it
+ glDisable(GL_BLEND);
+ }
switch (blend_mode) {
+ case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED: {
+
+ // nothing to do here
+
+ } break;
case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX: {
+
glBlendEquation(GL_FUNC_ADD);
if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 1dc17f98d5..c7f2e54efb 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -84,6 +84,9 @@ public:
Color canvas_item_modulate;
Transform2D extra_matrix;
Transform2D final_transform;
+ bool using_skeleton;
+ Transform2D skeleton_transform;
+ Transform2D skeleton_transform_inverse;
} state;
@@ -120,10 +123,10 @@ public:
virtual void canvas_end();
_FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false);
- _FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map);
+ _FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map, bool p_force = false);
_FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs);
- _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
+ _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const int *p_bones, const float *p_weights);
_FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
_FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip);
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index ca39d9f966..1abdaa5f80 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -111,8 +111,6 @@ static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GL
strcpy(debType, "Portability");
else if (type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB)
strcpy(debType, "Performance");
- else if (type == _EXT_DEBUG_TYPE_OTHER_ARB)
- strcpy(debType, "Other");
if (severity == _EXT_DEBUG_SEVERITY_HIGH_ARB)
strcpy(debSev, "High");
@@ -292,7 +290,11 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
glViewport(0, 0, window_w, window_h);
glDisable(GL_BLEND);
glDepthMask(GL_FALSE);
- glClearColor(p_color.r, p_color.g, p_color.b, 1.0);
+ if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ } else {
+ glClearColor(p_color.r, p_color.g, p_color.b, 1.0);
+ }
glClear(GL_COLOR_BUFFER_BIT);
canvas->canvas_begin();
@@ -331,6 +333,27 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
storage->free(texture); // free since it's only one frame that stays there
+ if (OS::get_singleton()->is_layered_allowed()) {
+ if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
+#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED)
+ Size2 wndsize = OS::get_singleton()->get_layered_buffer_size();
+ uint8_t *data = OS::get_singleton()->get_layered_buffer_data();
+ if (data) {
+ glReadPixels(0, 0, wndsize.x, wndsize.y, GL_BGRA, GL_UNSIGNED_BYTE, data);
+ OS::get_singleton()->swap_layered_buffer();
+
+ return;
+ }
+#endif
+ } else {
+ //clear alpha
+ glColorMask(false, false, false, true);
+ glClearColor(0, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColorMask(true, true, true, true);
+ }
+ }
+
OS::get_singleton()->swap_buffers();
}
@@ -367,6 +390,27 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target, const Re
void RasterizerGLES3::end_frame(bool p_swap_buffers) {
+ if (OS::get_singleton()->is_layered_allowed()) {
+ if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
+#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED)
+ Size2 wndsize = OS::get_singleton()->get_layered_buffer_size();
+ uint8_t *data = OS::get_singleton()->get_layered_buffer_data();
+ if (data) {
+ glReadPixels(0, 0, wndsize.x, wndsize.y, GL_BGRA, GL_UNSIGNED_BYTE, data);
+ OS::get_singleton()->swap_layered_buffer();
+
+ return;
+ }
+#endif
+ } else {
+ //clear alpha
+ glColorMask(false, false, false, true);
+ glClearColor(0, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColorMask(true, true, true, true);
+ }
+ }
+
if (p_swap_buffers)
OS::get_singleton()->swap_buffers();
else
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 5b6b3d44f2..8da2c2f9c2 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -2362,7 +2362,11 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C
ERR_FAIL_COND(!tex);
glActiveTexture(GL_TEXTURE0);
- glBindTexture(tex->target, tex->tex_id);
+
+ if (tex->proxy && tex->proxy->tex_id)
+ glBindTexture(tex->target, tex->proxy->tex_id);
+ else
+ glBindTexture(tex->target, tex->tex_id);
if (storage->config.srgb_decode_supported && tex->srgb && !tex->using_srgb) {
@@ -3906,6 +3910,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FILMIC_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_FILMIC);
state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_ACES_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_ACES);
state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINDHART_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_REINHARDT);
+ state.tonemap_shader.set_conditional(TonemapShaderGLES3::KEEP_3D_LINEAR, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]);
state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE, env->auto_exposure);
state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC, env->glow_bicubic_upscale);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index f91ed35331..85ae69f8b8 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -828,6 +828,58 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
//texture_set_flags(p_texture,texture->flags);
}
+// Uploads pixel data to a sub-region of a texture, for the specified mipmap.
+// The texture pixels must have been allocated before, because most features seen in texture_set_data() make no sense in a partial update.
+// TODO If we want this to be usable without pre-filling pixels with a full image, we have to call glTexImage2D() with null data.
+void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side) {
+
+ Texture *texture = texture_owner.get(p_texture);
+
+ ERR_FAIL_COND(!texture);
+ ERR_FAIL_COND(!texture->active);
+ ERR_FAIL_COND(texture->render_target);
+ ERR_FAIL_COND(texture->format != p_image->get_format());
+ ERR_FAIL_COND(p_image.is_null());
+ ERR_FAIL_COND(src_w <= 0 || src_h <= 0);
+ ERR_FAIL_COND(src_x < 0 || src_y < 0 || src_x + src_w > p_image->get_width() || src_y + src_h > p_image->get_height());
+ ERR_FAIL_COND(dst_x < 0 || dst_y < 0 || dst_x + src_w > texture->alloc_width || dst_y + src_h > texture->alloc_height);
+ ERR_FAIL_COND(p_dst_mip < 0 || p_dst_mip >= texture->mipmaps);
+
+ GLenum type;
+ GLenum format;
+ GLenum internal_format;
+ bool compressed;
+ bool srgb;
+
+ // Because OpenGL wants data as a dense array, we have to extract the sub-image if the source rect isn't the full image
+ Ref<Image> p_sub_img = p_image;
+ if (src_x > 0 || src_y > 0 || src_w != p_image->get_width() || src_h != p_image->get_height()) {
+ p_sub_img = p_image->get_rect(Rect2(src_x, src_y, src_w, src_h));
+ }
+
+ Ref<Image> img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, format, internal_format, type, compressed, srgb);
+
+ GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_cube_side] : GL_TEXTURE_2D;
+
+ PoolVector<uint8_t>::Read read = img->get_data().read();
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(texture->target, texture->tex_id);
+
+ int src_data_size = img->get_data().size();
+ int src_ofs = 0;
+
+ if (texture->compressed) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glCompressedTexSubImage2D(blit_target, p_dst_mip, dst_x, dst_y, src_w, src_h, internal_format, src_data_size, &read[src_ofs]);
+
+ } else {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ // `format` has to match the internal_format used when the texture was created
+ glTexSubImage2D(blit_target, p_dst_mip, dst_x, dst_y, src_w, src_h, format, type, &read[src_ofs]);
+ }
+}
+
Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side) const {
Texture *texture = texture_owner.get(p_texture);
@@ -1615,6 +1667,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB);
shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL);
shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA);
+ shaders.actions_canvas.render_mode_values["blend_disabled"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_DISABLED);
shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED);
shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY);
@@ -1912,7 +1965,7 @@ void RasterizerStorageGLES3::material_set_param(RID p_material, const StringName
Variant RasterizerStorageGLES3::material_get_param(RID p_material, const StringName &p_param) const {
const Material *material = material_owner.get(p_material);
- ERR_FAIL_COND_V(!material, RID());
+ ERR_FAIL_COND_V(!material, Variant());
if (material->params.has(p_param))
return material->params[p_param];
@@ -4496,6 +4549,15 @@ Transform2D RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleto
return ret;
}
+void RasterizerStorageGLES3::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
+
+ Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+
+ ERR_FAIL_COND(!skeleton->use_2d);
+
+ skeleton->base_transform_2d = p_base_transform;
+}
+
void RasterizerStorageGLES3::update_dirty_skeletons() {
glActiveTexture(GL_TEXTURE0);
@@ -5833,7 +5895,10 @@ void RasterizerStorageGLES3::update_particles() {
tex = resources.white_tex;
} break;
}
+ } else if (t->proxy && t->proxy->tex_id) {
+ target = t->proxy->target;
+ tex = t->proxy->tex_id;
} else {
target = t->target;
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index ef2b247266..6b626cbd00 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -340,6 +340,7 @@ public:
virtual RID texture_create();
virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT);
+ virtual void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT);
virtual Ref<Image> texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const;
virtual void texture_set_flags(RID p_texture, uint32_t p_flags);
virtual uint32_t texture_get_flags(RID p_texture) const;
@@ -420,6 +421,7 @@ public:
BLEND_MODE_SUB,
BLEND_MODE_MUL,
BLEND_MODE_PMALPHA,
+ BLEND_MODE_DISABLED,
};
int blend_mode;
@@ -868,6 +870,7 @@ public:
GLuint texture;
SelfList<Skeleton> update_list;
Set<RasterizerScene::InstanceBase *> instances; //instances using skeleton
+ Transform2D base_transform_2d;
Skeleton() :
update_list(this) {
@@ -891,6 +894,7 @@ public:
virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const;
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
+ virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
/* Light API */
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 1f3b76f5cd..eb8d6c485b 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -911,6 +911,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n";
+ actions[VS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n";
/* PARTICLES SHADER */
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 3bbeb1149d..326aab4c7c 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -4,6 +4,11 @@
layout(location=0) in highp vec2 vertex;
layout(location=3) in vec4 color_attrib;
+#ifdef USE_SKELETON
+layout(location=6) in uvec4 bone_indices; // attrib:6
+layout(location=7) in vec4 bone_weights; // attrib:7
+#endif
+
#ifdef USE_TEXTURE_RECT
uniform vec4 dst_rect;
@@ -51,6 +56,12 @@ out highp vec2 pixel_size_interp;
#endif
+#ifdef USE_SKELETON
+uniform mediump sampler2D skeleton_texture; // texunit:-1
+uniform highp mat4 skeleton_transform;
+uniform highp mat4 skeleton_transform_inverse;
+#endif
+
#ifdef USE_LIGHTING
layout(std140) uniform LightData { //ubo:1
@@ -75,7 +86,6 @@ out vec4 light_uv_interp;
out vec4 local_rot;
-
#ifdef USE_SHADOWS
out highp vec2 pos;
#endif
@@ -101,6 +111,7 @@ MATERIAL_UNIFORMS
#endif
+
VERTEX_SHADER_GLOBALS
void main() {
@@ -146,6 +157,7 @@ void main() {
#endif
+
#define extra_matrix extra_matrix2
{
@@ -175,6 +187,49 @@ VERTEX_SHADER_CODE
#endif
+#ifdef USE_SKELETON
+
+ if (bone_weights!=vec4(0.0)){ //must be a valid bone
+ //skeleton transform
+
+ ivec4 bone_indicesi = ivec4(bone_indices);
+
+ ivec2 tex_ofs = ivec2( bone_indicesi.x%256, (bone_indicesi.x/256)*2 );
+
+ highp mat2x4 m = mat2x4(
+ texelFetch(skeleton_texture,tex_ofs,0),
+ texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0)
+ ) * bone_weights.x;
+
+ tex_ofs = ivec2( bone_indicesi.y%256, (bone_indicesi.y/256)*2 );
+
+ m+= mat2x4(
+ texelFetch(skeleton_texture,tex_ofs,0),
+ texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0)
+ ) * bone_weights.y;
+
+ tex_ofs = ivec2( bone_indicesi.z%256, (bone_indicesi.z/256)*2 );
+
+ m+= mat2x4(
+ texelFetch(skeleton_texture,tex_ofs,0),
+ texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0)
+ ) * bone_weights.z;
+
+
+ tex_ofs = ivec2( bone_indicesi.w%256, (bone_indicesi.w/256)*2 );
+
+ m+= mat2x4(
+ texelFetch(skeleton_texture,tex_ofs,0),
+ texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0)
+ ) * bone_weights.w;
+
+ mat4 bone_matrix = skeleton_transform * transpose(mat4(m[0],m[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0))) * skeleton_transform_inverse;
+
+ outvec = bone_matrix * outvec;
+ }
+
+#endif
+
gl_Position = projection_matrix * outvec;
#ifdef USE_LIGHTING
@@ -207,6 +262,7 @@ uniform mediump sampler2D color_texture; // texunit:0
uniform highp vec2 color_texpixel_size;
uniform mediump sampler2D normal_texture; // texunit:1
+
in highp vec2 uv_interp;
in mediump vec4 color_interp;
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index d3644bffdd..f5481c597c 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1206,6 +1206,7 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 bino
float omni_attenuation = pow( max(1.0 - normalized_distance, 0.0), omni_lights[idx].light_direction_attenuation.w );
vec3 light_attenuation = vec3(omni_attenuation);
+#if !defined(SHADOWS_DISABLED)
if (omni_lights[idx].light_params.w>0.5) {
//there is a shadowmap
@@ -1252,6 +1253,7 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 bino
#endif
light_attenuation*=mix(omni_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow);
}
+#endif //SHADOWS_DISABLED
light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,omni_lights[idx].light_color_energy.rgb,light_attenuation,albedo,transmission,omni_lights[idx].light_params.z*p_blob_intensity,roughness,metallic,rim * omni_attenuation,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
@@ -1270,6 +1272,7 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi
spot_attenuation*= 1.0 - pow( spot_rim, spot_lights[idx].light_params.x);
vec3 light_attenuation = vec3(spot_attenuation);
+#if !defined(SHADOWS_DISABLED)
if (spot_lights[idx].light_params.w>0.5) {
//there is a shadowmap
highp vec4 splane=(spot_lights[idx].shadow_matrix * vec4(vertex,1.0));
@@ -1287,6 +1290,7 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi
#endif
light_attenuation*=mix(spot_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow);
}
+#endif //SHADOWS_DISABLED
light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,spot_lights[idx].light_color_energy.rgb,light_attenuation,albedo,transmission,spot_lights[idx].light_params.z*p_blob_intensity,roughness,metallic,rim * spot_attenuation,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
@@ -1785,6 +1789,7 @@ FRAGMENT_SHADER_CODE
float depth_z = -vertex.z;
#ifdef LIGHT_DIRECTIONAL_SHADOW
+#if !defined(SHADOWS_DISABLED)
#ifdef LIGHT_USE_PSSM4
if (depth_z < shadow_split_offsets.w) {
@@ -1927,6 +1932,7 @@ FRAGMENT_SHADER_CODE
}
+#endif // !defined(SHADOWS_DISABLED)
#endif //LIGHT_DIRECTIONAL_SHADOW
#ifdef USE_VERTEX_LIGHTING
diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl
index 2f671158b2..a75871f08e 100644
--- a/drivers/gles3/shaders/tonemap.glsl
+++ b/drivers/gles3/shaders/tonemap.glsl
@@ -258,9 +258,13 @@ void main() {
#endif
+#ifdef KEEP_3D_LINEAR
+ // leave color as is...
+#else
//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)));
+#endif
#if defined(USING_GLOW)
glow = mix( (vec3(1.0)+a)*pow(glow,vec3(1.0/2.4))-a , 12.92*glow , lessThan(glow,vec3(0.0031308)));
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 733c7cc80c..0f47949b4b 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -340,13 +340,22 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
bytes = byte_size;
}
- int ret = pa_stream_write(ad->pa_str, ptr, bytes, NULL, 0LL, PA_SEEK_RELATIVE);
+ ret = pa_stream_write(ad->pa_str, ptr, bytes, NULL, 0LL, PA_SEEK_RELATIVE);
if (ret >= 0) {
byte_size -= bytes;
ptr = (const char *)ptr + bytes;
}
} else {
- pa_mainloop_iterate(ad->pa_ml, 1, NULL);
+ ret = pa_mainloop_iterate(ad->pa_ml, 0, NULL);
+ if (ret == 0) {
+ // If pa_mainloop_iterate returns 0 sleep for 1 msec to wait
+ // for the stream to be able to process more bytes
+ ad->unlock();
+
+ OS::get_singleton()->delay_usec(1000);
+
+ ad->lock();
+ }
}
}
}
diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp
index ed6f2e24ed..457486797f 100644
--- a/drivers/rtaudio/audio_driver_rtaudio.cpp
+++ b/drivers/rtaudio/audio_driver_rtaudio.cpp
@@ -133,7 +133,7 @@ Error AudioDriverRtAudio::init() {
break;
} catch (RtAudioError &e) {
// try with less channels
- ERR_PRINT("Unable to open audio, retrying with fewer channels..");
+ ERR_PRINT("Unable to open audio, retrying with fewer channels...");
switch (speaker_mode) {
case SPEAKER_SURROUND_51: speaker_mode = SPEAKER_MODE_STEREO; break;
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index a7a3eef935..c25d34125d 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -136,7 +136,7 @@ void FileAccessUnix::close() {
if (save_path != "") {
//unlink(save_path.utf8().get_data());
- //print_line("renaming..");
+ //print_line("renaming...");
int rename_error = rename((save_path + ".tmp").utf8().get_data(), save_path.utf8().get_data());
if (rename_error && close_fail_notify) {
@@ -184,7 +184,7 @@ size_t FileAccessUnix::get_position() const {
ERR_FAIL_COND_V(!f, 0);
- int pos = ftell(f);
+ long pos = ftell(f);
if (pos < 0) {
check_errors();
ERR_FAIL_V(0);
@@ -196,10 +196,10 @@ size_t FileAccessUnix::get_len() const {
ERR_FAIL_COND_V(!f, 0);
- int pos = ftell(f);
+ long pos = ftell(f);
ERR_FAIL_COND_V(pos < 0, 0);
ERR_FAIL_COND_V(fseek(f, 0, SEEK_END), 0);
- int size = ftell(f);
+ long size = ftell(f);
ERR_FAIL_COND_V(size < 0, 0);
ERR_FAIL_COND_V(fseek(f, pos, SEEK_SET), 0);
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index a7fb0c3887..949609bb9a 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -101,7 +101,7 @@ IP_Address IP_Unix::_resolve_hostname(const String &p_hostname, Type p_type) {
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_ADDRCONFIG;
};
- hints.ai_flags &= !AI_NUMERICHOST;
+ hints.ai_flags &= ~AI_NUMERICHOST;
int s = getaddrinfo(p_hostname.utf8().get_data(), NULL, &hints, &result);
if (s != 0) {
@@ -111,6 +111,8 @@ IP_Address IP_Unix::_resolve_hostname(const String &p_hostname, Type p_type) {
if (result == NULL || result->ai_addr == NULL) {
ERR_PRINT("Invalid response from getaddrinfo");
+ if (result)
+ freeaddrinfo(result);
return IP_Address();
};
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 31c8e4ade9..05dfd69f58 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -73,6 +73,23 @@ void OS_Unix::debug_break() {
assert(false);
};
+static void handle_interrupt(int sig) {
+ if (ScriptDebugger::get_singleton() == NULL)
+ return;
+
+ ScriptDebugger::get_singleton()->set_depth(-1);
+ ScriptDebugger::get_singleton()->set_lines_left(1);
+}
+
+void OS_Unix::initialize_debugging() {
+
+ if (ScriptDebugger::get_singleton() != NULL) {
+ struct sigaction action;
+ action.sa_handler = handle_interrupt;
+ sigaction(SIGINT, &action, NULL);
+ }
+}
+
int OS_Unix::unix_initialize_audio(int p_audio_driver) {
return 0;
@@ -227,7 +244,7 @@ OS::TimeZoneInfo OS_Unix::get_time_zone_info() const {
void OS_Unix::delay_usec(uint32_t p_usec) const {
- struct timespec rem = { p_usec / 1000000, (p_usec % 1000000) * 1000 };
+ struct timespec rem = { static_cast<time_t>(p_usec / 1000000), static_cast<long>((p_usec % 1000000) * 1000) };
while (nanosleep(&rem, &rem) == EINTR) {
}
}
@@ -349,6 +366,12 @@ Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle
String path = p_path;
+ if (FileAccess::exists(path) && path.is_rel_path()) {
+ // dlopen expects a slash, in this case a leading ./ for it to be interpreted as a relative path,
+ // otherwise it will end up searching various system directories for the lib instead and finally failing.
+ path = "./" + path;
+ }
+
if (!FileAccess::exists(path)) {
//this code exists so gdnative can load .so files from within the executable path
path = get_executable_path().get_base_dir().plus_file(p_path.get_file());
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index db0fe1e00b..95b74d23ff 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -101,6 +101,7 @@ public:
virtual int get_processor_count() const;
virtual void debug_break();
+ virtual void initialize_debugging();
virtual String get_executable_path() const;
virtual String get_user_data_dir() const;
diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp
index 17112e5ab5..6d798f32f9 100644
--- a/drivers/unix/stream_peer_tcp_posix.cpp
+++ b/drivers/unix/stream_peer_tcp_posix.cpp
@@ -124,11 +124,14 @@ void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port,
sock_type = p_sock_type;
sockfd = p_sockfd;
#ifndef NO_FCNTL
- fcntl(sockfd, F_SETFL, O_NONBLOCK);
+ if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) {
+ WARN_PRINT("Error setting socket as non blocking");
+ }
#else
int bval = 1;
- ioctl(sockfd, FIONBIO, &bval);
-
+ if (ioctl(sockfd, FIONBIO, &bval) < 0) {
+ WARN_PRINT("Error setting socket as non blocking");
+ }
#endif
status = STATUS_CONNECTING;
@@ -150,10 +153,14 @@ Error StreamPeerTCPPosix::connect_to_host(const IP_Address &p_host, uint16_t p_p
};
#ifndef NO_FCNTL
- fcntl(sockfd, F_SETFL, O_NONBLOCK);
+ if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) {
+ WARN_PRINT("Error setting socket as non blocking");
+ }
#else
int bval = 1;
- ioctl(sockfd, FIONBIO, &bval);
+ if (ioctl(sockfd, FIONBIO, &bval) < 0) {
+ WARN_PRINT("Error setting socket as non blocking");
+ }
#endif
struct sockaddr_storage their_addr;
@@ -308,7 +315,9 @@ void StreamPeerTCPPosix::set_no_delay(bool p_enabled) {
ERR_FAIL_COND(!is_connected_to_host());
int flag = p_enabled ? 1 : 0;
- setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
+ if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) < 0) {
+ ERR_PRINT("Unable to set TCP no delay option");
+ }
}
bool StreamPeerTCPPosix::is_connected_to_host() const {
diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp
index 07ffe3b00a..67ab981f46 100644
--- a/drivers/unix/tcp_server_posix.cpp
+++ b/drivers/unix/tcp_server_posix.cpp
@@ -91,10 +91,14 @@ Error TCPServerPosix::listen(uint16_t p_port, const IP_Address &p_bind_address)
ERR_FAIL_COND_V(sockfd == -1, FAILED);
#ifndef NO_FCNTL
- fcntl(sockfd, F_SETFL, O_NONBLOCK);
+ if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) {
+ WARN_PRINT("Error setting socket as non blocking");
+ }
#else
int bval = 1;
- ioctl(sockfd, FIONBIO, &bval);
+ if (ioctl(sockfd, FIONBIO, &bval) < 0) {
+ WARN_PRINT("Error setting socket as non blocking");
+ }
#endif
int reuse = 1;
@@ -113,6 +117,7 @@ Error TCPServerPosix::listen(uint16_t p_port, const IP_Address &p_bind_address)
ERR_FAIL_V(FAILED);
};
} else {
+ close(sockfd);
return ERR_ALREADY_IN_USE;
};
@@ -157,10 +162,14 @@ Ref<StreamPeerTCP> TCPServerPosix::take_connection() {
int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &size);
ERR_FAIL_COND_V(fd == -1, Ref<StreamPeerTCP>());
#ifndef NO_FCNTL
- fcntl(fd, F_SETFL, O_NONBLOCK);
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ WARN_PRINT("Error setting socket as non blocking");
+ }
#else
int bval = 1;
- ioctl(fd, FIONBIO, &bval);
+ if (ioctl(fd, FIONBIO, &bval) < 0) {
+ WARN_PRINT("Error setting socket as non blocking");
+ }
#endif
Ref<StreamPeerTCPPosix> conn = memnew(StreamPeerTCPPosix);
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index 8b09d76bef..aa0fd34e0a 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -134,7 +134,7 @@ void FileAccessWindows::close() {
if (save_path != "") {
//unlink(save_path.utf8().get_data());
- //print_line("renaming..");
+ //print_line("renaming...");
//_wunlink(save_path.c_str()); //unlink if exists
//int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str());
@@ -162,7 +162,7 @@ void FileAccessWindows::close() {
}
if (rename_error) {
attempts--;
- OS::get_singleton()->delay_usec(1000000); //wait 100msec and try again
+ OS::get_singleton()->delay_usec(100000); // wait 100msec and try again
}
}
diff --git a/drivers/windows/stream_peer_tcp_winsock.cpp b/drivers/windows/stream_peer_tcp_winsock.cpp
index 55775fc231..cb501ce35d 100644
--- a/drivers/windows/stream_peer_tcp_winsock.cpp
+++ b/drivers/windows/stream_peer_tcp_winsock.cpp
@@ -335,7 +335,9 @@ Error StreamPeerTCPWinsock::connect_to_host(const IP_Address &p_host, uint16_t p
void StreamPeerTCPWinsock::set_no_delay(bool p_enabled) {
ERR_FAIL_COND(!is_connected_to_host());
int flag = p_enabled ? 1 : 0;
- setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
+ if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) != 0) {
+ ERR_PRINT("Unable to set TCP no delay option");
+ }
}
int StreamPeerTCPWinsock::get_available_bytes() const {
diff --git a/drivers/windows/tcp_server_winsock.cpp b/drivers/windows/tcp_server_winsock.cpp
index 413a0d19b5..ddb955549f 100644
--- a/drivers/windows/tcp_server_winsock.cpp
+++ b/drivers/windows/tcp_server_winsock.cpp
@@ -105,6 +105,7 @@ Error TCPServerWinsock::listen(uint16_t p_port, const IP_Address &p_bind_address
ERR_FAIL_V(FAILED);
};
} else {
+ closesocket(sockfd);
return ERR_ALREADY_IN_USE;
};