diff options
author | Anton Yabchinskiy <arn@bestmx.ru> | 2015-07-29 23:01:36 +0300 |
---|---|---|
committer | Anton Yabchinskiy <arn@bestmx.ru> | 2015-07-29 23:01:36 +0300 |
commit | dc8df8a91a995796f0f330bf6bb6b209f6dfce08 (patch) | |
tree | 46cfe09124703b07860754d6b44e0289422e0573 /drivers | |
parent | 16746f157f83d666079ba3266acec13d35b84c3f (diff) | |
parent | 922356b903061cda7591090bf19e8346c3a78cf5 (diff) |
Merge branch 'master' of github.com:okamstudio/godot
Diffstat (limited to 'drivers')
142 files changed, 3743 insertions, 1763 deletions
diff --git a/drivers/SCsub b/drivers/SCsub index 3715c9b112..4618d86b44 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -1,92 +1,95 @@ -Import('env')
-
-env.drivers_sources=[]
-#env.add_source_files(env.drivers_sources,"*.cpp")
-env.Append(CPPPATH=["vorbis"])
-Export('env')
-
-SConscript('unix/SCsub');
-SConscript('alsa/SCsub');
-SConscript('ao/SCsub');
-SConscript('pulseaudio/SCsub');
-SConscript('windows/SCsub');
-SConscript('gles2/SCsub');
-SConscript('gl_context/SCsub');
-SConscript('openssl/SCsub');
-
-if (env["png"]=="yes"):
- SConscript("png/SCsub");
-if (env["jpg"]=="yes"):
- SConscript("jpg/SCsub");
-if (env["webp"]=="yes"):
- SConscript("webp/SCsub");
-SConscript("dds/SCsub");
-SConscript("pvr/SCsub");
-SConscript("etc1/SCsub")
-if (env["builtin_zlib"]=="yes"):
- SConscript("builtin_zlib/SCsub");
-if (env["openssl"]=="builtin"):
- SConscript("builtin_openssl2/SCsub");
-
-SConscript("rtaudio/SCsub");
-SConscript("nedmalloc/SCsub");
-SConscript("trex/SCsub");
-SConscript("chibi/SCsub");
-if (env["vorbis"]=="yes" or env["speex"]=="yes" or env["theora"]=="yes"):
- SConscript("ogg/SCsub");
-if (env["vorbis"]=="yes"):
- SConscript("vorbis/SCsub");
-if (env["tools"]=="yes"):
- SConscript("convex_decomp/SCsub");
-
-if env["theora"]=="yes":
- SConscript("theoraplayer/SCsub")
-if (env["theora"]=="yes"):
- SConscript("theora/SCsub");
-if (env['speex']=='yes'):
- SConscript("speex/SCsub");
-if (env['musepack']=='yes'):
- SConscript("mpc/SCsub");
-if (env["squish"]=="yes" and env["tools"]=="yes"):
- SConscript("squish/SCsub");
-
-num = 0
-cur_base = ""
-total = len(env.drivers_sources)
-max_src = 64
-list = []
-lib_list = []
-
-import string
-
-for f in env.drivers_sources:
- fname = ""
- if type(f) == type(""):
- fname = env.File(f).path
- else:
- fname = env.File(f)[0].path
- #base = string.join(fname.split("/")[:-1], "/")
- fname = fname.replace("\\", "/")
- base = string.join(fname.split("/")[:2], "/")
- if base != cur_base and len(list) > max_src:
- lib = env.Library("drivers"+str(num), list)
- lib_list.append(lib)
- list = []
- num = num+1
- cur_base = base
- list.append(f)
-
-if len(list) > 0:
- lib = env.Library("drivers"+str(num), list)
- lib_list.append(lib)
-
-
-drivers_base=[]
-env.add_source_files(drivers_base,"*.cpp")
-lib_list.insert(0, env.Library("drivers", drivers_base))
-
-env.Prepend(LIBS=lib_list)
-
-#lib = env.Library("drivers",env.drivers_sources)
-#env.Prepend(LIBS=[lib])
-
+Import('env') + +env.drivers_sources=[] +#env.add_source_files(env.drivers_sources,"*.cpp") +env.Append(CPPPATH=["vorbis"]) +Export('env') + +SConscript('unix/SCsub'); +SConscript('alsa/SCsub'); +SConscript('ao/SCsub'); +SConscript('pulseaudio/SCsub'); +SConscript('windows/SCsub'); +SConscript('gles2/SCsub'); +SConscript('gl_context/SCsub'); +SConscript('openssl/SCsub'); + +if (env["png"]=="yes"): + SConscript("png/SCsub"); +if (env["jpg"]=="yes"): + SConscript("jpg/SCsub"); +if (env["webp"]=="yes"): + SConscript("webp/SCsub"); +SConscript("dds/SCsub"); +SConscript("pvr/SCsub"); +SConscript("etc1/SCsub") +if (env["builtin_zlib"]=="yes"): + SConscript("builtin_zlib/SCsub"); +if (env["openssl"]=="builtin"): + SConscript("builtin_openssl2/SCsub"); + +SConscript("rtaudio/SCsub"); +SConscript("nedmalloc/SCsub"); +SConscript("nrex/SCsub"); +SConscript("chibi/SCsub"); +if (env["vorbis"]=="yes" or env["speex"]=="yes" or env["theora"]=="yes"): + SConscript("ogg/SCsub"); +if (env["vorbis"]=="yes"): + SConscript("vorbis/SCsub"); +if (env["tools"]=="yes"): + SConscript("convex_decomp/SCsub"); + +if env["theora"]=="yes": + SConscript("theoraplayer/SCsub") +if (env["theora"]=="yes"): + SConscript("theora/SCsub"); +if (env['speex']=='yes'): + SConscript("speex/SCsub"); +if (env['musepack']=='yes'): + SConscript("mpc/SCsub"); +if (env["squish"]=="yes" and env["tools"]=="yes"): + SConscript("squish/SCsub"); + +num = 0 +cur_base = "" +total = len(env.drivers_sources) +max_src = 64 +list = [] +lib_list = [] + +import string + +if env['vsproj']=="yes": + env.AddToVSProject(env.drivers_sources) + +for f in env.drivers_sources: + fname = "" + if type(f) == type(""): + fname = env.File(f).path + else: + fname = env.File(f)[0].path + #base = string.join(fname.split("/")[:-1], "/") + fname = fname.replace("\\", "/") + base = string.join(fname.split("/")[:2], "/") + if base != cur_base and len(list) > max_src: + lib = env.Library("drivers"+str(num), list) + lib_list.append(lib) + list = [] + num = num+1 + cur_base = base + list.append(f) + +if len(list) > 0: + lib = env.Library("drivers"+str(num), list) + lib_list.append(lib) + + +drivers_base=[] +env.add_source_files(drivers_base,"*.cpp") +lib_list.insert(0, env.Library("drivers", drivers_base)) + +env.Prepend(LIBS=lib_list) + +#lib = env.Library("drivers",env.drivers_sources) +#env.Prepend(LIBS=[lib]) + diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp index 9d9a856376..4bc35f86ee 100644 --- a/drivers/alsa/audio_driver_alsa.cpp +++ b/drivers/alsa/audio_driver_alsa.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h index 86cdde6215..10f9298859 100644 --- a/drivers/alsa/audio_driver_alsa.h +++ b/drivers/alsa/audio_driver_alsa.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_config.h b/drivers/chibi/cp_config.h index 070c74d130..9cd754ed47 100644 --- a/drivers/chibi/cp_config.h +++ b/drivers/chibi/cp_config.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_envelope.cpp b/drivers/chibi/cp_envelope.cpp index 8eb3bd5ba0..6ed42a1167 100644 --- a/drivers/chibi/cp_envelope.cpp +++ b/drivers/chibi/cp_envelope.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_envelope.h b/drivers/chibi/cp_envelope.h index 67df8384c2..e01605ada3 100644 --- a/drivers/chibi/cp_envelope.h +++ b/drivers/chibi/cp_envelope.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_file_access_wrapper.cpp b/drivers/chibi/cp_file_access_wrapper.cpp index 66212b2b23..d7c6c6d0b6 100644 --- a/drivers/chibi/cp_file_access_wrapper.cpp +++ b/drivers/chibi/cp_file_access_wrapper.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_file_access_wrapper.h b/drivers/chibi/cp_file_access_wrapper.h index 57f3d53e75..c54ce5868d 100644 --- a/drivers/chibi/cp_file_access_wrapper.h +++ b/drivers/chibi/cp_file_access_wrapper.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_instrument.cpp b/drivers/chibi/cp_instrument.cpp index 9a96da2481..2e5af70565 100644 --- a/drivers/chibi/cp_instrument.cpp +++ b/drivers/chibi/cp_instrument.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_instrument.h b/drivers/chibi/cp_instrument.h index 863b31c80a..8b434402c5 100644 --- a/drivers/chibi/cp_instrument.h +++ b/drivers/chibi/cp_instrument.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader.h b/drivers/chibi/cp_loader.h index 243b8145ae..7763c395b9 100644 --- a/drivers/chibi/cp_loader.h +++ b/drivers/chibi/cp_loader.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader_it.cpp b/drivers/chibi/cp_loader_it.cpp index dae6b26d97..74dd228437 100644 --- a/drivers/chibi/cp_loader_it.cpp +++ b/drivers/chibi/cp_loader_it.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader_it.h b/drivers/chibi/cp_loader_it.h index 6a192386e2..6ba605bf04 100644 --- a/drivers/chibi/cp_loader_it.h +++ b/drivers/chibi/cp_loader_it.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader_it_info.cpp b/drivers/chibi/cp_loader_it_info.cpp index fc230a3342..0cfd73f1e3 100644 --- a/drivers/chibi/cp_loader_it_info.cpp +++ b/drivers/chibi/cp_loader_it_info.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader_it_instruments.cpp b/drivers/chibi/cp_loader_it_instruments.cpp index f315b9b5c8..6293be162c 100644 --- a/drivers/chibi/cp_loader_it_instruments.cpp +++ b/drivers/chibi/cp_loader_it_instruments.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader_it_patterns.cpp b/drivers/chibi/cp_loader_it_patterns.cpp index 30d87dbebf..c79dffc180 100644 --- a/drivers/chibi/cp_loader_it_patterns.cpp +++ b/drivers/chibi/cp_loader_it_patterns.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader_it_samples.cpp b/drivers/chibi/cp_loader_it_samples.cpp index 040f9d4dd7..24d3a12781 100644 --- a/drivers/chibi/cp_loader_it_samples.cpp +++ b/drivers/chibi/cp_loader_it_samples.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader_mod.cpp b/drivers/chibi/cp_loader_mod.cpp index 1ea3a93e9c..98174ff9b1 100644 --- a/drivers/chibi/cp_loader_mod.cpp +++ b/drivers/chibi/cp_loader_mod.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader_mod.h b/drivers/chibi/cp_loader_mod.h index cf16635ef0..77245349b7 100644 --- a/drivers/chibi/cp_loader_mod.h +++ b/drivers/chibi/cp_loader_mod.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader_s3m.cpp b/drivers/chibi/cp_loader_s3m.cpp index 8b9871463f..c21f7bdd38 100644 --- a/drivers/chibi/cp_loader_s3m.cpp +++ b/drivers/chibi/cp_loader_s3m.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader_s3m.h b/drivers/chibi/cp_loader_s3m.h index 9fccef0886..6fe9f0ca44 100644 --- a/drivers/chibi/cp_loader_s3m.h +++ b/drivers/chibi/cp_loader_s3m.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader_xm.cpp b/drivers/chibi/cp_loader_xm.cpp index 228567afd6..8bde6b673e 100644 --- a/drivers/chibi/cp_loader_xm.cpp +++ b/drivers/chibi/cp_loader_xm.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_loader_xm.h b/drivers/chibi/cp_loader_xm.h index 230dff6be7..0a2465475f 100644 --- a/drivers/chibi/cp_loader_xm.h +++ b/drivers/chibi/cp_loader_xm.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_mixer.h b/drivers/chibi/cp_mixer.h index 28fc11459c..bac2087edf 100644 --- a/drivers/chibi/cp_mixer.h +++ b/drivers/chibi/cp_mixer.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_note.h b/drivers/chibi/cp_note.h index 17de7e72ee..5d2c01844a 100644 --- a/drivers/chibi/cp_note.h +++ b/drivers/chibi/cp_note.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_order.h b/drivers/chibi/cp_order.h index ca3684d154..a20e202bde 100644 --- a/drivers/chibi/cp_order.h +++ b/drivers/chibi/cp_order.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_pattern.cpp b/drivers/chibi/cp_pattern.cpp index b880071cca..cc65833d68 100644 --- a/drivers/chibi/cp_pattern.cpp +++ b/drivers/chibi/cp_pattern.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_pattern.h b/drivers/chibi/cp_pattern.h index b8d1e0a18d..22611eabab 100644 --- a/drivers/chibi/cp_pattern.h +++ b/drivers/chibi/cp_pattern.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_player_data.cpp b/drivers/chibi/cp_player_data.cpp index 99bc4fddd2..76d8f280d2 100644 --- a/drivers/chibi/cp_player_data.cpp +++ b/drivers/chibi/cp_player_data.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_player_data.h b/drivers/chibi/cp_player_data.h index d62cef17a1..36a27942cb 100644 --- a/drivers/chibi/cp_player_data.h +++ b/drivers/chibi/cp_player_data.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_player_data_control.cpp b/drivers/chibi/cp_player_data_control.cpp index 96ffae667b..d5ca648fff 100644 --- a/drivers/chibi/cp_player_data_control.cpp +++ b/drivers/chibi/cp_player_data_control.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -233,7 +233,7 @@ int CPPlayer::get_channel_voice(int p_channel) { const char* CPPlayer::get_voice_sample_name(int p_voice) { - const char *name; + const char *name = NULL; @@ -302,7 +302,7 @@ const char * CPPlayer::get_voice_instrument_name(int p_voice) { - const char *name; + const char *name = NULL; diff --git a/drivers/chibi/cp_player_data_effects.cpp b/drivers/chibi/cp_player_data_effects.cpp index e116b3b473..eb62b8d962 100644 --- a/drivers/chibi/cp_player_data_effects.cpp +++ b/drivers/chibi/cp_player_data_effects.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_player_data_envelopes.cpp b/drivers/chibi/cp_player_data_envelopes.cpp index 12456ab082..94378b8bf4 100644 --- a/drivers/chibi/cp_player_data_envelopes.cpp +++ b/drivers/chibi/cp_player_data_envelopes.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_player_data_events.cpp b/drivers/chibi/cp_player_data_events.cpp index 32335040bc..7a7cfdf5bb 100644 --- a/drivers/chibi/cp_player_data_events.cpp +++ b/drivers/chibi/cp_player_data_events.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_player_data_filter.cpp b/drivers/chibi/cp_player_data_filter.cpp index 75e8bc961a..fd87e4ae7a 100644 --- a/drivers/chibi/cp_player_data_filter.cpp +++ b/drivers/chibi/cp_player_data_filter.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_player_data_nna.cpp b/drivers/chibi/cp_player_data_nna.cpp index f87045c309..3960234f5e 100644 --- a/drivers/chibi/cp_player_data_nna.cpp +++ b/drivers/chibi/cp_player_data_nna.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_player_data_notes.cpp b/drivers/chibi/cp_player_data_notes.cpp index d61ac0e30f..ea3ba42e86 100644 --- a/drivers/chibi/cp_player_data_notes.cpp +++ b/drivers/chibi/cp_player_data_notes.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_player_data_reserved.cpp b/drivers/chibi/cp_player_data_reserved.cpp index 43e913a54e..8d9439158b 100644 --- a/drivers/chibi/cp_player_data_reserved.cpp +++ b/drivers/chibi/cp_player_data_reserved.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_player_data_utils.cpp b/drivers/chibi/cp_player_data_utils.cpp index 543d525f3f..5294fc8139 100644 --- a/drivers/chibi/cp_player_data_utils.cpp +++ b/drivers/chibi/cp_player_data_utils.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_sample.cpp b/drivers/chibi/cp_sample.cpp index 667d045d7c..bff24d4c4c 100644 --- a/drivers/chibi/cp_sample.cpp +++ b/drivers/chibi/cp_sample.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_sample.h b/drivers/chibi/cp_sample.h index 2017ab0659..71b57aaa81 100644 --- a/drivers/chibi/cp_sample.h +++ b/drivers/chibi/cp_sample.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_sample_defs.h b/drivers/chibi/cp_sample_defs.h index c17b6fac51..32817efc7d 100644 --- a/drivers/chibi/cp_sample_defs.h +++ b/drivers/chibi/cp_sample_defs.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_sample_manager.cpp b/drivers/chibi/cp_sample_manager.cpp index 0a18d7b0ab..601db07acf 100644 --- a/drivers/chibi/cp_sample_manager.cpp +++ b/drivers/chibi/cp_sample_manager.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_sample_manager.h b/drivers/chibi/cp_sample_manager.h index 35ecb59c7a..2891034482 100644 --- a/drivers/chibi/cp_sample_manager.h +++ b/drivers/chibi/cp_sample_manager.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_song.cpp b/drivers/chibi/cp_song.cpp index 3751d76c25..956e2ee6d4 100644 --- a/drivers/chibi/cp_song.cpp +++ b/drivers/chibi/cp_song.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_song.h b/drivers/chibi/cp_song.h index fb6e7f7f29..6c35b43c76 100644 --- a/drivers/chibi/cp_song.h +++ b/drivers/chibi/cp_song.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_tables.cpp b/drivers/chibi/cp_tables.cpp index f30aeca543..9f1ae30c9a 100644 --- a/drivers/chibi/cp_tables.cpp +++ b/drivers/chibi/cp_tables.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/cp_tables.h b/drivers/chibi/cp_tables.h index 4f4a8c07bd..6c3c9271b0 100644 --- a/drivers/chibi/cp_tables.h +++ b/drivers/chibi/cp_tables.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/event_stream_chibi.cpp b/drivers/chibi/event_stream_chibi.cpp index 2deb83e2bc..e87e0a9aaa 100644 --- a/drivers/chibi/event_stream_chibi.cpp +++ b/drivers/chibi/event_stream_chibi.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/chibi/event_stream_chibi.h b/drivers/chibi/event_stream_chibi.h index 3f322f7a65..7b2ee4b471 100644 --- a/drivers/chibi/event_stream_chibi.h +++ b/drivers/chibi/event_stream_chibi.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/convex_decomp/b2Polygon.cpp b/drivers/convex_decomp/b2Polygon.cpp index 49a3e74c2a..668313967e 100644 --- a/drivers/convex_decomp/b2Polygon.cpp +++ b/drivers/convex_decomp/b2Polygon.cpp @@ -970,6 +970,7 @@ int32 DecomposeConvex(b2Polygon* p, b2Polygon* results, int32 maxPolys) { } if (nTri < 1) { //Still no luck? Oh well... + delete[] triangulated; return -1; } int32 nPolys = PolygonizeTriangles(triangulated, nTri, results, maxPolys); diff --git a/drivers/etc1/SCsub b/drivers/etc1/SCsub index 152dc3f4d0..251c3ffb86 100644 --- a/drivers/etc1/SCsub +++ b/drivers/etc1/SCsub @@ -6,7 +6,8 @@ etc_sources = [ "etc1/rg_etc1.cpp" ] -env.drivers_sources+=etc_sources +if (env["etc1"] != "no"): + env.drivers_sources+=etc_sources #env.add_source_files(env.drivers_sources, etc_sources) diff --git a/drivers/etc1/rg_etc1.cpp b/drivers/etc1/rg_etc1.cpp index 63877e6d12..fd109f003c 100644 --- a/drivers/etc1/rg_etc1.cpp +++ b/drivers/etc1/rg_etc1.cpp @@ -24,6 +24,9 @@ namespace rg_etc1
{
+ inline long labs(long val) {
+ return val < 0 ? -val : val;
+ }
inline int intabs(int val) {
@@ -1913,7 +1916,7 @@ done: for (uint packed_c = 0; packed_c < limit; packed_c++)
{
int v = etc1_decode_value(diff, inten, selector, packed_c);
- uint err = intabs(v - color);
+ uint err = labs(v - static_cast<int>(color));
//printf("err: %d - %u = %u\n",v,color,err);
if (err < best_error)
{
diff --git a/drivers/gl_context/context_gl.h b/drivers/gl_context/context_gl.h index 392f8341ae..6b06ccdc37 100644 --- a/drivers/gl_context/context_gl.h +++ b/drivers/gl_context/context_gl.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 3660be20db..d3a5f3b5bc 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -91,6 +91,10 @@ static RasterizerGLES2* _singleton = NULL; +#ifdef GLES_NO_CLIENT_ARRAYS +static float GlobalVertexBuffer[MAX_POLYGON_VERTICES * 8] = {0}; +#endif + static const GLenum prim_type[]={GL_POINTS,GL_LINES,GL_TRIANGLES,GL_TRIANGLE_FAN}; _FORCE_INLINE_ static void _set_color_attrib(const Color& p_color) { @@ -1009,10 +1013,16 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu bool force_clamp_to_edge = !(texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) && (nearest_power_of_2(texture->alloc_height)!=texture->alloc_height || nearest_power_of_2(texture->alloc_width)!=texture->alloc_width); - if (!force_clamp_to_edge && texture->flags&VS::TEXTURE_FLAG_REPEAT && texture->target != GL_TEXTURE_CUBE_MAP) { + if (!force_clamp_to_edge && (texture->flags&VS::TEXTURE_FLAG_REPEAT || texture->flags&VS::TEXTURE_FLAG_MIRRORED_REPEAT) && texture->target != GL_TEXTURE_CUBE_MAP) { - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + if (texture->flags&VS::TEXTURE_FLAG_MIRRORED_REPEAT){ + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT ); + } + else{ + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + } } else { //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); @@ -1042,6 +1052,8 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu int size,ofs; img.get_mipmap_offset_and_size(i,ofs,size); + //print_line("mipmap: "+itos(i)+" size: "+itos(size)+" w: "+itos(mm_w)+", h: "+itos(mm_h)); + if (texture->compressed) { glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glCompressedTexImage2D( blit_target, i, format,w,h,0,size,&read[ofs] ); @@ -1049,7 +1061,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu } else { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); if (texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) { - glTexSubImage2D( blit_target, i, 0,0,w,h,format,GL_UNSIGNED_BYTE,&read[ofs] ); + glTexSubImage2D( blit_target, i, 0,0,w, h,format,GL_UNSIGNED_BYTE,&read[ofs] ); } else { glTexImage2D(blit_target, i, internal_format, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]); } @@ -1257,7 +1269,6 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) { p_flags&=VS::TEXTURE_FLAG_FILTER;//can change only filter } - glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; @@ -1265,10 +1276,16 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) { bool force_clamp_to_edge = !(p_flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) && (nearest_power_of_2(texture->alloc_height)!=texture->alloc_height || nearest_power_of_2(texture->alloc_width)!=texture->alloc_width); - if (!force_clamp_to_edge && texture->flags&VS::TEXTURE_FLAG_REPEAT && texture->target != GL_TEXTURE_CUBE_MAP) { + if (!force_clamp_to_edge && (texture->flags&VS::TEXTURE_FLAG_REPEAT || texture->flags&VS::TEXTURE_FLAG_MIRRORED_REPEAT) && texture->target != GL_TEXTURE_CUBE_MAP) { - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + if (texture->flags&VS::TEXTURE_FLAG_MIRRORED_REPEAT){ + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT ); + } + else { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + } } else { //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); glTexParameterf( texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); @@ -1607,7 +1624,8 @@ Variant RasterizerGLES2::shader_get_default_param(RID p_shader, const StringName RID RasterizerGLES2::material_create() { - return material_owner.make_rid( memnew( Material ) ); + RID material = material_owner.make_rid( memnew( Material ) ); + return material; } void RasterizerGLES2::material_set_shader(RID p_material, RID p_shader) { @@ -1647,6 +1665,9 @@ void RasterizerGLES2::material_set_param(RID p_material, const StringName& p_par } } else { + if (p_value.get_type()==Variant::NIL) + return; + Material::UniformData ud; ud.index=-1; ud.value=p_value; @@ -4262,17 +4283,21 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) { glReadPixels( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height,GL_RGBA,GL_UNSIGNED_BYTE,w.ptr()); } - uint32_t *imgptr = (uint32_t*)w.ptr(); - for(int y=0;y<(viewport.height/2);y++) { + bool flip = current_rt==NULL; + + if (flip) { + uint32_t *imgptr = (uint32_t*)w.ptr(); + for(int y=0;y<(viewport.height/2);y++) { - uint32_t *ptr1 = &imgptr[y*viewport.width]; - uint32_t *ptr2 = &imgptr[(viewport.height-y-1)*viewport.width]; + uint32_t *ptr1 = &imgptr[y*viewport.width]; + uint32_t *ptr2 = &imgptr[(viewport.height-y-1)*viewport.width]; - for(int x=0;x<viewport.width;x++) { + for(int x=0;x<viewport.width;x++) { - uint32_t tmp = ptr1[x]; - ptr1[x]=ptr2[x]; - ptr2[x]=tmp; + uint32_t tmp = ptr1[x]; + ptr1[x]=ptr2[x]; + ptr2[x]=tmp; + } } } @@ -4381,7 +4406,7 @@ void RasterizerGLES2::begin_shadow_map( RID p_light_instance, int p_shadow_pass } -void RasterizerGLES2::set_camera(const Transform& p_world,const CameraMatrix& p_projection) { +void RasterizerGLES2::set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint) { camera_transform=p_world; if (current_rt && current_rt_vflip) { @@ -4389,10 +4414,11 @@ void RasterizerGLES2::set_camera(const Transform& p_world,const CameraMatrix& p_ } camera_transform_inverse=camera_transform.inverse(); camera_projection=p_projection; - camera_plane = Plane( camera_transform.origin, camera_transform.basis.get_axis(2) ); + camera_plane = Plane( camera_transform.origin, -camera_transform.basis.get_axis(2) ); camera_z_near=camera_projection.get_z_near(); camera_z_far=camera_projection.get_z_far(); camera_projection.get_viewport_size(camera_vp_size.x,camera_vp_size.y); + camera_ortho=p_ortho_hint; } void RasterizerGLES2::add_light( RID p_light_instance ) { @@ -4595,6 +4621,10 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { if (fragment_flags.uses_normal) { enablers.push_back("#define NORMAL_USED\n"); } + if (fragment_flags.uses_normalmap) { + enablers.push_back("#define USE_NORMALMAP\n"); + } + if (light_flags.uses_light) { enablers.push_back("#define USE_LIGHT_SHADER_CODE\n"); } @@ -4751,8 +4781,11 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD e->geometry_cmp=p_geometry_cmp; e->material=m; e->instance=p_instance; - //e->depth=camera_plane.distance_to(p_world->origin); - e->depth=camera_transform.origin.distance_to(p_instance->transform.origin); + if (camera_ortho) { + e->depth=camera_plane.distance_to(p_instance->transform.origin); + } else { + e->depth=camera_transform.origin.distance_to(p_instance->transform.origin); + } e->owner=p_owner; e->light_type=0; e->additive=false; @@ -5197,7 +5230,7 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material DEBUG_TEST_ERROR("Material arameters"); if (p_material->shader_cache->uses_time) { - material_shader.set_uniform(MaterialShaderGLES2::TIME,Math::fmod(last_time,300.0)); + material_shader.set_uniform(MaterialShaderGLES2::TIME,Math::fmod(last_time,shader_time_rollback)); draw_next_frame=true; } //if uses TIME - draw_next_frame=true @@ -7980,8 +8013,16 @@ void RasterizerGLES2::canvas_set_clip(bool p_clip, const Rect2& p_rect) { if (p_clip) { glEnable(GL_SCISSOR_TEST); - glScissor(viewport.x+p_rect.pos.x,viewport.y+ (viewport.height-(p_rect.pos.y+p_rect.size.height)), - p_rect.size.width,p_rect.size.height); + //glScissor(viewport.x+p_rect.pos.x,viewport.y+ (viewport.height-(p_rect.pos.y+p_rect.size.height)), + + int x = p_rect.pos.x; + int y = window_size.height-(p_rect.pos.y+p_rect.size.y); + int w = p_rect.size.x; + int h = p_rect.size.y; + + glScissor(x,y,w,h); + + } else { glDisable(GL_SCISSOR_TEST); @@ -8340,20 +8381,22 @@ void RasterizerGLES2::canvas_draw_primitive(const Vector<Point2>& p_points, cons void RasterizerGLES2::canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor) { - bool do_colors=false; + bool do_colors=false; + Color m; + if (p_singlecolor) { + m = *p_colors; + m.a*=canvas_opacity; + _set_color_attrib(m); + } else if (!p_colors) { + m = Color(1, 1, 1, canvas_opacity); + _set_color_attrib(m); + } else + do_colors=true; - if (p_singlecolor) { - Color m = *p_colors; - m.a*=canvas_opacity; - _set_color_attrib(m); - } else if (!p_colors) { - _set_color_attrib( Color(1,1,1,canvas_opacity)); - } else - do_colors=true; + Texture *texture = _bind_canvas_texture(p_texture); - Texture *texture = _bind_canvas_texture(p_texture); - - glEnableVertexAttribArray(VS::ARRAY_VERTEX); +#ifndef GLES_NO_CLIENT_ARRAYS + glEnableVertexAttribArray(VS::ARRAY_VERTEX); glVertexAttribPointer( VS::ARRAY_VERTEX, 2 ,GL_FLOAT, false, sizeof(Vector2), p_vertices ); if (do_colors) { @@ -8383,11 +8426,78 @@ void RasterizerGLES2::canvas_draw_polygon(int p_vertex_count, const int* p_indic }; glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_SHORT, _draw_poly_indices ); #endif - //glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_INT, p_indices ); } else { glDrawArrays(GL_TRIANGLES,0,p_vertex_count); } + +#else //WebGL specific impl. + glBindBuffer(GL_ARRAY_BUFFER, gui_quad_buffer); + float *b = GlobalVertexBuffer; + int ofs = 0; + if(p_vertex_count > MAX_POLYGON_VERTICES){ + print_line("Too many vertices to render"); + return; + } + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer( VS::ARRAY_VERTEX, 2 ,GL_FLOAT, false, sizeof(float)*2, ((float*)0)+ofs ); + for(int i=0;i<p_vertex_count;i++) { + b[ofs++]=p_vertices[i].x; + b[ofs++]=p_vertices[i].y; + } + + if (p_colors && do_colors) { + + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer( VS::ARRAY_COLOR, 4 ,GL_FLOAT, false, sizeof(float)*4, ((float*)0)+ofs ); + for(int i=0;i<p_vertex_count;i++) { + b[ofs++]=p_colors[i].r; + b[ofs++]=p_colors[i].g; + b[ofs++]=p_colors[i].b; + b[ofs++]=p_colors[i].a; + } + + } else { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + } + + + if (p_uvs) { + + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer( VS::ARRAY_TEX_UV, 2 ,GL_FLOAT, false, sizeof(float)*2, ((float*)0)+ofs ); + for(int i=0;i<p_vertex_count;i++) { + b[ofs++]=p_uvs[i].x; + b[ofs++]=p_uvs[i].y; + } + + } else { + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + glBufferSubData(GL_ARRAY_BUFFER,0,ofs*4,&b[0]); + + //bind the indices buffer. + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_buffer); + + static const int _max_draw_poly_indices = 16*1024; // change this size if needed!!! + ERR_FAIL_COND(p_vertex_count > _max_draw_poly_indices); + static uint16_t _draw_poly_indices[_max_draw_poly_indices]; + for (int i=0; i<p_vertex_count; i++) { + _draw_poly_indices[i] = p_indices[i]; + //OS::get_singleton()->print("ind: %d ", p_indices[i]); + }; + + //copy the data to GPU. + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, p_vertex_count * sizeof(uint16_t), &_draw_poly_indices[0]); + + //draw the triangles. + glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_SHORT, 0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +#endif + _rinfo.ci_draw_commands++; }; @@ -9005,8 +9115,17 @@ void RasterizerGLES2::_canvas_item_render_commands(CanvasItem *p_item,CanvasItem } else { glEnable(GL_SCISSOR_TEST); - glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), - current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + //glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), + //current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + + int x = current_clip->final_clip_rect.pos.x; + int y = window_size.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.y); + int w = current_clip->final_clip_rect.size.x; + int h = current_clip->final_clip_rect.size.y; + + glScissor(x,y,w,h); + + reclip=false; } } @@ -9116,7 +9235,7 @@ void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItemMaterial *mat } if (shader->uses_time) { - canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,300.0)); + canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,shader_time_rollback)); draw_next_frame=true; } //if uses TIME - draw_next_frame=true @@ -9180,8 +9299,21 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const if (current_clip) { glEnable(GL_SCISSOR_TEST); - glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), - current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + //glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), + //current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + +/* int x = viewport.x+current_clip->final_clip_rect.pos.x; + int y = window_size.height-(viewport.y+current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.y); + int w = current_clip->final_clip_rect.size.x; + int h = current_clip->final_clip_rect.size.y; +*/ + int x = current_clip->final_clip_rect.pos.x; + int y = window_size.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.y); + int w = current_clip->final_clip_rect.size.x; + int h = current_clip->final_clip_rect.size.y; + + glScissor(x,y,w,h); + } else { glDisable(GL_SCISSOR_TEST); @@ -9263,7 +9395,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const _canvas_item_setup_shader_uniforms(material,shader_cache); } - bool unshaded = material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED; + bool unshaded = (material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED) || ci->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX; if (unshaded) { canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,Color(1,1,1,1)); @@ -9335,6 +9467,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const while(light) { + if (ci->light_mask&light->item_mask && p_z>=light->z_min && p_z<=light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache,light->rect_cache)) { //intersects this light @@ -9372,6 +9505,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const } + bool has_shadow = light->shadow_buffer.is_valid() && ci->light_mask&light->item_shadow_mask; canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,has_shadow); @@ -9414,6 +9548,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_TEXTURE,max_texture_units-3); canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX,light->shadow_matrix_cache); canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult); + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_SHADOW_COLOR,light->shadow_color); } @@ -9470,8 +9605,17 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const if (reclip) { glEnable(GL_SCISSOR_TEST); - glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), - current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + //glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), + //current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + + int x = current_clip->final_clip_rect.pos.x; + int y = window_size.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.y); + int w = current_clip->final_clip_rect.size.x; + int h = current_clip->final_clip_rect.size.y; + + glScissor(x,y,w,h); + + } @@ -10669,13 +10813,27 @@ void RasterizerGLES2::init() { current_rt=NULL; current_vd=NULL; current_debug=VS::SCENARIO_DEBUG_DISABLED; + camera_ortho=false; glGenBuffers(1,&gui_quad_buffer); glBindBuffer(GL_ARRAY_BUFFER,gui_quad_buffer); - glBufferData(GL_ARRAY_BUFFER,128,NULL,GL_DYNAMIC_DRAW); +#ifdef GLES_NO_CLIENT_ARRAYS //WebGL specific implementation. + glBufferData(GL_ARRAY_BUFFER, 8 * MAX_POLYGON_VERTICES,NULL,GL_DYNAMIC_DRAW); +#else + glBufferData(GL_ARRAY_BUFFER,128,NULL,GL_DYNAMIC_DRAW); +#endif glBindBuffer(GL_ARRAY_BUFFER,0); //unbind +#ifdef GLES_NO_CLIENT_ARRAYS //webgl indices buffer + glGenBuffers(1, &indices_buffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_buffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 16*1024, NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);// unbind +#endif + + shader_time_rollback = GLOBAL_DEF("rasterizer/shader_time_rollback",300); + using_canvas_bg=false; _update_framebuffer(); DEBUG_TEST_ERROR("Initializing"); @@ -10683,7 +10841,10 @@ void RasterizerGLES2::init() { void RasterizerGLES2::finish() { + free(default_material); + free(shadow_material); free(canvas_shadow_blur); + free( overdraw_material ); } int RasterizerGLES2::get_render_info(VS::RenderInfo p_info) { diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index ad18c8e7a1..d337ecfb64 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,6 +31,8 @@ #include "servers/visual/rasterizer.h" +#define MAX_POLYGON_VERTICES 4096 //used for WebGL canvas_draw_polygon call. + #ifdef GLES2_ENABLED #include "image.h" @@ -828,6 +830,7 @@ class RasterizerGLES2 : public Rasterizer { GLuint base_framebuffer; GLuint gui_quad_buffer; + GLuint indices_buffer; @@ -1049,6 +1052,7 @@ class RasterizerGLES2 : public Rasterizer { float camera_z_near; float camera_z_far; Size2 camera_vp_size; + bool camera_ortho; Set<String> extensions; bool texscreen_copied; bool texscreen_used; @@ -1270,6 +1274,7 @@ class RasterizerGLES2 : public Rasterizer { Environment *current_env; VS::ScenarioDebugMode current_debug; RID overdraw_material; + float shader_time_rollback; mutable MaterialShaderGLES2 material_shader; @@ -1585,7 +1590,7 @@ public: virtual void begin_shadow_map( RID p_light_instance, int p_shadow_pass ); - virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection); + virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint); virtual void add_light( RID p_light_instance ); ///< all "add_light" calls happen before add_geometry calls diff --git a/drivers/gles2/rasterizer_instance_gles2.cpp b/drivers/gles2/rasterizer_instance_gles2.cpp index eec9431f36..a8d478c6e0 100644 --- a/drivers/gles2/rasterizer_instance_gles2.cpp +++ b/drivers/gles2/rasterizer_instance_gles2.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/gles2/rasterizer_instance_gles2.h b/drivers/gles2/rasterizer_instance_gles2.h index 97dcb7bc73..f5ac5f1fe2 100644 --- a/drivers/gles2/rasterizer_instance_gles2.h +++ b/drivers/gles2/rasterizer_instance_gles2.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 69bd269948..157f2e398b 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -243,6 +243,10 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a if (vnode->name==vname_normal) { uses_normal=true; } + if (vnode->name==vname_normalmap || vnode->name==vname_normalmap_depth) { + uses_normalmap=true; + uses_normal=true; + } if (vnode->name==vname_screen_uv) { uses_screen_uv=true; @@ -427,6 +431,42 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a // code="get_texpos(gl_ProjectionMatrixInverse * texture2D( depth_texture, clamp(("+dump_node_code(onode->arguments[1],p_level)+").xy,vec2(0.0),vec2(1.0))*gl_LightSource[5].specular.zw+gl_LightSource[5].specular.xy)"; //code="(texture2D( screen_texture, ("+dump_node_code(onode->arguments[1],p_level)+").xy).rgb"; break; + } else if (custom_h && callfunc=="cosh_custom") { + + if (!cosh_used) { + global_code= "float cosh_custom(float val)\n"\ + "{\n"\ + " float tmp = exp(val);\n"\ + " float cosH = (tmp + 1.0 / tmp) / 2.0;\n"\ + " return cosH;\n"\ + "}\n"+global_code; + cosh_used=true; + } + code="cosh_custom("+dump_node_code(onode->arguments[1],p_level)+""; + } else if (custom_h && callfunc=="sinh_custom") { + + if (!sinh_used) { + global_code= "float sinh_custom(float val)\n"\ + "{\n"\ + " float tmp = exp(val);\n"\ + " float sinH = (tmp - 1.0 / tmp) / 2.0;\n"\ + " return sinH;\n"\ + "}\n"+global_code; + sinh_used=true; + } + code="sinh_custom("+dump_node_code(onode->arguments[1],p_level)+""; + } else if (custom_h && callfunc=="tanh_custom") { + + if (!tanh_used) { + global_code= "float tanh_custom(float val)\n"\ + "{\n"\ + " float tmp = exp(val);\n"\ + " float tanH = (tmp - 1.0 / tmp) / (tmp + 1.0 / tmp);\n"\ + " return tanH;\n"\ + "}\n"+global_code; + tanh_used=true; + } + code="tanh_custom("+dump_node_code(onode->arguments[1],p_level)+""; } else { @@ -630,6 +670,9 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.use_var2_interp=false; r_flags.uses_normalmap=false; r_flags.uses_normal=false; + sinh_used=false; + tanh_used=false; + cosh_used=false; String error; int errline,errcol; @@ -658,12 +701,18 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.uses_shadow_color=uses_shadow_color; r_code_line=code; r_globals_line=global_code; - return OK; } ShaderCompilerGLES2::ShaderCompilerGLES2() { +#ifdef GLEW_ENABLED + //use custom functions because they are not supported in GLSL120 + custom_h=true; +#else + custom_h=false; +#endif + replace_table["bool"]= "bool"; replace_table["float" ]= "float"; replace_table["vec2" ]= "vec2"; @@ -682,9 +731,17 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { replace_table["acos" ]= "acos"; replace_table["atan" ]= "atan"; replace_table["atan2"]= "atan"; - replace_table["sinh" ]= "sinh"; - replace_table["cosh" ]= "cosh"; - replace_table["tanh" ]= "tanh"; + + if (custom_h) { + replace_table["sinh" ]= "sinh_custom"; + replace_table["cosh" ]= "cosh_custom"; + replace_table["tanh" ]= "tanh_custom"; + } else { + replace_table["sinh" ]= "sinh"; + replace_table["cosh" ]= "cosh"; + replace_table["tanh" ]= "tanh"; + } + replace_table["pow" ]= "pow"; replace_table["exp" ]= "exp"; replace_table["log" ]= "log"; @@ -810,6 +867,8 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { mode_replace_table[4]["POSITION"]="gl_Position"; mode_replace_table[4]["NORMAL"]="normal"; + mode_replace_table[4]["NORMALMAP"]="normal_map"; + mode_replace_table[4]["NORMALMAP_DEPTH"]="normal_depth"; mode_replace_table[4]["UV"]="uv_interp"; mode_replace_table[4]["SRC_COLOR"]="color_interp"; mode_replace_table[4]["COLOR"]="color"; @@ -861,6 +920,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { vname_light="LIGHT"; vname_time="TIME"; vname_normalmap="NORMALMAP"; + vname_normalmap_depth="NORMALMAP_DEPTH"; vname_normal="NORMAL"; vname_texpixel_size="TEXTURE_PIXEL_SIZE"; vname_world_vec="WORLD_VERTEX"; diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h index 87016fd968..43902a7536 100644 --- a/drivers/gles2/shader_compiler_gles2.h +++ b/drivers/gles2/shader_compiler_gles2.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -56,6 +56,13 @@ private: bool uses_worldvec; bool vertex_code_writes_vertex; bool uses_shadow_color; + + bool sinh_used; + bool tanh_used; + bool cosh_used; + + bool custom_h; + Flags *flags; StringName vname_discard; @@ -72,6 +79,7 @@ private: StringName vname_light; StringName vname_time; StringName vname_normalmap; + StringName vname_normalmap_depth; StringName vname_normal; StringName vname_texpixel_size; StringName vname_world_vec; diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp index 6a4596cb1e..e94930fffb 100644 --- a/drivers/gles2/shader_gles2.cpp +++ b/drivers/gles2/shader_gles2.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h index 9cd6142eb0..4604fd5501 100644 --- a/drivers/gles2/shader_gles2.h +++ b/drivers/gles2/shader_gles2.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index c4f0847870..e297b328cd 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -152,6 +152,7 @@ uniform vec4 modulate; uniform sampler2D light_texture; uniform vec4 light_color; +uniform vec4 light_shadow_color; uniform float light_height; varying vec4 light_uv_interp; @@ -207,7 +208,17 @@ void main() { { +#if defined(USE_NORMALMAP) + vec3 normal_map=vec3(0.0,0.0,1.0); + float normal_depth=1.0; +#endif + FRAGMENT_SHADER_CODE + +#if defined(USE_NORMALMAP) + normal = mix(vec3(0.0,0.0,1.0), normal_map * vec3(2.0,-2.0,1.0) - vec3( 1.0, -1.0, 0.0 ), normal_depth ); +#endif + } #ifdef DEBUG_ENCODED_32 highp float enc32 = dot( color,highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ); @@ -296,7 +307,7 @@ LIGHT_SHADER_CODE } - highp vec4 s = shadow_matrix * highp vec4(point,0.0,1.0); + highp vec4 s = shadow_matrix * vec4(point,0.0,1.0); s.xyz/=s.w; su=s.x*0.5+0.5; sz=s.z*0.5+0.5; @@ -369,7 +380,8 @@ LIGHT_SHADER_CODE #if defined(USE_LIGHT_SHADOW_COLOR) color=mix(shadow_color,color,shadow_attenuation); #else - color*=shadow_attenuation; + //color*=shadow_attenuation; + color=mix(light_shadow_color,color,shadow_attenuation); #endif //use shadows #endif diff --git a/drivers/mpc/mpc_reader.c b/drivers/mpc/mpc_reader.c index e1d151fe50..550c5ecb54 100644 --- a/drivers/mpc/mpc_reader.c +++ b/drivers/mpc/mpc_reader.c @@ -36,6 +36,7 @@ #include <mpc/reader.h> #include "internal.h" #include <stdio.h> +#include <string.h> // memset() #define STDIO_MAGIC 0xF34B963C ///< Just a random safe-check value... typedef struct mpc_reader_stdio_t { diff --git a/drivers/nrex/README.md b/drivers/nrex/README.md new file mode 100644 index 0000000000..f150a5d76f --- /dev/null +++ b/drivers/nrex/README.md @@ -0,0 +1,64 @@ +# NREX: Node RegEx + +Small node-based regular expression library. It only does text pattern +matchhing, not replacement. To use add the files `nrex.hpp`, `nrex.cpp` +and `nrex_config.h` to your project and follow the example: + + nrex regex; + regex.compile("^(fo+)bar$"); + + nrex_result captures[regex.capture_size()]; + if (regex.match("foobar", captures)) + { + std::cout << captures[0].start << std::endl; + std::cout << captures[0].length << std::endl; + } + +More details about its use is documented in `nrex.hpp` + +Currently supported features: + * Capturing `()` and non-capturing `(?:)` groups + * Any character `.` + * Shorthand caracter classes `\w\W\s\S\d\D` + * User-defined character classes such as `[A-Za-z]` + * Simple quantifiers `?`, `*` and `+` + * Range quantifiers `{0,1}` + * Lazy (non-greedy) quantifiers `*?` + * Begining `^` and end `$` anchors + * Alternation `|` + * Backreferences `\1` to `\99` + +To do list: + * Unicode `\uFFFF` code points + +## License + +Copyright (c) 2015, Zher Huei Lee +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/drivers/trex/SCsub b/drivers/nrex/SCsub index 877be8e3d9..2441d3061b 100644 --- a/drivers/trex/SCsub +++ b/drivers/nrex/SCsub @@ -2,8 +2,7 @@ Import('env') sources = [ - - 'trex.c', + 'nrex.cpp', 'regex.cpp', ] env.add_source_files(env.drivers_sources, sources) diff --git a/drivers/nrex/nrex.cpp b/drivers/nrex/nrex.cpp new file mode 100644 index 0000000000..696d46240e --- /dev/null +++ b/drivers/nrex/nrex.cpp @@ -0,0 +1,910 @@ +// NREX: Node RegEx +// +// Copyright (c) 2015, Zher Huei Lee +// All rights reserved. +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#include "nrex.hpp" + +#ifdef NREX_UNICODE +#include <wctype.h> +#include <wchar.h> +#define NREX_ISALPHANUM iswalnum +#define NREX_STRLEN wcslen +#else +#include <ctype.h> +#include <string.h> +#define NREX_ISALPHANUM isalnum +#define NREX_STRLEN strlen +#endif + +#ifdef NREX_THROW_ERROR +#define NREX_COMPILE_ERROR(M) throw nrex_compile_error(M) +#else +#define NREX_COMPILE_ERROR(M) reset(); return false +#endif + +#ifndef NREX_NEW +#define NREX_NEW(X) new X +#define NREX_NEW_ARRAY(X, N) new X[N] +#define NREX_DELETE(X) delete X +#define NREX_DELETE_ARRAY(X) delete[] X +#endif + +template<typename T> +class nrex_array +{ + private: + T* _data; + unsigned int _reserved; + unsigned int _size; + public: + nrex_array() + : _data(NREX_NEW_ARRAY(T, 2)) + , _reserved(2) + , _size(0) + { + } + + ~nrex_array() + { + NREX_DELETE_ARRAY(_data); + } + + unsigned int size() const + { + return _size; + } + + void reserve(unsigned int size) + { + T* old = _data; + _data = NREX_NEW_ARRAY(T, size); + _reserved = size; + for (unsigned int i = 0; i < _size; ++i) + { + _data[i] = old[i]; + } + NREX_DELETE_ARRAY(old); + } + + void push(T item) + { + if (_size == _reserved) + { + reserve(_reserved * 2); + } + _data[_size] = item; + _size++; + } + + T& top() + { + return _data[_size - 1]; + } + + const T& operator[] (unsigned int i) const + { + return _data[i]; + } + + void pop() + { + if (_size > 0) + { + --_size; + } + } +}; + +static nrex_char nrex_unescape(nrex_char repr) +{ + switch (repr) + { + case '^': return '^'; + case '$': return '$'; + case '(': return '('; + case ')': return ')'; + case '\\': return '\\'; + case '.': return '.'; + case '+': return '+'; + case '*': return '*'; + case '?': return '?'; + case '-': return '-'; + case 'a': return '\a'; + case 'e': return '\e'; + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + case 'v': return '\v'; + } + return 0; +} + +struct nrex_search +{ + public: + const nrex_char* str; + nrex_result* captures; + int end; + bool complete; + + nrex_char at(int pos) + { + return str[pos]; + } + + nrex_search(const nrex_char* str, nrex_result* captures) + : str(str) + , captures(captures) + , end(0) + { + } +}; + +struct nrex_node +{ + nrex_node* next; + nrex_node* previous; + nrex_node* parent; + bool quantifiable; + + nrex_node(bool quantify = false) + : next(NULL) + , previous(NULL) + , parent(NULL) + , quantifiable(quantify) + { + } + + virtual ~nrex_node() + { + if (next) + { + NREX_DELETE(next); + } + } + + virtual int test(nrex_search* s, int pos) const + { + return next ? next->test(s, pos) : -1; + } + + virtual int test_parent(nrex_search* s, int pos) const + { + if (next) + { + pos = next->test(s, pos); + } + if (parent && pos >= 0) + { + pos = parent->test_parent(s, pos); + } + if (pos >= 0) + { + s->complete = true; + } + return pos; + } +}; + +struct nrex_node_group : public nrex_node +{ + int capturing; + bool negate; + nrex_array<nrex_node*> childset; + nrex_node* back; + + nrex_node_group(int capturing) + : nrex_node(true) + , capturing(capturing) + , negate(false) + , back(NULL) + { + } + + virtual ~nrex_node_group() + { + for (unsigned int i = 0; i < childset.size(); ++i) + { + NREX_DELETE(childset[i]); + } + + } + + int test(nrex_search* s, int pos) const + { + if (capturing >= 0) + { + s->captures[capturing].start = pos; + } + for (unsigned int i = 0; i < childset.size(); ++i) + { + s->complete = false; + int res = childset[i]->test(s, pos); + if (s->complete) + { + return res; + } + if (negate) + { + if (res < 0) + { + res = pos + 1; + } + else + { + return -1; + } + } + if (res >= 0) + { + if (capturing >= 0) + { + s->captures[capturing].length = res - pos; + } + return next ? next->test(s, res) : res; + } + } + return -1; + } + + virtual int test_parent(nrex_search* s, int pos) const + { + if (capturing >= 0) + { + s->captures[capturing].length = pos - s->captures[capturing].start; + } + return nrex_node::test_parent(s, pos); + } + + void add_childset() + { + back = NULL; + } + + void add_child(nrex_node* node) + { + node->parent = this; + node->previous = back; + if (back) + { + back->next = node; + } + else + { + childset.push(node); + } + back = node; + } + + nrex_node* swap_back(nrex_node* node) + { + if (!back) + { + add_child(node); + return NULL; + } + nrex_node* old = back; + if (!old->previous) + { + childset.pop(); + } + back = old->previous; + add_child(node); + return old; + } +}; + +struct nrex_node_char : public nrex_node +{ + nrex_char ch; + + nrex_node_char(nrex_char c) + : nrex_node(true) + , ch(c) + { + } + + int test(nrex_search* s, int pos) const + { + if (s->end == pos || s->at(pos) != ch) + { + return -1; + } + return next ? next->test(s, pos + 1) : pos + 1; + } +}; + +struct nrex_node_range : public nrex_node +{ + nrex_char start; + nrex_char end; + + nrex_node_range(nrex_char s, nrex_char e) + : nrex_node(true) + , start(s) + , end(e) + { + } + + int test(nrex_search* s, int pos) const + { + if (s->end == pos) + { + return -1; + } + nrex_char c = s->at(pos); + if (c < start || end < c) + { + return -1; + } + return next ? next->test(s, pos + 1) : pos + 1; + } +}; + +static bool nrex_is_whitespace(nrex_char repr) +{ + switch (repr) + { + case ' ': + case '\t': + case '\r': + case '\n': + case '\f': + return true; + } + return false; +} + +static bool nrex_is_shorthand(nrex_char repr) +{ + switch (repr) + { + case 'W': + case 'w': + case 'D': + case 'd': + case 'S': + case 's': + return true; + } + return false; +} + +struct nrex_node_shorthand : public nrex_node +{ + nrex_char repr; + + nrex_node_shorthand(nrex_char c) + : nrex_node(true) + , repr(c) + { + } + + int test(nrex_search* s, int pos) const + { + if (s->end == pos) + { + return -1; + } + bool found = false; + bool invert = false; + nrex_char c = s->at(pos); + switch (repr) + { + case '.': + found = true; + break; + case 'W': + invert = true; + case 'w': + if (c == '_' || NREX_ISALPHANUM(c)) + { + found = true; + } + break; + case 'D': + invert = true; + case 'd': + if ('0' <= c && c <= '9') + { + found = true; + } + break; + case 'S': + invert = true; + case 's': + if (nrex_is_whitespace(c)) + { + found = true; + } + break; + } + if (found == invert) + { + return -1; + } + return next ? next->test(s, pos + 1) : pos + 1; + } +}; + +static bool nrex_is_quantifier(nrex_char repr) +{ + switch (repr) + { + case '?': + case '*': + case '+': + case '{': + return true; + } + return false; +} + +struct nrex_node_quantifier : public nrex_node +{ + int min; + int max; + bool greedy; + nrex_node* child; + + nrex_node_quantifier() + : nrex_node() + , min(0) + , max(0) + , greedy(true) + , child(NULL) + { + } + + virtual ~nrex_node_quantifier() + { + if (child) + { + NREX_DELETE(child); + } + } + + int test(nrex_search* s, int pos) const + { + nrex_array<int> backtrack; + backtrack.push(pos); + while (backtrack.top() <= s->end) + { + if (max >= 1 && backtrack.size() > (unsigned int)max) + { + break; + } + if (!greedy && (unsigned int)min < backtrack.size()) + { + int res = backtrack.top(); + if (next) + { + res = next->test(s, res); + } + if (s->complete) + { + return res; + } + if (res >= 0 && parent->test_parent(s, res) >= 0) + { + return res; + } + } + int res = child->test(s, backtrack.top()); + if (s->complete) + { + return res; + } + if (res < 0 || res == backtrack.top()) + { + break; + } + backtrack.push(res); + } + while (greedy && (unsigned int) min < backtrack.size()) + { + int res = backtrack.top(); + if (next) + { + res = next->test(s, res); + } + if (res >= 0 && parent->test_parent(s, res) >= 0) + { + return res; + } + if (s->complete) + { + return res; + } + backtrack.pop(); + } + return -1; + } +}; + +struct nrex_node_anchor : public nrex_node +{ + bool end; + + nrex_node_anchor(bool end) + : nrex_node() + , end(end) + { + } + + int test(nrex_search* s, int pos) const + { + if (!end && pos != 0) + { + return -1; + } + else if (end && pos != s->end) + { + return -1; + } + return next ? next->test(s, pos) : pos; + } +}; + +struct nrex_node_backreference : public nrex_node +{ + int ref; + + nrex_node_backreference(int ref) + : nrex_node(true) + , ref(ref) + { + } + + int test(nrex_search* s, int pos) const + { + nrex_result& r = s->captures[ref]; + for (int i = 0; i < r.length; ++i) + { + if (pos + i >= s->end) + { + return -1; + } + if (s->at(r.start + i) != s->at(pos + i)) + { + return -1; + } + } + return next ? next->test(s, pos + r.length) : pos + r.length; + } +}; + +nrex::nrex() + : _capturing(0) + , _root(NULL) +{ +} + +nrex::~nrex() +{ + if (_root) + { + NREX_DELETE(_root); + } +} + +bool nrex::valid() const +{ + return (_root != NULL); +} + +void nrex::reset() +{ + _capturing = 0; + if (_root) + { + NREX_DELETE(_root); + } + _root = NULL; +} + +int nrex::capture_size() const +{ + return _capturing + 1; +} + +bool nrex::compile(const nrex_char* pattern) +{ + reset(); + nrex_node_group* root = NREX_NEW(nrex_node_group(_capturing)); + nrex_array<nrex_node_group*> stack; + stack.push(root); + _root = root; + + for (const nrex_char* c = pattern; c[0] != '\0'; ++c) + { + if (c[0] == '(') + { + if (c[1] == '?') + { + if (c[2] == ':') + { + c = &c[2]; + nrex_node_group* group = NREX_NEW(nrex_node_group(-1)); + stack.top()->add_child(group); + stack.push(group); + } + else + { + NREX_COMPILE_ERROR("unrecognised qualifier for parenthesis"); + } + } + else if (_capturing < 99) + { + nrex_node_group* group = NREX_NEW(nrex_node_group(++_capturing)); + stack.top()->add_child(group); + stack.push(group); + } + else + { + nrex_node_group* group = NREX_NEW(nrex_node_group(-1)); + stack.top()->add_child(group); + stack.push(group); + } + } + else if (c[0] == ')') + { + if (stack.size() > 1) + { + stack.pop(); + } + else + { + NREX_COMPILE_ERROR("unexpected ')'"); + } + } + else if (c[0] == '[') + { + nrex_node_group* group = NREX_NEW(nrex_node_group(-1)); + stack.top()->add_child(group); + if (c[1] == '^') + { + group->negate = true; + ++c; + } + while (true) + { + group->add_childset(); + ++c; + if (c[0] == '\0') + { + NREX_COMPILE_ERROR("unclosed character class '[]'"); + } + if (c[0] == ']') + { + break; + } + else if (c[0] == '\\') + { + nrex_char unescaped = nrex_unescape(c[1]); + if (unescaped) + { + group->add_child(NREX_NEW(nrex_node_char(unescaped))); + ++c; + } + else if (nrex_is_shorthand(c[1])) + { + group->add_child(NREX_NEW(nrex_node_shorthand(c[1]))); + ++c; + } + else + { + NREX_COMPILE_ERROR("escape token not recognised"); + } + } + else + { + if (c[1] == '-' && c[2] != '\0') + { + bool range = false; + if ('A' <= c[0] && c[0] <= 'Z' && 'A' <= c[2] && c[2] <= 'Z') + { + range = true; + } + if ('a' <= c[0] && c[0] <= 'z' && 'a' <= c[2] && c[2] <= 'z') + { + range = true; + } + if ('0' <= c[0] && c[0] <= '9' && '0' <= c[2] && c[2] <= '9') + { + range = true; + } + if (range) + { + group->add_child(NREX_NEW(nrex_node_range(c[0], c[2]))); + c = &c[2]; + continue; + } + } + group->add_child(NREX_NEW(nrex_node_char(c[0]))); + } + + } + } + else if (nrex_is_quantifier(c[0])) + { + nrex_node_quantifier* quant = NREX_NEW(nrex_node_quantifier); + quant->child = stack.top()->swap_back(quant); + if (quant->child == NULL || !quant->child->quantifiable) + { + NREX_COMPILE_ERROR("element not quantifiable"); + } + quant->child->previous = NULL; + quant->child->next = NULL; + quant->child->parent = quant; + if (c[0] == '?') + { + quant->min = 0; + quant->max = 1; + } + else if (c[0] == '+') + { + quant->min = 1; + quant->max = -1; + } + else if (c[0] == '*') + { + quant->min = 0; + quant->max = -1; + } + else if (c[0] == '{') + { + bool max_set = false; + quant->min = 0; + quant->max = -1; + while (true) + { + ++c; + if (c[0] == '\0') + { + NREX_COMPILE_ERROR("unclosed range quantifier '{}'"); + } + else if (c[0] == '}') + { + break; + } + else if (c[0] == ',') + { + max_set = true; + continue; + } + else if (c[0] < '0' || '9' < c[0]) + { + NREX_COMPILE_ERROR("expected numeric digits, ',' or '}'"); + } + if (max_set) + { + if (quant->max < 0) + { + quant->max = int(c[0] - '0'); + } + else + { + quant->max = quant->max * 10 + int(c[0] - '0'); + } + } + else + { + quant->min = quant->min * 10 + int(c[0] - '0'); + } + } + if (!max_set) + { + quant->max = quant->min; + } + } + if (c[1] == '?') + { + quant->greedy = false; + ++c; + } + } + else if (c[0] == '|') + { + stack.top()->add_childset(); + } + else if (c[0] == '^' || c[0] == '$') + { + stack.top()->add_child(NREX_NEW(nrex_node_anchor((c[0] == '$')))); + } + else if (c[0] == '.') + { + stack.top()->add_child(NREX_NEW(nrex_node_shorthand('.'))); + } + else if (c[0] == '\\') + { + nrex_char unescaped = nrex_unescape(c[1]); + if (unescaped) + { + stack.top()->add_child(NREX_NEW(nrex_node_char(unescaped))); + ++c; + } + else if (nrex_is_shorthand(c[1])) + { + stack.top()->add_child(NREX_NEW(nrex_node_shorthand(c[1]))); + ++c; + } + else if ('1' <= c[1] && c[1] <= '9') + { + int ref = 0; + if ('0' <= c[2] && c[2] <= '9') + { + ref = int(c[1] - '0') * 10 + int(c[2] - '0'); + c = &c[2]; + } + else + { + ref = int(c[1] - '0'); + ++c; + } + if (ref > _capturing) + { + NREX_COMPILE_ERROR("backreference to non-existent capture"); + } + stack.top()->add_child(NREX_NEW(nrex_node_backreference(ref))); + } + else + { + NREX_COMPILE_ERROR("escape token not recognised"); + } + } + else + { + stack.top()->add_child(NREX_NEW(nrex_node_char(c[0]))); + } + } + return true; +} + +bool nrex::match(const nrex_char* str, nrex_result* captures, int offset, int end) const +{ + nrex_search s(str, captures); + if (end >= offset) + { + s.end = end; + } + else + { + s.end = NREX_STRLEN(str); + } + for (int i = offset; i < s.end; ++i) + { + for (int c = 0; c <= _capturing; ++c) + { + captures[c].start = 0; + captures[c].length = 0; + } + if (_root->test(&s, i) >= 0) + { + return true; + } + } + return false; +} diff --git a/drivers/nrex/nrex.hpp b/drivers/nrex/nrex.hpp new file mode 100644 index 0000000000..2a6aa08e1d --- /dev/null +++ b/drivers/nrex/nrex.hpp @@ -0,0 +1,144 @@ +// NREX: Node RegEx +// +// Copyright (c) 2015, Zher Huei Lee +// All rights reserved. +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#ifndef NREX_HPP +#define NREX_HPP + +#include "nrex_config.h" + +#ifdef NREX_UNICODE +typedef wchar_t nrex_char; +#else +typedef char nrex_char; +#endif + +/*! + * \brief Struct to contain the range of a capture result + * + * The range provided is relative to the begining of the searched string. + * + * \see nrex_node::match() + */ +struct nrex_result +{ + public: + int start; /*!< Start of text range */ + int length; /*!< Length of text range */ +}; + +class nrex_node; + +/*! + * \brief Holds the compiled regex pattern + */ +class nrex +{ + private: + int _capturing; + nrex_node* _root; + public: + nrex(); + ~nrex(); + + /*! + * \brief Removes the compiled regex and frees up the memory + */ + void reset(); + + /*! + * \brief Checks if there is a compiled regex being stored + * \return True if present, False if not present + */ + bool valid() const; + + /*! + * \brief Provides number of captures the compiled regex uses + * + * This is used to provide the array size of the captures needed for + * nrex::match() to work. The size is actually the number of capture + * groups + one for the matching of the entire pattern. The result is + * always capped at 100. + * + * \return The number of captures + */ + int capture_size() const; + + /*! + * \brief Compiles the provided regex pattern + * + * This automatically removes the existing compiled regex if already + * present. + * + * If the NREX_THROW_ERROR was defined it would automatically throw a + * runtime error nrex_compile_error if it encounters a problem when + * parsing the pattern. + * + * \param The regex pattern + * \return True if the pattern was succesfully compiled + */ + bool compile(const nrex_char* pattern); + + /*! + * \brief Uses the pattern to search through the provided string + * \param str The text to search through. It only needs to be + * null terminated if the end point is not provided. + * This also determines the starting anchor. + * \param captures The array of results to store the capture results. + * The size of that array needs to be the same as the + * size given in nrex::capture_size(). As it matches + * the function fills the array with the results. 0 is + * the result for the entire pattern, 1 and above + * corresponds to the regex capture group if present. + * \param offset The starting point of the search. This does not move + * the starting anchor. Defaults to 0. + * \param end The end point of the search. This also determines + * the ending anchor. If a number less than the offset + * is provided, the search would be done until null + * termination. Defaults to -1. + * \return True if a match was found. False otherwise. + */ + bool match(const nrex_char* str, nrex_result* captures, int offset = 0, int end = -1) const; +}; + +#ifdef NREX_THROW_ERROR + +#include <stdexcept> + +class nrex_compile_error : std::runtime_error +{ + public: + nrex_compile_error(const char* message) + : std::runtime_error(message) + { + } + + ~nrex_compile_error() throw() + { + } +}; + +#endif + +#endif // NREX_HPP diff --git a/drivers/nrex/nrex_config.h b/drivers/nrex/nrex_config.h new file mode 100644 index 0000000000..540f34f8b4 --- /dev/null +++ b/drivers/nrex/nrex_config.h @@ -0,0 +1,12 @@ +// Godot-specific configuration +// To use this, replace nrex_config.h + +#include "core/os/memory.h" + +#define NREX_UNICODE +//#define NREX_THROW_ERROR + +#define NREX_NEW(X) memnew(X) +#define NREX_NEW_ARRAY(X, N) memnew_arr(X, N) +#define NREX_DELETE(X) memdelete(X) +#define NREX_DELETE_ARRAY(X) memdelete_arr(X) diff --git a/drivers/nrex/regex.cpp b/drivers/nrex/regex.cpp new file mode 100644 index 0000000000..0a813c3490 --- /dev/null +++ b/drivers/nrex/regex.cpp @@ -0,0 +1,114 @@ +/*************************************************/ +/* regex.cpp */ +/*************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/*************************************************/ +/* Source code within this file is: */ +/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */ +/* All Rights Reserved. */ +/*************************************************/ + +#include "regex.h" +#include "nrex.hpp" +#include "core/os/memory.h" + +void RegEx::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("compile","pattern"),&RegEx::compile); + ObjectTypeDB::bind_method(_MD("find","text","start","end"),&RegEx::find, DEFVAL(0), DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("clear"),&RegEx::clear); + ObjectTypeDB::bind_method(_MD("is_valid"),&RegEx::is_valid); + ObjectTypeDB::bind_method(_MD("get_capture_count"),&RegEx::get_capture_count); + ObjectTypeDB::bind_method(_MD("get_capture","capture"),&RegEx::get_capture); + ObjectTypeDB::bind_method(_MD("get_captures"),&RegEx::_bind_get_captures); + +}; + +StringArray RegEx::_bind_get_captures() const { + + StringArray ret; + int count = get_capture_count(); + for (int i=0; i<count; i++) { + + String c = get_capture(i); + ret.push_back(c); + }; + + return ret; + +}; + +void RegEx::clear() { + + text.clear(); + captures.clear(); + exp.reset(); + +}; + +bool RegEx::is_valid() const { + + return exp.valid(); + +}; + +int RegEx::get_capture_count() const { + + return exp.capture_size(); +} + +String RegEx::get_capture(int capture) const { + + ERR_FAIL_COND_V( get_capture_count() <= capture, String() ); + + return text.substr(captures[capture].start, captures[capture].length); + +} + +Error RegEx::compile(const String& p_pattern) { + + clear(); + + exp.compile(p_pattern.c_str()); + + ERR_FAIL_COND_V( !exp.valid(), FAILED ); + + captures.resize(exp.capture_size()); + + return OK; + +}; + +int RegEx::find(const String& p_text, int p_start, int p_end) const { + + ERR_FAIL_COND_V( !exp.valid(), -1 ); + ERR_FAIL_COND_V( p_text.length() < p_start, -1 ); + ERR_FAIL_COND_V( p_text.length() < p_end, -1 ); + + bool res = exp.match(p_text.c_str(), &captures[0], p_start, p_end); + + if (res) { + text = p_text; + return captures[0].start; + } + text.clear(); + return -1; + +}; + +RegEx::RegEx(const String& p_pattern) { + + compile(p_pattern); + +}; + +RegEx::RegEx() { + +}; + +RegEx::~RegEx() { + + clear(); + +}; diff --git a/drivers/trex/regex.h b/drivers/nrex/regex.h index 899bfd0189..0626029705 100644 --- a/drivers/trex/regex.h +++ b/drivers/nrex/regex.h @@ -13,34 +13,31 @@ #define REGEX_H #include "ustring.h" -#include "list.h" +#include "vector.h" #include "core/reference.h" -struct TRex; +#include "nrex.hpp" class RegEx : public Reference { OBJ_TYPE(RegEx, Reference); mutable String text; - TRex *exp; + mutable Vector<nrex_result> captures; + nrex exp; protected: static void _bind_methods(); - - int _bind_find(const String& p_text, int p_start = 0, int p_end = -1) const; StringArray _bind_get_captures() const; + public: void clear(); - - Error compile(const String& p_pattern); bool is_valid() const; - bool match(const String& p_text, List<String>* p_captures = NULL, int p_start = 0, int p_end = -1) const; - bool find(const String& p_text, int& p_rstart, int &p_rend, List<String>* p_captures = NULL, int p_start = 0, int p_end = -1) const; int get_capture_count() const; - Error get_capture_limits(int p_capture, int& p_start, int& p_len) const; - String get_capture(int p_idx) const; + String get_capture(int capture) const; + Error compile(const String& p_pattern); + int find(const String& p_text, int p_start = 0, int p_end = -1) const; RegEx(); RegEx(const String& p_pattern); diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp index 6fc20f36f7..2a4720b07b 100644 --- a/drivers/png/image_loader_png.cpp +++ b/drivers/png/image_loader_png.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,6 +31,8 @@ #include "print_string.h" #include "os/os.h" + + void ImageLoaderPNG::_read_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length) { FileAccess *f = (FileAccess*)png_get_io_ptr(png_ptr); @@ -253,6 +255,7 @@ void ImageLoaderPNG::get_recognized_extensions(List<String> *p_extensions) const struct PNGReadStatus { int offset; + int size; const unsigned char *image; }; @@ -261,17 +264,26 @@ static void user_read_data(png_structp png_ptr,png_bytep data, png_size_t p_leng PNGReadStatus *rstatus; rstatus=(PNGReadStatus*)png_get_io_ptr(png_ptr); - memcpy(data,&rstatus->image[rstatus->offset],p_length); - rstatus->offset+=p_length; + int to_read=p_length; + if (rstatus->size>=0) { + to_read = MIN( p_length, rstatus->size - rstatus->offset); + } + memcpy(data,&rstatus->image[rstatus->offset],to_read); + rstatus->offset+=to_read; + + if (to_read<p_length) { + memset(&data[to_read],0,p_length-to_read); + } } -static Image _load_mem_png(const uint8_t* p_png) { +static Image _load_mem_png(const uint8_t* p_png,int p_size) { PNGReadStatus prs; prs.image=p_png; prs.offset=0; + prs.size=p_size; Image img; Error err = ImageLoaderPNG::_load_image(&prs,user_read_data,&img); @@ -283,9 +295,10 @@ static Image _load_mem_png(const uint8_t* p_png) { static Image _lossless_unpack_png(const DVector<uint8_t>& p_data) { + int len = p_data.size(); DVector<uint8_t>::Read r = p_data.read(); ERR_FAIL_COND_V(r[0]!='P' || r[1]!='N' || r[2]!='G' || r[3]!=' ',Image()); - return _load_mem_png(&r[4]); + return _load_mem_png(&r[4],len-4); } @@ -424,6 +437,7 @@ static DVector<uint8_t> _lossless_pack_png(const Image& p_image) { ImageLoaderPNG::ImageLoaderPNG() { + Image::_png_mem_loader_func=_load_mem_png; Image::lossless_unpacker=_lossless_unpack_png; Image::lossless_packer=_lossless_pack_png; diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h index 77f575339c..8413a7eae1 100644 --- a/drivers/png/image_loader_png.h +++ b/drivers/png/image_loader_png.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -40,7 +40,10 @@ class ImageLoaderPNG : public ImageFormatLoader { static void _read_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length); + public: + + static Error _load_image(void *rf_up,png_rw_ptr p_func,Image *p_image); virtual Error load_image(Image *p_image,FileAccess *f); virtual void get_recognized_extensions(List<String> *p_extensions) const; diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp index 462051b21e..76e0c03c46 100644 --- a/drivers/png/resource_saver_png.cpp +++ b/drivers/png/resource_saver_png.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -75,6 +75,9 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t if (bool(texture->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR)) { text+="tolinear=true\n"; } + if (bool(texture->get_flags()&Texture::FLAG_MIRRORED_REPEAT)) { + text+="mirroredrepeat=true\n"; + } if (text!="" || FileAccess::exists(p_path+".flags")) { diff --git a/drivers/pvr/AlphaBitmap.h b/drivers/pvr/AlphaBitmap.h new file mode 100644 index 0000000000..57c6b026ea --- /dev/null +++ b/drivers/pvr/AlphaBitmap.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Bitmap.h" + +namespace Javelin { + +class AlphaBitmap : public Bitmap { +public: + AlphaBitmap(int w, int h) + : Bitmap(w, h, 1) { + } + + const unsigned char *GetData() const { return data; } + + unsigned char *GetData() { return data; } +}; + +} diff --git a/drivers/pvr/BitScale.cpp b/drivers/pvr/BitScale.cpp new file mode 100644 index 0000000000..97b3f0aa25 --- /dev/null +++ b/drivers/pvr/BitScale.cpp @@ -0,0 +1,184 @@ +#include "BitScale.h" + + +const uint8_t Javelin::Data::BITSCALE_5_TO_8[32] = { + 0, 8, 16, 24, 32, 41, 49, 57, 65, 74, + 82, 90, 98, 106, 115, 123, 131, 139, 148, 156, + 164, 172, 180, 189, 197, 205, 213, 222, 230, 238, + 246, 255}; + +const uint8_t Javelin::Data::BITSCALE_4_TO_8[16] = { + 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, + 170, 187, 204, 221, 238, 255}; + +const uint8_t Javelin::Data::BITSCALE_3_TO_8[8] = { + 0, 36, 72, 109, 145, 182, 218, 255}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_5_FLOOR[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, + 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, + 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, + 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, + 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, + 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, + 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, + 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, + 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, + 30, 30, 30, 30, 30, 31}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_4_FLOOR[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 15}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_3_FLOOR[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 7}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_5_CEIL[256] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, + 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, + 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, + 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, + 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, + 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, + 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, + 28, 29, 29, 29, 29, 29, 29, 29, 29, 30, + 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, + 31, 31, 31, 31, 31, 31}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_4_CEIL[256] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_3_CEIL[256] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7}; + diff --git a/drivers/pvr/BitScale.h b/drivers/pvr/BitScale.h new file mode 100644 index 0000000000..36613aeeee --- /dev/null +++ b/drivers/pvr/BitScale.h @@ -0,0 +1,28 @@ +//============================================================================ + +#pragma once + +#include "typedefs.h" + +//============================================================================ + +namespace Javelin +{ + namespace Data + { +//============================================================================ + + extern const uint8_t BITSCALE_5_TO_8[32]; + extern const uint8_t BITSCALE_4_TO_8[16]; + extern const uint8_t BITSCALE_3_TO_8[8]; + extern const uint8_t BITSCALE_8_TO_5_FLOOR[256]; + extern const uint8_t BITSCALE_8_TO_4_FLOOR[256]; + extern const uint8_t BITSCALE_8_TO_3_FLOOR[256]; + extern const uint8_t BITSCALE_8_TO_5_CEIL[256]; + extern const uint8_t BITSCALE_8_TO_4_CEIL[256]; + extern const uint8_t BITSCALE_8_TO_3_CEIL[256]; + +//============================================================================ + } // namespace Data +} // namespace Javelin +//============================================================================ diff --git a/drivers/pvr/BitUtility.h b/drivers/pvr/BitUtility.h new file mode 100644 index 0000000000..588ff3e892 --- /dev/null +++ b/drivers/pvr/BitUtility.h @@ -0,0 +1,19 @@ +#pragma once + +namespace Javelin { + +class BitUtility { +public: + static bool IsPowerOf2(unsigned int x) { + return (x & (x - 1)) == 0; + } + + static unsigned int RotateRight(unsigned int value, unsigned int shift) { + if ((shift &= sizeof(value) * 8 - 1) == 0) { + return value; + } + return (value >> shift) | (value << (sizeof(value) * 8 - shift)); + } +}; + +} diff --git a/drivers/pvr/Bitmap.h b/drivers/pvr/Bitmap.h new file mode 100644 index 0000000000..508ed8cb75 --- /dev/null +++ b/drivers/pvr/Bitmap.h @@ -0,0 +1,34 @@ +#pragma once + +#include "Point2.h" + +namespace Javelin { + +class Bitmap { +public: + int width; + int height; + unsigned char *data; + + Bitmap(int w, int h, int bytesPerPixel) + : width(w) + , height(h) + , data(new unsigned char[width * height * bytesPerPixel]) { + } + + virtual ~Bitmap() { + delete [] data; + } + + Point2<int> GetSize() const { return Point2<int>(width, height); } + + int GetArea() const { return width * height; } + + int GetBitmapWidth() const { return width; } + + int GetBitmapHeight() const { return height; } + + const unsigned char *GetRawData() const { return data; } +}; + +} diff --git a/drivers/pvr/ColorRgba.h b/drivers/pvr/ColorRgba.h new file mode 100644 index 0000000000..0701420566 --- /dev/null +++ b/drivers/pvr/ColorRgba.h @@ -0,0 +1,152 @@ +#pragma once + +namespace Javelin { + +template<typename T> +class ColorRgb { +public: + T b; + T g; + T r; + + + ColorRgb() + : b(0) + , g(0) + , r(0) { + } + + ColorRgb(T red, T green, T blue) + : b(blue) + , g(green) + , r(red) { + } + + ColorRgb(const ColorRgb<T> &x) + : b(x.b) + , g(x.g) + , r(x.r) { + } + + ColorRgb<int> operator *(int x) { + return ColorRgb<int>(r * x, g * x, b * x); + } + + ColorRgb<int> operator +(const ColorRgb<T> &x) const { + return ColorRgb<int>(r + (int)x.r, g + (int)x.g, b + (int)x.b); + } + + ColorRgb<int> operator -(const ColorRgb<T> &x) const { + return ColorRgb<int>(r - (int)x.r, g - (int)x.g, b - (int)x.b); + } + + int operator %(const ColorRgb<T> &x) const { + return r * (int)x.r + g * (int)x.g + b * (int)x.b; + } + + bool operator ==(const ColorRgb<T> &x) const { + return r == x.r && g == x.g && b == x.b; + } + + bool operator !=(const ColorRgb<T> &x) const { + return r != x.r || g != x.g || b != x.b; + } + + void SetMin(const ColorRgb<T> &x) { + if (x.r < r) { + r = x.r; + } + if (x.g < g) { + g = x.g; + } + if (x.b < b) { + b = x.b; + } + } + + void SetMax(const ColorRgb<T> &x) { + if (x.r > r) { + r = x.r; + } + if (x.g > g) { + g = x.g; + } + if (x.b > b) { + b = x.b; + } + } +}; + +template<typename T> +class ColorRgba : public ColorRgb<T> { +public: + T a; + + ColorRgba() : + a(0) { + } + + ColorRgba(T red, T green, T blue, T alpha) + : ColorRgb<T>(red, green, blue) + , a(alpha) { + } + + ColorRgba(const ColorRgba<T> &x) + : ColorRgb<T>(x.r, x.g, x.b) + , a(x.a) { + } + + ColorRgba<int> operator *(int x) { + return ColorRgba<T>(ColorRgb<T>::r * x, + ColorRgb<T>::g * x, + ColorRgb<T>::b * x, + a * x); + } + + ColorRgba<int> operator +(const ColorRgba<T> &x) { + return ColorRgba<T>(ColorRgb<T>::r + (int)x.r, + ColorRgb<T>::g + (int)x.g, + ColorRgb<T>::b + (int)x.b, + a + (int)x.a); + } + + ColorRgba<int> operator -(const ColorRgba<T> &x) { + return ColorRgba<T>(ColorRgb<T>::r - (int)x.r, + ColorRgb<T>::g - (int)x.g, + ColorRgb<T>::b - (int)x.b, + a - (int)x.a); + } + + int operator %(const ColorRgba<T> &x) { + return ColorRgb<T>::r * (int)x.r + + ColorRgb<T>::g * (int)x.g + + ColorRgb<T>::b * (int)x.b + + a * (int)x.a; + } + + bool operator ==(const ColorRgba<T> &x) { + return ColorRgb<T>::r == x.r && ColorRgb<T>::g == x.g && + ColorRgb<T>::b == x.b && a == x.a; + } + + bool operator !=(const ColorRgba<T> &x) { + return ColorRgb<T>::r != x.r || ColorRgb<T>::g != x.g || + ColorRgb<T>::b != x.b || a != x.a; + } + + void SetMin(const ColorRgba<T> &x) { + ColorRgb<T>::SetMin(x); + if (x.a < a) { + a = x.a; + } + } + + void SetMax(const ColorRgba<T> &x) { + ColorRgb<T>::SetMax(x); + if (x.a > a) { + a = x.a; + } + } +}; + +} diff --git a/drivers/pvr/Interval.h b/drivers/pvr/Interval.h new file mode 100644 index 0000000000..a7252e8375 --- /dev/null +++ b/drivers/pvr/Interval.h @@ -0,0 +1,21 @@ +#pragma once + +namespace Javelin { + +template<typename T> +class Interval { +public: + T min; + T max; + + Interval() { + } + + Interval<T> &operator|=(const T &x) { + min.SetMin(x); + max.SetMax(x); + return *this; + } +}; + +} diff --git a/drivers/pvr/MortonTable.cpp b/drivers/pvr/MortonTable.cpp new file mode 100644 index 0000000000..29a5af67f6 --- /dev/null +++ b/drivers/pvr/MortonTable.cpp @@ -0,0 +1,43 @@ +//============================================================================ + +#include "MortonTable.h" + +//============================================================================ + +const unsigned short Javelin::Data::MORTON_TABLE[256] = +{ + 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, + 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, + 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, + 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, + 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, + 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, + 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, + 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, + 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, + 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, + 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, + 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, + 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, + 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, + 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, + 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, + 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, + 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, + 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, + 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, + 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, + 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, + 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, + 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, + 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, + 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, + 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, + 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, + 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, + 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, + 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, + 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 +}; + +//============================================================================ diff --git a/drivers/pvr/MortonTable.h b/drivers/pvr/MortonTable.h new file mode 100644 index 0000000000..7a27e59544 --- /dev/null +++ b/drivers/pvr/MortonTable.h @@ -0,0 +1,18 @@ +//============================================================================ + +#pragma once + +//============================================================================ + +namespace Javelin +{ + namespace Data + { +//============================================================================ + + extern const unsigned short MORTON_TABLE[256]; + +//============================================================================ + } // namespace Data +} // namespace Javelin +//============================================================================ diff --git a/drivers/pvr/Point2.h b/drivers/pvr/Point2.h new file mode 100644 index 0000000000..89fa4b6322 --- /dev/null +++ b/drivers/pvr/Point2.h @@ -0,0 +1,17 @@ +#pragma once + +namespace Javelin { + +template<typename T> +class Point2 { +public: + T x; + T y; + + Point2(int a, int b) + : x(a) + , y(b) { + } +}; + +} diff --git a/drivers/pvr/PvrTcDecoder.cpp b/drivers/pvr/PvrTcDecoder.cpp new file mode 100644 index 0000000000..d8a36b342c --- /dev/null +++ b/drivers/pvr/PvrTcDecoder.cpp @@ -0,0 +1,144 @@ +//============================================================================ + +#include "PvrTcDecoder.h" +#include "PvrTcPacket.h" + +#include "MortonTable.h" +#include <assert.h> + +//============================================================================ + +using namespace Javelin; +using Data::MORTON_TABLE; + +//============================================================================ + +inline unsigned PvrTcDecoder::GetMortonNumber(int x, int y) +{ + return MORTON_TABLE[x >> 8] << 17 | MORTON_TABLE[y >> 8] << 16 | MORTON_TABLE[x & 0xFF] << 1 | MORTON_TABLE[y & 0xFF]; +} + +//============================================================================ + +void PvrTcDecoder::DecodeRgb4Bpp(ColorRgb<unsigned char>* result, const Point2<int>& size, const void* data) +{ + assert(size.x == size.y); + + const int blocks = size.x / 4; + const int blockMask = blocks-1; + const PvrTcPacket* packets = static_cast<const PvrTcPacket*>(data); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const PvrTcPacket* packet = packets + GetMortonNumber(x, y); + + unsigned mod = packet->modulationData; + const unsigned char (*weights)[4] = PvrTcPacket::WEIGHTS + 4*packet->usePunchthroughAlpha; + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] + + p1->GetColorRgbA() * (*factor)[1] + + p2->GetColorRgbA() * (*factor)[2] + + p3->GetColorRgbA() * (*factor)[3]; + + ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] + + p1->GetColorRgbB() * (*factor)[1] + + p2->GetColorRgbB() * (*factor)[2] + + p3->GetColorRgbB() * (*factor)[3]; + + const unsigned char* w = weights[mod&3]; + ColorRgb<unsigned char> c; + c.r = (ca.r * w[0] + cb.r * w[1]) >> 7; + c.g = (ca.g * w[0] + cb.g * w[1]) >> 7; + c.b = (ca.b * w[0] + cb.b * w[1]) >> 7; + + result[(py+y*4)*size.x + (px+x*4)] = c; + mod >>= 2; + factor++; + } + } + } + } +} + +void PvrTcDecoder::DecodeRgba4Bpp(ColorRgba<unsigned char>* result, const Point2<int>& size, const void* data) +{ + assert(size.x == size.y); + + const int blocks = size.x / 4; + const int blockMask = blocks-1; + const PvrTcPacket* packets = static_cast<const PvrTcPacket*>(data); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const PvrTcPacket* packet = packets + GetMortonNumber(x, y); + + unsigned mod = packet->modulationData; + const unsigned char (*weights)[4] = PvrTcPacket::WEIGHTS + 4*packet->usePunchthroughAlpha; + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgba<int> ca = p0->GetColorRgbaA() * (*factor)[0] + + p1->GetColorRgbaA() * (*factor)[1] + + p2->GetColorRgbaA() * (*factor)[2] + + p3->GetColorRgbaA() * (*factor)[3]; + + ColorRgba<int> cb = p0->GetColorRgbaB() * (*factor)[0] + + p1->GetColorRgbaB() * (*factor)[1] + + p2->GetColorRgbaB() * (*factor)[2] + + p3->GetColorRgbaB() * (*factor)[3]; + + const unsigned char* w = weights[mod&3]; + ColorRgba<unsigned char> c; + c.r = (ca.r * w[0] + cb.r * w[1]) >> 7; + c.g = (ca.g * w[0] + cb.g * w[1]) >> 7; + c.b = (ca.b * w[0] + cb.b * w[1]) >> 7; + c.a = (ca.a * w[2] + cb.a * w[3]) >> 7; + + result[(py+y*4)*size.x + (px+x*4)] = c; + mod >>= 2; + factor++; + } + } + } + } +} + +//============================================================================ diff --git a/drivers/pvr/PvrTcDecoder.h b/drivers/pvr/PvrTcDecoder.h new file mode 100644 index 0000000000..1b6fcf964c --- /dev/null +++ b/drivers/pvr/PvrTcDecoder.h @@ -0,0 +1,25 @@ +//============================================================================ + +#pragma once +#include "Point2.h" +#include "ColorRgba.h" + +//============================================================================ + +namespace Javelin +{ +//============================================================================ + + class PvrTcDecoder + { + public: + static void DecodeRgb4Bpp(ColorRgb<unsigned char>* result, const Point2<int>& size, const void* data); + static void DecodeRgba4Bpp(ColorRgba<unsigned char>* result, const Point2<int>& size, const void* data); + + private: + static unsigned GetMortonNumber(int x, int y); + }; + +//============================================================================ +} +//============================================================================ diff --git a/drivers/pvr/PvrTcEncoder.cpp b/drivers/pvr/PvrTcEncoder.cpp new file mode 100644 index 0000000000..587b1320f1 --- /dev/null +++ b/drivers/pvr/PvrTcEncoder.cpp @@ -0,0 +1,474 @@ +//============================================================================ + +#include "PvrTcEncoder.h" +#include "AlphaBitmap.h" +#include "PvrTcPacket.h" +#include "RgbBitmap.h" +#include "RgbaBitmap.h" +#include "MortonTable.h" +#include "BitUtility.h" +#include "Interval.h" +#include <assert.h> +#include <math.h> +#include <stdint.h> + +//============================================================================ + +using namespace Javelin; +using Data::MORTON_TABLE; + +//============================================================================ + +static const unsigned char MODULATION_LUT[16] = +{ + 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3 +}; + +//============================================================================ + +inline unsigned PvrTcEncoder::GetMortonNumber(int x, int y) +{ + return MORTON_TABLE[x >> 8] << 17 | MORTON_TABLE[y >> 8] << 16 | MORTON_TABLE[x & 0xFF] << 1 | MORTON_TABLE[y & 0xFF]; +} + +//============================================================================ + +void PvrTcEncoder::EncodeAlpha2Bpp(void* result, const AlphaBitmap& bitmap) +{ + int size = bitmap.GetBitmapWidth(); + assert(size == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(size)); + + // Blocks in each dimension. + int xBlocks = size/8; + int yBlocks = size/4; + + const unsigned char* bitmapData = bitmap.GetRawData(); + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + for(int y = 0; y < yBlocks; ++y) + { + for(int x = 0; x < xBlocks; ++x) + { + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->colorAIsOpaque = 0; + packet->colorA = 0x7ff; // White, with 0 alpha + packet->colorBIsOpaque = 1; + packet->colorB = 0x7fff; // White with full alpha + + const unsigned char* blockBitmapData = &bitmapData[y*4*size + x*8]; + + uint32_t modulationData = 0; + for(int py = 0; py < 4; ++py) + { + const unsigned char* rowBitmapData = blockBitmapData; + for(int px = 0; px < 8; ++px) + { + unsigned char pixel = *rowBitmapData++; + modulationData = BitUtility::RotateRight(modulationData | (pixel >> 7), 1); + } + blockBitmapData += size; + } + packet->modulationData = modulationData; + } + } +} + +void PvrTcEncoder::EncodeAlpha4Bpp(void* result, const AlphaBitmap& bitmap) +{ + int size = bitmap.GetBitmapWidth(); + assert(size == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(size)); + + // Blocks in each dimension. + int blocks = size/4; + + const unsigned char* bitmapData = bitmap.GetRawData(); + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->colorAIsOpaque = 0; + packet->colorA = 0x7ff; // White, with 0 alpha + packet->colorBIsOpaque = 1; + packet->colorB = 0x7fff; // White with full alpha + + const unsigned char* blockBitmapData = &bitmapData[(y*size + x)*4]; + + uint32_t modulationData = 0; + for(int py = 0; py < 4; ++py) + { + const unsigned char* rowBitmapData = blockBitmapData; + for(int px = 0; px < 4; ++px) + { + unsigned char pixel = *rowBitmapData++; + modulationData = BitUtility::RotateRight(modulationData | MODULATION_LUT[pixel>>4], 2); + } + blockBitmapData += size; + } + packet->modulationData = modulationData; + } + } +} + +//============================================================================ + +typedef Interval<ColorRgb<unsigned char> > ColorRgbBoundingBox; + +static void CalculateBoundingBox(ColorRgbBoundingBox& cbb, const RgbBitmap& bitmap, int blockX, int blockY) +{ + int size = bitmap.GetBitmapWidth(); + const ColorRgb<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4; + + cbb.min = data[0]; + cbb.max = data[0]; + cbb |= data[1]; + cbb |= data[2]; + cbb |= data[3]; + + cbb |= data[size]; + cbb |= data[size+1]; + cbb |= data[size+2]; + cbb |= data[size+3]; + + cbb |= data[2*size]; + cbb |= data[2*size+1]; + cbb |= data[2*size+2]; + cbb |= data[2*size+3]; + + cbb |= data[3*size]; + cbb |= data[3*size+1]; + cbb |= data[3*size+2]; + cbb |= data[3*size+3]; +} + +void PvrTcEncoder::EncodeRgb4Bpp(void* result, const RgbBitmap& bitmap) +{ + assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth())); + const int size = bitmap.GetBitmapWidth(); + const int blocks = size / 4; + const int blockMask = blocks-1; + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + ColorRgbBoundingBox cbb; + CalculateBoundingBox(cbb, bitmap, x, y); + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->SetColorA(cbb.min); + packet->SetColorB(cbb.max); + } + } + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + const ColorRgb<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4; + + uint32_t modulationData = 0; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] + + p1->GetColorRgbA() * (*factor)[1] + + p2->GetColorRgbA() * (*factor)[2] + + p3->GetColorRgbA() * (*factor)[3]; + + ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] + + p1->GetColorRgbB() * (*factor)[1] + + p2->GetColorRgbB() * (*factor)[2] + + p3->GetColorRgbB() * (*factor)[3]; + + const ColorRgb<unsigned char>& pixel = data[py*size + px]; + ColorRgb<int> d = cb - ca; + ColorRgb<int> p; + p.r=pixel.r*16; + p.g=pixel.g*16; + p.b=pixel.b*16; + ColorRgb<int> v = p - ca; + + // PVRTC uses weightings of 0, 3/8, 5/8 and 1 + // The boundaries for these are 3/16, 1/2 (=8/16), 13/16 + int projection = (v % d) * 16; + int lengthSquared = d % d; + if(projection > 3*lengthSquared) modulationData++; + if(projection > 8*lengthSquared) modulationData++; + if(projection > 13*lengthSquared) modulationData++; + + modulationData = BitUtility::RotateRight(modulationData, 2); + + factor++; + } + } + + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->modulationData = modulationData; + } + } +} + +//============================================================================ + +static void CalculateBoundingBox(ColorRgbBoundingBox& cbb, const RgbaBitmap& bitmap, int blockX, int blockY) +{ + int size = bitmap.GetBitmapWidth(); + const ColorRgba<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4; + + cbb.min = data[0]; + cbb.max = data[0]; + + cbb |= data[1]; + cbb |= data[2]; + cbb |= data[3]; + + cbb |= data[size]; + cbb |= data[size+1]; + cbb |= data[size+2]; + cbb |= data[size+3]; + + cbb |= data[2*size]; + cbb |= data[2*size+1]; + cbb |= data[2*size+2]; + cbb |= data[2*size+3]; + + cbb |= data[3*size]; + cbb |= data[3*size+1]; + cbb |= data[3*size+2]; + cbb |= data[3*size+3]; +} + +void PvrTcEncoder::EncodeRgb4Bpp(void* result, const RgbaBitmap& bitmap) +{ + assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth())); + const int size = bitmap.GetBitmapWidth(); + const int blocks = size / 4; + const int blockMask = blocks-1; + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + ColorRgbBoundingBox cbb; + CalculateBoundingBox(cbb, bitmap, x, y); + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->SetColorA(cbb.min); + packet->SetColorB(cbb.max); + } + } + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + const ColorRgba<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4; + + uint32_t modulationData = 0; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] + + p1->GetColorRgbA() * (*factor)[1] + + p2->GetColorRgbA() * (*factor)[2] + + p3->GetColorRgbA() * (*factor)[3]; + + ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] + + p1->GetColorRgbB() * (*factor)[1] + + p2->GetColorRgbB() * (*factor)[2] + + p3->GetColorRgbB() * (*factor)[3]; + + const ColorRgb<unsigned char>& pixel = data[py*size + px]; + ColorRgb<int> d = cb - ca; + ColorRgb<int> p; + p.r=pixel.r*16; + p.g=pixel.g*16; + p.b=pixel.b*16; + ColorRgb<int> v = p - ca; + + // PVRTC uses weightings of 0, 3/8, 5/8 and 1 + // The boundaries for these are 3/16, 1/2 (=8/16), 13/16 + int projection = (v % d) * 16; + int lengthSquared = d % d; + if(projection > 3*lengthSquared) modulationData++; + if(projection > 8*lengthSquared) modulationData++; + if(projection > 13*lengthSquared) modulationData++; + + modulationData = BitUtility::RotateRight(modulationData, 2); + + factor++; + } + } + + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->modulationData = modulationData; + } + } +} + +//============================================================================ + +typedef Interval<ColorRgba<unsigned char> > ColorRgbaBoundingBox; + +static void CalculateBoundingBox(ColorRgbaBoundingBox& cbb, const RgbaBitmap& bitmap, int blockX, int blockY) +{ + int size = bitmap.GetBitmapWidth(); + const ColorRgba<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4; + + cbb.min = data[0]; + cbb.max = data[0]; + + cbb |= data[1]; + cbb |= data[2]; + cbb |= data[3]; + + cbb |= data[size]; + cbb |= data[size+1]; + cbb |= data[size+2]; + cbb |= data[size+3]; + + cbb |= data[2*size]; + cbb |= data[2*size+1]; + cbb |= data[2*size+2]; + cbb |= data[2*size+3]; + + cbb |= data[3*size]; + cbb |= data[3*size+1]; + cbb |= data[3*size+2]; + cbb |= data[3*size+3]; +} + +void PvrTcEncoder::EncodeRgba4Bpp(void* result, const RgbaBitmap& bitmap) +{ + assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth())); + const int size = bitmap.GetBitmapWidth(); + const int blocks = size / 4; + const int blockMask = blocks-1; + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + ColorRgbaBoundingBox cbb; + CalculateBoundingBox(cbb, bitmap, x, y); + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->SetColorA(cbb.min); + packet->SetColorB(cbb.max); + } + } + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + const ColorRgba<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4; + + uint32_t modulationData = 0; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgba<int> ca = p0->GetColorRgbaA() * (*factor)[0] + + p1->GetColorRgbaA() * (*factor)[1] + + p2->GetColorRgbaA() * (*factor)[2] + + p3->GetColorRgbaA() * (*factor)[3]; + + ColorRgba<int> cb = p0->GetColorRgbaB() * (*factor)[0] + + p1->GetColorRgbaB() * (*factor)[1] + + p2->GetColorRgbaB() * (*factor)[2] + + p3->GetColorRgbaB() * (*factor)[3]; + + const ColorRgba<unsigned char>& pixel = data[py*size + px]; + ColorRgba<int> d = cb - ca; + ColorRgba<int> p; + p.r=pixel.r*16; + p.g=pixel.g*16; + p.b=pixel.b*16; + p.a=pixel.a*16; + ColorRgba<int> v = p - ca; + + // PVRTC uses weightings of 0, 3/8, 5/8 and 1 + // The boundaries for these are 3/16, 1/2 (=8/16), 13/16 + int projection = (v % d) * 16; + int lengthSquared = d % d; + if(projection > 3*lengthSquared) modulationData++; + if(projection > 8*lengthSquared) modulationData++; + if(projection > 13*lengthSquared) modulationData++; + + modulationData = BitUtility::RotateRight(modulationData, 2); + + factor++; + } + } + + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->modulationData = modulationData; + } + } +} + +//============================================================================ diff --git a/drivers/pvr/PvrTcEncoder.h b/drivers/pvr/PvrTcEncoder.h new file mode 100644 index 0000000000..b9344367d9 --- /dev/null +++ b/drivers/pvr/PvrTcEncoder.h @@ -0,0 +1,40 @@ +//============================================================================ + +#pragma once +#include "ColorRgba.h" + +//============================================================================ + +namespace Javelin +{ +//============================================================================ + + class AlphaBitmap; + class RgbBitmap; + class RgbaBitmap; + + class PvrTcEncoder + { + public: + // Result must be large enough for bitmap.GetArea()/4 bytes + static void EncodeAlpha2Bpp(void* result, const AlphaBitmap& bitmap); + + // Result must be large enough for bitmap.GetArea()/2 bytes + static void EncodeAlpha4Bpp(void* result, const AlphaBitmap& bitmap); + + // Result must be large enough for bitmap.GetArea()/2 bytes + static void EncodeRgb4Bpp(void* result, const RgbBitmap& bitmap); + + // Result must be large enough for bitmap.GetArea()/2 bytes + static void EncodeRgb4Bpp(void* result, const RgbaBitmap& bitmap); + + // Result must be large enough for bitmap.GetArea()/2 bytes + static void EncodeRgba4Bpp(void* result, const RgbaBitmap& bitmap); + + private: + static unsigned GetMortonNumber(int x, int y); + }; + +//============================================================================ +} +//============================================================================ diff --git a/drivers/pvr/PvrTcPacket.cpp b/drivers/pvr/PvrTcPacket.cpp new file mode 100644 index 0000000000..2e40d371e8 --- /dev/null +++ b/drivers/pvr/PvrTcPacket.cpp @@ -0,0 +1,209 @@ +//============================================================================ + +#include "PvrTcPacket.h" +#include "BitScale.h" + +//============================================================================ + +using namespace Javelin; + +//============================================================================ + +const unsigned char PvrTcPacket::BILINEAR_FACTORS[16][4] = +{ + { 4, 4, 4, 4 }, + { 2, 6, 2, 6 }, + { 8, 0, 8, 0 }, + { 6, 2, 6, 2 }, + + { 2, 2, 6, 6 }, + { 1, 3, 3, 9 }, + { 4, 0, 12, 0 }, + { 3, 1, 9, 3 }, + + { 8, 8, 0, 0 }, + { 4, 12, 0, 0 }, + { 16, 0, 0, 0 }, + { 12, 4, 0, 0 }, + + { 6, 6, 2, 2 }, + { 3, 9, 1, 3 }, + { 12, 0, 4, 0 }, + { 9, 3, 3, 1 }, +}; + +// Weights are { colorA, colorB, alphaA, alphaB } +const unsigned char PvrTcPacket::WEIGHTS[8][4] = +{ + // Weights for Mode=0 + { 8, 0, 8, 0 }, + { 5, 3, 5, 3 }, + { 3, 5, 3, 5 }, + { 0, 8, 0, 8 }, + + // Weights for Mode=1 + { 8, 0, 8, 0 }, + { 4, 4, 4, 4 }, + { 4, 4, 0, 0 }, + { 0, 8, 0, 8 }, +}; + +//============================================================================ + +ColorRgb<int> PvrTcPacket::GetColorRgbA() const +{ + if(colorAIsOpaque) + { + unsigned char r = colorA >> 9; + unsigned char g = colorA >> 4 & 0x1f; + unsigned char b = colorA & 0xf; + return ColorRgb<int>(Data::BITSCALE_5_TO_8[r], + Data::BITSCALE_5_TO_8[g], + Data::BITSCALE_4_TO_8[b]); + } + else + { + unsigned char r = (colorA >> 7) & 0xf; + unsigned char g = (colorA >> 3) & 0xf; + unsigned char b = colorA & 7; + return ColorRgb<int>(Data::BITSCALE_4_TO_8[r], + Data::BITSCALE_4_TO_8[g], + Data::BITSCALE_3_TO_8[b]); + } +} + +ColorRgb<int> PvrTcPacket::GetColorRgbB() const +{ + if(colorBIsOpaque) + { + unsigned char r = colorB >> 10; + unsigned char g = colorB >> 5 & 0x1f; + unsigned char b = colorB & 0x1f; + return ColorRgb<int>(Data::BITSCALE_5_TO_8[r], + Data::BITSCALE_5_TO_8[g], + Data::BITSCALE_5_TO_8[b]); + } + else + { + unsigned char r = colorB >> 8 & 0xf; + unsigned char g = colorB >> 4 & 0xf; + unsigned char b = colorB & 0xf; + return ColorRgb<int>(Data::BITSCALE_4_TO_8[r], + Data::BITSCALE_4_TO_8[g], + Data::BITSCALE_4_TO_8[b]); + } +} + +ColorRgba<int> PvrTcPacket::GetColorRgbaA() const +{ + if(colorAIsOpaque) + { + unsigned char r = colorA >> 9; + unsigned char g = colorA >> 4 & 0x1f; + unsigned char b = colorA & 0xf; + return ColorRgba<int>(Data::BITSCALE_5_TO_8[r], + Data::BITSCALE_5_TO_8[g], + Data::BITSCALE_4_TO_8[b], + 255); + } + else + { + unsigned char a = colorA >> 11 & 7; + unsigned char r = colorA >> 7 & 0xf; + unsigned char g = colorA >> 3 & 0xf; + unsigned char b = colorA & 7; + return ColorRgba<int>(Data::BITSCALE_4_TO_8[r], + Data::BITSCALE_4_TO_8[g], + Data::BITSCALE_3_TO_8[b], + Data::BITSCALE_3_TO_8[a]); + } +} + +ColorRgba<int> PvrTcPacket::GetColorRgbaB() const +{ + if(colorBIsOpaque) + { + unsigned char r = colorB >> 10; + unsigned char g = colorB >> 5 & 0x1f; + unsigned char b = colorB & 0x1f; + return ColorRgba<int>(Data::BITSCALE_5_TO_8[r], + Data::BITSCALE_5_TO_8[g], + Data::BITSCALE_5_TO_8[b], + 255); + } + else + { + unsigned char a = colorB >> 12 & 7; + unsigned char r = colorB >> 8 & 0xf; + unsigned char g = colorB >> 4 & 0xf; + unsigned char b = colorB & 0xf; + return ColorRgba<int>(Data::BITSCALE_4_TO_8[r], + Data::BITSCALE_4_TO_8[g], + Data::BITSCALE_4_TO_8[b], + Data::BITSCALE_3_TO_8[a]); + } +} + +//============================================================================ + +void PvrTcPacket::SetColorA(const ColorRgb<unsigned char>& c) +{ + int r = Data::BITSCALE_8_TO_5_FLOOR[c.r]; + int g = Data::BITSCALE_8_TO_5_FLOOR[c.g]; + int b = Data::BITSCALE_8_TO_4_FLOOR[c.b]; + colorA = r<<9 | g<<4 | b; + colorAIsOpaque = true; +} + +void PvrTcPacket::SetColorB(const ColorRgb<unsigned char>& c) +{ + int r = Data::BITSCALE_8_TO_5_CEIL[c.r]; + int g = Data::BITSCALE_8_TO_5_CEIL[c.g]; + int b = Data::BITSCALE_8_TO_5_CEIL[c.b]; + colorB = r<<10 | g<<5 | b; + colorBIsOpaque = true; +} + +void PvrTcPacket::SetColorA(const ColorRgba<unsigned char>& c) +{ + int a = Data::BITSCALE_8_TO_3_FLOOR[c.a]; + if(a == 7) + { + int r = Data::BITSCALE_8_TO_5_FLOOR[c.r]; + int g = Data::BITSCALE_8_TO_5_FLOOR[c.g]; + int b = Data::BITSCALE_8_TO_4_FLOOR[c.b]; + colorA = r<<9 | g<<4 | b; + colorAIsOpaque = true; + } + else + { + int r = Data::BITSCALE_8_TO_4_FLOOR[c.r]; + int g = Data::BITSCALE_8_TO_4_FLOOR[c.g]; + int b = Data::BITSCALE_8_TO_3_FLOOR[c.b]; + colorA = a<<11 | r<<7 | g<<3 | b; + colorAIsOpaque = false; + } +} + +void PvrTcPacket::SetColorB(const ColorRgba<unsigned char>& c) +{ + int a = Data::BITSCALE_8_TO_3_CEIL[c.a]; + if(a == 7) + { + int r = Data::BITSCALE_8_TO_5_CEIL[c.r]; + int g = Data::BITSCALE_8_TO_5_CEIL[c.g]; + int b = Data::BITSCALE_8_TO_5_CEIL[c.b]; + colorB = r<<10 | g<<5 | b; + colorBIsOpaque = true; + } + else + { + int r = Data::BITSCALE_8_TO_4_CEIL[c.r]; + int g = Data::BITSCALE_8_TO_4_CEIL[c.g]; + int b = Data::BITSCALE_8_TO_4_CEIL[c.b]; + colorB = a<<12 | r<<8 | g<<4 | b; + colorBIsOpaque = false; + } +} + +//============================================================================ diff --git a/drivers/pvr/PvrTcPacket.h b/drivers/pvr/PvrTcPacket.h new file mode 100644 index 0000000000..ac3b6a4dd1 --- /dev/null +++ b/drivers/pvr/PvrTcPacket.h @@ -0,0 +1,65 @@ +//============================================================================ +// +// Modulation data specifies weightings of colorA to colorB for each pixel +// +// For mode = 0 +// 00: 0/8 +// 01: 3/8 +// 10: 5/8 +// 11: 8/8 +// +// For mode = 1 +// 00: 0/8 +// 01: 4/8 +// 10: 4/8 with alpha punchthrough +// 11: 8/8 +// +// For colorIsOpaque=0 +// 3 bits A +// 4 bits R +// 4 bits G +// 3/4 bits B +// +// For colorIsOpaque=1 +// 5 bits R +// 5 bits G +// 4/5 bits B +// +//============================================================================ + +#pragma once +#include "ColorRgba.h" + +//============================================================================ + +namespace Javelin +{ +//============================================================================ + + struct PvrTcPacket + { + unsigned int modulationData; + unsigned usePunchthroughAlpha : 1; + unsigned colorA : 14; + unsigned colorAIsOpaque : 1; + unsigned colorB : 15; + unsigned colorBIsOpaque : 1; + + ColorRgb<int> GetColorRgbA() const; + ColorRgb<int> GetColorRgbB() const; + ColorRgba<int> GetColorRgbaA() const; + ColorRgba<int> GetColorRgbaB() const; + + void SetColorA(const ColorRgb<unsigned char>& c); + void SetColorB(const ColorRgb<unsigned char>& c); + + void SetColorA(const ColorRgba<unsigned char>& c); + void SetColorB(const ColorRgba<unsigned char>& c); + + static const unsigned char BILINEAR_FACTORS[16][4]; + static const unsigned char WEIGHTS[8][4]; + }; + +//============================================================================ +} // namespace Javelin +//============================================================================ diff --git a/drivers/pvr/RgbBitmap.h b/drivers/pvr/RgbBitmap.h new file mode 100644 index 0000000000..cf1d78667d --- /dev/null +++ b/drivers/pvr/RgbBitmap.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Bitmap.h" +#include "ColorRgba.h" + +namespace Javelin { + +class RgbBitmap : public Bitmap { +public: + RgbBitmap(int w, int h) + : Bitmap(w, h, 3) { + } + + const ColorRgb<unsigned char> *GetData() const { + return reinterpret_cast<ColorRgb<unsigned char> *>(data); + } + + ColorRgb<unsigned char> *GetData() { + return reinterpret_cast<ColorRgb<unsigned char> *>(data); + } +}; + +} diff --git a/drivers/pvr/RgbaBitmap.h b/drivers/pvr/RgbaBitmap.h new file mode 100644 index 0000000000..66b5542c1a --- /dev/null +++ b/drivers/pvr/RgbaBitmap.h @@ -0,0 +1,23 @@ +#pragma once + +#include "ColorRgba.h" +#include "Bitmap.h" + +namespace Javelin { + +class RgbaBitmap : public Bitmap { +public: + RgbaBitmap(int w, int h) + : Bitmap(w, h, 4) { + } + + const ColorRgba<unsigned char> *GetData() const { + return reinterpret_cast<ColorRgba<unsigned char> *>(data); + } + + ColorRgba<unsigned char> *GetData() { + return reinterpret_cast<ColorRgba<unsigned char> *>(data); + } +}; + +} diff --git a/drivers/pvr/SCsub b/drivers/pvr/SCsub index bd4c6f3f88..44b8c3d6bb 100644 --- a/drivers/pvr/SCsub +++ b/drivers/pvr/SCsub @@ -2,10 +2,14 @@ Import('env') pvr_sources = [ + "pvr/BitScale.cpp", + "pvr/MortonTable.cpp", + "pvr/PvrTcDecoder.cpp", + "pvr/PvrTcEncoder.cpp", + "pvr/PvrTcPacket.cpp", "pvr/texture_loader_pvr.cpp" ] env.drivers_sources+=pvr_sources #env.add_source_files(env.drivers_sources, pvr_sources) - diff --git a/drivers/pvr/texture_loader_pvr.cpp b/drivers/pvr/texture_loader_pvr.cpp index b12e0c28b8..5268b953f4 100644 --- a/drivers/pvr/texture_loader_pvr.cpp +++ b/drivers/pvr/texture_loader_pvr.cpp @@ -1,6 +1,8 @@ #include "texture_loader_pvr.h" #include "os/file_access.h" #include <string.h> +#include "PvrTcEncoder.h" +#include "RgbaBitmap.h" static void _pvrtc_decompress(Image* p_img); @@ -154,10 +156,59 @@ String ResourceFormatPVR::get_resource_type(const String &p_path) const { } + +static void _compress_pvrtc4(Image * p_img) { + + Image img = *p_img; + + bool make_mipmaps=false; + if (img.get_width()%8 || img.get_height()%8) { + make_mipmaps=img.get_mipmaps()>0; + img.resize(img.get_width()+(8-(img.get_width()%8)),img.get_height()+(8-(img.get_height()%8))); + } + img.convert(Image::FORMAT_RGBA); + if (img.get_mipmaps()==0 && make_mipmaps) + img.generate_mipmaps(); + + bool use_alpha=img.detect_alpha(); + + Image new_img; + new_img.create(img.get_width(),img.get_height(),true,use_alpha?Image::FORMAT_PVRTC4_ALPHA:Image::FORMAT_PVRTC4); + DVector<uint8_t> data=new_img.get_data(); + { + DVector<uint8_t>::Write wr=data.write(); + DVector<uint8_t>::Read r=img.get_data().read(); + + + for(int i=0;i<=new_img.get_mipmaps();i++) { + + int ofs,size,w,h; + img.get_mipmap_offset_size_and_dimensions(i,ofs,size,w,h); + Javelin::RgbaBitmap bm(w,h); + copymem(bm.GetData(),&r[ofs],size); + { + Javelin::ColorRgba<unsigned char> *dp = bm.GetData(); + for(int j=0;j<size/4;j++) { + SWAP(dp[j].r,dp[j].b); + } + } + + new_img.get_mipmap_offset_size_and_dimensions(i,ofs,size,w,h); + Javelin::PvrTcEncoder::EncodeRgba4Bpp(&wr[ofs],bm); + } + + } + + *p_img = Image(new_img.get_width(),new_img.get_height(),new_img.get_mipmaps(),new_img.get_format(),data); + +} + ResourceFormatPVR::ResourceFormatPVR() { Image::_image_decompress_pvrtc=_pvrtc_decompress; + Image::_image_compress_pvrtc4_func=_compress_pvrtc4; + Image::_image_compress_pvrtc2_func=_compress_pvrtc4; } diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp index e4bb1a343a..01f6a8b5b0 100644 --- a/drivers/register_driver_types.cpp +++ b/drivers/register_driver_types.cpp @@ -48,7 +48,7 @@ #endif -#include "drivers/trex/regex.h" +#include "drivers/nrex/regex.h" #ifdef MUSEPACK_ENABLED #include "mpc/audio_stream_mpc.h" @@ -222,7 +222,10 @@ void register_driver_types() { #endif #endif +#ifdef ETC1_ENABLED _register_etc1_compress_func(); +#endif + initialize_chibi(); } diff --git a/drivers/rtaudio/RtAudio.cpp b/drivers/rtaudio/RtAudio.cpp index 04e7b4422e..8876f72e21 100644 --- a/drivers/rtaudio/RtAudio.cpp +++ b/drivers/rtaudio/RtAudio.cpp @@ -46,6 +46,7 @@ #include <cstdlib>
#include <cstring>
#include <climits>
+#include <algorithm>
// Static variable definitions.
const unsigned int RtApi::MAX_SAMPLE_RATES = 14;
@@ -63,6 +64,22 @@ const unsigned int RtApi::SAMPLE_RATES[] = { #define MUTEX_DESTROY(A) DeleteCriticalSection(A)
#define MUTEX_LOCK(A) EnterCriticalSection(A)
#define MUTEX_UNLOCK(A) LeaveCriticalSection(A)
+
+ #include "tchar.h"
+
+ static std::string convertCharPointerToStdString(const char *text)
+ {
+ return std::string(text);
+ }
+
+ static std::string convertCharPointerToStdString(const wchar_t *text)
+ {
+ int length = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, NULL, NULL);
+ std::string s( length-1, '\0' );
+ WideCharToMultiByte(CP_UTF8, 0, text, -1, &s[0], length, NULL, NULL);
+ return s;
+ }
+
#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__)
// pthread API
#define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL)
@@ -184,7 +201,7 @@ RtAudio :: RtAudio( RtAudio::Api api ) getCompiledApi( apis );
for ( unsigned int i=0; i<apis.size(); i++ ) {
openRtApi( apis[i] );
- if ( rtapi_->getDeviceCount() ) break;
+ if ( rtapi_ && rtapi_->getDeviceCount() ) break;
}
if ( rtapi_ ) return;
@@ -766,9 +783,14 @@ RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device ) bool haveValueRange = false;
info.sampleRates.clear();
for ( UInt32 i=0; i<nRanges; i++ ) {
- if ( rangeList[i].mMinimum == rangeList[i].mMaximum )
- info.sampleRates.push_back( (unsigned int) rangeList[i].mMinimum );
- else {
+ if ( rangeList[i].mMinimum == rangeList[i].mMaximum ) {
+ unsigned int tmpSr = (unsigned int) rangeList[i].mMinimum;
+ info.sampleRates.push_back( tmpSr );
+
+ if ( !info.preferredSampleRate || ( tmpSr <= 48000 && tmpSr > info.preferredSampleRate ) )
+ info.preferredSampleRate = tmpSr;
+
+ } else {
haveValueRange = true;
if ( rangeList[i].mMinimum > minimumRate ) minimumRate = rangeList[i].mMinimum;
if ( rangeList[i].mMaximum < maximumRate ) maximumRate = rangeList[i].mMaximum;
@@ -777,8 +799,12 @@ RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device ) if ( haveValueRange ) {
for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
- if ( SAMPLE_RATES[k] >= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate )
+ if ( SAMPLE_RATES[k] >= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate ) {
info.sampleRates.push_back( SAMPLE_RATES[k] );
+
+ if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
+ info.preferredSampleRate = SAMPLE_RATES[k];
+ }
}
}
@@ -1385,6 +1411,18 @@ void RtApiCore :: closeStream( void ) CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
+ if (handle) {
+ AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster };
+
+ property.mSelector = kAudioDeviceProcessorOverload;
+ property.mScope = kAudioObjectPropertyScopeGlobal;
+ if (AudioObjectRemovePropertyListener( handle->id[0], &property, xrunListener, (void *) handle ) != noErr) {
+ errorText_ = "RtApiCore::closeStream(): error removing property listener!";
+ error( RtAudioError::WARNING );
+ }
+ }
if ( stream_.state == STREAM_RUNNING )
AudioDeviceStop( handle->id[0], callbackHandler );
#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
@@ -1396,6 +1434,18 @@ void RtApiCore :: closeStream( void ) }
if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {
+ if (handle) {
+ AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster };
+
+ property.mSelector = kAudioDeviceProcessorOverload;
+ property.mScope = kAudioObjectPropertyScopeGlobal;
+ if (AudioObjectRemovePropertyListener( handle->id[1], &property, xrunListener, (void *) handle ) != noErr) {
+ errorText_ = "RtApiCore::closeStream(): error removing property listener!";
+ error( RtAudioError::WARNING );
+ }
+ }
if ( stream_.state == STREAM_RUNNING )
AudioDeviceStop( handle->id[1], callbackHandler );
#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
@@ -1989,7 +2039,9 @@ RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device ) // Get the current jack server sample rate.
info.sampleRates.clear();
- info.sampleRates.push_back( jack_get_sample_rate( client ) );
+
+ info.preferredSampleRate = jack_get_sample_rate( client );
+ info.sampleRates.push_back( info.preferredSampleRate );
// Count the available ports containing the client name as device
// channels. Jack "input ports" equal RtAudio output channels.
@@ -2769,8 +2821,12 @@ RtAudio::DeviceInfo RtApiAsio :: getDeviceInfo( unsigned int device ) info.sampleRates.clear();
for ( unsigned int i=0; i<MAX_SAMPLE_RATES; i++ ) {
result = ASIOCanSampleRate( (ASIOSampleRate) SAMPLE_RATES[i] );
- if ( result == ASE_OK )
+ if ( result == ASE_OK ) {
info.sampleRates.push_back( SAMPLE_RATES[i] );
+
+ if ( !info.preferredSampleRate || ( SAMPLE_RATES[i] <= 48000 && SAMPLE_RATES[i] > info.preferredSampleRate ) )
+ info.preferredSampleRate = SAMPLE_RATES[i];
+ }
}
// Determine supported data types ... just check first channel and assume rest are the same.
@@ -2829,9 +2885,12 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne unsigned int firstChannel, unsigned int sampleRate,
RtAudioFormat format, unsigned int *bufferSize,
RtAudio::StreamOptions *options )
-{
+{////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ bool isDuplexInput = mode == INPUT && stream_.mode == OUTPUT;
+
// For ASIO, a duplex stream MUST use the same driver.
- if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] != device ) {
+ if ( isDuplexInput && stream_.device[0] != device ) {
errorText_ = "RtApiAsio::probeDeviceOpen: an ASIO duplex stream must use the same device for input and output!";
return FAILURE;
}
@@ -2845,7 +2904,7 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne }
// Only load the driver once for duplex stream.
- if ( mode != INPUT || stream_.mode != OUTPUT ) {
+ if ( !isDuplexInput ) {
// The getDeviceInfo() function will not work when a stream is open
// because ASIO does not allow multiple devices to run at the same
// time. Thus, we'll probe the system before opening a stream and
@@ -2866,22 +2925,26 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne }
}
+ // keep them before any "goto error", they are used for error cleanup + goto device boundary checks
+ bool buffersAllocated = false;
+ AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
+ unsigned int nChannels;
+
+
// Check the device channel count.
long inputChannels, outputChannels;
result = ASIOGetChannels( &inputChannels, &outputChannels );
if ( result != ASE_OK ) {
- drivers.removeCurrentDriver();
errorStream_ << "RtApiAsio::probeDeviceOpen: error (" << getAsioErrorString( result ) << ") getting channel count (" << driverName << ").";
errorText_ = errorStream_.str();
- return FAILURE;
+ goto error;
}
if ( ( mode == OUTPUT && (channels+firstChannel) > (unsigned int) outputChannels) ||
( mode == INPUT && (channels+firstChannel) > (unsigned int) inputChannels) ) {
- drivers.removeCurrentDriver();
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested channel count (" << channels << ") + offset (" << firstChannel << ").";
errorText_ = errorStream_.str();
- return FAILURE;
+ goto error;
}
stream_.nDeviceChannels[mode] = channels;
stream_.nUserChannels[mode] = channels;
@@ -2890,30 +2953,27 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne // Verify the sample rate is supported.
result = ASIOCanSampleRate( (ASIOSampleRate) sampleRate );
if ( result != ASE_OK ) {
- drivers.removeCurrentDriver();
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested sample rate (" << sampleRate << ").";
errorText_ = errorStream_.str();
- return FAILURE;
+ goto error;
}
// Get the current sample rate
ASIOSampleRate currentRate;
result = ASIOGetSampleRate( ¤tRate );
if ( result != ASE_OK ) {
- drivers.removeCurrentDriver();
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error getting sample rate.";
errorText_ = errorStream_.str();
- return FAILURE;
+ goto error;
}
// Set the sample rate only if necessary
if ( currentRate != sampleRate ) {
result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate );
if ( result != ASE_OK ) {
- drivers.removeCurrentDriver();
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error setting sample rate (" << sampleRate << ").";
errorText_ = errorStream_.str();
- return FAILURE;
+ goto error;
}
}
@@ -2924,10 +2984,9 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne else channelInfo.isInput = true;
result = ASIOGetChannelInfo( &channelInfo );
if ( result != ASE_OK ) {
- drivers.removeCurrentDriver();
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting data format.";
errorText_ = errorStream_.str();
- return FAILURE;
+ goto error;
}
// Assuming WINDOWS host is always little-endian.
@@ -2956,10 +3015,9 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne }
if ( stream_.deviceFormat[mode] == 0 ) {
- drivers.removeCurrentDriver();
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") data format not supported by RtAudio.";
errorText_ = errorStream_.str();
- return FAILURE;
+ goto error;
}
// Set the buffer size. For a duplex stream, this will end up
@@ -2968,49 +3026,63 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne long minSize, maxSize, preferSize, granularity;
result = ASIOGetBufferSize( &minSize, &maxSize, &preferSize, &granularity );
if ( result != ASE_OK ) {
- drivers.removeCurrentDriver();
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting buffer size.";
errorText_ = errorStream_.str();
- return FAILURE;
+ goto error;
}
- if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize;
- else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize;
- else if ( granularity == -1 ) {
- // Make sure bufferSize is a power of two.
- int log2_of_min_size = 0;
- int log2_of_max_size = 0;
+ if ( isDuplexInput ) {
+ // When this is the duplex input (output was opened before), then we have to use the same
+ // buffersize as the output, because it might use the preferred buffer size, which most
+ // likely wasn't passed as input to this. The buffer sizes have to be identically anyway,
+ // So instead of throwing an error, make them equal. The caller uses the reference
+ // to the "bufferSize" param as usual to set up processing buffers.
- for ( unsigned int i = 0; i < sizeof(long) * 8; i++ ) {
- if ( minSize & ((long)1 << i) ) log2_of_min_size = i;
- if ( maxSize & ((long)1 << i) ) log2_of_max_size = i;
- }
+ *bufferSize = stream_.bufferSize;
- long min_delta = std::abs( (long)*bufferSize - ((long)1 << log2_of_min_size) );
- int min_delta_num = log2_of_min_size;
+ } else {
+ if ( *bufferSize == 0 ) *bufferSize = preferSize;
+ else if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize;
+ else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize;
+ else if ( granularity == -1 ) {
+ // Make sure bufferSize is a power of two.
+ int log2_of_min_size = 0;
+ int log2_of_max_size = 0;
- for (int i = log2_of_min_size + 1; i <= log2_of_max_size; i++) {
- long current_delta = std::abs( (long)*bufferSize - ((long)1 << i) );
- if (current_delta < min_delta) {
- min_delta = current_delta;
- min_delta_num = i;
+ for ( unsigned int i = 0; i < sizeof(long) * 8; i++ ) {
+ if ( minSize & ((long)1 << i) ) log2_of_min_size = i;
+ if ( maxSize & ((long)1 << i) ) log2_of_max_size = i;
}
- }
- *bufferSize = ( (unsigned int)1 << min_delta_num );
- if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize;
- else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize;
- }
- else if ( granularity != 0 ) {
- // Set to an even multiple of granularity, rounding up.
- *bufferSize = (*bufferSize + granularity-1) / granularity * granularity;
+ long min_delta = std::abs( (long)*bufferSize - ((long)1 << log2_of_min_size) );
+ int min_delta_num = log2_of_min_size;
+
+ for (int i = log2_of_min_size + 1; i <= log2_of_max_size; i++) {
+ long current_delta = std::abs( (long)*bufferSize - ((long)1 << i) );
+ if (current_delta < min_delta) {
+ min_delta = current_delta;
+ min_delta_num = i;
+ }
+ }
+
+ *bufferSize = ( (unsigned int)1 << min_delta_num );
+ if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize;
+ else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize;
+ }
+ else if ( granularity != 0 ) {
+ // Set to an even multiple of granularity, rounding up.
+ *bufferSize = (*bufferSize + granularity-1) / granularity * granularity;
+ }
}
- if ( mode == INPUT && stream_.mode == OUTPUT && stream_.bufferSize != *bufferSize ) {
- drivers.removeCurrentDriver();
+ /*
+ // we don't use it anymore, see above!
+ // Just left it here for the case...
+ if ( isDuplexInput && stream_.bufferSize != *bufferSize ) {
errorText_ = "RtApiAsio::probeDeviceOpen: input/output buffersize discrepancy!";
- return FAILURE;
+ goto error;
}
+ */
stream_.bufferSize = *bufferSize;
stream_.nBuffers = 2;
@@ -3022,16 +3094,13 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne stream_.deviceInterleaved[mode] = false;
// Allocate, if necessary, our AsioHandle structure for the stream.
- AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
if ( handle == 0 ) {
try {
handle = new AsioHandle;
}
catch ( std::bad_alloc& ) {
- //if ( handle == NULL ) {
- drivers.removeCurrentDriver();
errorText_ = "RtApiAsio::probeDeviceOpen: error allocating AsioHandle memory.";
- return FAILURE;
+ goto error;
}
handle->bufferInfos = 0;
@@ -3046,15 +3115,14 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne // Create the ASIO internal buffers. Since RtAudio sets up input
// and output separately, we'll have to dispose of previously
// created output buffers for a duplex stream.
- long inputLatency, outputLatency;
if ( mode == INPUT && stream_.mode == OUTPUT ) {
ASIODisposeBuffers();
if ( handle->bufferInfos ) free( handle->bufferInfos );
}
// Allocate, initialize, and save the bufferInfos in our stream callbackInfo structure.
- bool buffersAllocated = false;
- unsigned int i, nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1];
+ unsigned int i;
+ nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1];
handle->bufferInfos = (ASIOBufferInfo *) malloc( nChannels * sizeof(ASIOBufferInfo) );
if ( handle->bufferInfos == NULL ) {
errorStream_ << "RtApiAsio::probeDeviceOpen: error allocating bufferInfo memory for driver (" << driverName << ").";
@@ -3075,6 +3143,15 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne infos->buffers[0] = infos->buffers[1] = 0;
}
+ // prepare for callbacks
+ stream_.sampleRate = sampleRate;
+ stream_.device[mode] = device;
+ stream_.mode = isDuplexInput ? DUPLEX : mode;
+
+ // store this class instance before registering callbacks, that are going to use it
+ asioCallbackInfo = &stream_.callbackInfo;
+ stream_.callbackInfo.object = (void *) this;
+
// Set up the ASIO callback structure and create the ASIO data buffers.
asioCallbacks.bufferSwitch = &bufferSwitch;
asioCallbacks.sampleRateDidChange = &sampleRateChanged;
@@ -3082,11 +3159,21 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne asioCallbacks.bufferSwitchTimeInfo = NULL;
result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks );
if ( result != ASE_OK ) {
+ // Standard method failed. This can happen with strict/misbehaving drivers that return valid buffer size ranges
+ // but only accept the preferred buffer size as parameter for ASIOCreateBuffers. eg. Creatives ASIO driver
+ // in that case, let's be naïve and try that instead
+ *bufferSize = preferSize;
+ stream_.bufferSize = *bufferSize;
+ result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks );
+ }
+
+ if ( result != ASE_OK ) {
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") creating buffers.";
errorText_ = errorStream_.str();
goto error;
}
- buffersAllocated = true;
+ buffersAllocated = true;
+ stream_.state = STREAM_STOPPED;
// Set flags for buffer conversion.
stream_.doConvertBuffer[mode] = false;
@@ -3109,11 +3196,9 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne bool makeBuffer = true;
bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
- if ( mode == INPUT ) {
- if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
- unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
- if ( bufferBytes <= bytesOut ) makeBuffer = false;
- }
+ if ( isDuplexInput && stream_.deviceBuffer ) {
+ unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
+ if ( bufferBytes <= bytesOut ) makeBuffer = false;
}
if ( makeBuffer ) {
@@ -3127,18 +3212,8 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne }
}
- stream_.sampleRate = sampleRate;
- stream_.device[mode] = device;
- stream_.state = STREAM_STOPPED;
- asioCallbackInfo = &stream_.callbackInfo;
- stream_.callbackInfo.object = (void *) this;
- if ( stream_.mode == OUTPUT && mode == INPUT )
- // We had already set up an output stream.
- stream_.mode = DUPLEX;
- else
- stream_.mode = mode;
-
// Determine device latencies
+ long inputLatency, outputLatency;
result = ASIOGetLatencies( &inputLatency, &outputLatency );
if ( result != ASE_OK ) {
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting latency.";
@@ -3158,32 +3233,38 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne return SUCCESS;
error:
- if ( buffersAllocated )
- ASIODisposeBuffers();
- drivers.removeCurrentDriver();
+ if ( !isDuplexInput ) {
+ // the cleanup for error in the duplex input, is done by RtApi::openStream
+ // So we clean up for single channel only
- if ( handle ) {
- CloseHandle( handle->condition );
- if ( handle->bufferInfos )
- free( handle->bufferInfos );
- delete handle;
- stream_.apiHandle = 0;
- }
+ if ( buffersAllocated )
+ ASIODisposeBuffers();
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
+ drivers.removeCurrentDriver();
+
+ if ( handle ) {
+ CloseHandle( handle->condition );
+ if ( handle->bufferInfos )
+ free( handle->bufferInfos );
+
+ delete handle;
+ stream_.apiHandle = 0;
}
- }
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
+
+ if ( stream_.userBuffer[mode] ) {
+ free( stream_.userBuffer[mode] );
+ stream_.userBuffer[mode] = 0;
+ }
+
+ if ( stream_.deviceBuffer ) {
+ free( stream_.deviceBuffer );
+ stream_.deviceBuffer = 0;
+ }
}
return FAILURE;
-}
+}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RtApiAsio :: closeStream()
{
@@ -3635,12 +3716,12 @@ public: outIndex_( 0 ) {}
~WasapiBuffer() {
- delete buffer_;
+ free( buffer_ );
}
// sets the length of the internal ring buffer
void setBufferSize( unsigned int bufferSize, unsigned int formatBytes ) {
- delete buffer_;
+ free( buffer_ );
buffer_ = ( char* ) calloc( bufferSize, formatBytes );
@@ -3799,7 +3880,7 @@ void convertBufferWasapi( char* outBuffer, float sampleStep = 1.0f / sampleRatio;
float inSampleFraction = 0.0f;
- outSampleCount = ( unsigned int ) ( inSampleCount * sampleRatio );
+ outSampleCount = ( unsigned int ) roundf( inSampleCount * sampleRatio );
// frame-by-frame, copy each relative input sample into it's corresponding output sample
for ( unsigned int outSample = 0; outSample < outSampleCount; outSample++ )
@@ -3945,7 +4026,6 @@ RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device ) RtAudio::DeviceInfo info;
unsigned int captureDeviceCount = 0;
unsigned int renderDeviceCount = 0;
- std::wstring deviceName;
std::string defaultDeviceName;
bool isCaptureDevice = false;
@@ -4048,8 +4128,7 @@ RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device ) goto Exit;
}
- deviceName = defaultDeviceNameProp.pwszVal;
- defaultDeviceName = std::string( deviceName.begin(), deviceName.end() );
+ defaultDeviceName = convertCharPointerToStdString(defaultDeviceNameProp.pwszVal);
// name
hr = devicePtr->OpenPropertyStore( STGM_READ, &devicePropStore );
@@ -4066,8 +4145,7 @@ RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device ) goto Exit;
}
- deviceName = deviceNameProp.pwszVal;
- info.name = std::string( deviceName.begin(), deviceName.end() );
+ info.name =convertCharPointerToStdString(deviceNameProp.pwszVal);
// is default
if ( isCaptureDevice ) {
@@ -4110,6 +4188,7 @@ RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device ) for ( unsigned int i = 0; i < MAX_SAMPLE_RATES; i++ ) {
info.sampleRates.push_back( SAMPLE_RATES[i] );
}
+ info.preferredSampleRate = deviceFormat->nSamplesPerSec;
// native format
info.nativeFormats = 0;
@@ -5245,14 +5324,11 @@ unsigned int RtApiDs :: getDeviceCount( void ) error( RtAudioError::WARNING );
}
- // Clean out any devices that may have disappeared.
- std::vector< int > indices;
- for ( unsigned int i=0; i<dsDevices.size(); i++ )
- if ( dsDevices[i].found == false ) indices.push_back( i );
- //unsigned int nErased = 0;
- for ( unsigned int i=0; i<indices.size(); i++ )
- dsDevices.erase( dsDevices.begin()+indices[i] );
- //dsDevices.erase( dsDevices.begin()-nErased++ );
+ // Clean out any devices that may have disappeared (code update submitted by Eli Zehngut).
+ for ( unsigned int i=0; i<dsDevices.size(); ) {
+ if ( dsDevices[i].found == false ) dsDevices.erase( dsDevices.begin() + i );
+ else i++;
+ }
return static_cast<unsigned int>(dsDevices.size());
}
@@ -5308,8 +5384,12 @@ RtAudio::DeviceInfo RtApiDs :: getDeviceInfo( unsigned int device ) info.sampleRates.clear();
for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
if ( SAMPLE_RATES[k] >= (unsigned int) outCaps.dwMinSecondarySampleRate &&
- SAMPLE_RATES[k] <= (unsigned int) outCaps.dwMaxSecondarySampleRate )
+ SAMPLE_RATES[k] <= (unsigned int) outCaps.dwMaxSecondarySampleRate ) {
info.sampleRates.push_back( SAMPLE_RATES[k] );
+
+ if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
+ info.preferredSampleRate = SAMPLE_RATES[k];
+ }
}
// Get format information.
@@ -6264,6 +6344,7 @@ void RtApiDs :: callbackEvent() if ( FAILED( result ) ) {
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
errorText_ = errorStream_.str();
+ MUTEX_UNLOCK( &stream_.mutex );
error( RtAudioError::SYSTEM_ERROR );
return;
}
@@ -6271,6 +6352,7 @@ void RtApiDs :: callbackEvent() if ( FAILED( result ) ) {
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
errorText_ = errorStream_.str();
+ MUTEX_UNLOCK( &stream_.mutex );
error( RtAudioError::SYSTEM_ERROR );
return;
}
@@ -6279,6 +6361,7 @@ void RtApiDs :: callbackEvent() if ( FAILED( result ) ) {
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
errorText_ = errorStream_.str();
+ MUTEX_UNLOCK( &stream_.mutex );
error( RtAudioError::SYSTEM_ERROR );
return;
}
@@ -6286,6 +6369,7 @@ void RtApiDs :: callbackEvent() if ( FAILED( result ) ) {
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
errorText_ = errorStream_.str();
+ MUTEX_UNLOCK( &stream_.mutex );
error( RtAudioError::SYSTEM_ERROR );
return;
}
@@ -6307,6 +6391,7 @@ void RtApiDs :: callbackEvent() if ( FAILED( result ) ) {
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
errorText_ = errorStream_.str();
+ MUTEX_UNLOCK( &stream_.mutex );
error( RtAudioError::SYSTEM_ERROR );
return;
}
@@ -6399,6 +6484,7 @@ void RtApiDs :: callbackEvent() if ( FAILED( result ) ) {
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking buffer during playback!";
errorText_ = errorStream_.str();
+ MUTEX_UNLOCK( &stream_.mutex );
error( RtAudioError::SYSTEM_ERROR );
return;
}
@@ -6412,6 +6498,7 @@ void RtApiDs :: callbackEvent() if ( FAILED( result ) ) {
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking buffer during playback!";
errorText_ = errorStream_.str();
+ MUTEX_UNLOCK( &stream_.mutex );
error( RtAudioError::SYSTEM_ERROR );
return;
}
@@ -6448,6 +6535,7 @@ void RtApiDs :: callbackEvent() if ( FAILED( result ) ) {
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
errorText_ = errorStream_.str();
+ MUTEX_UNLOCK( &stream_.mutex );
error( RtAudioError::SYSTEM_ERROR );
return;
}
@@ -6509,6 +6597,7 @@ void RtApiDs :: callbackEvent() if ( FAILED( result ) ) {
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
errorText_ = errorStream_.str();
+ MUTEX_UNLOCK( &stream_.mutex );
error( RtAudioError::SYSTEM_ERROR );
return;
}
@@ -6523,6 +6612,7 @@ void RtApiDs :: callbackEvent() if ( FAILED( result ) ) {
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking capture buffer!";
errorText_ = errorStream_.str();
+ MUTEX_UNLOCK( &stream_.mutex );
error( RtAudioError::SYSTEM_ERROR );
return;
}
@@ -6544,6 +6634,7 @@ void RtApiDs :: callbackEvent() if ( FAILED( result ) ) {
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking capture buffer!";
errorText_ = errorStream_.str();
+ MUTEX_UNLOCK( &stream_.mutex );
error( RtAudioError::SYSTEM_ERROR );
return;
}
@@ -6582,21 +6673,6 @@ static unsigned __stdcall callbackHandler( void *ptr ) return 0;
}
-#include "tchar.h"
-
-static std::string convertTChar( LPCTSTR name )
-{
-#if defined( UNICODE ) || defined( _UNICODE )
- int length = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);
- std::string s( length-1, '\0' );
- WideCharToMultiByte(CP_UTF8, 0, name, -1, &s[0], length, NULL, NULL);
-#else
- std::string s( name );
-#endif
-
- return s;
-}
-
static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,
LPCTSTR description,
LPCTSTR /*module*/,
@@ -6638,7 +6714,7 @@ static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid, }
// If good device, then save its name and guid.
- std::string name = convertTChar( description );
+ std::string name = convertCharPointerToStdString( description );
//if ( name == "Primary Sound Driver" || name == "Primary Sound Capture Driver" )
if ( lpguid == NULL )
name = "Default Device";
@@ -6820,6 +6896,7 @@ RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device ) // Count cards and devices
card = -1;
+ subdevice = -1;
snd_card_next( &card );
while ( card >= 0 ) {
sprintf( name, "hw:%d", card );
@@ -7033,8 +7110,12 @@ RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device ) // Test our discrete set of sample rate values.
info.sampleRates.clear();
for ( unsigned int i=0; i<MAX_SAMPLE_RATES; i++ ) {
- if ( snd_pcm_hw_params_test_rate( phandle, params, SAMPLE_RATES[i], 0 ) == 0 )
+ if ( snd_pcm_hw_params_test_rate( phandle, params, SAMPLE_RATES[i], 0 ) == 0 ) {
info.sampleRates.push_back( SAMPLE_RATES[i] );
+
+ if ( !info.preferredSampleRate || ( SAMPLE_RATES[i] <= 48000 && SAMPLE_RATES[i] > info.preferredSampleRate ) )
+ info.preferredSampleRate = SAMPLE_RATES[i];
+ }
}
if ( info.sampleRates.size() == 0 ) {
snd_pcm_close( phandle );
@@ -7959,6 +8040,8 @@ void RtApiAlsa :: callbackEvent() errorStream_ << "RtApiAlsa::callbackEvent: error preparing device after underrun, " << snd_strerror( result ) << ".";
errorText_ = errorStream_.str();
}
+ else
+ errorText_ = "RtApiAlsa::callbackEvent: audio write error, underrun.";
}
else {
errorStream_ << "RtApiAlsa::callbackEvent: error, current state is " << snd_pcm_state_name( state ) << ", " << snd_strerror( result ) << ".";
@@ -8067,6 +8150,7 @@ RtAudio::DeviceInfo RtApiPulse::getDeviceInfo( unsigned int /*device*/ ) for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr )
info.sampleRates.push_back( *sr );
+ info.preferredSampleRate = 48000;
info.nativeFormats = RTAUDIO_SINT16 | RTAUDIO_SINT32 | RTAUDIO_FLOAT32;
return info;
@@ -8429,7 +8513,7 @@ bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode, pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );
int error;
- if ( !options->streamName.empty() ) streamName = options->streamName;
+ if ( options && !options->streamName.empty() ) streamName = options->streamName;
switch ( mode ) {
case INPUT:
pa_buffer_attr buffer_attr;
@@ -8635,6 +8719,10 @@ RtAudio::DeviceInfo RtApiOss :: getDeviceInfo( unsigned int device ) for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
if ( ainfo.rates[i] == SAMPLE_RATES[k] ) {
info.sampleRates.push_back( SAMPLE_RATES[k] );
+
+ if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
+ info.preferredSampleRate = SAMPLE_RATES[k];
+
break;
}
}
@@ -8643,8 +8731,12 @@ RtAudio::DeviceInfo RtApiOss :: getDeviceInfo( unsigned int device ) else {
// Check min and max rate values;
for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
- if ( ainfo.min_rate <= (int) SAMPLE_RATES[k] && ainfo.max_rate >= (int) SAMPLE_RATES[k] )
+ if ( ainfo.min_rate <= (int) SAMPLE_RATES[k] && ainfo.max_rate >= (int) SAMPLE_RATES[k] ) {
info.sampleRates.push_back( SAMPLE_RATES[k] );
+
+ if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
+ info.preferredSampleRate = SAMPLE_RATES[k];
+ }
}
}
diff --git a/drivers/rtaudio/RtAudio.h b/drivers/rtaudio/RtAudio.h index 1f1b63072c..7d45d36529 100644 --- a/drivers/rtaudio/RtAudio.h +++ b/drivers/rtaudio/RtAudio.h @@ -310,12 +310,13 @@ class RtAudio bool isDefaultOutput; /*!< true if this is the default output device. */ bool isDefaultInput; /*!< true if this is the default input device. */ std::vector<unsigned int> sampleRates; /*!< Supported sample rates (queried from list of standard rates). */ + unsigned int preferredSampleRate; /*!< Preferred sample rate, eg. for WASAPI the system sample rate. */ RtAudioFormat nativeFormats; /*!< Bit mask of supported data formats. */ // Default constructor. DeviceInfo() :probed(false), outputChannels(0), inputChannels(0), duplexChannels(0), - isDefaultOutput(false), isDefaultInput(false), nativeFormats(0) {} + isDefaultOutput(false), isDefaultInput(false), preferredSampleRate(0), nativeFormats(0) {} }; //! The structure for specifying input or ouput stream parameters. diff --git a/drivers/speex/audio_stream_speex.cpp b/drivers/speex/audio_stream_speex.cpp index a6bac78b4d..bcf4c515f8 100644 --- a/drivers/speex/audio_stream_speex.cpp +++ b/drivers/speex/audio_stream_speex.cpp @@ -21,7 +21,7 @@ void AudioStreamSpeex::update() { //printf("update, loops %i, read ofs %i\n", (int)loops, read_ofs); //printf("playing %i, paused %i\n", (int)playing, (int)paused); - if (!playing || paused || !data.size()) + if (!active || !playing || paused || !data.size()) return; /* diff --git a/drivers/theora/codec.h b/drivers/theora/codec.h index 5c2669630c..9b816e5cfd 100644 --- a/drivers/theora/codec.h +++ b/drivers/theora/codec.h @@ -15,7 +15,7 @@ ********************************************************************/ -/**\mainpage +/**\file * * \section intro Introduction * diff --git a/drivers/theoraplayer/video_stream_theoraplayer.cpp b/drivers/theoraplayer/video_stream_theoraplayer.cpp index 9f4a44ae9d..ef1f5651ab 100644 --- a/drivers/theoraplayer/video_stream_theoraplayer.cpp +++ b/drivers/theoraplayer/video_stream_theoraplayer.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -388,7 +388,7 @@ void VideoStreamTheoraplayer::pop_frame(Ref<ImageTexture> p_tex) { { DVector<uint8_t>::Write wr = data.write(); uint8_t* ptr = wr.ptr(); - memcpy(ptr, f->getBuffer(), imgsize); + copymem(ptr, f->getBuffer(), imgsize); } /* for (int i=0; i<h; i++) { diff --git a/drivers/trex/TRexpp.h b/drivers/trex/TRexpp.h deleted file mode 100644 index 8391e47414..0000000000 --- a/drivers/trex/TRexpp.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _TREXPP_H_
-#define _TREXPP_H_
-/***************************************************************
- T-Rex a tiny regular expression library
-
- Copyright (C) 2003-2004 Alberto Demichelis
-
- This software is provided 'as-is', without any express
- or implied warranty. In no event will the authors be held
- liable for any damages arising from the use of this software.
-
- Permission is granted to anyone to use this software for
- any purpose, including commercial applications, and to alter
- it and redistribute it freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented;
- you must not claim that you wrote the original software.
- If you use this software in a product, an acknowledgment
- in the product documentation would be appreciated but
- is not required.
-
- 2. Altered source versions must be plainly marked as such,
- and must not be misrepresented as being the original software.
-
- 3. This notice may not be removed or altered from any
- source distribution.
-
-****************************************************************/
-
-extern "C" {
-#include "trex.h"
-}
-
-struct TRexParseException{TRexParseException(const TRexChar *c):desc(c){}const TRexChar *desc;};
-
-class TRexpp {
-public:
- TRexpp() { _exp = (TRex *)0; }
- ~TRexpp() { CleanUp(); }
- // compiles a regular expression
- void Compile(const TRexChar *pattern) {
- const TRexChar *error;
- CleanUp();
- if(!(_exp = trex_compile(pattern,&error)))
- throw TRexParseException(error);
- }
- // return true if the given text match the expression
- bool Match(const TRexChar* text) {
- return _exp?(trex_match(_exp,text) != 0):false;
- }
- // Searches for the first match of the expression in a zero terminated string
- bool Search(const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end) {
- return _exp?(trex_search(_exp,text,out_begin,out_end) != 0):false;
- }
- // Searches for the first match of the expression in a string sarting at text_begin and ending at text_end
- bool SearchRange(const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end) {
- return _exp?(trex_searchrange(_exp,text_begin,text_end,out_begin,out_end) != 0):false;
- }
- bool GetSubExp(int n, const TRexChar** out_begin, int *out_len)
- {
- TRexMatch match;
- TRexBool res = _exp?(trex_getsubexp(_exp,n,&match)):TRex_False;
- if(res) {
- *out_begin = match.begin;
- *out_len = match.len;
- return true;
- }
- return false;
- }
- int GetSubExpCount() { return _exp?trex_getsubexpcount(_exp):0; }
-private:
- void CleanUp() { if(_exp) trex_free(_exp); _exp = (TRex *)0; }
- TRex *_exp;
-};
-#endif //_TREXPP_H_
\ No newline at end of file diff --git a/drivers/trex/history.txt b/drivers/trex/history.txt deleted file mode 100644 index 5cfe8770b4..0000000000 --- a/drivers/trex/history.txt +++ /dev/null @@ -1,15 +0,0 @@ -===version 1.3
--fixed a bug for GCC users(thx Brendan)
-
-===version 1.2
--added word boundary match \b and \B
--added vertical tab escape \v
--\w now also matches '_' (underscore)
--fixed greediness for * and +
-
-===version 1.1 , April 1, 2004
--fixed some minor bug
--added predefined character classes(\w,\W,\s,\S etc...)
-
-===version 1.0 , February 23, 2004
--first public realase
\ No newline at end of file diff --git a/drivers/trex/readme.txt b/drivers/trex/readme.txt deleted file mode 100644 index 1d93558e92..0000000000 --- a/drivers/trex/readme.txt +++ /dev/null @@ -1,171 +0,0 @@ -T-REX 1.3 http://tiny-rex.sourceforge.net
-----------------------------------------------------------------------
- T-Rex a tiny regular expression library
-
- Copyright (C) 2003-2006 Alberto Demichelis
-
- This software is provided 'as-is', without any express
- or implied warranty. In no event will the authors be held
- liable for any damages arising from the use of this software.
-
- Permission is granted to anyone to use this software for
- any purpose, including commercial applications, and to alter
- it and redistribute it freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented;
- you must not claim that you wrote the original software.
- If you use this software in a product, an acknowledgment
- in the product documentation would be appreciated but
- is not required.
-
- 2. Altered source versions must be plainly marked as such,
- and must not be misrepresented as being the original software.
-
- 3. This notice may not be removed or altered from any
- source distribution.
-
-----------------------------------------------------------------------
-TRex implements the following expressions
-
-\ Quote the next metacharacter
-^ Match the beginning of the string
-. Match any character
-$ Match the end of the string
-| Alternation
-() Grouping (creates a capture)
-[] Character class
-
-==GREEDY CLOSURES==
-* Match 0 or more times
-+ Match 1 or more times
-? Match 1 or 0 times
-{n} Match exactly n times
-{n,} Match at least n times
-{n,m} Match at least n but not more than m times
-
-==ESCAPE CHARACTERS==
-\t tab (HT, TAB)
-\n newline (LF, NL)
-\r return (CR)
-\f form feed (FF)
-
-==PREDEFINED CLASSES==
-\l lowercase next char
-\u uppercase next char
-\a letters
-\A non letters
-\w alphanimeric [0-9a-zA-Z]
-\W non alphanimeric
-\s space
-\S non space
-\d digits
-\D non nondigits
-\x exadecimal digits
-\X non exadecimal digits
-\c control charactrs
-\C non control charactrs
-\p punctation
-\P non punctation
-\b word boundary
-\B non word boundary
-
-----------------------------------------------------------------------
-API DOC
-----------------------------------------------------------------------
-TRex *trex_compile(const TRexChar *pattern,const TRexChar **error);
-
-compiles an expression and returns a pointer to the compiled version.
-in case of failure returns NULL.The returned object has to be deleted
-through the function trex_free().
-
-pattern
- a pointer to a zero terminated string containing the pattern that
- has to be compiled.
-error
- apointer to a string pointer that will be set with an error string
- in case of failure.
-
-----------------------------------------------------------------------
-void trex_free(TRex *exp)
-
-deletes a expression structure created with trex_compile()
-
-exp
- the expression structure that has to be deleted
-
-----------------------------------------------------------------------
-TRexBool trex_match(TRex* exp,const TRexChar* text)
-
-returns TRex_True if the string specified in the parameter text is an
-exact match of the expression, otherwise returns TRex_False.
-
-exp
- the compiled expression
-text
- the string that has to be tested
-
-----------------------------------------------------------------------
-TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end)
-
-searches the first match of the expressin in the string specified in the parameter text.
-if the match is found returns TRex_True and the sets out_begin to the beginning of the
-match and out_end at the end of the match; otherwise returns TRex_False.
-
-exp
- the compiled expression
-text
- the string that has to be tested
-out_begin
- a pointer to a string pointer that will be set with the beginning of the match
-out_end
- a pointer to a string pointer that will be set with the end of the match
-
-----------------------------------------------------------------------
-TREX_API TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end)
-
-searches the first match of the expressin in the string delimited
-by the parameter text_begin and text_end.
-if the match is found returns TRex_True and the sets out_begin to the beginning of the
-match and out_end at the end of the match; otherwise returns TRex_False.
-
-exp
- the compiled expression
-text_begin
- a pointer to the beginnning of the string that has to be tested
-text_end
- a pointer to the end of the string that has to be tested
-out_begin
- a pointer to a string pointer that will be set with the beginning of the match
-out_end
- a pointer to a string pointer that will be set with the end of the match
-
-----------------------------------------------------------------------
-int trex_getsubexpcount(TRex* exp)
-
-returns the number of sub expressions matched by the expression
-
-exp
- the compiled expression
-
----------------------------------------------------------------------
-TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *submatch)
-
-retrieve the begin and and pointer to the length of the sub expression indexed
-by n. The result is passed trhough the struct TRexMatch:
-
-typedef struct {
- const TRexChar *begin;
- int len;
-} TRexMatch;
-
-the function returns TRex_True if n is valid index otherwise TRex_False.
-
-exp
- the compiled expression
-n
- the index of the submatch
-submatch
- a pointer to structure that will store the result
-
-this function works also after a match operation has been performend.
-
diff --git a/drivers/trex/regex.cpp b/drivers/trex/regex.cpp deleted file mode 100644 index 11cd6256e2..0000000000 --- a/drivers/trex/regex.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/*************************************************/ -/* regex.cpp */ -/*************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/*************************************************/ -/* Source code within this file is: */ -/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */ -/* All Rights Reserved. */ -/*************************************************/ - -#include "regex.h" - -extern "C" { - -#define _UNICODE -#include "trex.h" - -}; - -void RegEx::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("compile","pattern"),&RegEx::compile); - ObjectTypeDB::bind_method(_MD("find","text", "start","end"),&RegEx::_bind_find, DEFVAL(0), DEFVAL(-1)); - ObjectTypeDB::bind_method(_MD("get_captures"),&RegEx::_bind_get_captures); -}; - -Error RegEx::compile(const String& p_pattern) { - - clear(); - const TRexChar* error; - exp = trex_compile(p_pattern.c_str(), &error); - ERR_FAIL_COND_V(!exp, FAILED); - return OK; -}; - - -int RegEx::_bind_find(const String& p_text, int p_start, int p_end) const { - - int start, end; - bool ret = find(p_text, start, end, NULL, p_start, p_end); - - return ret?start:-1; -}; - -bool RegEx::find(const String& p_text, int& p_rstart, int &p_rend, List<String>* p_captures, int p_start, int p_end) const { - - ERR_FAIL_COND_V( !exp, false ); - text=p_text; - - const CharType* str = p_text.c_str(); - const CharType* start = str + p_start; - const CharType* end = str + (p_end == -1?p_text.size():p_end); - - const CharType* out_begin; - const CharType* out_end; - - bool ret = trex_searchrange(exp, start, end, &out_begin, &out_end); - if (ret) { - - p_rstart = out_begin - str; - p_rend = out_end - str; - - if (p_captures) { - - int count = get_capture_count(); - for (int i=0; i<count; i++) { - - int start, len; - get_capture_limits(i, start, len); - p_captures->push_back(p_text.substr(start, len)); - }; - }; - } else { - - p_rstart = -1; - }; - - return ret; -}; - - -bool RegEx::match(const String& p_text, List<String>* p_captures, int p_start, int p_end) const { - - ERR_FAIL_COND_V( !exp, false ); - - int start, end; - return find(p_text, start, end, p_captures, p_start, p_end); -}; - -int RegEx::get_capture_count() const { - - ERR_FAIL_COND_V( exp == NULL, -1 ); - - return trex_getsubexpcount(exp); -}; - -Error RegEx::get_capture_limits(int p_capture, int& p_start, int& p_len) const { - - ERR_FAIL_COND_V( exp == NULL, ERR_UNCONFIGURED ); - - TRexMatch match; - TRexBool res = trex_getsubexp(exp, p_capture, &match); - ERR_FAIL_COND_V( !res, FAILED ); - p_start = (int)(match.begin - text.c_str()); - p_len = match.len; - - return OK; -}; - -String RegEx::get_capture(int p_idx) const { - - ERR_FAIL_COND_V( exp == NULL, "" ); - int start, len; - Error ret = get_capture_limits(p_idx, start, len); - ERR_FAIL_COND_V(ret != OK, ""); - if (len == 0) - return ""; - return text.substr(start, len); -}; - -StringArray RegEx::_bind_get_captures() const { - - StringArray ret; - int count = get_capture_count(); - for (int i=0; i<count; i++) { - - String c = get_capture(i); - ret.push_back(c); - }; - - return ret; -}; - -bool RegEx::is_valid() const { - - return exp != NULL; -}; - -void RegEx::clear() { - - if (exp) { - - trex_free(exp); - exp = NULL; - }; -}; - -RegEx::RegEx(const String& p_pattern) { - - exp = NULL; - compile(p_pattern); -}; - -RegEx::RegEx() { - - exp = NULL; -}; - -RegEx::~RegEx() { - - clear(); -}; diff --git a/drivers/trex/test.c b/drivers/trex/test.c deleted file mode 100644 index 69db49c1af..0000000000 --- a/drivers/trex/test.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "trex.h"
-#include <stdio.h>
-#include <string.h>
-
-#ifdef _UNICODE
-#define trex_sprintf swprintf
-#else
-#define trex_sprintf sprintf
-#endif
-
-int main(int argc, char* argv[])
-{
- const TRexChar *begin,*end;
- TRexChar sTemp[200];
- const TRexChar *error = NULL;
- TRex *x = trex_compile(_TREXC("(x{1,5})xx"),&error);
- if(x) {
- trex_sprintf(sTemp,_TREXC("xxxxxxx"));
- if(trex_search(x,sTemp,&begin,&end))
- {
- int i,n = trex_getsubexpcount(x);
- TRexMatch match;
- for(i = 0; i < n; i++)
- {
- TRexChar t[200];
- trex_getsubexp(x,i,&match);
- trex_sprintf(t,_TREXC("[%%d]%%.%ds\n"),match.len);
- trex_printf(t,i,match.begin);
- }
- trex_printf(_TREXC("match! %d sub matches\n"),trex_getsubexpcount(x));
- }
- else {
- trex_printf(_TREXC("no match!\n"));
- }
- trex_free(x);
- }
- else {
- trex_printf(_TREXC("compilation error [%s]!\n"),error?error:_TREXC("undefined"));
- }
- return 0;
-}
diff --git a/drivers/trex/trex.c b/drivers/trex/trex.c deleted file mode 100644 index b3668c3a11..0000000000 --- a/drivers/trex/trex.c +++ /dev/null @@ -1,643 +0,0 @@ - /* see copyright notice in trex.h */
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <setjmp.h>
-#include "trex.h"
-
-#ifdef _UINCODE
-#define scisprint iswprint
-#define scstrlen wcslen
-#define scprintf wprintf
-#define _SC(x) L##c
-#else
-#define scisprint isprint
-#define scstrlen strlen
-#define scprintf printf
-#define _SC(x) (x)
-#endif
-
-#ifdef _DEBUG
-#include <stdio.h>
-
-static const TRexChar *g_nnames[] =
-{
- _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"),
- _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"),
- _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),
- _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB")
-};
-
-#endif
-#define OP_GREEDY (MAX_CHAR+1) // * + ? {n}
-#define OP_OR (MAX_CHAR+2)
-#define OP_EXPR (MAX_CHAR+3) //parentesis ()
-#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:)
-#define OP_DOT (MAX_CHAR+5)
-#define OP_CLASS (MAX_CHAR+6)
-#define OP_CCLASS (MAX_CHAR+7)
-#define OP_NCLASS (MAX_CHAR+8) //negates class the [^
-#define OP_RANGE (MAX_CHAR+9)
-#define OP_CHAR (MAX_CHAR+10)
-#define OP_EOL (MAX_CHAR+11)
-#define OP_BOL (MAX_CHAR+12)
-#define OP_WB (MAX_CHAR+13)
-
-#define TREX_SYMBOL_ANY_CHAR ('.')
-#define TREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
-#define TREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*')
-#define TREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?')
-#define TREX_SYMBOL_BRANCH ('|')
-#define TREX_SYMBOL_END_OF_STRING ('$')
-#define TREX_SYMBOL_BEGINNING_OF_STRING ('^')
-#define TREX_SYMBOL_ESCAPE_CHAR ('\\')
-
-
-typedef int TRexNodeType;
-
-typedef struct tagTRexNode{
- TRexNodeType type;
- int left;
- int right;
- int next;
-}TRexNode;
-
-struct TRex{
- const TRexChar *_eol;
- const TRexChar *_bol;
- const TRexChar *_p;
- int _first;
- int _op;
- TRexNode *_nodes;
- int _nallocated;
- int _nsize;
- int _nsubexpr;
- TRexMatch *_matches;
- int _currsubexp;
- void *_jmpbuf;
- const TRexChar **_error;
-};
-
-static int trex_list(TRex *exp);
-
-static int trex_newnode(TRex *exp, TRexNodeType type)
-{
- TRexNode n;
- int newid;
- n.type = type;
- n.next = n.right = n.left = -1;
- if(type == OP_EXPR)
- n.right = exp->_nsubexpr++;
- if(exp->_nallocated < (exp->_nsize + 1)) {
- //int oldsize = exp->_nallocated;
- exp->_nallocated *= 2;
- exp->_nodes = (TRexNode *)realloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode));
- }
- exp->_nodes[exp->_nsize++] = n;
- newid = exp->_nsize - 1;
- return (int)newid;
-}
-
-static void trex_error(TRex *exp,const TRexChar *error)
-{
- if(exp->_error) *exp->_error = error;
- longjmp(*((jmp_buf*)exp->_jmpbuf),-1);
-}
-
-static void trex_expect(TRex *exp, int n){
- if((*exp->_p) != n)
- trex_error(exp, _SC("expected paren"));
- exp->_p++;
-}
-
-static TRexChar trex_escapechar(TRex *exp)
-{
- if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR){
- exp->_p++;
- switch(*exp->_p) {
- case 'v': exp->_p++; return '\v';
- case 'n': exp->_p++; return '\n';
- case 't': exp->_p++; return '\t';
- case 'r': exp->_p++; return '\r';
- case 'f': exp->_p++; return '\f';
- default: return (*exp->_p++);
- }
- } else if(!scisprint(*exp->_p)) trex_error(exp,_SC("letter expected"));
- return (*exp->_p++);
-}
-
-static int trex_charclass(TRex *exp,int classid)
-{
- int n = trex_newnode(exp,OP_CCLASS);
- exp->_nodes[n].left = classid;
- return n;
-}
-
-static int trex_charnode(TRex *exp,TRexBool isclass)
-{
- TRexChar t;
- if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) {
- exp->_p++;
- switch(*exp->_p) {
- case 'n': exp->_p++; return trex_newnode(exp,'\n');
- case 't': exp->_p++; return trex_newnode(exp,'\t');
- case 'r': exp->_p++; return trex_newnode(exp,'\r');
- case 'f': exp->_p++; return trex_newnode(exp,'\f');
- case 'v': exp->_p++; return trex_newnode(exp,'\v');
- case 'a': case 'A': case 'w': case 'W': case 's': case 'S':
- case 'd': case 'D': case 'x': case 'X': case 'c': case 'C':
- case 'p': case 'P': case 'l': case 'u':
- {
- t = *exp->_p; exp->_p++;
- return trex_charclass(exp,t);
- }
- case 'b':
- case 'B':
- if(!isclass) {
- int node = trex_newnode(exp,OP_WB);
- exp->_nodes[node].left = *exp->_p;
- exp->_p++;
- return node;
- } //else default
- default:
- t = *exp->_p; exp->_p++;
- return trex_newnode(exp,t);
- }
- }
- else if(!scisprint(*exp->_p)) {
-
- trex_error(exp,_SC("letter expected"));
- }
- t = *exp->_p; exp->_p++;
- return trex_newnode(exp,t);
-}
-static int trex_class(TRex *exp)
-{
- int ret = -1;
- int first = -1,chain;
- if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING){
- ret = trex_newnode(exp,OP_NCLASS);
- exp->_p++;
- }else ret = trex_newnode(exp,OP_CLASS);
-
- if(*exp->_p == ']') trex_error(exp,_SC("empty class"));
- chain = ret;
- while(*exp->_p != ']' && exp->_p != exp->_eol) {
- if(*exp->_p == '-' && first != -1){
- int r,t;
- if(*exp->_p++ == ']') trex_error(exp,_SC("unfinished range"));
- r = trex_newnode(exp,OP_RANGE);
- if(first>*exp->_p) trex_error(exp,_SC("invalid range"));
- if(exp->_nodes[first].type == OP_CCLASS) trex_error(exp,_SC("cannot use character classes in ranges"));
- exp->_nodes[r].left = exp->_nodes[first].type;
- t = trex_escapechar(exp);
- exp->_nodes[r].right = t;
- exp->_nodes[chain].next = r;
- chain = r;
- first = -1;
- }
- else{
- if(first!=-1){
- int c = first;
- exp->_nodes[chain].next = c;
- chain = c;
- first = trex_charnode(exp,TRex_True);
- }
- else{
- first = trex_charnode(exp,TRex_True);
- }
- }
- }
- if(first!=-1){
- int c = first;
- exp->_nodes[chain].next = c;
- chain = c;
- first = -1;
- }
- /* hack? */
- exp->_nodes[ret].left = exp->_nodes[ret].next;
- exp->_nodes[ret].next = -1;
- return ret;
-}
-
-static int trex_parsenumber(TRex *exp)
-{
- int ret = *exp->_p-'0';
- int positions = 10;
- exp->_p++;
- while(isdigit(*exp->_p)) {
- ret = ret*10+(*exp->_p++-'0');
- if(positions==1000000000) trex_error(exp,_SC("overflow in numeric constant"));
- positions *= 10;
- };
- return ret;
-}
-
-static int trex_element(TRex *exp)
-{
- int ret = -1;
- switch(*exp->_p)
- {
- case '(': {
- int expr,newn;
- exp->_p++;
-
-
- if(*exp->_p =='?') {
- exp->_p++;
- trex_expect(exp,':');
- expr = trex_newnode(exp,OP_NOCAPEXPR);
- }
- else
- expr = trex_newnode(exp,OP_EXPR);
- newn = trex_list(exp);
- exp->_nodes[expr].left = newn;
- ret = expr;
- trex_expect(exp,')');
- }
- break;
- case '[':
- exp->_p++;
- ret = trex_class(exp);
- trex_expect(exp,']');
- break;
- case TREX_SYMBOL_END_OF_STRING: exp->_p++; ret = trex_newnode(exp,OP_EOL);break;
- case TREX_SYMBOL_ANY_CHAR: exp->_p++; ret = trex_newnode(exp,OP_DOT);break;
- default:
- ret = trex_charnode(exp,TRex_False);
- break;
- }
-
- {
- int op;
- TRexBool isgreedy = TRex_False;
- unsigned short p0 = 0, p1 = 0;
- switch(*exp->_p){
- case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break;
- case TREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break;
- case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = TRex_True; break;
- case '{':
- exp->_p++;
- if(!isdigit(*exp->_p)) trex_error(exp,_SC("number expected"));
- p0 = (unsigned short)trex_parsenumber(exp);
- /*******************************/
- switch(*exp->_p) {
- case '}':
- p1 = p0; exp->_p++;
- break;
- case ',':
- exp->_p++;
- p1 = 0xFFFF;
- if(isdigit(*exp->_p)){
- p1 = (unsigned short)trex_parsenumber(exp);
- }
- trex_expect(exp,'}');
- break;
- default:
- trex_error(exp,_SC(", or } expected"));
- }
- /*******************************/
- isgreedy = TRex_True;
- break;
-
- }
- if(isgreedy) {
- int nnode = trex_newnode(exp,OP_GREEDY);
- op = OP_GREEDY;
- exp->_nodes[nnode].left = ret;
- exp->_nodes[nnode].right = ((p0)<<16)|p1;
- ret = nnode;
- }
- }
- if((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) {
- int nnode = trex_element(exp);
- exp->_nodes[ret].next = nnode;
- }
-
- return ret;
-}
-
-static int trex_list(TRex *exp)
-{
- int ret=-1,e;
- if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) {
- exp->_p++;
- ret = trex_newnode(exp,OP_BOL);
- }
- e = trex_element(exp);
- if(ret != -1) {
- exp->_nodes[ret].next = e;
- }
- else ret = e;
-
- if(*exp->_p == TREX_SYMBOL_BRANCH) {
- int temp,tright;
- exp->_p++;
- temp = trex_newnode(exp,OP_OR);
- exp->_nodes[temp].left = ret;
- tright = trex_list(exp);
- exp->_nodes[temp].right = tright;
- ret = temp;
- }
- return ret;
-}
-
-static TRexBool trex_matchcclass(int cclass,TRexChar c)
-{
- switch(cclass) {
- case 'a': return isalpha(c)?TRex_True:TRex_False;
- case 'A': return !isalpha(c)?TRex_True:TRex_False;
- case 'w': return (isalnum(c) || c == '_')?TRex_True:TRex_False;
- case 'W': return (!isalnum(c) && c != '_')?TRex_True:TRex_False;
- case 's': return isspace(c)?TRex_True:TRex_False;
- case 'S': return !isspace(c)?TRex_True:TRex_False;
- case 'd': return isdigit(c)?TRex_True:TRex_False;
- case 'D': return !isdigit(c)?TRex_True:TRex_False;
- case 'x': return isxdigit(c)?TRex_True:TRex_False;
- case 'X': return !isxdigit(c)?TRex_True:TRex_False;
- case 'c': return iscntrl(c)?TRex_True:TRex_False;
- case 'C': return !iscntrl(c)?TRex_True:TRex_False;
- case 'p': return ispunct(c)?TRex_True:TRex_False;
- case 'P': return !ispunct(c)?TRex_True:TRex_False;
- case 'l': return islower(c)?TRex_True:TRex_False;
- case 'u': return isupper(c)?TRex_True:TRex_False;
- }
- return TRex_False; /*cannot happen*/
-}
-
-static TRexBool trex_matchclass(TRex* exp,TRexNode *node,TRexChar c)
-{
- do {
- switch(node->type) {
- case OP_RANGE:
- if(c >= node->left && c <= node->right) return TRex_True;
- break;
- case OP_CCLASS:
- if(trex_matchcclass(node->left,c)) return TRex_True;
- break;
- default:
- if(c == node->type)return TRex_True;
- }
- } while((node->next != -1) && (node = &exp->_nodes[node->next]));
- return TRex_False;
-}
-
-static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *str,TRexNode *next)
-{
-
- TRexNodeType type = node->type;
- switch(type) {
- case OP_GREEDY: {
- //TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL;
- TRexNode *greedystop = NULL;
- int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
- const TRexChar *s=str, *good = str;
-
- if(node->next != -1) {
- greedystop = &exp->_nodes[node->next];
- }
- else {
- greedystop = next;
- }
-
- while((nmaches == 0xFFFF || nmaches < p1)) {
-
- const TRexChar *stop;
- if(!(s = trex_matchnode(exp,&exp->_nodes[node->left],s,greedystop)))
- break;
- nmaches++;
- good=s;
- if(greedystop) {
- //checks that 0 matches satisfy the expression(if so skips)
- //if not would always stop(for instance if is a '?')
- if(greedystop->type != OP_GREEDY ||
- (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0))
- {
- TRexNode *gnext = NULL;
- if(greedystop->next != -1) {
- gnext = &exp->_nodes[greedystop->next];
- }else if(next && next->next != -1){
- gnext = &exp->_nodes[next->next];
- }
- stop = trex_matchnode(exp,greedystop,s,gnext);
- if(stop) {
- //if satisfied stop it
- if(p0 == p1 && p0 == nmaches) break;
- else if(nmaches >= p0 && p1 == 0xFFFF) break;
- else if(nmaches >= p0 && nmaches <= p1) break;
- }
- }
- }
-
- if(s >= exp->_eol)
- break;
- }
- if(p0 == p1 && p0 == nmaches) return good;
- else if(nmaches >= p0 && p1 == 0xFFFF) return good;
- else if(nmaches >= p0 && nmaches <= p1) return good;
- return NULL;
- }
- case OP_OR: {
- const TRexChar *asd = str;
- TRexNode *temp=&exp->_nodes[node->left];
- while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) {
- if(temp->next != -1)
- temp = &exp->_nodes[temp->next];
- else
- return asd;
- }
- asd = str;
- temp = &exp->_nodes[node->right];
- while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) {
- if(temp->next != -1)
- temp = &exp->_nodes[temp->next];
- else
- return asd;
- }
- return NULL;
- break;
- }
- case OP_EXPR:
- case OP_NOCAPEXPR:{
- TRexNode *n = &exp->_nodes[node->left];
- const TRexChar *cur = str;
- int capture = -1;
- if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
- capture = exp->_currsubexp;
- exp->_matches[capture].begin = cur;
- exp->_currsubexp++;
- }
-
- do {
- TRexNode *subnext = NULL;
- if(n->next != -1) {
- subnext = &exp->_nodes[n->next];
- }else {
- subnext = next;
- }
- if(!(cur = trex_matchnode(exp,n,cur,subnext))) {
- if(capture != -1){
- exp->_matches[capture].begin = 0;
- exp->_matches[capture].len = 0;
- }
- return NULL;
- }
- } while((n->next != -1) && (n = &exp->_nodes[n->next]));
-
- if(capture != -1)
- exp->_matches[capture].len = cur - exp->_matches[capture].begin;
- return cur;
- }
- case OP_WB:
- if((str == exp->_bol && !isspace(*str))
- || (str == exp->_eol && !isspace(*(str-1)))
- || (!isspace(*str) && isspace(*(str+1)))
- || (isspace(*str) && !isspace(*(str+1))) ) {
- return (node->left == 'b')?str:NULL;
- }
- return (node->left == 'b')?NULL:str;
- case OP_BOL:
- if(str == exp->_bol) return str;
- return NULL;
- case OP_EOL:
- if(str == exp->_eol) return str;
- return NULL;
- case OP_DOT:{
- *str++;
- }
- return str;
- case OP_NCLASS:
- case OP_CLASS:
- if(trex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?TRex_True:TRex_False):(type == OP_NCLASS?TRex_True:TRex_False)) {
- *str++;
- return str;
- }
- return NULL;
- case OP_CCLASS:
- if(trex_matchcclass(node->left,*str)) {
- *str++;
- return str;
- }
- return NULL;
- default: /* char */
- if(*str != node->type) return NULL;
- *str++;
- return str;
- }
- return NULL;
-}
-
-/* public api */
-TRex *trex_compile(const TRexChar *pattern,const TRexChar **error)
-{
- TRex *exp = (TRex *)malloc(sizeof(TRex));
- exp->_eol = exp->_bol = NULL;
- exp->_p = pattern;
- exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar);
- exp->_nodes = (TRexNode *)malloc(exp->_nallocated * sizeof(TRexNode));
- exp->_nsize = 0;
- exp->_matches = 0;
- exp->_nsubexpr = 0;
- exp->_first = trex_newnode(exp,OP_EXPR);
- exp->_error = error;
- exp->_jmpbuf = malloc(sizeof(jmp_buf));
- if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {
- int res = trex_list(exp);
- exp->_nodes[exp->_first].left = res;
- if(*exp->_p!='\0')
- trex_error(exp,_SC("unexpected character"));
-#ifdef _DEBUG
- {
- int nsize,i;
- TRexNode *t;
- nsize = exp->_nsize;
- t = &exp->_nodes[0];
- scprintf(_SC("\n"));
- for(i = 0;i < nsize; i++) {
- if(exp->_nodes[i].type>MAX_CHAR)
- scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);
- else
- scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type);
- scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next);
- }
- scprintf(_SC("\n"));
- }
-#endif
- exp->_matches = (TRexMatch *) malloc(exp->_nsubexpr * sizeof(TRexMatch));
- memset(exp->_matches,0,exp->_nsubexpr * sizeof(TRexMatch));
- }
- else{
- trex_free(exp);
- return NULL;
- }
- return exp;
-}
-
-void trex_free(TRex *exp)
-{
- if(exp) {
- if(exp->_nodes) free(exp->_nodes);
- if(exp->_jmpbuf) free(exp->_jmpbuf);
- if(exp->_matches) free(exp->_matches);
- free(exp);
- }
-}
-
-TRexBool trex_match(TRex* exp,const TRexChar* text)
-{
- const TRexChar* res = NULL;
- exp->_bol = text;
- exp->_eol = text + scstrlen(text);
- exp->_currsubexp = 0;
- res = trex_matchnode(exp,exp->_nodes,text,NULL);
- if(res == NULL || res != exp->_eol)
- return TRex_False;
- return TRex_True;
-}
-
-TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end)
-{
- const TRexChar *cur = NULL;
- int node = exp->_first;
- if(text_begin >= text_end) return TRex_False;
- exp->_bol = text_begin;
- exp->_eol = text_end;
- do {
- cur = text_begin;
- while(node != -1) {
- exp->_currsubexp = 0;
- cur = trex_matchnode(exp,&exp->_nodes[node],cur,NULL);
- if(!cur)
- break;
- node = exp->_nodes[node].next;
- }
- *text_begin++;
- } while(cur == NULL && text_begin != text_end);
-
- if(cur == NULL)
- return TRex_False;
-
- --text_begin;
-
- if(out_begin) *out_begin = text_begin;
- if(out_end) *out_end = cur;
- return TRex_True;
-}
-
-TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end)
-{
- return trex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end);
-}
-
-int trex_getsubexpcount(TRex* exp)
-{
- return exp->_nsubexpr;
-}
-
-TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp)
-{
- if( n<0 || n >= exp->_nsubexpr) return TRex_False;
- *subexp = exp->_matches[n];
- return TRex_True;
-}
-
diff --git a/drivers/trex/trex.h b/drivers/trex/trex.h deleted file mode 100644 index 46e2e73fd5..0000000000 --- a/drivers/trex/trex.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef _TREX_H_
-#define _TREX_H_
-/***************************************************************
- T-Rex a tiny regular expression library
-
- Copyright (C) 2003-2006 Alberto Demichelis
-
- This software is provided 'as-is', without any express
- or implied warranty. In no event will the authors be held
- liable for any damages arising from the use of this software.
-
- Permission is granted to anyone to use this software for
- any purpose, including commercial applications, and to alter
- it and redistribute it freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented;
- you must not claim that you wrote the original software.
- If you use this software in a product, an acknowledgment
- in the product documentation would be appreciated but
- is not required.
-
- 2. Altered source versions must be plainly marked as such,
- and must not be misrepresented as being the original software.
-
- 3. This notice may not be removed or altered from any
- source distribution.
-
-****************************************************************/
-
-#define _UNICODE
-
-
-#ifdef _UNICODE
-#define TRexChar wchar_t
-#define MAX_CHAR 0xFFFF
-#define _TREXC(c) L##c
-#define trex_strlen wcslen
-#define trex_printf wprintf
-#else
-#define TRexChar char
-#define MAX_CHAR 0xFF
-#define _TREXC(c) (c)
-#define trex_strlen strlen
-#define trex_printf printf
-#endif
-
-#ifndef TREX_API
-#define TREX_API extern
-#endif
-
-#define TRex_True 1
-#define TRex_False 0
-
-typedef unsigned int TRexBool;
-typedef struct TRex TRex;
-
-typedef struct {
- const TRexChar *begin;
- int len;
-} TRexMatch;
-
-TREX_API TRex *trex_compile(const TRexChar *pattern,const TRexChar **error);
-TREX_API void trex_free(TRex *exp);
-TREX_API TRexBool trex_match(TRex* exp,const TRexChar* text);
-TREX_API TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end);
-TREX_API TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end);
-TREX_API int trex_getsubexpcount(TRex* exp);
-TREX_API TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp);
-
-#endif
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 5f51865432..0c0867e030 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -87,7 +87,7 @@ bool DirAccessUnix::dir_exists(String p_dir) { if (p_dir.is_rel_path()) - p_dir=current_dir+"/"+p_dir; + p_dir=get_current_dir().plus_file(p_dir); else p_dir=fix_path(p_dir); @@ -278,9 +278,16 @@ String DirAccessUnix::get_current_dir() { Error DirAccessUnix::rename(String p_path,String p_new_path) { - p_path=fix_path(p_path); - p_new_path=fix_path(p_new_path); - + if (p_path.is_rel_path()) + p_path=get_current_dir().plus_file(p_path); + else + p_path=fix_path(p_path); + + if (p_new_path.is_rel_path()) + p_new_path=get_current_dir().plus_file(p_new_path); + else + p_new_path=fix_path(p_new_path); + return ::rename(p_path.utf8().get_data(),p_new_path.utf8().get_data())==0?OK:FAILED; } Error DirAccessUnix::remove(String p_path) { diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h index f6089ccfe1..3091e01511 100644 --- a/drivers/unix/dir_access_unix.h +++ b/drivers/unix/dir_access_unix.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 2f91eee90e..76042089ff 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index 0dedfce6ac..5b0f0e7cb7 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index ad0d4e00ea..989aba52bb 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h index 2fd5cf964b..5798ac8137 100644 --- a/drivers/unix/ip_unix.h +++ b/drivers/unix/ip_unix.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/memory_pool_static_malloc.cpp b/drivers/unix/memory_pool_static_malloc.cpp index 4711f4f090..e0bab27a63 100644 --- a/drivers/unix/memory_pool_static_malloc.cpp +++ b/drivers/unix/memory_pool_static_malloc.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -153,7 +153,7 @@ void* MemoryPoolStaticMalloc::_realloc(void *p_memory,size_t p_bytes) { return alloc( p_bytes ); } - if (p_bytes<=0) { + if (p_bytes==0) { this->free(p_memory); ERR_FAIL_COND_V( p_bytes < 0 , NULL ); diff --git a/drivers/unix/memory_pool_static_malloc.h b/drivers/unix/memory_pool_static_malloc.h index 626fec826e..a96259556d 100644 --- a/drivers/unix/memory_pool_static_malloc.h +++ b/drivers/unix/memory_pool_static_malloc.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/mutex_posix.cpp b/drivers/unix/mutex_posix.cpp index 166dfa4b19..73563ea538 100644 --- a/drivers/unix/mutex_posix.cpp +++ b/drivers/unix/mutex_posix.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/mutex_posix.h b/drivers/unix/mutex_posix.h index 3496473688..9b50d7963e 100644 --- a/drivers/unix/mutex_posix.h +++ b/drivers/unix/mutex_posix.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index d51a7c74e8..f6d9e0fb4e 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -57,8 +57,14 @@ #include <errno.h> #include <assert.h> #include "globals.h" + +extern bool _print_error_enabled; + void OS_Unix::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) { + if (!_print_error_enabled) + return; + if (p_rationale && p_rationale[0]) { print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale); @@ -218,10 +224,14 @@ uint64_t OS_Unix::get_unix_time() const { }; -OS::Date OS_Unix::get_date() const { +OS::Date OS_Unix::get_date(bool utc) const { time_t t=time(NULL); - struct tm *lt=localtime(&t); + struct tm *lt; + if (utc) + lt=gmtime(&t); + else + lt=localtime(&t); Date ret; ret.year=1900+lt->tm_year; ret.month=(Month)lt->tm_mon; @@ -231,17 +241,47 @@ OS::Date OS_Unix::get_date() const { return ret; } -OS::Time OS_Unix::get_time() const { - +OS::Time OS_Unix::get_time(bool utc) const { time_t t=time(NULL); - struct tm *lt=localtime(&t); + struct tm *lt; + if (utc) + lt=gmtime(&t); + else + lt=localtime(&t); Time ret; ret.hour=lt->tm_hour; ret.min=lt->tm_min; ret.sec=lt->tm_sec; + get_time_zone_info(); return ret; } - + +OS::TimeZoneInfo OS_Unix::get_time_zone_info() const { + time_t t = time(NULL); + struct tm *lt = localtime(&t); + char name[16]; + strftime(name, 16, "%Z", lt); + name[15] = 0; + TimeZoneInfo ret; + ret.name = name; + + char bias_buf[16]; + strftime(bias_buf, 16, "%z", lt); + int bias; + bias_buf[15] = 0; + sscanf(bias_buf, "%d", &bias); + + // convert from ISO 8601 (1 minute=1, 1 hour=100) to minutes + int hour = (int)bias / 100; + int minutes = bias % 100; + if (bias < 0) + ret.bias = hour * 60 - minutes; + else + ret.bias = hour * 60 + minutes; + + return ret; +} + void OS_Unix::delay_usec(uint32_t p_usec) const { usleep(p_usec); diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 1dcf0bd2fd..8bb57eda12 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -88,8 +88,9 @@ public: virtual String get_name(); - virtual Date get_date() const; - virtual Time get_time() const; + virtual Date get_date(bool utc) const; + virtual Time get_time(bool utc) const; + virtual TimeZoneInfo get_time_zone_info() const; virtual uint64_t get_unix_time() const; diff --git a/drivers/unix/semaphore_posix.cpp b/drivers/unix/semaphore_posix.cpp index 6f1b8931f9..fba4cd3641 100644 --- a/drivers/unix/semaphore_posix.cpp +++ b/drivers/unix/semaphore_posix.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/semaphore_posix.h b/drivers/unix/semaphore_posix.h index de563c28c4..6f938455b3 100644 --- a/drivers/unix/semaphore_posix.h +++ b/drivers/unix/semaphore_posix.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 8d937d9ca8..2301d8b6c4 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h index 1259b46ff2..9b1716ac42 100644 --- a/drivers/unix/stream_peer_tcp_posix.h +++ b/drivers/unix/stream_peer_tcp_posix.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index dfcf479fc0..4f9ee62cde 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h index 053aba0d10..17a9fd1d98 100644 --- a/drivers/unix/tcp_server_posix.h +++ b/drivers/unix/tcp_server_posix.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp index e5d6a02579..03963a9756 100644 --- a/drivers/unix/thread_posix.cpp +++ b/drivers/unix/thread_posix.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h index a088f1d5de..4f76f3d7b3 100644 --- a/drivers/unix/thread_posix.h +++ b/drivers/unix/thread_posix.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.cpp b/drivers/vorbis/audio_stream_ogg_vorbis.cpp index 996f75d165..ed292621e9 100644 --- a/drivers/vorbis/audio_stream_ogg_vorbis.cpp +++ b/drivers/vorbis/audio_stream_ogg_vorbis.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.h b/drivers/vorbis/audio_stream_ogg_vorbis.h index dd84fd1601..8a35fc09cb 100644 --- a/drivers/vorbis/audio_stream_ogg_vorbis.h +++ b/drivers/vorbis/audio_stream_ogg_vorbis.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/vorbis/psy.c b/drivers/vorbis/psy.c index 9a86151cec..29d2824372 100644 --- a/drivers/vorbis/psy.c +++ b/drivers/vorbis/psy.c @@ -1160,7 +1160,7 @@ void _vp_couple_quantize_normalize(int blobno, However, this is a temporary patch. by Aoyumi @ 2004/04/18 */ - /*float derate = (1.0 - de*((float)(j-limit+i) / (float)(n-limit))); + /*float derate = (1.0 - de*((float)(j-limit+i) / (float)(n-limit))); */ /* elliptical if(reM[j]+reA[j]<0){ reM[j] = - (qeM[j] = (fabs(reM[j])+fabs(reA[j]))*derate*derate); diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index 4c265a1ab2..7c81e8e051 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -70,21 +70,11 @@ bool DirAccessWindows::list_dir_begin() { _cisdir=false; _cishidden=false; - if (unicode) { - list_dir_end(); - p->h = FindFirstFileExW((current_dir+"\\*").c_str(), FindExInfoStandard, &p->fu, FindExSearchNameMatch, NULL, 0); + list_dir_end(); + p->h = FindFirstFileExW((current_dir+"\\*").c_str(), FindExInfoStandard, &p->fu, FindExSearchNameMatch, NULL, 0); - return (p->h==INVALID_HANDLE_VALUE); - } else { - - list_dir_end(); - p->h = FindFirstFileExA((current_dir+"\\*").ascii().get_data(), FindExInfoStandard, &p->fu, FindExSearchNameMatch, NULL, 0); - - return (p->h==INVALID_HANDLE_VALUE); - - } + return (p->h==INVALID_HANDLE_VALUE); - return false; } @@ -93,38 +83,20 @@ String DirAccessWindows::get_next() { if (p->h==INVALID_HANDLE_VALUE) return ""; - if (unicode) { - _cisdir=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); - _cishidden=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN); + _cisdir=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + _cishidden=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN); - String name=p->fu.cFileName; - - if (FindNextFileW(p->h, &p->fu) == 0) { - - FindClose(p->h); - p->h=INVALID_HANDLE_VALUE; - } - - return name; - } else { + String name=p->fu.cFileName; -#ifndef WINRT_ENABLED - _cisdir=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); - _cishidden=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN); + if (FindNextFileW(p->h, &p->fu) == 0) { - String name=p->f.cFileName; - - if (FindNextFileA(p->h, &p->f) == 0) { + FindClose(p->h); + p->h=INVALID_HANDLE_VALUE; + } - FindClose(p->h); - p->h=INVALID_HANDLE_VALUE; - } + return name; - return name; -#endif - return ""; - } } bool DirAccessWindows::current_is_dir() const { @@ -174,63 +146,38 @@ Error DirAccessWindows::change_dir(String p_dir) { p_dir=fix_path(p_dir); - if (unicode) { - wchar_t real_current_dir_name[2048]; - GetCurrentDirectoryW(2048,real_current_dir_name); - String prev_dir=real_current_dir_name; + wchar_t real_current_dir_name[2048]; + GetCurrentDirectoryW(2048,real_current_dir_name); + String prev_dir=real_current_dir_name; - SetCurrentDirectoryW(current_dir.c_str()); - bool worked=(SetCurrentDirectoryW(p_dir.c_str())!=0); + SetCurrentDirectoryW(current_dir.c_str()); + bool worked=(SetCurrentDirectoryW(p_dir.c_str())!=0); - String base = _get_root_path(); - if (base!="") { + String base = _get_root_path(); + if (base!="") { - GetCurrentDirectoryW(2048,real_current_dir_name); - String new_dir; - new_dir = String(real_current_dir_name).replace("\\","/"); - if (!new_dir.begins_with(base)) { - worked=false; - } + GetCurrentDirectoryW(2048,real_current_dir_name); + String new_dir; + new_dir = String(real_current_dir_name).replace("\\","/"); + if (!new_dir.begins_with(base)) { + worked=false; } + } - if (worked) { - - GetCurrentDirectoryW(2048,real_current_dir_name); - current_dir=real_current_dir_name; // TODO, utf8 parser - current_dir=current_dir.replace("\\","/"); - - } //else { - - SetCurrentDirectoryW(prev_dir.c_str()); - //} - - return worked?OK:ERR_INVALID_PARAMETER; - } else { - - char real_current_dir_name[2048]; - GetCurrentDirectoryA(2048,real_current_dir_name); - String prev_dir=real_current_dir_name; - - SetCurrentDirectoryA(current_dir.ascii().get_data()); - bool worked=(SetCurrentDirectory(p_dir.ascii().get_data())!=0); - - if (worked) { - - GetCurrentDirectoryA(2048,real_current_dir_name); - current_dir=real_current_dir_name; // TODO, utf8 parser - current_dir=current_dir.replace("\\","/"); + if (worked) { - }// else { - SetCurrentDirectoryA(prev_dir.ascii().get_data()); - //} + GetCurrentDirectoryW(2048,real_current_dir_name); + current_dir=real_current_dir_name; // TODO, utf8 parser + current_dir=current_dir.replace("\\","/"); - return worked?OK:ERR_INVALID_PARAMETER; + } //else { - } + SetCurrentDirectoryW(prev_dir.c_str()); + //} - return OK; + return worked?OK:ERR_INVALID_PARAMETER; #endif } @@ -246,34 +193,20 @@ Error DirAccessWindows::make_dir(String p_dir) { p_dir=fix_path(p_dir); - p_dir.replace("/","\\"); + //p_dir.replace("/","\\"); bool success; int err; - if (unicode) { - wchar_t real_current_dir_name[2048]; - GetCurrentDirectoryW(2048,real_current_dir_name); - - SetCurrentDirectoryW(current_dir.c_str()); - - success=CreateDirectoryW(p_dir.c_str(), NULL); - err = GetLastError(); - - SetCurrentDirectoryW(real_current_dir_name); - - } else { + wchar_t real_current_dir_name[2048]; + GetCurrentDirectoryW(2048,real_current_dir_name); - char real_current_dir_name[2048]; - GetCurrentDirectoryA(2048,real_current_dir_name); + SetCurrentDirectoryW(current_dir.c_str()); - SetCurrentDirectoryA(current_dir.ascii().get_data()); + success=CreateDirectoryW(p_dir.c_str(), NULL); + err = GetLastError(); - success=CreateDirectoryA(p_dir.ascii().get_data(), NULL); - err = GetLastError(); - - SetCurrentDirectoryA(real_current_dir_name); - } + SetCurrentDirectoryW(real_current_dir_name); if (success) { return OK; @@ -313,81 +246,59 @@ bool DirAccessWindows::file_exists(String p_file) { GLOBAL_LOCK_FUNCTION if (!p_file.is_abs_path()) - p_file=get_current_dir()+"/"+p_file; + p_file=get_current_dir().plus_file(p_file); p_file=fix_path(p_file); - p_file.replace("/","\\"); - - WIN32_FILE_ATTRIBUTE_DATA fileInfo; - - if (unicode) { + //p_file.replace("/","\\"); - DWORD fileAttr; + //WIN32_FILE_ATTRIBUTE_DATA fileInfo; - fileAttr = GetFileAttributesExW(p_file.c_str(), GetFileExInfoStandard, &fileInfo); - if (0 == fileAttr) - return false; + DWORD fileAttr; - return !(fileAttr&FILE_ATTRIBUTE_DIRECTORY); - - } else { - DWORD fileAttr; + fileAttr = GetFileAttributesW(p_file.c_str()); + if (INVALID_FILE_ATTRIBUTES == fileAttr) + return false; - fileAttr = GetFileAttributesExA(p_file.ascii().get_data(), GetFileExInfoStandard, &fileInfo); - if (0 == fileAttr) - return false; + return !(fileAttr&FILE_ATTRIBUTE_DIRECTORY); - return !(fileAttr&FILE_ATTRIBUTE_DIRECTORY); - - } - - return false; } bool DirAccessWindows::dir_exists(String p_dir) { GLOBAL_LOCK_FUNCTION - if (!p_dir.is_abs_path()) - p_dir=get_current_dir()+"/"+p_dir; - - p_dir=fix_path(p_dir); - - p_dir.replace("/","\\"); - - WIN32_FILE_ATTRIBUTE_DATA fileInfo; - - if (unicode) { - - DWORD fileAttr; + if (p_dir.is_rel_path()) + p_dir=get_current_dir().plus_file(p_dir); + else + p_dir=fix_path(p_dir); - fileAttr = GetFileAttributesExW(p_dir.c_str(), GetFileExInfoStandard, &fileInfo); - if (0 == fileAttr) - return false; + //p_dir.replace("/","\\"); - return (fileAttr&FILE_ATTRIBUTE_DIRECTORY); + //WIN32_FILE_ATTRIBUTE_DATA fileInfo; - } else { -#ifndef WINRT_ENABLED - DWORD fileAttr; - fileAttr = GetFileAttributesExA(p_dir.ascii().get_data(), GetFileExInfoStandard, &fileInfo); - if (0 == fileAttr) - return false; + DWORD fileAttr; - return (fileAttr&FILE_ATTRIBUTE_DIRECTORY); + fileAttr = GetFileAttributesW(p_dir.c_str()); + if (INVALID_FILE_ATTRIBUTES == fileAttr) + return false; + return (fileAttr&FILE_ATTRIBUTE_DIRECTORY); -#endif - } - return false; } Error DirAccessWindows::rename(String p_path,String p_new_path) { - p_path=fix_path(p_path); - p_new_path=fix_path(p_new_path); - + if (p_path.is_rel_path()) + p_path=get_current_dir().plus_file(p_path); + else + p_path=fix_path(p_path); + + if (p_new_path.is_rel_path()) + p_new_path=get_current_dir().plus_file(p_new_path); + else + p_new_path=fix_path(p_new_path); + if (file_exists(p_new_path)) { if (remove(p_new_path) != OK) { return FAILED; @@ -402,12 +313,15 @@ Error DirAccessWindows::remove(String p_path) { p_path=fix_path(p_path); printf("erasing %s\n",p_path.utf8().get_data()); - WIN32_FILE_ATTRIBUTE_DATA fileInfo; - DWORD fileAttr = GetFileAttributesExW(p_path.c_str(), GetFileExInfoStandard, &fileInfo); - if (fileAttr == INVALID_FILE_ATTRIBUTES) - return FAILED; + //WIN32_FILE_ATTRIBUTE_DATA fileInfo; + //DWORD fileAttr = GetFileAttributesExW(p_path.c_str(), GetFileExInfoStandard, &fileInfo); - if (fileAttr & FILE_ATTRIBUTE_DIRECTORY) + DWORD fileAttr; + + fileAttr = GetFileAttributesW(p_path.c_str()); + if (INVALID_FILE_ATTRIBUTES == fileAttr) + return FAILED; + if ((fileAttr&FILE_ATTRIBUTE_DIRECTORY)) return ::_wrmdir(p_path.c_str())==0?OK:FAILED; else return ::_wunlink(p_path.c_str())==0?OK:FAILED; @@ -471,13 +385,6 @@ DirAccessWindows::DirAccessWindows() { } } - unicode=true; - - - /* We are running Windows 95/98/ME, so no unicode allowed */ - if ( SetCurrentDirectoryW ( L"." ) == FALSE && GetLastError () == ERROR_CALL_NOT_IMPLEMENTED ) - unicode=false; - change_dir("."); #endif } diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h index 4a668a7364..384bc8327d 100644 --- a/drivers/windows/dir_access_windows.h +++ b/drivers/windows/dir_access_windows.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -56,7 +56,7 @@ class DirAccessWindows : public DirAccess { String current_dir; - bool unicode; + bool _cisdir; bool _cishidden; diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 19a62967ea..90903f2cbd 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h index 8f16d66fe1..a2598bfeec 100644 --- a/drivers/windows/file_access_windows.h +++ b/drivers/windows/file_access_windows.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/windows/mutex_windows.cpp b/drivers/windows/mutex_windows.cpp index 3b2004285a..09f8590510 100644 --- a/drivers/windows/mutex_windows.cpp +++ b/drivers/windows/mutex_windows.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/windows/mutex_windows.h b/drivers/windows/mutex_windows.h index 9a3875f053..9447f17a1c 100644 --- a/drivers/windows/mutex_windows.h +++ b/drivers/windows/mutex_windows.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/windows/semaphore_windows.cpp b/drivers/windows/semaphore_windows.cpp index bfd53f9837..50cdf7cce5 100644 --- a/drivers/windows/semaphore_windows.cpp +++ b/drivers/windows/semaphore_windows.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/windows/semaphore_windows.h b/drivers/windows/semaphore_windows.h index f87b868a68..43f6c0b560 100644 --- a/drivers/windows/semaphore_windows.h +++ b/drivers/windows/semaphore_windows.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/windows/shell_windows.cpp b/drivers/windows/shell_windows.cpp index 3994252c48..670f4e483d 100644 --- a/drivers/windows/shell_windows.cpp +++ b/drivers/windows/shell_windows.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/windows/shell_windows.h b/drivers/windows/shell_windows.h index 8bbf51514c..98eae81175 100644 --- a/drivers/windows/shell_windows.h +++ b/drivers/windows/shell_windows.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/windows/thread_windows.cpp b/drivers/windows/thread_windows.cpp index 40efa5acd5..6a9e97ba01 100644 --- a/drivers/windows/thread_windows.cpp +++ b/drivers/windows/thread_windows.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/windows/thread_windows.h b/drivers/windows/thread_windows.h index d15e77d065..3c8f92ce57 100644 --- a/drivers/windows/thread_windows.h +++ b/drivers/windows/thread_windows.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ |