summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/tests/test_gui.cpp12
-rw-r--r--core/bind/core_bind.cpp10
-rw-r--r--core/image.cpp12
-rw-r--r--core/image.h1
-rw-r--r--demos/2d/light_mask/burano.pngbin0 -> 974437 bytes
-rw-r--r--demos/2d/light_mask/engine.cfg8
-rw-r--r--demos/2d/light_mask/lightmask.scnbin0 -> 2916 bytes
-rw-r--r--demos/2d/light_mask/splat.pngbin0 -> 18255 bytes
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp59
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp8
-rw-r--r--drivers/gles2/shader_compiler_gles2.h3
-rw-r--r--drivers/gles2/shaders/canvas.glsl12
-rw-r--r--drivers/pvr/AlphaBitmap.h18
-rw-r--r--drivers/pvr/BitScale.cpp184
-rw-r--r--drivers/pvr/BitScale.h28
-rw-r--r--drivers/pvr/BitUtility.h19
-rw-r--r--drivers/pvr/Bitmap.h34
-rw-r--r--drivers/pvr/ColorRgba.h152
-rw-r--r--drivers/pvr/Interval.h21
-rw-r--r--drivers/pvr/MortonTable.cpp43
-rw-r--r--drivers/pvr/MortonTable.h18
-rw-r--r--drivers/pvr/Point2.h17
-rw-r--r--drivers/pvr/PvrTcDecoder.cpp144
-rw-r--r--drivers/pvr/PvrTcDecoder.h25
-rw-r--r--drivers/pvr/PvrTcEncoder.cpp474
-rw-r--r--drivers/pvr/PvrTcEncoder.h40
-rw-r--r--drivers/pvr/PvrTcPacket.cpp209
-rw-r--r--drivers/pvr/PvrTcPacket.h65
-rw-r--r--drivers/pvr/RgbBitmap.h23
-rw-r--r--drivers/pvr/RgbaBitmap.h23
-rw-r--r--drivers/pvr/SCsub6
-rw-r--r--drivers/pvr/texture_loader_pvr.cpp51
-rw-r--r--modules/gdscript/gd_functions.cpp2
-rw-r--r--platform/android/java/src/com/android/godot/Godot.java21
-rw-r--r--scene/2d/canvas_item.cpp33
-rw-r--r--scene/2d/canvas_item.h15
-rw-r--r--scene/2d/light_2d.cpp42
-rw-r--r--scene/2d/light_2d.h18
-rw-r--r--scene/main/viewport.cpp2
-rw-r--r--scene/scene_string_names.cpp1
-rw-r--r--scene/scene_string_names.h1
-rw-r--r--servers/visual/rasterizer.h10
-rw-r--r--servers/visual/shader_language.cpp2
-rw-r--r--servers/visual/visual_server_raster.cpp17
-rw-r--r--servers/visual/visual_server_raster.h8
-rw-r--r--servers/visual/visual_server_wrap_mt.h7
-rw-r--r--servers/visual_server.h19
-rw-r--r--tools/editor/pvrtc_compress.cpp28
48 files changed, 1858 insertions, 87 deletions
diff --git a/bin/tests/test_gui.cpp b/bin/tests/test_gui.cpp
index 17a6a4111c..70cff12c44 100644
--- a/bin/tests/test_gui.cpp
+++ b/bin/tests/test_gui.cpp
@@ -132,7 +132,7 @@ public:
frame->add_child( button );
-#if 0
+
Sprite *tf = memnew( Sprite );
frame->add_child(tf);
Image img;
@@ -140,14 +140,14 @@ public:
img.resize(512,512);
img.generate_mipmaps();
- img.compress();
- Ref<Texture> text = memnew( Texture );
- text->create_from_image(img);
- tf->set_texture(text);
+ img.compress(Image::COMPRESS_PVRTC4);
+ Ref<ImageTexture> tt = memnew( ImageTexture );
+ tt->create_from_image(img);
+ tf->set_texture(tt);
tf->set_pos(Point2(50,50));
//tf->set_scale(Point2(0.3,0.3));
-
+#if 0
return;
#endif
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 5839467388..439855fbb7 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -709,13 +709,13 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_screen_count"),&_OS::get_screen_count);
ObjectTypeDB::bind_method(_MD("get_current_screen"),&_OS::get_current_screen);
- ObjectTypeDB::bind_method(_MD("set_current_screen"),&_OS::set_current_screen);
- ObjectTypeDB::bind_method(_MD("get_screen_position"),&_OS::get_screen_position,DEFVAL(0));
- ObjectTypeDB::bind_method(_MD("get_screen_size"),&_OS::get_screen_size,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("set_current_screen","screen"),&_OS::set_current_screen);
+ ObjectTypeDB::bind_method(_MD("get_screen_position","screen"),&_OS::get_screen_position,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("get_screen_size","screen"),&_OS::get_screen_size,DEFVAL(0));
ObjectTypeDB::bind_method(_MD("get_window_position"),&_OS::get_window_position);
- ObjectTypeDB::bind_method(_MD("set_window_position"),&_OS::set_window_position);
+ ObjectTypeDB::bind_method(_MD("set_window_position","position"),&_OS::set_window_position);
ObjectTypeDB::bind_method(_MD("get_window_size"),&_OS::get_window_size);
- ObjectTypeDB::bind_method(_MD("set_window_size"),&_OS::set_window_size);
+ ObjectTypeDB::bind_method(_MD("set_window_size","size"),&_OS::set_window_size);
ObjectTypeDB::bind_method(_MD("set_window_fullscreen","enabled"),&_OS::set_window_fullscreen);
ObjectTypeDB::bind_method(_MD("is_window_fullscreen"),&_OS::is_window_fullscreen);
ObjectTypeDB::bind_method(_MD("set_window_resizable","enabled"),&_OS::set_window_resizable);
diff --git a/core/image.cpp b/core/image.cpp
index 17ee569b6b..ea09787f01 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -134,6 +134,18 @@ void Image::get_mipmap_offset_and_size(int p_mipmap,int &r_ofs, int &r_size) con
}
+void Image::get_mipmap_offset_size_and_dimensions(int p_mipmap,int &r_ofs, int &r_size,int &w, int& h) const {
+
+
+ int ofs;
+ _get_mipmap_offset_and_size(p_mipmap,ofs,w,h);
+ int ofs2,w2,h2;
+ _get_mipmap_offset_and_size(p_mipmap+1,ofs2,w2,h2);
+ r_ofs=ofs;
+ r_size=ofs2-ofs;
+
+}
+
void Image::put_pixel(int p_x,int p_y, const Color& p_color,int p_mipmap){
ERR_FAIL_INDEX(p_mipmap,mipmaps+1);
diff --git a/core/image.h b/core/image.h
index f4c96703b9..8ef7a54c78 100644
--- a/core/image.h
+++ b/core/image.h
@@ -236,6 +236,7 @@ public:
int get_mipmap_offset(int p_mipmap) const; //get where the mipmap begins in data
void get_mipmap_offset_and_size(int p_mipmap,int &r_ofs, int &r_size) const; //get where the mipmap begins in data
+ void get_mipmap_offset_size_and_dimensions(int p_mipmap,int &r_ofs, int &r_size,int &w, int& h) const; //get where the mipmap begins in data
/**
* Resize the image, using the prefered interpolation method.
diff --git a/demos/2d/light_mask/burano.png b/demos/2d/light_mask/burano.png
new file mode 100644
index 0000000000..6eec09d585
--- /dev/null
+++ b/demos/2d/light_mask/burano.png
Binary files differ
diff --git a/demos/2d/light_mask/engine.cfg b/demos/2d/light_mask/engine.cfg
new file mode 100644
index 0000000000..8b0ae6f61d
--- /dev/null
+++ b/demos/2d/light_mask/engine.cfg
@@ -0,0 +1,8 @@
+[application]
+
+name="Using Lights As Mask"
+main_scene="res://lightmask.scn"
+
+[rasterizer]
+
+shadow_filter=3
diff --git a/demos/2d/light_mask/lightmask.scn b/demos/2d/light_mask/lightmask.scn
new file mode 100644
index 0000000000..08805f44c6
--- /dev/null
+++ b/demos/2d/light_mask/lightmask.scn
Binary files differ
diff --git a/demos/2d/light_mask/splat.png b/demos/2d/light_mask/splat.png
new file mode 100644
index 0000000000..8c35f068a0
--- /dev/null
+++ b/demos/2d/light_mask/splat.png
Binary files differ
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index ae5f3d8f2f..b40eccb239 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -1033,32 +1033,33 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
int mipmaps= (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && img.get_mipmaps()>0) ? img.get_mipmaps() +1 : 1;
- int w=img.get_width();
- int h=img.get_height();
+ //int w=img.get_width();
+ //int h=img.get_height();
int tsize=0;
for(int i=0;i<mipmaps;i++) {
int size,ofs;
- img.get_mipmap_offset_and_size(i,ofs,size);
+ int mm_w,mm_h;
+ img.get_mipmap_offset_size_and_dimensions(i,ofs,size,mm_w,mm_h);
if (texture->compressed) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glCompressedTexImage2D( blit_target, i, format,w,h,0,size,&read[ofs] );
+ glCompressedTexImage2D( blit_target, i, format,mm_w,mm_h,0,size,&read[ofs] );
} 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,mm_w, mm_h,format,GL_UNSIGNED_BYTE,&read[ofs] );
} else {
- glTexImage2D(blit_target, i, internal_format, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]);
+ glTexImage2D(blit_target, i, internal_format, mm_w, mm_h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]);
}
}
tsize+=size;
- w = MAX(1,w>>1);
- h = MAX(1,h>>1);
+ //w = MAX(Image::,w>>1);
+ //h = MAX(1,h>>1);
}
@@ -4611,6 +4612,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
if (fragment_flags.uses_texpixel_size) {
enablers.push_back("#define USE_TEXPIXEL_SIZE\n");
}
+ if (light_flags.uses_shadow_color) {
+ enablers.push_back("#define USE_LIGHT_SHADOW_COLOR\n");
+ }
if (vertex_flags.uses_worldvec) {
enablers.push_back("#define USE_WORLD_VEC\n");
@@ -9260,7 +9264,9 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
_canvas_item_setup_shader_uniforms(material,shader_cache);
}
- if (material && material->unshaded) {
+ bool unshaded = material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED;
+
+ if (unshaded) {
canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,Color(1,1,1,1));
reset_modulate=true;
} else if (reset_modulate) {
@@ -9317,13 +9323,15 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_opacity = ci->final_opacity;
- _canvas_item_render_commands<false>(ci,current_clip,reclip);
- if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && (!material || !material->unshaded)) {
+ if (unshaded || (p_modulate.a>0.001 && (!material || material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT)))
+ _canvas_item_render_commands<false>(ci,current_clip,reclip);
+
+ if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && !unshaded) {
CanvasLight *light = p_light;
bool light_used=false;
- bool subtract=false;
+ VS::CanvasLightMode mode=VS::CANVAS_LIGHT_MODE_ADD;
while(light) {
@@ -9332,21 +9340,28 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
//intersects this light
- if (!light_used || subtract!=light->subtract) {
+ if (!light_used || mode!=light->mode) {
- subtract=light->subtract;
+ mode=light->mode;
- if (subtract) {
+ switch(mode) {
- glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE);
-
- } else {
+ case VS::CANVAS_LIGHT_MODE_ADD: {
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
- glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ } break;
+ case VS::CANVAS_LIGHT_MODE_SUB: {
+ glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ } break;
+ case VS::CANVAS_LIGHT_MODE_MIX: {
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ } break;
}
+
}
if (!light_used) {
@@ -9384,7 +9399,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX,light->light_shader_xform);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS,light->light_shader_pos);
- canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,light->color);
+ canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,Color(light->color.r*light->energy,light->color.g*light->energy,light->color.b*light->energy,light->color.a));
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX,light->xform_cache.affine_inverse());
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index 8d378ceec1..69bd269948 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -266,6 +266,9 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
uses_normal=true;
}
+ if (vnode->name==vname_shadow) {
+ uses_shadow_color=true;
+ }
}
@@ -616,6 +619,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
uses_texpixel_size=false;
uses_worldvec=false;
vertex_code_writes_vertex=false;
+ uses_shadow_color=false;
uniforms=r_uniforms;
flags=&r_flags;
r_flags.use_color_interp=false;
@@ -651,6 +655,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
r_flags.uses_normal=uses_normal;
r_flags.uses_texpixel_size=uses_texpixel_size;
r_flags.uses_worldvec=uses_worldvec;
+ r_flags.uses_shadow_color=uses_shadow_color;
r_code_line=code;
r_globals_line=global_code;
@@ -827,7 +832,9 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
mode_replace_table[5]["LIGHT_VEC"]="light_vec";
mode_replace_table[5]["LIGHT_HEIGHT"]="light_height";
mode_replace_table[5]["LIGHT_COLOR"]="light";
+ mode_replace_table[5]["LIGHT_UV"]="light_uv";
mode_replace_table[5]["LIGHT"]="light_out";
+ mode_replace_table[5]["SHADOW"]="shadow_color";
mode_replace_table[5]["SCREEN_UV"]="screen_uv";
mode_replace_table[5]["POINT_COORD"]="gl_PointCoord";
mode_replace_table[5]["TIME"]="time";
@@ -857,5 +864,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
vname_normal="NORMAL";
vname_texpixel_size="TEXTURE_PIXEL_SIZE";
vname_world_vec="WORLD_VERTEX";
+ vname_shadow="SHADOW";
}
diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h
index 87722602fd..87016fd968 100644
--- a/drivers/gles2/shader_compiler_gles2.h
+++ b/drivers/gles2/shader_compiler_gles2.h
@@ -55,6 +55,7 @@ private:
bool uses_texpixel_size;
bool uses_worldvec;
bool vertex_code_writes_vertex;
+ bool uses_shadow_color;
Flags *flags;
StringName vname_discard;
@@ -74,6 +75,7 @@ private:
StringName vname_normal;
StringName vname_texpixel_size;
StringName vname_world_vec;
+ StringName vname_shadow;
Map<StringName,ShaderLanguage::Uniform> *uniforms;
@@ -110,6 +112,7 @@ public:
bool uses_normal;
bool uses_texpixel_size;
bool uses_worldvec;
+ bool uses_shadow_color;
};
Error compile(const String& p_code, ShaderLanguage::ShaderType p_type, String& r_code_line, String& r_globals_line, Flags& r_flags, Map<StringName,ShaderLanguage::Uniform> *r_uniforms=NULL);
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index baa7e664b5..c4f0847870 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -230,7 +230,11 @@ FRAGMENT_SHADER_CODE
float att=1.0;
- vec4 light = texture2D(light_texture,light_uv_interp.xy) * light_color;
+ vec2 light_uv = light_uv_interp.xy;
+ vec4 light = texture2D(light_texture,light_uv) * light_color;
+#if defined(USE_LIGHT_SHADOW_COLOR)
+ vec4 shadow_color=vec4(0.0,0.0,0.0,0.0);
+#endif
#if defined(USE_LIGHT_SHADER_CODE)
//light is written by the light shader
@@ -362,7 +366,11 @@ LIGHT_SHADER_CODE
#endif
- color.rgb*=shadow_attenuation;
+#if defined(USE_LIGHT_SHADOW_COLOR)
+ color=mix(shadow_color,color,shadow_attenuation);
+#else
+ color*=shadow_attenuation;
+#endif
//use shadows
#endif
}
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..6b46d65e3c
--- /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()
+ : r(0)
+ , g(0)
+ , b(0) {
+ }
+
+ ColorRgb(T red, T green, T blue)
+ : r(red)
+ , g(green)
+ , b(blue) {
+ }
+
+ ColorRgb(const ColorRgb<T> &x)
+ : r(x.r)
+ , g(x.g)
+ , b(x.b) {
+ }
+
+ 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/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp
index f37b2f645a..ce2cb14643 100644
--- a/modules/gdscript/gd_functions.cpp
+++ b/modules/gdscript/gd_functions.cpp
@@ -575,7 +575,7 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
}
//str+="\n";
- OS::get_singleton()->print("%s\n",str.utf8().get_data());
+ OS::get_singleton()->print("%s",str.utf8().get_data());
r_ret=Variant();
} break;
diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java
index 1fd37c98cd..2abb4cec53 100644
--- a/platform/android/java/src/com/android/godot/Godot.java
+++ b/platform/android/java/src/com/android/godot/Godot.java
@@ -571,9 +571,24 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
}
@Override public void onSensorChanged(SensorEvent event) {
- float x = event.values[0];
- float y = event.values[1];
- float z = event.values[2];
+ Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
+ int displayRotation = display.getRotation();
+
+ float[] adjustedValues = new float[3];
+ final int axisSwap[][] = {
+ { 1, -1, 0, 1 }, // ROTATION_0
+ {-1, -1, 1, 0 }, // ROTATION_90
+ {-1, 1, 0, 1 }, // ROTATION_180
+ { 1, 1, 1, 0 } }; // ROTATION_270
+
+ final int[] as = axisSwap[displayRotation];
+ adjustedValues[0] = (float)as[0] * event.values[ as[2] ];
+ adjustedValues[1] = (float)as[1] * event.values[ as[3] ];
+ adjustedValues[2] = event.values[2];
+
+ float x = adjustedValues[0];
+ float y = adjustedValues[1];
+ float z = adjustedValues[2];
GodotLib.accelerometer(x,y,z);
}
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index c3ff03d8f4..118ba33bc6 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -42,8 +42,8 @@ bool CanvasItemMaterial::_set(const StringName& p_name, const Variant& p_value)
if (p_name==SceneStringNames::get_singleton()->shader_shader) {
set_shader(p_value);
return true;
- } else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
- set_unshaded(p_value);
+ } else if (p_name==SceneStringNames::get_singleton()->shading_mode) {
+ set_shading_mode(ShadingMode(p_value.operator int()));
return true;
} else {
@@ -74,10 +74,10 @@ bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const {
r_ret=get_shader();
return true;
- } else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
+ } else if (p_name==SceneStringNames::get_singleton()->shading_mode) {
- r_ret=unshaded;
+ r_ret=shading_mode;
return true;
} else {
@@ -100,7 +100,7 @@ bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const {
void CanvasItemMaterial::_get_property_list( List<PropertyInfo> *p_list) const {
p_list->push_back( PropertyInfo( Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE,"CanvasItemShader,CanvasItemShaderGraph" ) );
- p_list->push_back( PropertyInfo( Variant::BOOL, "shader/unshaded") );
+ p_list->push_back( PropertyInfo( Variant::INT, "shader/shading_mode",PROPERTY_HINT_ENUM,"Normal,Unshaded,Light Only") );
if (!shader.is_null()) {
@@ -161,25 +161,30 @@ RID CanvasItemMaterial::get_rid() const {
return material;
}
-void CanvasItemMaterial::set_unshaded(bool p_unshaded) {
+void CanvasItemMaterial::set_shading_mode(ShadingMode p_mode) {
- unshaded=p_unshaded;
- VS::get_singleton()->canvas_item_material_set_unshaded(material,p_unshaded);
+ shading_mode=p_mode;
+ VS::get_singleton()->canvas_item_material_set_shading_mode(material,VS::CanvasItemShadingMode(p_mode));
}
-bool CanvasItemMaterial::is_unshaded() const{
-
- return unshaded;
+CanvasItemMaterial::ShadingMode CanvasItemMaterial::get_shading_mode() const {
+ return shading_mode;
}
+
void CanvasItemMaterial::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"),&CanvasItemMaterial::set_shader);
ObjectTypeDB::bind_method(_MD("get_shader:Shader"),&CanvasItemMaterial::get_shader);
ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItemMaterial::set_shader_param);
ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItemMaterial::get_shader_param);
- ObjectTypeDB::bind_method(_MD("set_unshaded","unshaded"),&CanvasItemMaterial::set_unshaded);
- ObjectTypeDB::bind_method(_MD("is_unshaded"),&CanvasItemMaterial::is_unshaded);
+ ObjectTypeDB::bind_method(_MD("set_shading_mode","mode"),&CanvasItemMaterial::set_shading_mode);
+ ObjectTypeDB::bind_method(_MD("get_shading_mode"),&CanvasItemMaterial::get_shading_mode);
+
+ BIND_CONSTANT( SHADING_NORMAL );
+ BIND_CONSTANT( SHADING_UNSHADED );
+ BIND_CONSTANT( SHADING_ONLY_LIGHT );
+
}
@@ -202,7 +207,7 @@ void CanvasItemMaterial::get_argument_options(const StringName& p_function,int p
CanvasItemMaterial::CanvasItemMaterial() {
material=VS::get_singleton()->canvas_item_material_create();
- unshaded=false;
+ shading_mode=SHADING_NORMAL;
}
CanvasItemMaterial::~CanvasItemMaterial(){
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index c43642a8ec..167f2b96f3 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -45,10 +45,17 @@ class CanvasItemMaterial : public Resource{
OBJ_TYPE(CanvasItemMaterial,Resource);
RID material;
Ref<Shader> shader;
- bool unshaded;
+public:
+ enum ShadingMode {
+ SHADING_NORMAL,
+ SHADING_UNSHADED,
+ SHADING_ONLY_LIGHT,
+ };
protected:
+ ShadingMode shading_mode;
+
bool _set(const StringName& p_name, const Variant& p_value);
bool _get(const StringName& p_name,Variant &r_ret) const;
void _get_property_list( List<PropertyInfo> *p_list) const;
@@ -66,14 +73,16 @@ public:
void set_shader_param(const StringName& p_param,const Variant& p_value);
Variant get_shader_param(const StringName& p_param) const;
- void set_unshaded(bool p_unshaded);
- bool is_unshaded() const;
+ void set_shading_mode(ShadingMode p_mode);
+ ShadingMode get_shading_mode() const;
virtual RID get_rid() const;
CanvasItemMaterial();
~CanvasItemMaterial();
};
+VARIANT_ENUM_CAST( CanvasItemMaterial::ShadingMode );
+
class CanvasItem : public Node {
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 4abb7e5436..c0ab544d42 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -96,6 +96,21 @@ float Light2D::get_height() const {
return height;
}
+void Light2D::set_energy( float p_energy) {
+
+ energy=p_energy;
+ VS::get_singleton()->canvas_light_set_energy(canvas_light,energy);
+
+}
+
+
+float Light2D::get_energy() const {
+
+ return energy;
+}
+
+
+
void Light2D::set_texture_scale( float p_scale) {
_scale=p_scale;
@@ -178,15 +193,15 @@ int Light2D::get_item_shadow_mask() const {
return item_shadow_mask;
}
-void Light2D::set_subtract_mode( bool p_enable ) {
+void Light2D::set_mode( Mode p_mode ) {
- subtract_mode=p_enable;
- VS::get_singleton()->canvas_light_set_subtract_mode(canvas_light,p_enable);
+ mode=p_mode;
+ VS::get_singleton()->canvas_light_set_mode(canvas_light,VS::CanvasLightMode(p_mode));
}
-bool Light2D::get_subtract_mode() const {
+Light2D::Mode Light2D::get_mode() const {
- return subtract_mode;
+ return mode;
}
void Light2D::set_shadow_enabled( bool p_enabled) {
@@ -260,6 +275,9 @@ void Light2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_height","height"),&Light2D::set_height);
ObjectTypeDB::bind_method(_MD("get_height"),&Light2D::get_height);
+ ObjectTypeDB::bind_method(_MD("set_energy","energy"),&Light2D::set_energy);
+ ObjectTypeDB::bind_method(_MD("get_energy"),&Light2D::get_energy);
+
ObjectTypeDB::bind_method(_MD("set_texture_scale","texture_scale"),&Light2D::set_texture_scale);
ObjectTypeDB::bind_method(_MD("get_texture_scale"),&Light2D::get_texture_scale);
@@ -283,8 +301,8 @@ void Light2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_item_shadow_mask","item_shadow_mask"),&Light2D::set_item_shadow_mask);
ObjectTypeDB::bind_method(_MD("get_item_shadow_mask"),&Light2D::get_item_shadow_mask);
- ObjectTypeDB::bind_method(_MD("set_subtract_mode","enable"),&Light2D::set_subtract_mode);
- ObjectTypeDB::bind_method(_MD("get_subtract_mode"),&Light2D::get_subtract_mode);
+ ObjectTypeDB::bind_method(_MD("set_mode","mode"),&Light2D::set_mode);
+ ObjectTypeDB::bind_method(_MD("get_mode"),&Light2D::get_mode);
ObjectTypeDB::bind_method(_MD("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled);
ObjectTypeDB::bind_method(_MD("is_shadow_enabled"),&Light2D::is_shadow_enabled);
@@ -300,7 +318,8 @@ void Light2D::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"scale",PROPERTY_HINT_RANGE,"0.01,4096,0.01"),_SCS("set_texture_scale"),_SCS("get_texture_scale"));
ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"subtract"),_SCS("set_subtract_mode"),_SCS("get_subtract_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy"),_SCS("set_energy"),_SCS("get_energy"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Add,Sub,Mix"),_SCS("set_mode"),_SCS("get_mode"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"range/height"),_SCS("set_height"),_SCS("get_height"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
@@ -312,6 +331,10 @@ void Light2D::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow/esm_multiplier",PROPERTY_HINT_RANGE,"1,4096,0.1"),_SCS("set_shadow_esm_multiplier"),_SCS("get_shadow_esm_multiplier"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_shadow_mask"),_SCS("get_item_shadow_mask"));
+ BIND_CONSTANT( MODE_ADD );
+ BIND_CONSTANT( MODE_SUB );
+ BIND_CONSTANT( MODE_MIX );
+
}
@@ -329,9 +352,10 @@ Light2D::Light2D() {
layer_max=0;
item_mask=1;
item_shadow_mask=1;
- subtract_mode=false;
+ mode=MODE_ADD;
shadow_buffer_size=2048;
shadow_esm_multiplier=80;
+ energy=1.0;
}
diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h
index 6cfb055fa9..ef875aec2f 100644
--- a/scene/2d/light_2d.h
+++ b/scene/2d/light_2d.h
@@ -6,6 +6,13 @@
class Light2D : public Node2D {
OBJ_TYPE(Light2D,Node2D);
+public:
+ enum Mode {
+ MODE_ADD,
+ MODE_SUB,
+ MODE_MIX,
+ };
+
private:
RID canvas_light;
bool enabled;
@@ -13,6 +20,7 @@ private:
Color color;
float height;
float _scale;
+ float energy;
int z_min;
int z_max;
int layer_min;
@@ -21,7 +29,7 @@ private:
int item_shadow_mask;
int shadow_buffer_size;
float shadow_esm_multiplier;
- bool subtract_mode;
+ Mode mode;
Ref<Texture> texture;
Vector2 texture_offset;
@@ -51,6 +59,9 @@ public:
void set_height( float p_height);
float get_height() const;
+ void set_energy( float p_energy);
+ float get_energy() const;
+
void set_texture_scale( float p_scale);
float get_texture_scale() const;
@@ -72,8 +83,8 @@ public:
void set_item_shadow_mask( int p_mask);
int get_item_shadow_mask() const;
- void set_subtract_mode( bool p_enable );
- bool get_subtract_mode() const;
+ void set_mode( Mode p_mode );
+ Mode get_mode() const;
void set_shadow_enabled( bool p_enabled);
bool is_shadow_enabled() const;
@@ -90,5 +101,6 @@ public:
~Light2D();
};
+VARIANT_ENUM_CAST(Light2D::Mode);
#endif // LIGHT_2D_H
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index ee400ae6d5..f0c71da153 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -406,7 +406,7 @@ void Viewport::_notification(int p_what) {
int rc = ss2d->intersect_point(point,res,64,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF);
for(int i=0;i<rc;i++) {
- if (res[i].collider) {
+ if (res[i].collider_id && res[i].collider) {
CollisionObject2D *co=res[i].collider->cast_to<CollisionObject2D>();
if (co) {
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index d4159f0946..76cb5929cf 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -42,6 +42,7 @@ SceneStringNames::SceneStringNames() {
input_event=StaticCString::create("input_event");
shader_shader=StaticCString::create("shader/shader");
shader_unshaded=StaticCString::create("shader/unshaded");
+ shading_mode=StaticCString::create("shader/shading_mode");
enter_tree=StaticCString::create("enter_tree");
exit_tree=StaticCString::create("exit_tree");
item_rect_changed=StaticCString::create("item_rect_changed");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index aa29ef57dc..a69e8ba0b5 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -57,6 +57,7 @@ public:
StringName item_rect_changed;
StringName shader_shader;
StringName shader_unshaded;
+ StringName shading_mode;
StringName enter_tree;
StringName exit_tree;
StringName size_flags_changed;
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index ebc210fe3d..62563a0771 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -577,6 +577,7 @@ public:
Color color;
Matrix32 xform;
float height;
+ float energy;
float scale;
int z_min;
int z_max;
@@ -584,7 +585,7 @@ public:
int layer_max;
int item_mask;
int item_shadow_mask;
- bool subtract;
+ VS::CanvasLightMode mode;
RID texture;
Vector2 texture_offset;
RID canvas;
@@ -616,8 +617,9 @@ public:
layer_max=0;
item_mask=1;
scale=1.0;
+ energy=1.0;
item_shadow_mask=-1;
- subtract=false;
+ mode=VS::CANVAS_LIGHT_MODE_ADD;
texture_cache=NULL;
next_ptr=NULL;
filter_next_ptr=NULL;
@@ -635,9 +637,9 @@ public:
Map<StringName,Variant> shader_param;
uint32_t shader_version;
Set<CanvasItem*> owners;
- bool unshaded;
+ VS::CanvasItemShadingMode shading_mode;
- CanvasItemMaterial() {unshaded=false; shader_version=0; }
+ CanvasItemMaterial() {shading_mode=VS::CANVAS_ITEM_SHADING_NORMAL; shader_version=0; }
};
struct CanvasItem {
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index af65a7a639..4ad8aa6c71 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -1171,7 +1171,9 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_light_builtins_defs[]={
{ "LIGHT_VEC", TYPE_VEC2},
{ "LIGHT_HEIGHT", TYPE_FLOAT},
{ "LIGHT_COLOR", TYPE_VEC4},
+ { "LIGHT_UV", TYPE_VEC2},
{ "LIGHT", TYPE_VEC4},
+ { "SHADOW", TYPE_VEC4},
{ "POINT_COORD", TYPE_VEC2},
// { "SCREEN_POS", TYPE_VEC2},
// { "SCREEN_TEXEL_SIZE", TYPE_VEC2},
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 916316a0e2..7a9db4ba11 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -3977,6 +3977,15 @@ void VisualServerRaster::canvas_light_set_height(RID p_light, float p_height){
clight->height=p_height;
}
+
+void VisualServerRaster::canvas_light_set_energy(RID p_light, float p_energy){
+
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->energy=p_energy;
+
+}
+
void VisualServerRaster::canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z){
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
@@ -4012,12 +4021,12 @@ void VisualServerRaster::canvas_light_set_item_shadow_mask(RID p_light, int p_ma
}
-void VisualServerRaster::canvas_light_set_subtract_mode(RID p_light, bool p_enable) {
+void VisualServerRaster::canvas_light_set_mode(RID p_light, CanvasLightMode p_mode) {
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
- clight->subtract=p_enable;
+ clight->mode=p_mode;
}
void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled){
@@ -4267,12 +4276,12 @@ Variant VisualServerRaster::canvas_item_material_get_shader_param(RID p_material
return material->shader_param[p_param];
}
-void VisualServerRaster::canvas_item_material_set_unshaded(RID p_material, bool p_unshaded){
+void VisualServerRaster::canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode) {
VS_CHANGED;
Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
ERR_FAIL_COND(!material);
- material->unshaded=p_unshaded;
+ material->shading_mode=p_mode;
}
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 72af793278..a89a685e30 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -1170,12 +1170,13 @@ public:
virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset);
virtual void canvas_light_set_color(RID p_light, const Color& p_color);
virtual void canvas_light_set_height(RID p_light, float p_height);
+ virtual void canvas_light_set_energy(RID p_light, float p_energy);
virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z);
virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer);
virtual void canvas_light_set_item_mask(RID p_light, int p_mask);
virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask);
- virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable);
+ virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode);
virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled);
virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size);
virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier);
@@ -1204,8 +1205,9 @@ public:
virtual RID canvas_item_material_create();
virtual void canvas_item_material_set_shader(RID p_material, RID p_shader);
virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value);
- virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const;
- virtual void canvas_item_material_set_unshaded(RID p_material, bool p_unshaded);
+ virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const;
+ virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode);
+
/* CURSOR */
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index ded4c6fc00..6cd374aa08 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -1160,12 +1160,13 @@ public:
FUNC2(canvas_light_set_texture_offset,RID,const Vector2&);
FUNC2(canvas_light_set_color,RID,const Color&);
FUNC2(canvas_light_set_height,RID,float);
+ FUNC2(canvas_light_set_energy,RID,float);
FUNC3(canvas_light_set_layer_range,RID,int,int);
FUNC3(canvas_light_set_z_range,RID,int,int);
FUNC2(canvas_light_set_item_mask,RID,int);
FUNC2(canvas_light_set_item_shadow_mask,RID,int);
- FUNC2(canvas_light_set_subtract_mode,RID,bool);
+ FUNC2(canvas_light_set_mode,RID,CanvasLightMode);
FUNC2(canvas_light_set_shadow_enabled,RID,bool);
FUNC2(canvas_light_set_shadow_buffer_size,RID,int);
FUNC2(canvas_light_set_shadow_esm_multiplier,RID,float);
@@ -1191,8 +1192,8 @@ public:
FUNC0R(RID,canvas_item_material_create);
FUNC2(canvas_item_material_set_shader,RID,RID);
FUNC3(canvas_item_material_set_shader_param,RID,const StringName&,const Variant&);
- FUNC2RC(Variant,canvas_item_material_get_shader_param,RID,const StringName&);
- FUNC2(canvas_item_material_set_unshaded,RID,bool);
+ FUNC2RC(Variant,canvas_item_material_get_shader_param,RID,const StringName&);
+ FUNC2(canvas_item_material_set_shading_mode,RID,CanvasItemShadingMode);
/* CURSOR */
FUNC2(cursor_set_rotation,float , int ); // radians
diff --git a/servers/visual_server.h b/servers/visual_server.h
index b6d354454e..e9425afbab 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -1014,12 +1014,19 @@ public:
virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset)=0;
virtual void canvas_light_set_color(RID p_light, const Color& p_color)=0;
virtual void canvas_light_set_height(RID p_light, float p_height)=0;
+ virtual void canvas_light_set_energy(RID p_light, float p_energy)=0;
virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z)=0;
virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer)=0;
virtual void canvas_light_set_item_mask(RID p_light, int p_mask)=0;
virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask)=0;
- virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable)=0;
+ enum CanvasLightMode {
+ CANVAS_LIGHT_MODE_ADD,
+ CANVAS_LIGHT_MODE_SUB,
+ CANVAS_LIGHT_MODE_MIX,
+ };
+
+ virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode)=0;
virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0;
virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size)=0;
virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier)=0;
@@ -1049,7 +1056,15 @@ public:
virtual void canvas_item_material_set_shader(RID p_material, RID p_shader)=0;
virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value)=0;
virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const=0;
- virtual void canvas_item_material_set_unshaded(RID p_material, bool p_unshaded)=0;
+
+
+ enum CanvasItemShadingMode {
+ CANVAS_ITEM_SHADING_NORMAL,
+ CANVAS_ITEM_SHADING_UNSHADED,
+ CANVAS_ITEM_SHADING_ONLY_LIGHT,
+ };
+
+ virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode)=0;
/* CURSOR */
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians
diff --git a/tools/editor/pvrtc_compress.cpp b/tools/editor/pvrtc_compress.cpp
index 9511d6a26d..777a05f272 100644
--- a/tools/editor/pvrtc_compress.cpp
+++ b/tools/editor/pvrtc_compress.cpp
@@ -32,11 +32,34 @@
#include "io/resource_saver.h"
#include "io/resource_loader.h"
#include "os/os.h"
-
+#include "os/file_access.h"
+static void (*_base_image_compress_pvrtc2_func)(Image *)=NULL;
+static void (*_base_image_compress_pvrtc4_func)(Image *)=NULL;
static void _compress_image(Image::CompressMode p_mode,Image *p_image) {
String ttpath = EditorSettings::get_singleton()->get("PVRTC/texture_tool");
+
+ if (ttpath.strip_edges()=="" || !FileAccess::exists(ttpath)) {
+ switch(p_mode) {
+
+ case Image::COMPRESS_PVRTC2:
+ if (_base_image_compress_pvrtc2_func)
+ _base_image_compress_pvrtc2_func(p_image);
+ else if (_base_image_compress_pvrtc4_func)
+ _base_image_compress_pvrtc4_func(p_image);
+
+ break;
+ case Image::COMPRESS_PVRTC4:
+ if (_base_image_compress_pvrtc4_func)
+ _base_image_compress_pvrtc4_func(p_image);
+
+ break;
+ default: ERR_FAIL();
+
+ }
+ return;
+ }
String spath = EditorSettings::get_singleton()->get_settings_path();
@@ -100,6 +123,9 @@ static void _compress_etc(Image *p_image) {
void _pvrtc_register_compressors() {
+ _base_image_compress_pvrtc2_func=Image::_image_compress_pvrtc2_func;
+ _base_image_compress_pvrtc4_func=Image::_image_compress_pvrtc4_func;
+
Image::_image_compress_pvrtc2_func=_compress_pvrtc2;
Image::_image_compress_pvrtc4_func=_compress_pvrtc4;
//Image::_image_compress_etc_func=_compress_etc; //use the built in one for ETC