summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/dds/SCsub7
-rw-r--r--modules/dds/config.py6
-rw-r--r--modules/dds/register_types.cpp44
-rw-r--r--modules/dds/register_types.h30
-rw-r--r--modules/dds/texture_loader_dds.cpp485
-rw-r--r--modules/dds/texture_loader_dds.h46
-rw-r--r--modules/etc1/SCsub19
-rw-r--r--modules/etc1/config.py6
-rw-r--r--modules/etc1/image_etc.cpp201
-rw-r--r--modules/etc1/image_etc.h35
-rw-r--r--modules/etc1/register_types.cpp47
-rw-r--r--modules/etc1/register_types.h30
-rw-r--r--modules/etc1/texture_loader_pkm.cpp84
-rw-r--r--modules/etc1/texture_loader_pkm.h18
-rw-r--r--modules/pbm/SCsub7
-rw-r--r--modules/pbm/bitmap_loader_pbm.cpp252
-rw-r--r--modules/pbm/bitmap_loader_pbm.h50
-rw-r--r--modules/pbm/config.py6
-rw-r--r--modules/pbm/register_types.cpp44
-rw-r--r--modules/pbm/register_types.h30
-rw-r--r--modules/pvr/SCsub23
-rw-r--r--modules/pvr/config.py6
-rw-r--r--modules/pvr/register_types.cpp44
-rw-r--r--modules/pvr/register_types.h30
-rw-r--r--modules/pvr/texture_loader_pvr.cpp711
-rw-r--r--modules/pvr/texture_loader_pvr.h50
26 files changed, 2311 insertions, 0 deletions
diff --git a/modules/dds/SCsub b/modules/dds/SCsub
new file mode 100644
index 0000000000..bcea3a84c0
--- /dev/null
+++ b/modules/dds/SCsub
@@ -0,0 +1,7 @@
+Import('env')
+Import('env_modules')
+
+env_modules.add_source_files(env.modules_sources, "*.cpp")
+
+Export('env_modules')
+Export('env')
diff --git a/modules/dds/config.py b/modules/dds/config.py
new file mode 100644
index 0000000000..368e97e152
--- /dev/null
+++ b/modules/dds/config.py
@@ -0,0 +1,6 @@
+
+def can_build(platform):
+ return True
+
+def configure(env):
+ pass
diff --git a/modules/dds/register_types.cpp b/modules/dds/register_types.cpp
new file mode 100644
index 0000000000..0d28e2bbef
--- /dev/null
+++ b/modules/dds/register_types.cpp
@@ -0,0 +1,44 @@
+/*************************************************************************/
+/* register_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "register_types.h"
+
+#include "texture_loader_dds.h"
+
+static ResourceFormatDDS *resource_loader_dds = NULL;
+
+void register_dds_types() {
+
+ resource_loader_dds = memnew( ResourceFormatDDS );
+ ResourceLoader::add_resource_format_loader(resource_loader_dds);
+}
+
+void unregister_dds_types() {
+
+ memdelete(resource_loader_dds);
+}
diff --git a/modules/dds/register_types.h b/modules/dds/register_types.h
new file mode 100644
index 0000000000..f9ecfb8ef9
--- /dev/null
+++ b/modules/dds/register_types.h
@@ -0,0 +1,30 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+void register_dds_types();
+void unregister_dds_types();
diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp
new file mode 100644
index 0000000000..0cc84f02f7
--- /dev/null
+++ b/modules/dds/texture_loader_dds.cpp
@@ -0,0 +1,485 @@
+/*************************************************************************/
+/* texture_loader_dds.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "texture_loader_dds.h"
+#include "os/file_access.h"
+
+
+enum {
+ DDS_MAGIC=0x20534444,
+ DDSD_CAPS=0x00000001,
+ DDSD_PIXELFORMAT=0x00001000,
+ DDSD_PITCH=0x00000008,
+ DDSD_LINEARSIZE=0x00080000,
+ DDSD_MIPMAPCOUNT=0x00020000,
+ DDPF_FOURCC=0x00000004,
+ DDPF_ALPHAPIXELS=0x00000001,
+ DDPF_INDEXED=0x00000020,
+ DDPF_RGB=0x00000040,
+};
+
+enum DDSFormat {
+
+ DDS_DXT1,
+ DDS_DXT3,
+ DDS_DXT5,
+ DDS_ATI1,
+ DDS_ATI2,
+ DDS_BGRA8,
+ DDS_BGR8,
+ DDS_RGBA8, //flipped in dds
+ DDS_RGB8, //flipped in dds
+ DDS_BGR5A1,
+ DDS_BGR565,
+ DDS_BGR10A2,
+ DDS_INDEXED,
+ DDS_LUMINANCE,
+ DDS_LUMINANCE_ALPHA,
+ DDS_MAX
+};
+
+struct DDSFormatInfo {
+ const char *name;
+ bool compressed;
+ bool palette;
+ uint32_t divisor;
+ uint32_t block_size;
+ Image::Format format;
+};
+
+
+static const DDSFormatInfo dds_format_info[DDS_MAX]={
+ {"DXT1",true,false,4,8,Image::FORMAT_BC1},
+ {"DXT3",true,false,4,16,Image::FORMAT_BC2},
+ {"DXT5",true,false,4,16,Image::FORMAT_BC3},
+ {"ATI1",true,false,4,8,Image::FORMAT_BC4},
+ {"ATI2",true,false,4,16,Image::FORMAT_BC5},
+ {"BGRA8",false,false,1,4,Image::FORMAT_RGBA},
+ {"BGR8",false,false,1,3,Image::FORMAT_RGB},
+ {"RGBA8",false,false,1,4,Image::FORMAT_RGBA},
+ {"RGB8",false,false,1,3,Image::FORMAT_RGB},
+ {"BGR5A1",false,false,1,2,Image::FORMAT_RGBA},
+ {"BGR565",false,false,1,2,Image::FORMAT_RGB},
+ {"BGR10A2",false,false,1,4,Image::FORMAT_RGBA},
+ {"INDEXED",false,true,1,1,Image::FORMAT_INDEXED},
+ {"GRAYSCALE",false,false,1,1,Image::FORMAT_GRAYSCALE},
+ {"GRAYSCALE_ALPHA",false,false,1,2,Image::FORMAT_GRAYSCALE_ALPHA}
+};
+
+
+RES ResourceFormatDDS::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+ if (r_error)
+ *r_error=ERR_CANT_OPEN;
+
+ Error err;
+ FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
+ if (!f)
+ return RES();
+
+ FileAccessRef fref(f);
+ if (r_error)
+ *r_error=ERR_FILE_CORRUPT;
+
+ ERR_EXPLAIN("Unable to open DDS texture file: "+p_path);
+ ERR_FAIL_COND_V(err!=OK,RES());
+
+ uint32_t magic = f->get_32();
+ uint32_t hsize = f->get_32();
+ uint32_t flags = f->get_32();
+ uint32_t width = f->get_32();
+ uint32_t height = f->get_32();
+ uint32_t pitch = f->get_32();
+ uint32_t depth = f->get_32();
+ uint32_t mipmaps = f->get_32();
+
+ //skip 11
+ for(int i=0;i<11;i++)
+ f->get_32();
+
+ //validate
+
+ if (magic!=DDS_MAGIC || hsize!=124 || !(flags&DDSD_PIXELFORMAT) || !(flags&DDSD_CAPS)) {
+
+ ERR_EXPLAIN("Invalid or Unsupported DDS texture file: "+p_path);
+ ERR_FAIL_V(RES());
+ }
+
+
+ uint32_t format_size = f->get_32();
+ uint32_t format_flags = f->get_32();
+ uint32_t format_fourcc = f->get_32();
+ uint32_t format_rgb_bits = f->get_32();
+ uint32_t format_red_mask = f->get_32();
+ uint32_t format_green_mask = f->get_32();
+ uint32_t format_blue_mask = f->get_32();
+ uint32_t format_alpha_mask = f->get_32();
+
+ uint32_t caps_1 = f->get_32();
+ uint32_t caps_2 = f->get_32();
+ uint32_t caps_ddsx = f->get_32();
+
+ //reserved skip
+ f->get_32();
+ f->get_32();
+
+ /*print_line("DDS width: "+itos(width));
+ print_line("DDS height: "+itos(height));
+ print_line("DDS mipmaps: "+itos(mipmaps));*/
+
+ //printf("fourcc: %x fflags: %x, rgbbits: %x, fsize: %x\n",format_fourcc,format_flags,format_rgb_bits,format_size);
+ //printf("rmask: %x gmask: %x, bmask: %x, amask: %x\n",format_red_mask,format_green_mask,format_blue_mask,format_alpha_mask);
+
+ //must avoid this later
+ while(f->get_pos()<128)
+ f->get_8();
+
+
+ DDSFormat dds_format;
+
+ if (format_flags&DDPF_FOURCC && format_fourcc==0x31545844) { //'1TXD'
+
+ dds_format=DDS_DXT1;
+ } else if (format_flags&DDPF_FOURCC && format_fourcc==0x33545844) { //'3TXD'
+
+ dds_format=DDS_DXT3;
+
+ } else if (format_flags&DDPF_FOURCC && format_fourcc==0x35545844) { //'5TXD'
+
+ dds_format=DDS_DXT5;
+ } else if (format_flags&DDPF_FOURCC && format_fourcc==0x31495441) { //'1ITA'
+
+ dds_format=DDS_ATI1;
+ } else if (format_flags&DDPF_FOURCC && format_fourcc==0x32495441) { //'2ITA'
+
+ dds_format=DDS_ATI2;
+
+ } else if (format_flags&DDPF_RGB && format_flags&DDPF_ALPHAPIXELS && format_rgb_bits==32 && format_red_mask==0xff0000 && format_green_mask==0xff00 && format_blue_mask==0xff && format_alpha_mask==0xff000000) {
+
+ dds_format=DDS_BGRA8;
+ } else if (format_flags&DDPF_RGB && !(format_flags&DDPF_ALPHAPIXELS ) && format_rgb_bits==24 && format_red_mask==0xff0000 && format_green_mask==0xff00 && format_blue_mask==0xff) {
+
+ dds_format=DDS_BGR8;
+ } else if (format_flags&DDPF_RGB && format_flags&DDPF_ALPHAPIXELS && format_rgb_bits==32 && format_red_mask==0xff && format_green_mask==0xff00 && format_blue_mask==0xff0000 && format_alpha_mask==0xff000000) {
+
+ dds_format=DDS_RGBA8;
+ } else if (format_flags&DDPF_RGB && !(format_flags&DDPF_ALPHAPIXELS ) && format_rgb_bits==24 && format_red_mask==0xff && format_green_mask==0xff00 && format_blue_mask==0xff0000) {
+
+ dds_format=DDS_RGB8;
+
+ } else if (format_flags&DDPF_RGB && format_flags&DDPF_ALPHAPIXELS && format_rgb_bits==16 && format_red_mask==0x00007c00 && format_green_mask==0x000003e0 && format_blue_mask==0x0000001f && format_alpha_mask==0x00008000) {
+
+ dds_format=DDS_BGR5A1;
+ } else if (format_flags&DDPF_RGB && format_flags&DDPF_ALPHAPIXELS && format_rgb_bits==32 && format_red_mask==0x3ff00000 && format_green_mask==0xffc00 && format_blue_mask==0x3ff && format_alpha_mask==0xc0000000) {
+
+ dds_format=DDS_BGR10A2;
+ } else if (format_flags&DDPF_RGB && !(format_flags&DDPF_ALPHAPIXELS) && format_rgb_bits==16 && format_red_mask==0x0000f800 && format_green_mask==0x000007e0 && format_blue_mask==0x0000001f) {
+
+ dds_format=DDS_BGR565;
+ } else if (!(format_flags&DDPF_ALPHAPIXELS) && format_rgb_bits==8 && format_red_mask==0xff && format_green_mask==0xff && format_blue_mask==0xff) {
+
+ dds_format=DDS_LUMINANCE;
+ } else if ((format_flags&DDPF_ALPHAPIXELS) && format_rgb_bits==16 && format_red_mask==0xff && format_green_mask==0xff && format_blue_mask==0xff && format_alpha_mask==0xff00) {
+
+ dds_format=DDS_LUMINANCE_ALPHA;
+ } else if (format_flags&DDPF_INDEXED && format_rgb_bits==8) {
+
+ dds_format=DDS_BGR565;
+ } else {
+
+ printf("unrecognized fourcc %x format_flags: %x - rgbbits %i - red_mask %x green mask %x blue mask %x alpha mask %x\n",format_fourcc,format_flags,format_rgb_bits,format_red_mask,format_green_mask,format_blue_mask,format_alpha_mask);
+ ERR_EXPLAIN("Unrecognized or Unsupported color layout in DDS: "+p_path);
+
+ ERR_FAIL_V(RES());
+
+ }
+
+ if (!(flags&DDSD_MIPMAPCOUNT))
+ mipmaps=1;
+
+// print_line("found format: "+String(dds_format_info[dds_format].name));
+
+ DVector<uint8_t> src_data;
+
+ const DDSFormatInfo &info=dds_format_info[dds_format];
+ uint32_t w = width;
+ uint32_t h = height;
+
+
+ if (info.compressed) {
+ //compressed bc
+
+ uint32_t size = MAX( info.divisor, w )/info.divisor * MAX( info.divisor, h )/info.divisor * info.block_size;
+ ERR_FAIL_COND_V( size!=pitch, RES() );
+ ERR_FAIL_COND_V( !(flags&DDSD_LINEARSIZE), RES() );
+
+ for(uint32_t i=1;i<mipmaps;i++) {
+
+ w=MAX(1,w>>1);
+ h=MAX(1,h>>1);
+ uint32_t bsize = MAX( info.divisor, w )/info.divisor * MAX( info.divisor, h )/info.divisor * info.block_size;
+ //printf("%i x %i - block: %i\n",w,h,bsize);
+ size+= bsize;
+ }
+
+ src_data.resize(size);
+ DVector<uint8_t>::Write wb = src_data.write();
+ f->get_buffer(wb.ptr(),size);
+ wb=DVector<uint8_t>::Write();
+
+ } else if (info.palette) {
+
+ //indexed
+ ERR_FAIL_COND_V( !(flags&DDSD_PITCH), RES());
+ ERR_FAIL_COND_V( format_rgb_bits!=8, RES() );
+
+ uint32_t size = pitch*height;
+ ERR_FAIL_COND_V( size != width*height * info.block_size, RES());
+
+ uint8_t pallete[256*4];
+ f->get_buffer(pallete,256*4);
+
+ int colsize=3;
+ for(int i=0;i<256;i++) {
+
+ if (pallete[i*4+3]<255)
+ colsize=4;
+ }
+
+ int w = width;
+ int h = height;
+
+ for(uint32_t i=1;i<mipmaps;i++) {
+
+ w=(w+1)>>1;
+ h=(h+1)>>1;
+ size+= w*h*info.block_size;
+ }
+
+ src_data.resize(size + 256*colsize );
+ DVector<uint8_t>::Write wb = src_data.write();
+ f->get_buffer(wb.ptr(),size);
+
+ for(int i=0;i<256;i++) {
+
+ int dst_ofs = size+i*colsize;
+ int src_ofs = i*4;
+ wb[dst_ofs+0]=pallete[src_ofs+2];
+ wb[dst_ofs+1]=pallete[src_ofs+1];
+ wb[dst_ofs+2]=pallete[src_ofs+0];
+ if (colsize==4)
+ wb[dst_ofs+3]=pallete[src_ofs+3];
+ }
+
+
+ wb=DVector<uint8_t>::Write();
+ } else {
+ //uncompressed generic...
+
+ uint32_t size = width*height*info.block_size;
+
+
+ for(uint32_t i=1;i<mipmaps;i++) {
+
+ w=(w+1)>>1;
+ h=(h+1)>>1;
+ size+= w*h*info.block_size;
+ }
+
+ if (dds_format==DDS_BGR565)
+ size=size*3/2;
+ else if (dds_format==DDS_BGR5A1)
+ size=size*2;
+
+ src_data.resize(size);
+ DVector<uint8_t>::Write wb = src_data.write();
+ f->get_buffer(wb.ptr(),size);
+
+
+ switch(dds_format) {
+
+ case DDS_BGR5A1: {
+
+ // TO RGBA
+ int colcount = size/4;
+
+ for(int i=colcount-1;i>=0;i--) {
+
+ int src_ofs = i*2;
+ int dst_ofs = i*4;
+
+ uint8_t a=wb[src_ofs+1]&0x80;
+ uint8_t b= wb[src_ofs]&0x1F;
+ uint8_t g= (wb[src_ofs]>>5) | ((wb[src_ofs+1]&0x3)<<3);
+ uint8_t r= (wb[src_ofs+1]>>2)&0x1F;
+ wb[dst_ofs+0]=r<<3;
+ wb[dst_ofs+1]=g<<3;
+ wb[dst_ofs+2]=b<<3;
+ wb[dst_ofs+3]=a?255:0;
+ }
+ } break;
+ case DDS_BGR565: {
+
+ int colcount = size/3;
+
+ for(int i=colcount-1;i>=0;i--) {
+
+ int src_ofs = i*2;
+ int dst_ofs = i*3;
+
+ uint8_t b= wb[src_ofs]&0x1F;
+ uint8_t g= (wb[src_ofs]>>5) | ((wb[src_ofs+1]&0x7)<<3);
+ uint8_t r= wb[src_ofs+1]>>3;
+ wb[dst_ofs+0]=r<<3;
+ wb[dst_ofs+1]=g<<2;
+ wb[dst_ofs+2]=b<<3;//b<<3;
+
+ }
+
+ } break;
+ case DDS_BGR10A2: {
+
+ // TO RGBA
+ int colcount = size/4;
+
+ for(int i=colcount-1;i>=0;i--) {
+
+ int ofs = i*4;
+
+ uint32_t w32 = uint32_t(wb[ofs+0]) | (uint32_t(wb[ofs+1])<<8) | (uint32_t(wb[ofs+2])<<16) | (uint32_t(wb[ofs+3])<<24);
+
+ uint8_t a= (w32&0xc0000000) >> 24;
+ uint8_t r= (w32&0x3ff00000) >> 22;
+ uint8_t g= (w32&0xffc00) >> 12;
+ uint8_t b= (w32&0x3ff) >> 2;
+
+
+ wb[ofs+0]=r;
+ wb[ofs+1]=g;
+ wb[ofs+2]=b;
+ wb[ofs+3]=a==0xc0 ? 255 : a; //0xc0 should be opaque
+
+ }
+ } break;
+ case DDS_BGRA8: {
+
+ int colcount = size/4;
+
+ for(int i=0;i<colcount;i++) {
+
+ SWAP( wb[i*4+0],wb[i*4+2] );
+ }
+
+ } break;
+ case DDS_BGR8: {
+
+ int colcount = size/3;
+
+ for(int i=0;i<colcount;i++) {
+
+ SWAP( wb[i*3+0],wb[i*3+2] );
+ }
+ } break;
+ case DDS_RGBA8: {
+
+ /* do nothing either
+ int colcount = size/4;
+
+ for(int i=0;i<colcount;i++) {
+
+ uint8_t r = wb[i*4+1];
+ uint8_t g = wb[i*4+2];
+ uint8_t b = wb[i*4+3];
+ uint8_t a = wb[i*4+0];
+
+ wb[i*4+0]=r;
+ wb[i*4+1]=g;
+ wb[i*4+2]=b;
+ wb[i*4+3]=a;
+ }
+ */
+ } break;
+ case DDS_RGB8: {
+
+ // do nothing
+ /*
+ int colcount = size/3;
+
+ for(int i=0;i<colcount;i++) {
+
+ SWAP( wb[i*3+0],wb[i*3+2] );
+ }*/
+ } break;
+ case DDS_LUMINANCE: {
+
+ // do nothing i guess?
+
+ } break;
+ case DDS_LUMINANCE_ALPHA: {
+
+ // do nothing i guess?
+
+ } break;
+
+ default: {}
+
+ }
+
+ wb=DVector<uint8_t>::Write();
+ }
+
+
+ Image img(width,height,mipmaps-1,info.format,src_data);
+
+ Ref<ImageTexture> texture = memnew( ImageTexture );
+ texture->create_from_image(img);
+
+ if (r_error)
+ *r_error=OK;
+
+
+ return texture;
+
+}
+
+void ResourceFormatDDS::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("dds");
+}
+
+bool ResourceFormatDDS::handles_type(const String& p_type) const {
+
+ return ObjectTypeDB::is_type(p_type,"Texture");
+}
+
+String ResourceFormatDDS::get_resource_type(const String &p_path) const {
+
+ if (p_path.extension().to_lower()=="dds")
+ return "ImageTexture";
+ return "";
+}
diff --git a/modules/dds/texture_loader_dds.h b/modules/dds/texture_loader_dds.h
new file mode 100644
index 0000000000..371eb1858c
--- /dev/null
+++ b/modules/dds/texture_loader_dds.h
@@ -0,0 +1,46 @@
+/*************************************************************************/
+/* texture_loader_dds.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef TEXTURE_LOADER_DDS_H
+#define TEXTURE_LOADER_DDS_H
+
+#include "scene/resources/texture.h"
+#include "io/resource_loader.h"
+
+class ResourceFormatDDS : public ResourceFormatLoader{
+public:
+
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String& p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+
+ virtual ~ResourceFormatDDS() {}
+};
+
+#endif // TEXTURE_LOADER_DDS_H
diff --git a/modules/etc1/SCsub b/modules/etc1/SCsub
new file mode 100644
index 0000000000..93c304fe7f
--- /dev/null
+++ b/modules/etc1/SCsub
@@ -0,0 +1,19 @@
+Import('env')
+Import('env_modules')
+
+# Thirdparty source files
+# Not unbundled so far since not widespread as shared library
+thirdparty_dir = "#thirdparty/rg-etc1/"
+thirdparty_etc1_sources = [
+ "rg_etc1.cpp",
+]
+thirdparty_etc1_sources = [thirdparty_dir + file for file in thirdparty_etc1_sources]
+
+env_modules.add_source_files(env.modules_sources, thirdparty_etc1_sources)
+env_modules.Append(CPPPATH = [thirdparty_dir])
+
+# Godot source files
+env_modules.add_source_files(env.modules_sources, "*.cpp")
+
+Export('env_modules')
+Export('env')
diff --git a/modules/etc1/config.py b/modules/etc1/config.py
new file mode 100644
index 0000000000..368e97e152
--- /dev/null
+++ b/modules/etc1/config.py
@@ -0,0 +1,6 @@
+
+def can_build(platform):
+ return True
+
+def configure(env):
+ pass
diff --git a/modules/etc1/image_etc.cpp b/modules/etc1/image_etc.cpp
new file mode 100644
index 0000000000..cf2384240b
--- /dev/null
+++ b/modules/etc1/image_etc.cpp
@@ -0,0 +1,201 @@
+/*************************************************************************/
+/* image_etc.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "image_etc.h"
+#include "image.h"
+#include "rg_etc1.h"
+#include "print_string.h"
+#include "os/copymem.h"
+static void _decompress_etc(Image *p_img) {
+
+ ERR_FAIL_COND(p_img->get_format()!=Image::FORMAT_ETC);
+
+ int imgw = p_img->get_width();
+ int imgh = p_img->get_height();
+ DVector<uint8_t> src=p_img->get_data();
+ DVector<uint8_t> dst;
+
+ DVector<uint8_t>::Read r = src.read();
+
+ int mmc=p_img->get_mipmaps();
+
+
+ for(int i=0;i<=mmc;i++) {
+
+ dst.resize(dst.size()+imgw*imgh*3);
+ const uint8_t *srcbr=&r[p_img->get_mipmap_offset(i)];
+ DVector<uint8_t>::Write w = dst.write();
+
+ uint8_t *wptr = &w[dst.size()-imgw*imgh*3];
+
+ int bw=MAX(imgw/4,1);
+ int bh=MAX(imgh/4,1);
+
+ for(int y=0;y<bh;y++) {
+
+ for(int x=0;x<bw;x++) {
+
+ uint8_t block[4*4*4];
+
+
+ rg_etc1::unpack_etc1_block(srcbr,(unsigned int*)block);
+ srcbr+=8;
+
+ int maxx=MIN(imgw,4);
+ int maxy=MIN(imgh,4);
+
+ for(int yy=0;yy<maxy;yy++) {
+
+ for(int xx=0;xx<maxx;xx++) {
+
+ uint32_t src_ofs = (yy*4+xx)*4;
+ uint32_t dst_ofs = ((y*4+yy)*imgw+x*4+xx)*3;
+ wptr[dst_ofs+0]=block[src_ofs+0];
+ wptr[dst_ofs+1]=block[src_ofs+1];
+ wptr[dst_ofs+2]=block[src_ofs+2];
+
+ }
+ }
+
+ }
+
+ }
+
+ imgw=MAX(1,imgw/2);
+ imgh=MAX(1,imgh/2);
+ }
+
+
+ r=DVector<uint8_t>::Read();
+ //print_line("Re Creating ETC into regular image: w "+itos(p_img->get_width())+" h "+itos(p_img->get_height())+" mm "+itos(p_img->get_mipmaps()));
+ *p_img=Image(p_img->get_width(),p_img->get_height(),p_img->get_mipmaps(),Image::FORMAT_RGB,dst);
+ if (p_img->get_mipmaps())
+ p_img->generate_mipmaps(-1,true);
+
+
+}
+
+static void _compress_etc(Image *p_img) {
+
+ Image img = *p_img;
+
+ int imgw=img.get_width(),imgh=img.get_height();
+
+ ERR_FAIL_COND( nearest_power_of_2(imgw)!=imgw || nearest_power_of_2(imgh)!=imgh );
+
+ if (img.get_format()!=Image::FORMAT_RGB)
+ img.convert(Image::FORMAT_RGB);
+
+
+ int mmc=img.get_mipmaps();
+ if (mmc==0)
+ img.generate_mipmaps(); // force mipmaps, so it works on most hardware
+
+
+ DVector<uint8_t> res_data;
+ DVector<uint8_t> dst_data;
+ DVector<uint8_t>::Read r = img.get_data().read();
+
+ int mc=0;
+
+
+ rg_etc1::etc1_pack_params pp;
+ pp.m_quality=rg_etc1::cLowQuality;
+ for(int i=0;i<=mmc;i++) {
+
+
+ int bw=MAX(imgw/4,1);
+ int bh=MAX(imgh/4,1);
+ const uint8_t *src = &r[img.get_mipmap_offset(i)];
+ int mmsize = MAX(bw,1)*MAX(bh,1)*8;
+ dst_data.resize(dst_data.size()+mmsize);
+ DVector<uint8_t>::Write w=dst_data.write();
+ uint8_t *dst = &w[dst_data.size()-mmsize];
+
+
+// print_line("bh: "+itos(bh)+" bw: "+itos(bw));
+
+ for(int y=0;y<bh;y++) {
+
+ for(int x=0;x<bw;x++) {
+
+// print_line("x: "+itos(x)+" y: "+itos(y));
+
+ uint8_t block[4*4*4];
+ zeromem(block,4*4*4);
+ uint8_t cblock[8];
+
+ int maxy = MIN(imgh,4);
+ int maxx = MIN(imgw,4);
+
+
+ for(int yy=0;yy<maxy;yy++) {
+
+ for(int xx=0;xx<maxx;xx++) {
+
+
+ uint32_t dst_ofs = (yy*4+xx)*4;
+ uint32_t src_ofs = ((y*4+yy)*imgw+x*4+xx)*3;
+ block[dst_ofs+0]=src[src_ofs+0];
+ block[dst_ofs+1]=src[src_ofs+1];
+ block[dst_ofs+2]=src[src_ofs+2];
+ block[dst_ofs+3]=255;
+
+ }
+ }
+
+ rg_etc1::pack_etc1_block(cblock, (const unsigned int*)block, pp);
+ for(int j=0;j<8;j++) {
+
+ dst[j]=cblock[j];
+ }
+
+ dst+=8;
+ }
+
+ }
+
+ imgw=MAX(1,imgw/2);
+ imgh=MAX(1,imgh/2);
+ mc++;
+
+ }
+
+ *p_img=Image(p_img->get_width(),p_img->get_height(),mc-1,Image::FORMAT_ETC,dst_data);
+
+
+}
+
+void _register_etc1_compress_func() {
+
+ rg_etc1::pack_etc1_block_init();
+ Image::_image_compress_etc_func=_compress_etc;
+ Image::_image_decompress_etc=_decompress_etc;
+
+
+}
diff --git a/modules/etc1/image_etc.h b/modules/etc1/image_etc.h
new file mode 100644
index 0000000000..edcff39bfd
--- /dev/null
+++ b/modules/etc1/image_etc.h
@@ -0,0 +1,35 @@
+/*************************************************************************/
+/* image_etc.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef IMAGE_ETC1_H
+#define IMAGE_ETC1_H
+
+
+void _register_etc1_compress_func();
+
+#endif // IMAGE_ETC_H
diff --git a/modules/etc1/register_types.cpp b/modules/etc1/register_types.cpp
new file mode 100644
index 0000000000..e9eba6c864
--- /dev/null
+++ b/modules/etc1/register_types.cpp
@@ -0,0 +1,47 @@
+/*************************************************************************/
+/* register_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "register_types.h"
+
+#include "image_etc.h"
+#include "texture_loader_pkm.h"
+
+static ResourceFormatPKM *resource_loader_pkm = NULL;
+
+void register_etc1_types() {
+
+ resource_loader_pkm = memnew( ResourceFormatPKM );
+ ResourceLoader::add_resource_format_loader(resource_loader_pkm);
+
+ _register_etc1_compress_func();
+}
+
+void unregister_etc1_types() {
+
+ memdelete(resource_loader_pkm);
+}
diff --git a/modules/etc1/register_types.h b/modules/etc1/register_types.h
new file mode 100644
index 0000000000..bc26699d54
--- /dev/null
+++ b/modules/etc1/register_types.h
@@ -0,0 +1,30 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+void register_etc1_types();
+void unregister_etc1_types();
diff --git a/modules/etc1/texture_loader_pkm.cpp b/modules/etc1/texture_loader_pkm.cpp
new file mode 100644
index 0000000000..275afc1fd6
--- /dev/null
+++ b/modules/etc1/texture_loader_pkm.cpp
@@ -0,0 +1,84 @@
+#include "texture_loader_pkm.h"
+#include "os/file_access.h"
+#include <string.h>
+
+struct ETC1Header {
+ char tag[6]; // "PKM 10"
+ uint16_t format; // Format == number of mips (== zero)
+ uint16_t texWidth; // Texture dimensions, multiple of 4 (big-endian)
+ uint16_t texHeight;
+ uint16_t origWidth; // Original dimensions (big-endian)
+ uint16_t origHeight;
+};
+
+RES ResourceFormatPKM::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+ if (r_error)
+ *r_error=ERR_CANT_OPEN;
+
+ Error err;
+ FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
+ if (!f)
+ return RES();
+
+ FileAccessRef fref(f);
+ if (r_error)
+ *r_error=ERR_FILE_CORRUPT;
+
+ ERR_EXPLAIN("Unable to open PKM texture file: "+p_path);
+ ERR_FAIL_COND_V(err!=OK,RES());
+
+ // big endian
+ f->set_endian_swap(true);
+
+ ETC1Header h;
+ ERR_EXPLAIN("Invalid or Unsupported PKM texture file: "+p_path);
+ f->get_buffer((uint8_t *) &h.tag, sizeof(h.tag));
+ if(strncmp(h.tag, "PKM 10", sizeof(h.tag)))
+ ERR_FAIL_V(RES());
+
+ h.format = f->get_16();
+ h.texWidth = f->get_16();
+ h.texHeight = f->get_16();
+ h.origWidth = f->get_16();
+ h.origHeight = f->get_16();
+
+ DVector<uint8_t> src_data;
+
+ uint32_t size = h.texWidth * h.texHeight / 2;
+ src_data.resize(size);
+ DVector<uint8_t>::Write wb = src_data.write();
+ f->get_buffer(wb.ptr(),size);
+ wb=DVector<uint8_t>::Write();
+
+ int mipmaps = h.format;
+ int width = h.origWidth;
+ int height = h.origHeight;
+
+ Image img(width,height,mipmaps,Image::FORMAT_ETC,src_data);
+
+ Ref<ImageTexture> texture = memnew( ImageTexture );
+ texture->create_from_image(img);
+
+ if (r_error)
+ *r_error=OK;
+
+ return texture;
+}
+
+void ResourceFormatPKM::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("pkm");
+}
+
+bool ResourceFormatPKM::handles_type(const String& p_type) const {
+
+ return ObjectTypeDB::is_type(p_type,"Texture");
+}
+
+String ResourceFormatPKM::get_resource_type(const String &p_path) const {
+
+ if (p_path.extension().to_lower()=="pkm")
+ return "ImageTexture";
+ return "";
+}
diff --git a/modules/etc1/texture_loader_pkm.h b/modules/etc1/texture_loader_pkm.h
new file mode 100644
index 0000000000..5788716d9f
--- /dev/null
+++ b/modules/etc1/texture_loader_pkm.h
@@ -0,0 +1,18 @@
+#ifndef TEXTURE_LOADER_PKM_H
+#define TEXTURE_LOADER_PKM_H
+
+#include "scene/resources/texture.h"
+#include "io/resource_loader.h"
+
+class ResourceFormatPKM : public ResourceFormatLoader{
+public:
+
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String& p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+
+ virtual ~ResourceFormatPKM() {}
+};
+
+#endif // TEXTURE_LOADER_PKM_H
diff --git a/modules/pbm/SCsub b/modules/pbm/SCsub
new file mode 100644
index 0000000000..bcea3a84c0
--- /dev/null
+++ b/modules/pbm/SCsub
@@ -0,0 +1,7 @@
+Import('env')
+Import('env_modules')
+
+env_modules.add_source_files(env.modules_sources, "*.cpp")
+
+Export('env_modules')
+Export('env')
diff --git a/modules/pbm/bitmap_loader_pbm.cpp b/modules/pbm/bitmap_loader_pbm.cpp
new file mode 100644
index 0000000000..1d08b10824
--- /dev/null
+++ b/modules/pbm/bitmap_loader_pbm.cpp
@@ -0,0 +1,252 @@
+/*************************************************************************/
+/* bitmap_loader_pbm.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "bitmap_loader_pbm.h"
+#include "os/file_access.h"
+#include "scene/resources/bit_mask.h"
+
+
+static bool _get_token(FileAccessRef& f,uint8_t &saved,DVector<uint8_t>& r_token,bool p_binary=false,bool p_single_chunk=false) {
+
+
+ int token_max = r_token.size();
+ DVector<uint8_t>::Write w;
+ if (token_max)
+ w=r_token.write();
+ int ofs=0;
+ bool lf=false;
+
+
+ while(true) {
+
+ uint8_t b;
+ if (saved) {
+ b=saved;
+ saved=0;
+ } else {
+ b = f->get_8();
+ }
+ if (f->eof_reached()) {
+ if (ofs) {
+ w=DVector<uint8_t>::Write();
+ r_token.resize(ofs);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ if (!ofs && !p_binary && b=='#') {
+ //skip comment
+ while(b!='\n') {
+ if (f->eof_reached()) {
+ return false;
+ }
+
+ b = f->get_8();
+ }
+
+ lf=true;
+
+ } else if (b<=32 && !(p_binary && (ofs || lf))) {
+
+ if (b=='\n') {
+ lf=true;
+ }
+
+
+ if (ofs && !p_single_chunk) {
+ w=DVector<uint8_t>::Write();
+ r_token.resize(ofs);
+ saved=b;
+
+ return true;
+ }
+ } else {
+
+ bool resized=false;
+ while (ofs>=token_max) {
+ if (token_max)
+ token_max<<=1;
+ else
+ token_max=1;
+ resized=true;
+ }
+ if (resized) {
+ w=DVector<uint8_t>::Write();
+ r_token.resize(token_max);
+ w=r_token.write();
+ }
+ w[ofs++]=b;
+ }
+ }
+
+ return false;
+}
+
+static int _get_number_from_token(DVector<uint8_t>& r_token) {
+
+ int len = r_token.size();
+ DVector<uint8_t>::Read r = r_token.read();
+ return String::to_int((const char*)r.ptr(),len);
+
+}
+
+
+RES ResourceFormatPBM::load(const String &p_path,const String& p_original_path,Error *r_error) {
+
+#define _RETURN(m_err)\
+{\
+ if (r_error)\
+ *r_error=m_err;\
+ ERR_FAIL_V(RES());\
+}
+
+
+ FileAccessRef f=FileAccess::open(p_path,FileAccess::READ);
+ uint8_t saved=0;
+ if (!f)
+ _RETURN(ERR_CANT_OPEN);
+
+ DVector<uint8_t> token;
+
+ if (!_get_token(f,saved,token)) {
+ _RETURN(ERR_PARSE_ERROR);
+ }
+
+ if (token.size()!=2) {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+ if (token[0]!='P') {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+ if (token[1]!='1' && token[1]!='4') {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+
+ bool bits = token[1]=='4';
+
+ if (!_get_token(f,saved,token)) {
+ _RETURN(ERR_PARSE_ERROR);
+ }
+
+ int width = _get_number_from_token(token);
+ if (width<=0) {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+
+
+ if (!_get_token(f,saved,token)) {
+ _RETURN(ERR_PARSE_ERROR);
+ }
+
+ int height = _get_number_from_token(token);
+ if (height<=0) {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+
+
+ Ref<BitMap> bm;
+ bm.instance();
+ bm->create(Size2i(width,height));
+
+ if (!bits) {
+
+ int required_bytes = width*height;
+ if (!_get_token(f,saved,token,false,true)) {
+ _RETURN(ERR_PARSE_ERROR);
+ }
+
+ if (token.size()<required_bytes) {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+
+ DVector<uint8_t>::Read r=token.read();
+
+ for(int i=0;i<height;i++) {
+ for(int j=0;j<width;j++) {
+
+
+ char num = r[i*width+j];
+ bm->set_bit(Point2i(j,i),num=='0');
+ }
+
+ }
+
+
+
+ } else {
+ //a single, entire token of bits!
+ if (!_get_token(f,saved,token,true)) {
+ _RETURN(ERR_PARSE_ERROR);
+ }
+ int required_bytes = Math::ceil((width*height)/8.0);
+ if (token.size()<required_bytes) {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+
+ DVector<uint8_t>::Read r=token.read();
+ int bitwidth = width;
+ if (bitwidth % 8)
+ bitwidth+=8-(bitwidth%8);
+
+ for(int i=0;i<height;i++) {
+ for(int j=0;j<width;j++) {
+
+ int ofs = bitwidth*i+j;
+
+ uint8_t byte = r[ofs/8];
+ bool bit = (byte>>(7-(ofs%8)))&1;
+
+ bm->set_bit(Point2i(j,i),!bit);
+
+ }
+
+ }
+
+ }
+
+ return bm;
+
+
+}
+
+void ResourceFormatPBM::get_recognized_extensions(List<String> *p_extensions) const {
+ p_extensions->push_back("pbm");
+}
+bool ResourceFormatPBM::handles_type(const String& p_type) const {
+ return p_type=="BitMap";
+}
+String ResourceFormatPBM::get_resource_type(const String &p_path) const {
+
+ if (p_path.extension().to_lower()=="pbm")
+ return "BitMap";
+ return "";
+}
+
+
diff --git a/modules/pbm/bitmap_loader_pbm.h b/modules/pbm/bitmap_loader_pbm.h
new file mode 100644
index 0000000000..4f7144b3e0
--- /dev/null
+++ b/modules/pbm/bitmap_loader_pbm.h
@@ -0,0 +1,50 @@
+/*************************************************************************/
+/* bitmap_loader_pbm.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef BITMAP_LOADER_PBM_H
+#define BITMAP_LOADER_PBM_H
+
+#include "io/resource_loader.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class ResourceFormatPBM : public ResourceFormatLoader {
+
+
+public:
+
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String& p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
+
+
+#endif
diff --git a/modules/pbm/config.py b/modules/pbm/config.py
new file mode 100644
index 0000000000..368e97e152
--- /dev/null
+++ b/modules/pbm/config.py
@@ -0,0 +1,6 @@
+
+def can_build(platform):
+ return True
+
+def configure(env):
+ pass
diff --git a/modules/pbm/register_types.cpp b/modules/pbm/register_types.cpp
new file mode 100644
index 0000000000..181083773a
--- /dev/null
+++ b/modules/pbm/register_types.cpp
@@ -0,0 +1,44 @@
+/*************************************************************************/
+/* register_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "register_types.h"
+
+#include "bitmap_loader_pbm.h"
+
+static ResourceFormatPBM * pbm_loader = NULL;
+
+void register_pbm_types() {
+
+ pbm_loader = memnew( ResourceFormatPBM );
+ ResourceLoader::add_resource_format_loader(pbm_loader);
+}
+
+void unregister_pbm_types() {
+
+ memdelete( pbm_loader );
+}
diff --git a/modules/pbm/register_types.h b/modules/pbm/register_types.h
new file mode 100644
index 0000000000..20c8133c2c
--- /dev/null
+++ b/modules/pbm/register_types.h
@@ -0,0 +1,30 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+void register_pbm_types();
+void unregister_pbm_types();
diff --git a/modules/pvr/SCsub b/modules/pvr/SCsub
new file mode 100644
index 0000000000..b169695018
--- /dev/null
+++ b/modules/pvr/SCsub
@@ -0,0 +1,23 @@
+Import('env')
+Import('env_modules')
+
+# Thirdparty source files
+# Not unbundled so far since not widespread as shared library
+thirdparty_dir = "#thirdparty/pvrtccompressor/"
+thirdparty_pvr_sources = [
+ "BitScale.cpp",
+ "MortonTable.cpp",
+ "PvrTcDecoder.cpp",
+ "PvrTcEncoder.cpp",
+ "PvrTcPacket.cpp",
+]
+thirdparty_pvr_sources = [thirdparty_dir + file for file in thirdparty_pvr_sources]
+
+env_modules.add_source_files(env.modules_sources, thirdparty_pvr_sources)
+env_modules.Append(CPPPATH = [thirdparty_dir])
+
+# Godot source files
+env_modules.add_source_files(env.modules_sources, "*.cpp")
+
+Export('env_modules')
+Export('env')
diff --git a/modules/pvr/config.py b/modules/pvr/config.py
new file mode 100644
index 0000000000..368e97e152
--- /dev/null
+++ b/modules/pvr/config.py
@@ -0,0 +1,6 @@
+
+def can_build(platform):
+ return True
+
+def configure(env):
+ pass
diff --git a/modules/pvr/register_types.cpp b/modules/pvr/register_types.cpp
new file mode 100644
index 0000000000..e5e18fb3d1
--- /dev/null
+++ b/modules/pvr/register_types.cpp
@@ -0,0 +1,44 @@
+/*************************************************************************/
+/* register_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "register_types.h"
+
+#include "texture_loader_pvr.h"
+
+static ResourceFormatPVR *resource_loader_pvr = NULL;
+
+void register_pvr_types() {
+
+ resource_loader_pvr = memnew( ResourceFormatPVR );
+ ResourceLoader::add_resource_format_loader(resource_loader_pvr);
+}
+
+void unregister_pvr_types() {
+
+ memdelete(resource_loader_pvr);
+}
diff --git a/modules/pvr/register_types.h b/modules/pvr/register_types.h
new file mode 100644
index 0000000000..d600f54d51
--- /dev/null
+++ b/modules/pvr/register_types.h
@@ -0,0 +1,30 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+void register_pvr_types();
+void unregister_pvr_types();
diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp
new file mode 100644
index 0000000000..3ab3240512
--- /dev/null
+++ b/modules/pvr/texture_loader_pvr.cpp
@@ -0,0 +1,711 @@
+/*************************************************************************/
+/* texture_loader_pvr.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "texture_loader_pvr.h"
+#include "os/file_access.h"
+#include <string.h>
+#include "PvrTcEncoder.h"
+#include "RgbaBitmap.h"
+
+static void _pvrtc_decompress(Image* p_img);
+
+enum PVRFLags {
+
+ PVR_HAS_MIPMAPS=0x00000100,
+ PVR_TWIDDLED=0x00000200,
+ PVR_NORMAL_MAP=0x00000400,
+ PVR_BORDER=0x00000800,
+ PVR_CUBE_MAP=0x00001000,
+ PVR_FALSE_MIPMAPS=0x00002000,
+ PVR_VOLUME_TEXTURES=0x00004000,
+ PVR_HAS_ALPHA=0x00008000,
+ PVR_VFLIP=0x00010000
+
+};
+
+
+
+RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path,Error *r_error) {
+
+ if (r_error)
+ *r_error=ERR_CANT_OPEN;
+
+ Error err;
+ FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
+ if (!f)
+ return RES();
+
+ FileAccessRef faref(f);
+
+ ERR_FAIL_COND_V(err,RES());
+
+ if (r_error)
+ *r_error=ERR_FILE_CORRUPT;
+
+ uint32_t hsize = f->get_32();
+
+ ERR_FAIL_COND_V(hsize!=52,RES());
+ uint32_t height = f->get_32();
+ uint32_t width = f->get_32();
+ uint32_t mipmaps = f->get_32();
+ uint32_t flags = f->get_32();
+ uint32_t surfsize = f->get_32();
+ uint32_t bpp = f->get_32();
+ uint32_t rmask = f->get_32();
+ uint32_t gmask = f->get_32();
+ uint32_t bmask = f->get_32();
+ uint32_t amask = f->get_32();
+ uint8_t pvrid[5]={0,0,0,0,0};
+ f->get_buffer(pvrid,4);
+ ERR_FAIL_COND_V(String((char*)pvrid)!="PVR!",RES());
+ uint32_t surfcount = f->get_32();
+
+/*
+ print_line("height: "+itos(height));
+ print_line("width: "+itos(width));
+ print_line("mipmaps: "+itos(mipmaps));
+ print_line("flags: "+itos(flags));
+ print_line("surfsize: "+itos(surfsize));
+ print_line("bpp: "+itos(bpp));
+ print_line("rmask: "+itos(rmask));
+ print_line("gmask: "+itos(gmask));
+ print_line("bmask: "+itos(bmask));
+ print_line("amask: "+itos(amask));
+ print_line("surfcount: "+itos(surfcount));
+*/
+
+ DVector<uint8_t> data;
+ data.resize(surfsize);
+
+ ERR_FAIL_COND_V(data.size()==0,RES());
+
+
+ DVector<uint8_t>::Write w = data.write();
+ f->get_buffer(&w[0],surfsize);
+ err = f->get_error();
+ ERR_FAIL_COND_V(err!=OK,RES());
+
+ Image::Format format=Image::FORMAT_MAX;
+
+
+ switch(flags&0xFF) {
+
+ case 0x18:
+ case 0xC: format=(flags&PVR_HAS_ALPHA)?Image::FORMAT_PVRTC2_ALPHA:Image::FORMAT_PVRTC2; break;
+ case 0x19:
+ case 0xD: format=(flags&PVR_HAS_ALPHA)?Image::FORMAT_PVRTC4_ALPHA:Image::FORMAT_PVRTC4; break;
+ case 0x16:
+ format=Image::FORMAT_GRAYSCALE; break;
+ case 0x17:
+ format=Image::FORMAT_GRAYSCALE_ALPHA; break;
+ case 0x20:
+ case 0x80:
+ case 0x81:
+ format=Image::FORMAT_BC1; break;
+ case 0x21:
+ case 0x22:
+ case 0x82:
+ case 0x83:
+ format=Image::FORMAT_BC2; break;
+ case 0x23:
+ case 0x24:
+ case 0x84:
+ case 0x85:
+ format=Image::FORMAT_BC3; break;
+ case 0x4:
+ case 0x15:
+ format=Image::FORMAT_RGB; break;
+ case 0x5:
+ case 0x12:
+ format=Image::FORMAT_RGBA; break;
+ case 0x36:
+ format=Image::FORMAT_ETC; break;
+ default:
+ ERR_EXPLAIN("Unsupported format in PVR texture: "+itos(flags&0xFF));
+ ERR_FAIL_V(RES());
+
+ }
+
+ w = DVector<uint8_t>::Write();
+
+ int tex_flags=Texture::FLAG_FILTER|Texture::FLAG_REPEAT;
+
+ if (mipmaps)
+ tex_flags|=Texture::FLAG_MIPMAPS;
+
+
+ print_line("flip: "+itos(flags&PVR_VFLIP));
+
+ Image image(width,height,mipmaps,format,data);
+ ERR_FAIL_COND_V(image.empty(),RES());
+
+ Ref<ImageTexture> texture = memnew( ImageTexture );
+ texture->create_from_image(image,tex_flags);
+
+ if (r_error)
+ *r_error=OK;
+
+ return texture;
+
+}
+
+void ResourceFormatPVR::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("pvr");
+}
+bool ResourceFormatPVR::handles_type(const String& p_type) const {
+
+ return ObjectTypeDB::is_type(p_type,"Texture");
+}
+String ResourceFormatPVR::get_resource_type(const String &p_path) const {
+
+
+ if (p_path.extension().to_lower()=="pvr")
+ return "Texture";
+ return "";
+}
+
+
+
+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;
+
+}
+
+/////////////////////////////////////////////////////////
+
+//PVRTC decompressor, Based on PVRTC decompressor by IMGTEC.
+
+/////////////////////////////////////////////////////////
+
+
+#define PT_INDEX 2
+#define BLK_Y_SIZE 4
+#define BLK_X_MAX 8
+#define BLK_X_2BPP 8
+#define BLK_X_4BPP 4
+
+#define WRAP_COORD(Val, Size) ((Val) & ((Size)-1))
+
+/*
+ Define an expression to either wrap or clamp large or small vals to the
+ legal coordinate range
+*/
+#define LIMIT_COORD(Val, Size, p_tiled) \
+ ((p_tiled)? WRAP_COORD((Val), (Size)): CLAMP((Val), 0, (Size)-1))
+
+
+struct PVRTCBlock {
+ //blocks are 64 bits
+ uint32_t data[2];
+};
+
+
+
+_FORCE_INLINE_ bool is_po2( uint32_t p_input ) {
+
+ if( p_input==0 )
+ return 0;
+ uint32_t minus1=p_input- 1;
+ return ((p_input|minus1)==(p_input^minus1))?1:0;
+}
+
+
+static void unpack_5554(const PVRTCBlock *p_block, int p_ab_colors[2][4]) {
+
+ uint32_t raw_bits[2];
+ raw_bits[0] = p_block->data[1] & (0xFFFE);
+ raw_bits[1] = p_block->data[1] >> 16;
+
+ for(int i=0;i<2;i++) {
+
+ if(raw_bits[i] & (1<<15)) {
+
+ p_ab_colors[i][0]= (raw_bits[i] >> 10) & 0x1F;
+ p_ab_colors[i][1]= (raw_bits[i] >> 5) & 0x1F;
+ p_ab_colors[i][2]= raw_bits[i] & 0x1F;
+ if(i==0)
+ p_ab_colors[0][2]|= p_ab_colors[0][2] >> 4;
+ p_ab_colors[i][3] = 0xF;
+ } else {
+
+ p_ab_colors[i][0] = (raw_bits[i] >> (8-1)) & 0x1E;
+ p_ab_colors[i][1] = (raw_bits[i] >> (4-1)) & 0x1E;
+
+ p_ab_colors[i][0] |= p_ab_colors[i][0] >> 4;
+ p_ab_colors[i][1] |= p_ab_colors[i][1] >> 4;
+
+ p_ab_colors[i][2] = (raw_bits[i] & 0xF) << 1;
+
+ if(i==0)
+ p_ab_colors[0][2] |= p_ab_colors[0][2] >> 3;
+ else
+ p_ab_colors[0][2] |= p_ab_colors[0][2] >> 4;
+
+ p_ab_colors[i][3] = (raw_bits[i] >> 11) & 0xE;
+ }
+ }
+}
+
+
+static void unpack_modulations(const PVRTCBlock *p_block, const int p_2bit, int p_modulation[8][16], int p_modulation_modes[8][16], int p_x, int p_y) {
+
+ int block_mod_mode = p_block->data[1] & 1;
+ uint32_t modulation_bits = p_block->data[0];
+
+ if(p_2bit && block_mod_mode) {
+
+ for(int y = 0; y < BLK_Y_SIZE; y++) {
+ for(int x = 0; x < BLK_X_2BPP; x++) {
+
+ p_modulation_modes[y+p_y][x+p_x] = block_mod_mode;
+
+ if(((x^y)&1) == 0) {
+ p_modulation[y+p_y][x+p_x] = modulation_bits & 3;
+ modulation_bits >>= 2;
+ }
+ }
+ }
+
+ } else if(p_2bit) {
+
+ for(int y = 0; y < BLK_Y_SIZE; y++) {
+ for(int x = 0; x < BLK_X_2BPP; x++) {
+ p_modulation_modes[y+p_y][x+p_x] = block_mod_mode;
+
+ if(modulation_bits & 1)
+ p_modulation[y+p_y][x+p_x] = 0x3;
+ else
+ p_modulation[y+p_y][x+p_x] = 0x0;
+
+ modulation_bits >>= 1;
+ }
+ }
+ } else {
+ for(int y = 0; y < BLK_Y_SIZE; y++) {
+ for(int x = 0; x < BLK_X_4BPP; x++) {
+ p_modulation_modes[y+p_y][x+p_x] = block_mod_mode;
+ p_modulation[y+p_y][x+p_x] = modulation_bits & 3;
+ modulation_bits >>= 2;
+ }
+ }
+ }
+
+ ERR_FAIL_COND(modulation_bits!=0);
+}
+
+
+
+static void interpolate_colors(const int p_colorp[4], const int p_colorq[4], const int p_colorr[4], const int p_colors[4], bool p_2bit, const int x, const int y, int r_result[4]) {
+ int u, v, uscale;
+ int k;
+
+ int tmp1, tmp2;
+
+ int P[4], Q[4], R[4], S[4];
+
+ for(k = 0; k < 4; k++) {
+ P[k] = p_colorp[k];
+ Q[k] = p_colorq[k];
+ R[k] = p_colorr[k];
+ S[k] = p_colors[k];
+ }
+
+ v = (y & 0x3) | ((~y & 0x2) << 1);
+
+ if(p_2bit)
+ u = (x & 0x7) | ((~x & 0x4) << 1);
+ else
+ u = (x & 0x3) | ((~x & 0x2) << 1);
+
+ v = v - BLK_Y_SIZE/2;
+
+ if(p_2bit) {
+ u = u - BLK_X_2BPP/2;
+ uscale = 8;
+ } else {
+ u = u - BLK_X_4BPP/2;
+ uscale = 4;
+ }
+
+ for(k = 0; k < 4; k++) {
+ tmp1 = P[k] * uscale + u * (Q[k] - P[k]);
+ tmp2 = R[k] * uscale + u * (S[k] - R[k]);
+
+ tmp1 = tmp1 * 4 + v * (tmp2 - tmp1);
+
+ r_result[k] = tmp1;
+ }
+
+ if(p_2bit) {
+ for(k = 0; k < 3; k++) {
+ r_result[k] >>= 2;
+ }
+
+ r_result[3] >>= 1;
+ } else {
+ for(k = 0; k < 3; k++) {
+ r_result[k] >>= 1;
+ }
+ }
+
+ for(k = 0; k < 4; k++) {
+ ERR_FAIL_COND(r_result[k] >= 256);
+ }
+
+
+ for(k = 0; k < 3; k++) {
+ r_result[k] += r_result[k] >> 5;
+ }
+
+ r_result[3] += r_result[3] >> 4;
+
+ for(k = 0; k < 4; k++) {
+ ERR_FAIL_COND(r_result[k] >= 256);
+ }
+
+}
+
+
+static void get_modulation_value(int x, int y, const int p_2bit, const int p_modulation[8][16], const int p_modulation_modes[8][16], int *r_mod, int *p_dopt)
+{
+ static const int rep_vals0[4] = {0, 3, 5, 8};
+ static const int rep_vals1[4] = {0, 4, 4, 8};
+
+ int mod_val;
+
+ y = (y & 0x3) | ((~y & 0x2) << 1);
+
+ if(p_2bit)
+ x = (x & 0x7) | ((~x & 0x4) << 1);
+ else
+ x = (x & 0x3) | ((~x & 0x2) << 1);
+
+ *p_dopt = 0;
+
+ if(p_modulation_modes[y][x]==0) {
+ mod_val = rep_vals0[p_modulation[y][x]];
+ } else if(p_2bit) {
+ if(((x^y)&1)==0)
+ mod_val = rep_vals0[p_modulation[y][x]];
+ else if(p_modulation_modes[y][x] == 1) {
+ mod_val = (rep_vals0[p_modulation[y-1][x]] +
+ rep_vals0[p_modulation[y+1][x]] +
+ rep_vals0[p_modulation[y][x-1]] +
+ rep_vals0[p_modulation[y][x+1]] + 2) / 4;
+ } else if(p_modulation_modes[y][x] == 2) {
+ mod_val = (rep_vals0[p_modulation[y][x-1]] +
+ rep_vals0[p_modulation[y][x+1]] + 1) / 2;
+ } else {
+ mod_val = (rep_vals0[p_modulation[y-1][x]] +
+ rep_vals0[p_modulation[y+1][x]] + 1) / 2;
+ }
+ } else {
+ mod_val = rep_vals1[p_modulation[y][x]];
+
+ *p_dopt = p_modulation[y][x] == PT_INDEX;
+ }
+
+ *r_mod =mod_val;
+}
+
+
+static int disable_twiddling = 0;
+
+static uint32_t twiddle_uv(uint32_t p_height, uint32_t p_width, uint32_t p_y, uint32_t p_x) {
+
+ uint32_t twiddled;
+
+ uint32_t min_dimension;
+ uint32_t max_value;
+
+ uint32_t scr_bit_pos;
+ uint32_t dst_bit_pos;
+
+ int shift_count;
+
+ ERR_FAIL_COND_V(p_y >= p_height,0);
+ ERR_FAIL_COND_V(p_x >= p_width,0);
+
+ ERR_FAIL_COND_V(!is_po2(p_height),0);
+ ERR_FAIL_COND_V(!is_po2(p_width),0);
+
+ if(p_height < p_width) {
+ min_dimension = p_height;
+ max_value = p_x;
+ } else {
+ min_dimension = p_width;
+ max_value = p_y;
+ }
+
+ if(disable_twiddling)
+ return (p_y* p_width + p_x);
+
+ scr_bit_pos = 1;
+ dst_bit_pos = 1;
+ twiddled = 0;
+ shift_count = 0;
+
+ while(scr_bit_pos < min_dimension) {
+ if(p_y & scr_bit_pos) {
+ twiddled |= dst_bit_pos;
+ }
+
+ if(p_x & scr_bit_pos) {
+ twiddled |= (dst_bit_pos << 1);
+ }
+
+ scr_bit_pos <<= 1;
+ dst_bit_pos <<= 2;
+ shift_count += 1;
+
+ }
+
+ max_value >>= shift_count;
+
+ twiddled |= (max_value << (2*shift_count));
+
+ return twiddled;
+}
+
+static void decompress_pvrtc(PVRTCBlock *p_comp_img, const int p_2bit, const int p_width, const int p_height, const int p_tiled, unsigned char* p_dst) {
+ int x, y;
+ int i, j;
+
+ int block_x, blk_y;
+ int block_xp1, blk_yp1;
+ int x_block_size;
+ int block_width, block_height;
+
+ int p_x, p_y;
+
+ int p_modulation[8][16];
+ int p_modulation_modes[8][16];
+
+ int Mod, DoPT;
+
+ unsigned int u_pos;
+
+ // local neighbourhood of blocks
+ PVRTCBlock *p_blocks[2][2];
+
+ PVRTCBlock *prev[2][2] = {{NULL, NULL}, {NULL, NULL}};
+
+ struct
+ {
+ int Reps[2][4];
+ }colors5554[2][2];
+
+
+ int ASig[4], BSig[4];
+
+ int r_result[4];
+
+ if(p_2bit)
+ x_block_size = BLK_X_2BPP;
+ else
+ x_block_size = BLK_X_4BPP;
+
+
+ block_width = MAX(2, p_width / x_block_size);
+ block_height = MAX(2, p_height / BLK_Y_SIZE);
+
+ for(y = 0; y < p_height; y++)
+ {
+ for(x = 0; x < p_width; x++)
+ {
+
+ block_x = (x - x_block_size/2);
+ blk_y = (y - BLK_Y_SIZE/2);
+
+ block_x = LIMIT_COORD(block_x, p_width, p_tiled);
+ blk_y = LIMIT_COORD(blk_y, p_height, p_tiled);
+
+
+ block_x /= x_block_size;
+ blk_y /= BLK_Y_SIZE;
+
+ block_xp1 = LIMIT_COORD(block_x+1, block_width, p_tiled);
+ blk_yp1 = LIMIT_COORD(blk_y+1, block_height, p_tiled);
+
+ p_blocks[0][0] = p_comp_img +twiddle_uv(block_height, block_width, blk_y, block_x);
+ p_blocks[0][1] = p_comp_img +twiddle_uv(block_height, block_width, blk_y, block_xp1);
+ p_blocks[1][0] = p_comp_img +twiddle_uv(block_height, block_width, blk_yp1, block_x);
+ p_blocks[1][1] = p_comp_img +twiddle_uv(block_height, block_width, blk_yp1, block_xp1);
+
+ if(memcmp(prev, p_blocks, 4*sizeof(void*)) != 0) {
+ p_y = 0;
+ for(i = 0; i < 2; i++) {
+ p_x = 0;
+ for(j = 0; j < 2; j++) {
+ unpack_5554(p_blocks[i][j], colors5554[i][j].Reps);
+
+ unpack_modulations(p_blocks[i][j],
+ p_2bit,
+ p_modulation,
+ p_modulation_modes,
+ p_x, p_y);
+
+ p_x += x_block_size;
+ }
+
+ p_y += BLK_Y_SIZE;
+ }
+
+
+ memcpy(prev, p_blocks, 4*sizeof(void*));
+ }
+
+
+ interpolate_colors(colors5554[0][0].Reps[0],
+ colors5554[0][1].Reps[0],
+ colors5554[1][0].Reps[0],
+ colors5554[1][1].Reps[0],
+ p_2bit, x, y,
+ ASig);
+
+ interpolate_colors(colors5554[0][0].Reps[1],
+ colors5554[0][1].Reps[1],
+ colors5554[1][0].Reps[1],
+ colors5554[1][1].Reps[1],
+ p_2bit, x, y,
+ BSig);
+
+ get_modulation_value(x,y, p_2bit, (const int (*)[16])p_modulation, (const int (*)[16])p_modulation_modes,
+ &Mod, &DoPT);
+
+ for(i = 0; i < 4; i++) {
+ r_result[i] = ASig[i] * 8 + Mod * (BSig[i] - ASig[i]);
+ r_result[i] >>= 3;
+ }
+
+ if(DoPT)
+ r_result[3] = 0;
+
+
+ u_pos = (x+y*p_width)<<2;
+ p_dst[u_pos+0] = (uint8_t)r_result[0];
+ p_dst[u_pos+1] = (uint8_t)r_result[1];
+ p_dst[u_pos+2] = (uint8_t)r_result[2];
+ p_dst[u_pos+3] = (uint8_t)r_result[3];
+ }
+ }
+}
+
+static void _pvrtc_decompress(Image* p_img) {
+
+// static void decompress_pvrtc(const void *p_comp_img, const int p_2bit, const int p_width, const int p_height, unsigned char* p_dst) {
+// decompress_pvrtc((PVRTCBlock*)p_comp_img,p_2bit,p_width,p_height,1,p_dst);
+// }
+
+ ERR_FAIL_COND( p_img->get_format()!=Image::FORMAT_PVRTC2 && p_img->get_format()!=Image::FORMAT_PVRTC2_ALPHA && p_img->get_format()!=Image::FORMAT_PVRTC4 && p_img->get_format()!=Image::FORMAT_PVRTC4_ALPHA);
+
+ bool _2bit = (p_img->get_format()==Image::FORMAT_PVRTC2 || p_img->get_format()==Image::FORMAT_PVRTC2_ALPHA );
+
+ DVector<uint8_t> data = p_img->get_data();
+ DVector<uint8_t>::Read r = data.read();
+
+
+ DVector<uint8_t> newdata;
+ newdata.resize( p_img->get_width() * p_img->get_height() * 4);
+ DVector<uint8_t>::Write w=newdata.write();
+
+ decompress_pvrtc((PVRTCBlock*)r.ptr(),_2bit,p_img->get_width(),p_img->get_height(),0,(unsigned char*)w.ptr());
+
+ //for(int i=0;i<newdata.size();i++) {
+ // print_line(itos(w[i]));
+ //}
+
+ w=DVector<uint8_t>::Write();
+ r=DVector<uint8_t>::Read();
+
+ bool make_mipmaps=p_img->get_mipmaps()>0;
+ Image newimg(p_img->get_width(),p_img->get_height(),0,Image::FORMAT_RGBA,newdata);
+ if (make_mipmaps)
+ newimg.generate_mipmaps();
+ *p_img=newimg;
+
+}
+
+
+
+
+
+
+
+
diff --git a/modules/pvr/texture_loader_pvr.h b/modules/pvr/texture_loader_pvr.h
new file mode 100644
index 0000000000..5efb3b2507
--- /dev/null
+++ b/modules/pvr/texture_loader_pvr.h
@@ -0,0 +1,50 @@
+/*************************************************************************/
+/* texture_loader_pvr.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef TEXTURE_LOADER_PVR_H
+#define TEXTURE_LOADER_PVR_H
+
+
+#include "scene/resources/texture.h"
+#include "io/resource_loader.h"
+
+
+class ResourceFormatPVR : public ResourceFormatLoader{
+public:
+
+ virtual RES load(const String &p_path,const String& p_original_path,Error *r_error=NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String& p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+
+ ResourceFormatPVR();
+ virtual ~ResourceFormatPVR() {}
+};
+
+
+#endif // TEXTURE_LOADER_PVR_H