summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
Diffstat (limited to 'o3d')
-rw-r--r--o3d/core/build.scons1
-rw-r--r--o3d/core/core.gyp2
-rw-r--r--o3d/core/cross/bitmap.cc827
-rw-r--r--o3d/core/cross/bitmap.h397
-rw-r--r--o3d/core/cross/bitmap_dds.cc102
-rw-r--r--o3d/core/cross/bitmap_jpg.cc21
-rw-r--r--o3d/core/cross/bitmap_png.cc19
-rw-r--r--o3d/core/cross/bitmap_test.cc359
-rw-r--r--o3d/core/cross/bitmap_tga.cc29
-rw-r--r--o3d/core/cross/buffer_test.cc1
-rw-r--r--o3d/core/cross/client.h7
-rw-r--r--o3d/core/cross/client_test.cc2
-rw-r--r--o3d/core/cross/command_buffer/texture_cb.cc40
-rw-r--r--o3d/core/cross/counter.h1
-rw-r--r--o3d/core/cross/curve_test.cc5
-rw-r--r--o3d/core/cross/draw_element_test.cc4
-rw-r--r--o3d/core/cross/draw_list_test.cc6
-rw-r--r--o3d/core/cross/effect_test.cc10
-rw-r--r--o3d/core/cross/element_test.cc4
-rw-r--r--o3d/core/cross/features.cc68
-rw-r--r--o3d/core/cross/features.h17
-rw-r--r--o3d/core/cross/features_test.cc61
-rw-r--r--o3d/core/cross/field_test.cc5
-rw-r--r--o3d/core/cross/function_test.cc4
-rw-r--r--o3d/core/cross/gl/renderer_gl.cc2
-rw-r--r--o3d/core/cross/gl/texture_gl.cc53
-rw-r--r--o3d/core/cross/gl/texture_gl.h10
-rw-r--r--o3d/core/cross/material_test.cc6
-rw-r--r--o3d/core/cross/message_queue.cc11
-rw-r--r--o3d/core/cross/message_queue_test.cc5
-rw-r--r--o3d/core/cross/pack.cc28
-rw-r--r--o3d/core/cross/pack.h37
-rw-r--r--o3d/core/cross/pack_test.cc4
-rw-r--r--o3d/core/cross/param_array_test.cc5
-rw-r--r--o3d/core/cross/param_object_test.cc4
-rw-r--r--o3d/core/cross/param_operation_test.cc5
-rw-r--r--o3d/core/cross/param_test.cc6
-rw-r--r--o3d/core/cross/primitive_test.cc4
-rw-r--r--o3d/core/cross/ray_intersection_info_test.cc4
-rw-r--r--o3d/core/cross/render_node_test.cc6
-rw-r--r--o3d/core/cross/skin_test.cc5
-rw-r--r--o3d/core/cross/state_set_test.cc4
-rw-r--r--o3d/core/cross/state_test.cc4
-rw-r--r--o3d/core/cross/stream_bank_test.cc4
-rw-r--r--o3d/core/cross/texture.cc259
-rw-r--r--o3d/core/cross/texture.h21
-rw-r--r--o3d/core/cross/texture_base.h9
-rw-r--r--o3d/core/cross/texture_base_test.cc10
-rw-r--r--o3d/core/cross/texture_test.cc2
-rw-r--r--o3d/core/cross/transform_test.cc5
-rw-r--r--o3d/core/cross/tree_traversal_test.cc6
-rw-r--r--o3d/core/win/d3d9/texture_d3d9.cc54
-rw-r--r--o3d/import/cross/collada.cc3
-rw-r--r--o3d/import/cross/gz_compressor_test.cc1
-rw-r--r--o3d/import/cross/gz_decompressor_test.cc1
-rw-r--r--o3d/import/cross/precompile.h7
-rw-r--r--o3d/import/cross/raw_data.h2
-rw-r--r--o3d/import/cross/raw_data_test.cc1
-rw-r--r--o3d/import/cross/tar_generator_test.cc1
-rw-r--r--o3d/import/cross/tar_processor_test.cc1
-rw-r--r--o3d/import/cross/targz_generator_test.cc1
-rw-r--r--o3d/import/cross/targz_processor_test.cc1
-rw-r--r--o3d/plugin/cross/async_loading.cc4
-rw-r--r--o3d/plugin/cross/o3d_glue.h1
-rw-r--r--o3d/plugin/idl/bitmap.idl62
-rw-r--r--o3d/plugin/idl/texture.idl54
-rw-r--r--o3d/samples/bitmap-draw-image.html32
-rw-r--r--o3d/tests/build.scons1
68 files changed, 1113 insertions, 1625 deletions
diff --git a/o3d/core/build.scons b/o3d/core/build.scons
index 593b301..e155919 100644
--- a/o3d/core/build.scons
+++ b/o3d/core/build.scons
@@ -66,6 +66,7 @@ cross_inputs = [
'cross/iclass_manager.cc',
'cross/ierror_status.cc',
'cross/id_manager.cc',
+ 'cross/image_utils.cc',
'cross/imain_thread_task_poster.cc',
'cross/material.cc',
'cross/math_utilities.cc',
diff --git a/o3d/core/core.gyp b/o3d/core/core.gyp
index 99d79c3..e0644a1 100644
--- a/o3d/core/core.gyp
+++ b/o3d/core/core.gyp
@@ -126,6 +126,7 @@
'cross/id_manager.h',
'cross/ierror_status.cc',
'cross/ierror_status.h',
+ 'cross/image_utils.cc',
'cross/imain_thread_task_poster.cc',
'cross/imain_thread_task_poster.h',
'cross/install_check.h',
@@ -372,6 +373,7 @@
'cross/field_test.cc',
'cross/float_n_test.cc',
'cross/function_test.cc',
+ 'cross/image_utils_test.cc',
'cross/material_test.cc',
'cross/math_utilities_test.cc',
'cross/matrix4_axis_rotation_test.cc',
diff --git a/o3d/core/cross/bitmap.cc b/o3d/core/cross/bitmap.cc
index 35dc34211..e44f5d9 100644
--- a/o3d/core/cross/bitmap.cc
+++ b/o3d/core/cross/bitmap.cc
@@ -44,6 +44,7 @@
#include "utils/cross/file_path_utils.h"
#include "base/file_path.h"
#include "base/file_util.h"
+#include "core/cross/features.h"
#include "core/cross/texture.h"
#include "import/cross/raw_data.h"
#include "import/cross/memory_buffer.h"
@@ -53,26 +54,9 @@ using file_util::OpenFile;
using file_util::CloseFile;
using file_util::GetFileSize;
-namespace {
-static const float kEpsilon = 0.0001f;
-static const float kPi = 3.14159265358979f;
-static const int kFilterSize = 3;
-
-// utility function, round float numbers into 0 to 255 integers.
-uint8 Safe8Round(float f) {
- f += 0.5f;
- if (f < 0.0f) {
- return 0;
- } else if (!(f < 255.0f)) {
- return 255;
- }
- return static_cast<uint8>(f);
-}
-} // anonymous namespace.
-
namespace o3d {
- O3D_DEFN_CLASS(Bitmap, ParamObject);
+O3D_DEFN_CLASS(Bitmap, ParamObject);
Bitmap::Bitmap(ServiceLocator* service_locator)
: ParamObject(service_locator),
@@ -83,54 +67,10 @@ Bitmap::Bitmap(ServiceLocator* service_locator)
num_mipmaps_(0),
is_cubemap_(false) {}
-// Gets the size of the buffer containing a an image, given its width, height
-// and format.
-unsigned int Bitmap::GetBufferSize(unsigned int width,
- unsigned int height,
- Texture::Format format) {
- DCHECK(CheckImageDimensions(width, height));
- unsigned int pixels = width * height;
- switch (format) {
- case Texture::XRGB8:
- case Texture::ARGB8:
- return 4 * sizeof(uint8) * pixels; // NOLINT
- case Texture::ABGR16F:
- return 4 * sizeof(uint16) * pixels; // NOLINT
- case Texture::R32F:
- return sizeof(float) * pixels; // NOLINT
- case Texture::ABGR32F:
- return 4 * sizeof(float) * pixels; // NOLINT
- case Texture::DXT1:
- case Texture::DXT3:
- case Texture::DXT5: {
- unsigned int blocks = ((width + 3) / 4) * ((height + 3) / 4);
- unsigned int bytes_per_block = format == Texture::DXT1 ? 8 : 16;
- return blocks * bytes_per_block;
- }
- case Texture::UNKNOWN_FORMAT:
- break;
- }
- // failed to find a matching format
- LOG(ERROR) << "Unrecognized Texture format type.";
- return 0;
-}
-
-// Gets the size of the buffer containing a mip-map chain, given its base
-// width, height, format and number of mip-map levels.
-unsigned int Bitmap::GetMipChainSize(unsigned int base_width,
- unsigned int base_height,
- Texture::Format format,
- unsigned int num_mipmaps) {
- DCHECK(CheckImageDimensions(base_width, base_height));
- unsigned int total_size = 0;
- unsigned int mip_width = base_width;
- unsigned int mip_height = base_height;
- for (unsigned int i = 0; i < num_mipmaps; ++i) {
- total_size += GetBufferSize(mip_width, mip_height, format);
- mip_width = std::max(1U, mip_width >> 1);
- mip_height = std::max(1U, mip_height >> 1);
- }
- return total_size;
+unsigned int Bitmap::GetMipSize(unsigned int level) const {
+ unsigned int mip_width = std::max(1U, width() >> level);
+ unsigned int mip_height = std::max(1U, height() >> level);
+ return image::ComputeMipChainSize(mip_width, mip_height, format(), 1);
}
void Bitmap::Allocate(Texture::Format format,
@@ -138,7 +78,7 @@ void Bitmap::Allocate(Texture::Format format,
unsigned int height,
unsigned int num_mipmaps,
bool cube_map) {
- DCHECK(CheckImageDimensions(width, height));
+ DCHECK(image::CheckImageDimensions(width, height));
switch (format) {
case Texture::XRGB8:
case Texture::ARGB8:
@@ -154,7 +94,7 @@ void Bitmap::Allocate(Texture::Format format,
break;
}
DCHECK(!cube_map || (width == height));
- DCHECK_LE(num_mipmaps, GetMipMapCount(width, height));
+ DCHECK_LE(num_mipmaps, image::ComputeMipMapCount(width, height));
DCHECK_GT(num_mipmaps, 0u);
format_ = format;
@@ -170,7 +110,7 @@ uint8 *Bitmap::GetMipData(unsigned int level) const {
DCHECK(!is_cubemap_);
if (!image_data_.get()) return NULL;
uint8 *data = image_data_.get();
- return data + GetMipChainSize(width_, height_, format_, level);
+ return data + GetMipChainSize(level);
}
uint8 *Bitmap::GetFaceMipData(TextureCUBE::CubeFace face,
@@ -180,9 +120,9 @@ uint8 *Bitmap::GetFaceMipData(TextureCUBE::CubeFace face,
uint8 *data = image_data_.get();
if (is_cubemap()) {
data += (face - TextureCUBE::FACE_POSITIVE_X) *
- GetMipChainSize(width_, height_, format_, num_mipmaps_);
+ GetMipChainSize(num_mipmaps_);
}
- return data + GetMipChainSize(width_, height_, format_, level);
+ return data + GetMipChainSize(level);
}
void Bitmap::SetRect(
@@ -195,8 +135,8 @@ void Bitmap::SetRect(
int src_pitch) {
DCHECK(src_data);
DCHECK(level < static_cast<int>(num_mipmaps()) && level >= 0);
- unsigned mip_width = Bitmap::GetMipDimension(level, width());
- unsigned mip_height = Bitmap::GetMipDimension(level, height());
+ unsigned mip_width = image::ComputeMipDimension(level, width());
+ unsigned mip_height = image::ComputeMipDimension(level, height());
DCHECK(dst_left + src_width <= mip_width &&
dst_top + src_height <= mip_height);
bool compressed = Texture::IsCompressedFormat(format());
@@ -206,22 +146,21 @@ void Bitmap::SetRect(
uint8* dst =
GetMipData(level) +
- Bitmap::GetMipChainSize(mip_width, dst_top, format(), 1) +
- Bitmap::GetMipChainSize(dst_left, 1, format(), 1);
+ image::ComputeMipChainSize(mip_width, dst_top, format(), 1) +
+ image::ComputeMipChainSize(dst_left, 1, format(), 1);
const uint8* src = static_cast<const uint8*>(src_data);
if (!compressed) {
- unsigned bytes_per_line = GetMipChainSize(src_width, 1, format(), 1);
- int dst_pitch = Bitmap::GetMipChainSize(mip_width, 1, format(), 1);
+ unsigned bytes_per_line = image::ComputePitch(format(), src_width);
+ int dst_pitch = image::ComputePitch(format(), mip_width);
for (unsigned yy = 0; yy < src_height; ++yy) {
memcpy(dst, src, bytes_per_line);
src += src_pitch;
dst += dst_pitch;
}
} else {
- memcpy(dst,
- src,
- Bitmap::GetMipChainSize(mip_width, mip_height, format(), 1));
+ memcpy(dst, src,
+ image::ComputeMipChainSize(mip_width, mip_height, format(), 1));
}
}
@@ -236,8 +175,8 @@ void Bitmap::SetFaceRect(
int src_pitch) {
DCHECK(src_data);
DCHECK(level < static_cast<int>(num_mipmaps()) && level >= 0);
- unsigned mip_width = Bitmap::GetMipDimension(level, width());
- unsigned mip_height = Bitmap::GetMipDimension(level, height());
+ unsigned mip_width = image::ComputeMipDimension(level, width());
+ unsigned mip_height = image::ComputeMipDimension(level, height());
DCHECK(dst_left + src_width <= mip_width &&
dst_top + src_height <= mip_height);
bool compressed = Texture::IsCompressedFormat(format());
@@ -247,13 +186,13 @@ void Bitmap::SetFaceRect(
uint8* dst =
GetFaceMipData(face, level) +
- Bitmap::GetMipChainSize(mip_width, dst_top, format(), 1) +
- Bitmap::GetMipChainSize(dst_left, 1, format(), 1);
+ image::ComputeMipChainSize(mip_width, dst_top, format(), 1) +
+ image::ComputeMipChainSize(dst_left, 1, format(), 1);
const uint8* src = static_cast<const uint8*>(src_data);
if (!compressed) {
- unsigned bytes_per_line = GetMipChainSize(src_width, 1, format(), 1);
- int dst_pitch = Bitmap::GetMipChainSize(mip_width, 1, format(), 1);
+ unsigned bytes_per_line = image::ComputePitch(format(), src_width);
+ int dst_pitch = image::ComputePitch(format(), mip_width);
for (unsigned yy = 0; yy < src_height; ++yy) {
memcpy(dst, src, bytes_per_line);
src += src_pitch;
@@ -262,65 +201,82 @@ void Bitmap::SetFaceRect(
} else {
memcpy(dst,
src,
- Bitmap::GetMipChainSize(mip_width, mip_height, format(), 1));
+ image::ComputeMipChainSize(mip_width, mip_height, format(), 1));
}
}
bool Bitmap::LoadFromStream(MemoryReadStream *stream,
const String &filename,
- ImageFileType file_type,
+ image::ImageFileType file_type,
bool generate_mipmaps) {
+ bool success = false;
// If we don't know what type to load, try to detect it based on the file
// name.
- if (file_type == UNKNOWN) {
- file_type = GetFileTypeFromFilename(filename.c_str());
+ if (file_type == image::UNKNOWN) {
+ file_type = image::GetFileTypeFromFilename(filename.c_str());
}
switch (file_type) {
- case TGA:
- if (LoadFromTGAStream(stream, filename, generate_mipmaps)) return true;
+ case image::TGA:
+ success = LoadFromTGAStream(stream, filename, generate_mipmaps);
break;
- case DDS:
- if (LoadFromDDSStream(stream, filename, generate_mipmaps)) return true;
+ case image::DDS:
+ success = LoadFromDDSStream(stream, filename, generate_mipmaps);
break;
- case PNG:
- if (LoadFromPNGStream(stream, filename, generate_mipmaps)) return true;
+ case image::PNG:
+ success = LoadFromPNGStream(stream, filename, generate_mipmaps);
break;
- case JPEG:
- if (LoadFromJPEGStream(stream, filename, generate_mipmaps)) return true;
+ case image::JPEG:
+ success = LoadFromJPEGStream(stream, filename, generate_mipmaps);
break;
- case UNKNOWN:
+ case image::UNKNOWN:
default:
break;
}
- // At this point we either could not detect the filetype, or possibly
- // the file extension was incorrect (eg. a JPEG image with a .png suffix)
- DLOG(INFO) << "Could not detect file type from filename \""
- << filename << "\". Trying all the loaders.";
- // We will try all the loaders, one by one, starting by the ones that can
- // have an early detect based on magic strings. We Seek(0) after each try
- // since each attempt changes the stream read position.
- if (LoadFromDDSStream(stream, filename, generate_mipmaps)) return true;
+ if (!success) {
+ // At this point we either could not detect the filetype, or possibly
+ // the file extension was incorrect (eg. a JPEG image with a .png suffix)
+ DLOG(INFO) << "Could not detect file type from filename \""
+ << filename << "\". Trying all the loaders.";
+ // We will try all the loaders, one by one, starting by the ones that can
+ // have an early detect based on magic strings. We Seek(0) after each try
+ // since each attempt changes the stream read position.
+ success = LoadFromDDSStream(stream, filename, generate_mipmaps);
+ if (!success) {
+ stream->Seek(0);
+ success = LoadFromPNGStream(stream, filename, generate_mipmaps);
+ }
- stream->Seek(0);
- if (LoadFromPNGStream(stream, filename, generate_mipmaps)) return true;
+ if (!success) {
+ stream->Seek(0);
+ success = LoadFromJPEGStream(stream, filename, generate_mipmaps);
+ }
- stream->Seek(0);
- if (LoadFromJPEGStream(stream, filename, generate_mipmaps)) return true;
+ if (!success) {
+ stream->Seek(0);
+ success = LoadFromTGAStream(stream, filename, generate_mipmaps);
+ }
+ }
- stream->Seek(0);
- if (LoadFromTGAStream(stream, filename, generate_mipmaps)) return true;
- DLOG(ERROR) << "Failed to load image \"" << filename
- << "\": unknown file type";
- return false;
+ if (success) {
+ Features* features = service_locator()->GetService<Features>();
+ DCHECK(features);
+ if (features->flip_textures()) {
+ FlipVertically();
+ }
+ } else {
+ DLOG(ERROR) << "Failed to load image \"" << filename
+ << "\": unknown file type";
+ }
+ return success;
}
// Given an arbitrary bitmap file, load it all into memory and then call our
// stream loader
bool Bitmap::LoadFromFile(const FilePath &filepath,
- ImageFileType file_type,
+ image::ImageFileType file_type,
bool generate_mipmaps) {
// Open the file.
bool result = false;
@@ -362,7 +318,7 @@ bool Bitmap::LoadFromFile(const FilePath &filepath,
// Given a RawData object containing image data in one of our known formats,
// decide which image format it is and call the correct loading function.
bool Bitmap::LoadFromRawData(RawData *raw_data,
- ImageFileType file_type,
+ image::ImageFileType file_type,
bool generate_mipmaps) {
String filename = raw_data->uri();
@@ -379,30 +335,30 @@ bool Bitmap::LoadFromRawData(RawData *raw_data,
return LoadFromStream(&stream, filename, file_type, generate_mipmaps);
}
-void Bitmap::DrawImage(Bitmap* src_img,
+void Bitmap::DrawImage(const Bitmap& src_img,
int src_x, int src_y,
int src_width, int src_height,
int dst_x, int dst_y,
int dst_width, int dst_height) {
- DCHECK(src_img->image_data());
+ DCHECK(src_img.image_data());
DCHECK(image_data());
// Clip source and destination rectangles to
// source and destination bitmaps.
// if src or dest rectangle is out of boundary,
// do nothing and return.
- if (!AdjustDrawImageBoundary(&src_x, &src_y,
- &src_width, &src_height,
- src_img->width_, src_img->height_,
- &dst_x, &dst_y,
- &dst_width, &dst_height,
- width_, height_))
+ if (!image::AdjustDrawImageBoundary(&src_x, &src_y,
+ &src_width, &src_height,
+ src_img.width_, src_img.height_,
+ &dst_x, &dst_y,
+ &dst_width, &dst_height,
+ width_, height_))
return;
unsigned int components = 0;
// check formats of source and dest images.
// format of source and dest should be the same.
- if (src_img->format_ != format_) {
+ if (src_img.format_ != format_) {
O3D_ERROR(service_locator()) << "DrawImage does not support "
<< "different formats.";
return;
@@ -410,378 +366,72 @@ void Bitmap::DrawImage(Bitmap* src_img,
// if src and dest are in the same size and drawImage is copying
// the entire bitmap on dest image, just perform memcpy.
if (src_x == 0 && src_y == 0 && dst_x == 0 && dst_y == 0 &&
- src_img->width_ == width_ && src_img->height_ == height_ &&
- src_width == src_img->width_ && src_height == src_img->height_ &&
+ src_img.width_ == width_ && src_img.height_ == height_ &&
+ src_width == src_img.width_ && src_height == src_img.height_ &&
dst_width == width_ && dst_height == height_) {
- memcpy(image_data(), src_img->image_data(), GetTotalSize());
+ memcpy(image_data(), src_img.image_data(), GetTotalSize());
return;
}
// if drawImage is not copying the whole bitmap, we need to check
// the format. currently only support XRGB8 and ARGB8
- if (src_img->format_ == Texture::XRGB8 ||
- src_img->format_ == Texture::ARGB8) {
+ if (src_img.format_ == Texture::XRGB8 ||
+ src_img.format_ == Texture::ARGB8) {
components = 4;
} else {
O3D_ERROR(service_locator()) << "DrawImage does not support format: "
- << src_img->format_ << " unless src and "
+ << src_img.format_ << " unless src and "
<< "dest images are in the same size and "
<< "copying the entire bitmap";
return;
}
- uint8* src_img_data = src_img->image_data();
+ uint8* src_img_data = src_img.image_data();
uint8* dst_img_data = image_data();
// crop part of image from src img, scale it in
// bilinear interpolation fashion, and paste it
// on dst img.
- LanczosScale(src_img_data, src_x, src_y,
- src_width, src_height,
- src_img->width_, src_img->height_,
- dst_img_data, width_ * components,
- dst_x, dst_y,
- dst_width, dst_height,
- width_, height_, components);
-}
-
-void Bitmap::LanczosScale(const uint8* src,
- int src_x, int src_y,
- int src_width, int src_height,
- int src_img_width, int src_img_height,
- uint8* dest, int dest_pitch,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int dest_img_width, int dest_img_height,
- int components) {
- // Scale the image horizontally to a temp buffer.
- int temp_img_width = abs(dest_width);
- int temp_img_height = abs(src_height);
- int temp_width = dest_width;
- int temp_height = src_height;
- int temp_x = 0, temp_y = 0;
- if (temp_width < 0)
- temp_x = abs(temp_width) - 1;
- if (temp_height < 0)
- temp_y = abs(temp_height) - 1;
-
- scoped_array<uint8> temp(new uint8[temp_img_width *
- temp_img_height * components]);
-
- LanczosResize1D(src, src_x, src_y, src_width, src_height,
- src_img_width, src_img_height,
- temp.get(), temp_img_width * components,
- temp_x, temp_y, temp_width,
- temp_img_width, temp_img_height, true, components);
-
- // Scale the temp buffer vertically to get the final result.
- LanczosResize1D(temp.get(), temp_x, temp_y, temp_height, temp_width,
- temp_img_width, temp_img_height,
- dest, dest_pitch,
- dest_x, dest_y, dest_height,
- dest_img_width, dest_img_height, false, components);
+ image::LanczosScale(src_img_data, src_x, src_y,
+ src_width, src_height,
+ src_img.width_, src_img.height_,
+ dst_img_data, width_ * components,
+ dst_x, dst_y,
+ dst_width, dst_height,
+ width_, height_, components);
}
-void Bitmap::LanczosResize1D(const uint8* src, int src_x, int src_y,
- int width, int height,
- int src_bmp_width, int src_bmp_height,
- uint8* out, int dest_pitch,
- int dest_x, int dest_y,
- int nwidth,
- int dest_bmp_width, int dest_bmp_height,
- bool isWidth, int components) {
- int pitch = dest_pitch / components;
- // calculate scale factor and init the weight array for lanczos filter.
- float scale = fabs(static_cast<float>(width) / nwidth);
- float support = kFilterSize * scale;
- scoped_array<float> weight(new float[static_cast<int>(support * 2) + 4]);
- // we assume width is the dimension we are scaling, and height stays
- // the same.
- for (int i = 0; i < abs(nwidth); ++i) {
- // center is the corresponding coordinate of i in original img.
- float center = (i + 0.5f) * scale;
- // boundary of weight array in original img.
- int xmin = static_cast<int>(floor(center - support));
- if (xmin < 0) xmin = 0;
- int xmax = static_cast<int>(ceil(center + support));
- if (xmax >= abs(width)) xmax = abs(width) - 1;
- // fill up weight array by lanczos filter.
- float wsum = 0.0;
- for (int ox = xmin; ox <= xmax; ++ox) {
- float wtemp;
- float dx = ox + 0.5f - center;
- // lanczos filter
- if (dx <= -kFilterSize || dx >= kFilterSize) {
- wtemp = 0.0;
- } else if (dx == 0.0) {
- wtemp = 1.0f;
- } else {
- wtemp = kFilterSize * sinf(kPi * dx) * sinf(kPi / kFilterSize * dx) /
- (kPi * kPi * dx * dx);
- }
-
- weight[ox - xmin] = wtemp;
- wsum += wtemp;
- }
- int wcount = xmax - xmin + 1;
-
- // Normalize the weights.
- if (fabs(wsum) > kEpsilon) {
- for (int k = 0; k < wcount; ++k) {
- weight[k] /= wsum;
- }
- }
- // Now that we've computed the filter weights for this x-position
- // of the image, we can apply that filter to all pixels in that
- // column.
- // calculate coordinate in new img.
- int x = i;
- if (nwidth < 0)
- x = -1 * x;
- // lower bound of coordinate in original img.
- if (width < 0)
- xmin = -1 * xmin;
- for (int j = 0; j < abs(height); ++j) {
- // coordinate in height, same in src and dest img.
- int base_y = j;
- if (height < 0)
- base_y = -1 * base_y;
- // TODO(yux): fix the vertical flip problem and merge this if-else
- // statement coz at that time, there would be no need to check
- // which measure we are scaling.
- if (isWidth) {
- const uint8* inrow = src + ((src_bmp_height - (src_y + base_y) - 1) *
- src_bmp_width + src_x + xmin) * components;
- uint8* outpix = out + ((dest_bmp_height - (dest_y + base_y) - 1) *
- pitch + dest_x + x) * components;
- int step = components;
- if (width < 0)
- step = -1 * step;
- for (int b = 0; b < components; ++b) {
- float sum = 0.0;
- for (int k = 0, xk = b; k < wcount; ++k, xk += step)
- sum += weight[k] * inrow[xk];
-
- outpix[b] = Safe8Round(sum);
- }
- } else {
- const uint8* inrow = src + (src_x + base_y + (src_bmp_height -
- (src_y + xmin) - 1) * src_bmp_width) *
- components;
- uint8* outpix = out + (dest_x + base_y + (dest_bmp_height -
- (dest_y + x) - 1) * pitch) * components;
-
- int step = src_bmp_width * components;
- if (width < 0)
- step = -1 * step;
- for (int b = 0; b < components; ++b) {
- float sum = 0.0;
- for (int k = 0, xk = b; k < wcount; ++k, xk -= step)
- sum += weight[k] * inrow[xk];
-
- outpix[b] = Safe8Round(sum);
- }
- }
- }
- }
-}
-
-Bitmap::ImageFileType Bitmap::GetFileTypeFromFilename(const char *filename) {
- // Convert the filename to lower case for matching.
- // NOTE: Surprisingly, "tolower" is not in the std namespace.
- String name(filename);
- std::transform(name.begin(), name.end(), name.begin(), ::tolower);
-
- // Dispatch loading functions based on filename extensions.
- String::size_type i = name.rfind(".");
- if (i == String::npos) {
- DLOG(INFO) << "Could not detect file type for image \""
- << filename << "\": no extension.";
- return UNKNOWN;
- }
-
- String extension = name.substr(i);
- if (extension == ".tga") {
- DLOG(INFO) << "Bitmap Found a TGA file : " << filename;
- return TGA;
- } else if (extension == ".dds") {
- DLOG(INFO) << "Bitmap Found a DDS file : " << filename;
- return DDS;
- } else if (extension == ".png") {
- DLOG(INFO) << "Bitmap Found a PNG file : " << filename;
- return PNG;
- } else if (extension == ".jpg" ||
- extension == ".jpeg" ||
- extension == ".jpe") {
- DLOG(INFO) << "Bitmap Found a JPEG file : " << filename;
- return JPEG;
- } else {
- return UNKNOWN;
- }
-}
-
-struct MimeTypeToFileType {
- const char *mime_type;
- Bitmap::ImageFileType file_type;
-};
-
-static const MimeTypeToFileType mime_type_map[] = {
- {"image/png", Bitmap::PNG},
- {"image/jpeg", Bitmap::JPEG},
- // No official MIME type for TGA or DDS.
-};
-
-Bitmap::ImageFileType Bitmap::GetFileTypeFromMimeType(const char *mime_type) {
- for (unsigned int i = 0; i < arraysize(mime_type_map); ++i) {
- if (!strcmp(mime_type, mime_type_map[i].mime_type))
- return mime_type_map[i].file_type;
- }
- return Bitmap::UNKNOWN;
-}
-
-void Bitmap::XYZToXYZA(uint8 *image_data, int pixel_count) {
- // We do this pixel by pixel, starting from the end to avoid overlapping
- // problems.
- for (int i = pixel_count - 1; i >= 0; --i) {
- image_data[i*4+3] = 0xff;
- image_data[i*4+2] = image_data[i*3+2];
- image_data[i*4+1] = image_data[i*3+1];
- image_data[i*4+0] = image_data[i*3+0];
+void Bitmap::GenerateMips(int source_level, int num_levels) {
+ if (source_level >= num_mipmaps() || source_level < 0) {
+ O3D_ERROR(service_locator()) << "source level out of range.";
+ return;
}
-}
-
-void Bitmap::RGBAToBGRA(uint8 *image_data, int pixel_count) {
- for (int i = 0; i < pixel_count; ++i) {
- uint8 c = image_data[i*4+0];
- image_data[i*4+0] = image_data[i*4+2];
- image_data[i*4+2] = c;
+ if (source_level + num_levels >= num_mipmaps() || num_levels < 0) {
+ O3D_ERROR(service_locator()) << "num levels out of range.";
+ return;
}
-}
-// Compute a texel, filtered from several source texels. This function assumes
-// minification.
-// Parameters:
-// x: x-coordinate of the destination texel in the destination image
-// y: y-coordinate of the destination texel in the destination image
-// dst_width: width of the destination image
-// dst_height: height of the destination image
-// dst_data: address of the destination image data
-// src_width: width of the source image
-// src_height: height of the source image
-// src_data: address of the source image data
-// components: number of components in the image.
-static void FilterTexel(unsigned int x,
- unsigned int y,
- unsigned int dst_width,
- unsigned int dst_height,
- uint8 *dst_data,
- unsigned int src_width,
- unsigned int src_height,
- const uint8 *src_data,
- unsigned int components) {
- DCHECK(Bitmap::CheckImageDimensions(src_width, src_height));
- DCHECK(Bitmap::CheckImageDimensions(dst_width, dst_height));
- DCHECK_LE(dst_width, src_width);
- DCHECK_LE(dst_height, src_height);
- DCHECK_LE(x, dst_width);
- DCHECK_LE(y, dst_height);
- // the texel at (x, y) represents the square of texture coordinates
- // [x/dst_w, (x+1)/dst_w) x [y/dst_h, (y+1)/dst_h).
- // This takes contributions from the texels:
- // [floor(x*src_w/dst_w), ceil((x+1)*src_w/dst_w)-1]
- // x
- // [floor(y*src_h/dst_h), ceil((y+1)*src_h/dst_h)-1]
- // from the previous level.
- unsigned int src_min_x = (x*src_width)/dst_width;
- unsigned int src_max_x = ((x+1)*src_width+dst_width-1)/dst_width - 1;
- unsigned int src_min_y = (y*src_height)/dst_height;
- unsigned int src_max_y = ((y+1)*src_height+dst_height-1)/dst_height - 1;
-
- // Find the contribution of source each texel, by computing the coverage of
- // the destination texel on the source texel. We do all the computations in
- // fixed point, at a src_height*src_width factor to be able to use ints,
- // but keep all the precision.
- // Accumulators need to be 64 bits though, because src_height*src_width can
- // be 24 bits for a 4kx4k base, to which we need to multiply the component
- // value which is another 8 bits (and we need to accumulate several of them).
-
- // NOTE: all of our formats use at most 4 components per pixel.
- // Instead of dynamically allocating a buffer for each pixel on the heap,
- // just allocate the worst case on the stack.
- DCHECK_LE(components, 4u);
- uint64 accum[4] = {0};
- for (unsigned int src_x = src_min_x; src_x <= src_max_x; ++src_x) {
- for (unsigned int src_y = src_min_y; src_y <= src_max_y; ++src_y) {
- // The contribution of a fully covered texel is 1/(m_x*m_y) where m_x is
- // the x-dimension minification factor (src_width/dst_width) and m_y is
- // the y-dimenstion minification factor (src_height/dst_height).
- // If the texel is partially covered (on a border), the contribution is
- // proportional to the covered area. We compute it as the product of the
- // covered x-length by the covered y-length.
-
- unsigned int x_contrib = dst_width;
- if (src_x * dst_width < x * src_width) {
- // source texel is across the left border of the footprint of the
- // destination texel.
- x_contrib = (src_x + 1) * dst_width - x * src_width;
- } else if ((src_x + 1) * dst_width > (x+1) * src_width) {
- // source texel is across the right border of the footprint of the
- // destination texel.
- x_contrib = (x+1) * src_width - src_x * dst_width;
- }
- DCHECK(x_contrib > 0);
- DCHECK(x_contrib <= dst_width);
- unsigned int y_contrib = dst_height;
- if (src_y * dst_height < y * src_height) {
- // source texel is across the top border of the footprint of the
- // destination texel.
- y_contrib = (src_y + 1) * dst_height - y * src_height;
- } else if ((src_y + 1) * dst_height > (y+1) * src_height) {
- // source texel is across the bottom border of the footprint of the
- // destination texel.
- y_contrib = (y+1) * src_height - src_y * dst_height;
- }
- DCHECK(y_contrib > 0);
- DCHECK(y_contrib <= dst_height);
- unsigned int contrib = x_contrib * y_contrib;
- for (unsigned int c = 0; c < components; ++c) {
- accum[c] +=
- contrib * src_data[(src_y * src_width + src_x) * components + c];
- }
- }
- }
- for (unsigned int c = 0; c < components; ++c) {
- uint64 value = accum[c] / (src_height * src_width);
- DCHECK_LE(value, 255u);
- dst_data[(y * dst_width + x) * components + c] =
- static_cast<uint8>(value);
- }
+ GenerateMipmaps(image::ComputeMipDimension(source_level, width()),
+ image::ComputeMipDimension(source_level, height()),
+ format(),
+ num_levels,
+ GetMipData(source_level));
}
+// NOTE: This only works for Bitmap since Bitmap knows the pitch.
bool Bitmap::GenerateMipmaps(unsigned int base_width,
unsigned int base_height,
Texture::Format format,
unsigned int num_mipmaps,
uint8 *data) {
- DCHECK(CheckImageDimensions(base_width, base_height));
- unsigned int components = 0;
- switch (format) {
- case Texture::XRGB8:
- case Texture::ARGB8:
- components = 4;
- break;
- case Texture::ABGR16F:
- case Texture::R32F:
- case Texture::ABGR32F:
- case Texture::DXT1:
- case Texture::DXT3:
- case Texture::DXT5:
- case Texture::UNKNOWN_FORMAT:
- DLOG(ERROR) << "Mip-map generation not supported for format: " << format;
- return false;
+ DCHECK(image::CheckImageDimensions(base_width, base_height));
+ unsigned int components = image::GetNumComponentsForFormat(format);
+ if (components == 0) {
+ DLOG(ERROR) << "Mip-map generation not supported for format: " << format;
+ return false;
}
- DCHECK_GE(std::max(base_width, base_height) >> (num_mipmaps-1), 1u);
+ DCHECK_GE(std::max(base_width, base_height) >> (num_mipmaps - 1), 1u);
uint8 *mip_data = data;
unsigned int mip_width = base_width;
unsigned int mip_height = base_height;
@@ -790,239 +440,14 @@ bool Bitmap::GenerateMipmaps(unsigned int base_width,
unsigned int prev_height = mip_height;
uint8 *prev_data = mip_data;
mip_data += components * mip_width * mip_height;
- DCHECK_EQ(mip_data, data + GetMipChainSize(base_width, base_height, format,
- level));
+ DCHECK_EQ(mip_data, data + image::ComputeMipChainSize(
+ base_width, base_height, format, level));
mip_width = std::max(1U, mip_width >> 1);
mip_height = std::max(1U, mip_height >> 1);
-
- if (mip_width * 2 == prev_width && mip_height * 2 == prev_height) {
- // Easy case: every texel maps to exactly 4 texels in the previous level.
- for (unsigned int y = 0; y < mip_height; ++y) {
- for (unsigned int x = 0; x < mip_width; ++x) {
- for (unsigned int c = 0; c < components; ++c) {
- // Average the 4 texels.
- unsigned int offset = (y*2*prev_width + x*2) * components + c;
- unsigned int value = prev_data[offset]; // (2x, 2y)
- value += prev_data[offset+components]; // (2x+1, 2y)
- value += prev_data[offset+prev_width*components]; // (2x, 2y+1)
- value +=
- prev_data[offset+(prev_width+1)*components]; // (2x+1, 2y+1)
- mip_data[(y*mip_width+x) * components + c] = value/4;
- }
- }
- }
- } else {
- for (unsigned int y = 0; y < mip_height; ++y) {
- for (unsigned int x = 0; x < mip_width; ++x) {
- FilterTexel(x, y, mip_width, mip_height, mip_data, prev_width,
- prev_height, prev_data, components);
- }
- }
- }
- }
-
- return true;
-}
-
-// Scales the image using basic point filtering.
-bool Bitmap::ScaleUpToPOT(unsigned int width,
- unsigned int height,
- Texture::Format format,
- const uint8 *src,
- uint8 *dst,
- int dst_pitch) {
- DCHECK(CheckImageDimensions(width, height));
- switch (format) {
- case Texture::XRGB8:
- case Texture::ARGB8:
- case Texture::ABGR16F:
- case Texture::R32F:
- case Texture::ABGR32F:
- break;
- case Texture::DXT1:
- case Texture::DXT3:
- case Texture::DXT5:
- case Texture::UNKNOWN_FORMAT:
- DCHECK(false);
- return false;
- }
- unsigned int pot_width = GetPOTSize(width);
- unsigned int pot_height = GetPOTSize(height);
- if (pot_width == width && pot_height == height && src == dst)
- return true;
- return Scale(
- width, height, format, src, pot_width, pot_height, dst, dst_pitch);
-}
-
-namespace {
-
-template <typename T>
-void PointScale(
- unsigned components,
- const uint8* src,
- unsigned src_width,
- unsigned src_height,
- uint8* dst,
- int dst_pitch,
- unsigned dst_width,
- unsigned dst_height) {
- const T* use_src = reinterpret_cast<const T*>(src);
- T* use_dst = reinterpret_cast<T*>(dst);
- int pitch = dst_pitch / sizeof(*use_src) / components;
- // Start from the end to be able to do it in place.
- for (unsigned int y = dst_height - 1; y < dst_height; --y) {
- // max value for y is dst_height - 1, which makes :
- // base_y = (2*dst_height - 1) * src_height / (2 * dst_height)
- // which is < src_height.
- unsigned int base_y = ((y * 2 + 1) * src_height) / (dst_height * 2);
- DCHECK_LT(base_y, src_height);
- for (unsigned int x = dst_width - 1; x < dst_width; --x) {
- unsigned int base_x = ((x * 2 + 1) * src_width) / (dst_width * 2);
- DCHECK_LT(base_x, src_width);
- for (unsigned int c = 0; c < components; ++c) {
- use_dst[(y * pitch + x) * components + c] =
- use_src[(base_y * src_width + base_x) * components + c];
- }
- }
- }
-}
-
-} // anonymous namespace
-
-// Scales the image using basic point filtering.
-bool Bitmap::Scale(unsigned int src_width,
- unsigned int src_height,
- Texture::Format format,
- const uint8 *src,
- unsigned int dst_width,
- unsigned int dst_height,
- uint8 *dst,
- int dst_pitch) {
- DCHECK(CheckImageDimensions(src_width, src_height));
- DCHECK(CheckImageDimensions(dst_width, dst_height));
- switch (format) {
- case Texture::XRGB8:
- case Texture::ARGB8: {
- PointScale<uint8>(4, src, src_width, src_height,
- dst, dst_pitch, dst_width, dst_height);
- break;
- }
- case Texture::ABGR16F: {
- PointScale<uint16>(4, src, src_width, src_height,
- dst, dst_pitch, dst_width, dst_height);
- break;
- }
- case Texture::R32F:
- case Texture::ABGR32F: {
- PointScale<float>(format == Texture::R32F ? 1 : 4,
- src, src_width, src_height,
- dst, dst_pitch, dst_width, dst_height);
- break;
- }
- case Texture::DXT1:
- case Texture::DXT3:
- case Texture::DXT5:
- case Texture::UNKNOWN_FORMAT:
- DCHECK(false);
- return false;
- }
- return true;
-}
-
-// Adjust boundaries when using DrawImage function in bitmap or texture.
-bool Bitmap::AdjustDrawImageBoundary(int* src_x, int* src_y,
- int* src_width, int* src_height,
- int src_bmp_width, int src_bmp_height,
- int* dest_x, int* dest_y,
- int* dest_width, int* dest_height,
- int dest_bmp_width, int dest_bmp_height) {
- // if src or dest rectangle is out of boundaries, do nothing.
- if ((*src_x < 0 && *src_x + *src_width <= 0) ||
- (*src_y < 0 && *src_y + *src_height <= 0) ||
- (*dest_x < 0 && *dest_x + *dest_width <= 0) ||
- (*dest_y < 0 && *dest_y + *dest_height <= 0) ||
- (*src_x >= src_bmp_width &&
- *src_x + *src_width >= src_bmp_width - 1) ||
- (*src_y >= src_bmp_height &&
- *src_y + *src_height >= src_bmp_height - 1) ||
- (*dest_x >= dest_bmp_width &&
- *dest_x + *dest_width >= dest_bmp_width - 1) ||
- (*dest_y >= dest_bmp_height &&
- *dest_y + *dest_height >= dest_bmp_height - 1))
- return false;
-
- // if start points are negative.
- // check whether src_x is negative.
- if (!AdjustDrawImageBoundHelper(src_x, dest_x,
- src_width, dest_width, src_bmp_width))
- return false;
- // check whether dest_x is negative.
- if (!AdjustDrawImageBoundHelper(dest_x, src_x,
- dest_width, src_width, dest_bmp_width))
- return false;
- // check whether src_y is negative.
- if (!AdjustDrawImageBoundHelper(src_y, dest_y,
- src_height, dest_height, src_bmp_height))
- return false;
- // check whether dest_y is negative.
- if (!AdjustDrawImageBoundHelper(dest_y, src_y,
- dest_height, src_height, dest_bmp_height))
- return false;
-
- // check any width or height becomes negative after adjustment.
- if (*src_width == 0 || *src_height == 0 ||
- *dest_width == 0 || *dest_height == 0) {
- return false;
- }
-
- return true;
-}
-
-// utility function called in AdjustDrawImageBoundary.
-// help to adjust a specific dimension,
-// if start point or ending point is out of boundary.
-bool Bitmap::AdjustDrawImageBoundHelper(int* src_a, int* dest_a,
- int* src_length, int* dest_length,
- int src_bmp_length) {
- if (*src_length == 0 || *dest_length == 0)
- return false;
-
- // check if start point is out of boundary.
- // if src_a < 0, src_length must be positive.
- if (*src_a < 0) {
- int src_length_delta = 0 - *src_a;
- *dest_a = *dest_a + (*dest_length) * src_length_delta / (*src_length);
- *dest_length = *dest_length - (*dest_length) *
- src_length_delta / (*src_length);
- *src_length = *src_length - src_length_delta;
- *src_a = 0;
- }
- // if src_a >= src_bmp_width, src_length must be negative.
- if (*src_a >= src_bmp_length) {
- int src_length_delta = *src_a - (src_bmp_length - 1);
- *dest_a = *dest_a - (*dest_length) * src_length_delta / (*src_length);
- *dest_length = *dest_length - (*dest_length) *
- src_length_delta / *src_length;
- *src_length = *src_length - src_length_delta;
- *src_a = src_bmp_length - 1;
- }
-
- if (*src_length == 0 || *dest_length == 0)
- return false;
- // check whether start point + related length is out of boundary.
- // if src_a + src_length > src_bmp_length, src_length must be positive.
- if (*src_a + *src_length > src_bmp_length) {
- int src_length_delta = *src_length - (src_bmp_length - *src_a);
- *dest_length = *dest_length - (*dest_length) *
- src_length_delta / (*src_length);
- *src_length = *src_length - src_length_delta;
- }
- // if src_a + src_length < -1, src_length must be negative.
- if (*src_a + *src_length < -1) {
- int src_length_delta = 0 - (*src_a + *src_length);
- *dest_length = *dest_length + (*dest_length) *
- src_length_delta / (*src_length);
- *src_length = *src_length + src_length_delta;
+ image::GenerateMipmap(
+ prev_width, prev_height, format,
+ prev_data, image::ComputePitch(format, prev_width),
+ mip_data, image::ComputePitch(format, mip_width));
}
return true;
@@ -1043,7 +468,7 @@ bool Bitmap::CheckAlphaIsOne() const {
const uint8 *data = GetFaceMipData(
static_cast<TextureCUBE::CubeFace>(face),
level) + 3;
- const uint8* end = data + Bitmap::GetBufferSize(
+ const uint8* end = data + image::ComputeBufferSize(
std::max(1U, width() >> level),
std::max(1U, height() >> level),
format());
@@ -1064,7 +489,7 @@ bool Bitmap::CheckAlphaIsOne() const {
const uint8 *data = GetFaceMipData(
static_cast<TextureCUBE::CubeFace>(face),
level);
- const uint8* end = data + Bitmap::GetBufferSize(
+ const uint8* end = data + image::ComputeBufferSize(
std::max(1U, width() >> level),
std::max(1U, height() >> level),
format());
@@ -1093,7 +518,7 @@ bool Bitmap::CheckAlphaIsOne() const {
const uint8 *data = GetFaceMipData(
static_cast<TextureCUBE::CubeFace>(face),
level) + 6;
- const uint8* end = data + Bitmap::GetBufferSize(
+ const uint8* end = data + image::ComputeBufferSize(
std::max(1U, width() >> level),
std::max(1U, height() >> level),
format());
@@ -1116,7 +541,7 @@ bool Bitmap::CheckAlphaIsOne() const {
const uint8* data = GetFaceMipData(
static_cast<TextureCUBE::CubeFace>(face),
level) + 12;
- const uint8* end = data + Bitmap::GetBufferSize(
+ const uint8* end = data + image::ComputeBufferSize(
std::max(1U, width() >> level),
std::max(1U, height() >> level),
format());
diff --git a/o3d/core/cross/bitmap.h b/o3d/core/cross/bitmap.h
index 0491aac..5bd3687 100644
--- a/o3d/core/cross/bitmap.h
+++ b/o3d/core/cross/bitmap.h
@@ -45,6 +45,7 @@
#include "base/cross/bits.h"
#include "core/cross/types.h"
#include "core/cross/texture.h"
+#include "core/cross/image_utils.h"
class FilePath;
@@ -67,29 +68,20 @@ class Bitmap : public ParamObject {
explicit Bitmap(ServiceLocator* service_locator);
virtual ~Bitmap() {}
- // We will fail to load images that are bigger than 4kx4k to avoid security
- // risks. GPUs don't usually support bigger sizes anyway.
- // The biggest bitmap buffer size with these dimensions is:
- // 4k x 4k x 4xsizeof(float) x6 x4/3 (x6 for cube maps, x4/3 for mipmaps)
- // That makes 2GB, representable in an unsigned int, so we will avoid wraps.
- static const unsigned int kMaxImageDimension = 4096;
- enum ImageFileType {
- UNKNOWN,
- TGA,
- JPEG,
- PNG,
- DDS,
+ enum Semantic {
+ FACE_POSITIVE_X,
+ FACE_NEGATIVE_X,
+ FACE_POSITIVE_Y,
+ FACE_NEGATIVE_Y,
+ FACE_POSITIVE_Z,
+ FACE_NEGATIVE_Z,
+ NORMAL,
+ SLICE,
};
- static bool CheckImageDimensions(unsigned int width, unsigned int height) {
- return width > 0 && height > 0 &&
- width <= kMaxImageDimension && height < kMaxImageDimension;
- }
-
- // Computes one dimension of a mip.
- static unsigned GetMipDimension(int level, unsigned dimension) {
- unsigned v = dimension >> level;
- return v > 0 ? v : 1u;
+ // Returns the pitch of the bitmap for a certain level.
+ int GetMipPitch(int level) const {
+ return image::ComputeMipPitch(format(), level, width());
}
// Creates a copy of a bitmap, copying the pixels as well.
@@ -184,16 +176,10 @@ class Bitmap : public ParamObject {
int src_pitch);
// Gets the total size of the bitmap data, counting all faces and mip levels.
- unsigned int GetTotalSize() {
- return (is_cubemap_ ? 6 : 1) *
- GetMipChainSize(width_, height_, format_, num_mipmaps_);
+ unsigned int GetTotalSize() const {
+ return (is_cubemap_ ? 6 : 1) * GetMipChainSize(num_mipmaps_);
}
- // Computes the number of bytes of a texture pixel buffer.
- static unsigned int GetBufferSize(unsigned int width,
- unsigned int height,
- Texture::Format format);
-
// Gets the image data for a given mip-map level.
// Parameters:
// level: mip level to get.
@@ -201,10 +187,13 @@ class Bitmap : public ParamObject {
// Gets the image data for a given mip-map level and cube map face.
// Parameters:
- // face: face of cube to get.
+ // face: face of cube to get. This parameter is ignored if
+ // this bitmap is not a cube map.
// level: mip level to get.
- uint8 *GetFaceMipData(TextureCUBE::CubeFace face,
- unsigned int level) const;
+ uint8 *GetFaceMipData(TextureCUBE::CubeFace face, unsigned int level) const;
+
+ // Gets the size of mip.
+ unsigned int GetMipSize(unsigned int level) const;
uint8 *image_data() const { return image_data_.get(); }
Texture::Format format() const { return format_; }
@@ -232,7 +221,7 @@ class Bitmap : public ParamObject {
// known extension, all the loaders will be tried.
// generate_mipmaps: whether or not to generate all the mip-map levels.
bool LoadFromFile(const FilePath &filepath,
- ImageFileType file_type,
+ image::ImageFileType file_type,
bool generate_mipmaps);
// Loads a bitmap from a RawData object.
@@ -244,39 +233,14 @@ class Bitmap : public ParamObject {
// be tried.
// generate_mipmaps: whether or not to generate all the mip-map levels.
bool LoadFromRawData(RawData *raw_data,
- ImageFileType file_type,
+ image::ImageFileType file_type,
bool generate_mipmaps);
- // Loads a bitmap from a MemoryReadStream.
- // Parameters:
- // stream: a stream for the bitmap data in one of the known formats
- // filename: a filename (or uri) of the original bitmap data
- // (may be an empty string)
- // file_type: the format of the bitmap data. If UNKNOWN, the file type
- // will be determined from the extension of |filename|
- // and if it is not a known extension, all the loaders
- // will be tried.
- // generate_mipmaps: whether or not to generate all the mip-map levels.
- bool LoadFromStream(MemoryReadStream *stream,
- const String &filename,
- ImageFileType file_type,
- bool generate_mipmaps);
-
- bool LoadFromPNGStream(MemoryReadStream *stream,
- const String &filename,
- bool generate_mipmaps);
-
- bool LoadFromTGAStream(MemoryReadStream *stream,
- const String &filename,
- bool generate_mipmaps);
-
- bool LoadFromDDSStream(MemoryReadStream *stream,
- const String &filename,
- bool generate_mipmaps);
-
- bool LoadFromJPEGStream(MemoryReadStream *stream,
- const String &filename,
- bool generate_mipmaps);
+ // Flips a bitmap vertically in place.
+ // This is needed instead of just using DrawImage because flipping DXT formats
+ // using generic algorithms would be lossy and extremely slow to reconvert
+ // from a flippable format back to a DXT format.
+ void FlipVertically();
// Saves to a PNG file. The image must be of the ARGB8 format, be a 2D image
// with no mip-maps (only the base level).
@@ -301,159 +265,19 @@ class Bitmap : public ParamObject {
// dest_y: y-coordinate of the starting pixel in the dest image.
// dest_width: width of the dest image to draw.
// dest_height: height of the dest image to draw.
- void DrawImage(Bitmap* source_img, int source_x, int source_y,
+ void DrawImage(const Bitmap& source_img, int source_x, int source_y,
int source_width, int source_height,
int dest_x, int dest_y,
int dest_width, int dest_height);
- // Crop part of an image from src, scale it to an arbitrary size
- // and paste in dest image. Utility function for all DrawImage
- // function in bitmap and textures. Scale operation is based on
- // Lanczos resampling.
- // Note: this doesn't work for DXTC, or floating-point images.
- //
- // Parameters:
- // src: source image which would be copied from.
- // src_x: x-coordinate of the starting pixel in the src image.
- // src_y: y-coordinate of the starting pixel in the src image.
- // src_width: width of the part in src image to be croped.
- // src_height: height of the part in src image to be croped.
- // src_img_width: width of the src image.
- // src_img_height: height of the src image.
- // dest: dest image which would be copied to.
- // dest_x: x-coordinate of the starting pixel in the dest image.
- // dest_y: y-coordinate of the starting pixel in the dest image.
- // dest_width: width of the part in dest image to be pasted to.
- // dest_height: height of the part in dest image to be pasted to.
- // dest_img_width: width of the dest image.
- // dest_img_height: height of the src image.
- // component: size of each pixel in terms of array element.
- // Returns:
- // true if crop and scale succeeds.
- static void LanczosScale(const uint8* src,
- int src_x, int src_y,
- int src_width, int src_height,
- int src_img_width, int src_img_height,
- uint8* dest, int dest_pitch,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int dest_img_width, int dest_img_height,
- int component);
-
- // Detects the type of image file based on the filename.
- static ImageFileType GetFileTypeFromFilename(const char *filename);
- // Detects the type of image file based on the mime-type.
- static ImageFileType GetFileTypeFromMimeType(const char *mime_type);
-
- // Adds filler alpha byte (0xff) after every pixel. Assumes buffer was
- // allocated with enough storage)
- // can convert RGB -> RGBA, BGR -> BGRA, etc.
- static void XYZToXYZA(uint8 *image_data, int pixel_count);
-
- // Swaps Red and Blue components in the image.
- static void RGBAToBGRA(uint8 *image_data, int pixel_count);
-
- // Gets the number of mip-maps required for a full chain starting at
- // width x height.
- static unsigned int GetMipMapCount(unsigned int width, unsigned int height) {
- return 1 + base::bits::Log2Floor(std::max(width, height));
- }
-
- // Gets the smallest power-of-two value that is at least as high as
- // dimension. This is the POT dimension used in ScaleUpToPOT.
- static unsigned int GetPOTSize(unsigned int dimension) {
- return 1 << base::bits::Log2Ceiling(dimension);
+ // Gets the size of the buffer containing a mip-map chain, given a number of
+ // mip-map levels.
+ unsigned int GetMipChainSize(unsigned int num_mipmaps) const {
+ return image::ComputeMipChainSize(width(), height(), format(), num_mipmaps);
}
- // Gets the size of the buffer containing a mip-map chain, given its base
- // width, height, format and number of mip-map levels.
- static unsigned int GetMipChainSize(unsigned int base_width,
- unsigned int base_height,
- Texture::Format format,
- unsigned int num_mipmaps);
-
- // Generates mip-map levels for a single image, using the data from the base
- // level.
- // NOTE: this doesn't work for DXTC, or floating-point images.
- //
- // Parameters:
- // base_width: the width of the base image.
- // base_height: the height of the base image.
- // format: the format of the data.
- // num_mipmaps: the number of mipmaps to generate.
- // data: the data containing the base image, and enough space for the
- // mip-maps.
- static bool GenerateMipmaps(unsigned int base_width,
- unsigned int base_height,
- Texture::Format format,
- unsigned int num_mipmaps,
- uint8 *data);
-
- // Scales an image up to power-of-two textures, using point filtering.
- // NOTE: this doesn't work for DXTC, or floating-point images.
- //
- // Parameters:
- // width: the non-power-of-two width of the original image.
- // height: the non-power-of-two height of the original image.
- // format: the format of the data.
- // src: the data containing the source data of the original image.
- // dst: a buffer with enough space for the power-of-two version. Pixels are
- // written from the end to the beginning so dst can be the same buffer
- // as src.
- // dst_pitch: Number of bytes across 1 row of pixels.
- static bool ScaleUpToPOT(unsigned int width,
- unsigned int height,
- Texture::Format format,
- const uint8 *src,
- uint8 *dst,
- int dst_pitch);
-
- // Scales an image to an arbitrary size, using point filtering.
- // NOTE: this doesn't work for DXTC, or floating-point images.
- //
- // Parameters:
- // src_width: the width of the original image.
- // src_height: the height of the original image.
- // format: the format of the data.
- // src: the data containing the source data of the original image.
- // dst_width: the width of the target image.
- // dst_height: the height of the target image.
- // dst: a buffer with enough space for the target version. Pixels are
- // written from the end to the beginning so dst can be the same buffer
- // as src if the transformation is an upscaling.
- // dst_pitch: Number of bytes across 1 row of pixels.
- static bool Scale(unsigned int src_width,
- unsigned int src_height,
- Texture::Format format,
- const uint8 *src,
- unsigned int dst_width,
- unsigned int dst_height,
- uint8 *dst,
- int dst_pitch);
-
- // adjust start points and boundaries when using DrawImage data
- // in bitmap and textures.
- // Parameters:
- // src_x: x-coordinate of the starting pixel in the source image.
- // src_y: y-coordinate of the starting pixel in the source image.
- // src_width: width of the source image to draw.
- // src_height: height of the source image to draw.
- // src_bmp_width: original width of source bitmap.
- // src_bmp_height: original height of source bitmap.
- // dest_x: x-coordinate of the starting pixel in the dest image.
- // dest_y: y-coordinate of the starting pixel in the dest image.
- // dest_width: width of the dest image to draw.
- // dest_height: height of the dest image to draw.
- // dest_bmp_width: original width of dest bitmap.
- // dest_bmp_height: original height of dest bitmap.
- // Returns:
- // false if src or dest rectangle is out of boundaries.
- static bool AdjustDrawImageBoundary(int* src_x, int* src_y,
- int* src_width, int* src_height,
- int src_bmp_width, int src_bmp_height,
- int* dest_x, int* dest_y,
- int* dest_width, int* dest_height,
- int dest_bmp_width, int dest_bmp_height);
+ // Generates Mips from the source_level for num_levels
+ void GenerateMips(int source_level, int num_levels);
private:
friend class IClassManager;
@@ -472,56 +296,117 @@ class Bitmap : public ParamObject {
// is this cube-map data
bool is_cubemap_;
- // utility function used in AdjustDrawImageBoundary.
- // It adjusts start point and related measures
- // for a specific dimension.
- // Parameter:
- // src_a: the coordinate which is negative.
- // dest_a: same coordinate in the other image.
- // src_length: length measure of source image to draw.
- // dest_length: length measure of dest image to draw.
- // src_bmp_length: length measure of src image.
- // Returns:
- // true if adjust is successful.
- static bool AdjustDrawImageBoundHelper(int* src_a, int* dest_a,
- int* src_length, int* dest_length,
- int src_bmp_length);
-
- // utility function for LanczosScale function.
- // Given an image, It can scale the image in one dimension to the new
- // length using a Lanczos3 windowsed-sinc filter. This filter has
- // fairly large support, in choosing it we favor quality over speed.
- // In parameters we assume the current dimension we are scaling is
- // width, but by changing the parameter, we can easily using this
- // function on height as well.
- // Parameter:
- // src: source image which would be copied from.
- // src_x: x-coordinate of the starting pixel in the source image.
- // src_y: y-coordinate of the starting pixel in the source image.
- // width: width of the part in src image to be croped.
- // height: height of the part in src image to be croped.
- // src_bmp_width: original width of source bitmap.
- // src_bmp_height: original height of source bitmap.
- // dest: dest image which would be copied to.
- // dest_x: x-coordinate of the starting pixel in the dest image.
- // dest_y: y-coordinate of the starting pixel in the dest image.
- // dest_bmp_width: original width of dest bitmap.
- // dest_bmp_height: original height of dest bitmap.
- // isWidth: which dimension we are working on.
- // components: size of each pixel in terms of array element.
- static void LanczosResize1D(const uint8* src, int src_x, int src_y,
- int width, int height,
- int src_bmp_width, int src_bmp_height,
- uint8* dest, int dest_pitch,
- int dest_x, int dest_y,
- int nwidth,
- int dest_bmp_width, int dest_bmp_height,
- bool isWidth, int components);
+ // Loads a bitmap from a MemoryReadStream.
+ // Parameters:
+ // stream: a stream for the bitmap data in one of the known formats
+ // filename: a filename (or uri) of the original bitmap data
+ // (may be an empty string)
+ // file_type: the format of the bitmap data. If UNKNOWN, the file type
+ // will be determined from the extension of |filename|
+ // and if it is not a known extension, all the loaders
+ // will be tried.
+ // generate_mipmaps: whether or not to generate all the mip-map levels.
+ bool LoadFromStream(MemoryReadStream *stream,
+ const String &filename,
+ image::ImageFileType file_type,
+ bool generate_mipmaps);
+
+ bool LoadFromPNGStream(MemoryReadStream *stream,
+ const String &filename,
+ bool generate_mipmaps);
+
+ bool LoadFromTGAStream(MemoryReadStream *stream,
+ const String &filename,
+ bool generate_mipmaps);
+
+ bool LoadFromDDSStream(MemoryReadStream *stream,
+ const String &filename,
+ bool generate_mipmaps);
+
+ bool LoadFromJPEGStream(MemoryReadStream *stream,
+ const String &filename,
+ bool generate_mipmaps);
+
+ bool GenerateMipmaps(unsigned int base_width,
+ unsigned int base_height,
+ Texture::Format format,
+ unsigned int num_mipmaps,
+ uint8 *data);
O3D_DECL_CLASS(Bitmap, ParamObject);
DISALLOW_COPY_AND_ASSIGN(Bitmap);
};
+class BitmapUncompressed : public Bitmap {
+ public:
+ explicit BitmapUncompressed(ServiceLocator* service_locator);
+};
+
+template <typename T>
+class TypedBitmapUncompressed : public BitmapUncompressed {
+ public:
+ typedef T ComponentType;
+ explicit TypedBitmapUncompressed(ServiceLocator* service_locator)
+ : BitmapUncompressed(service_locator) {
+ }
+};
+
+class Bitmap8 : public TypedBitmapUncompressed<uint8> {
+ public:
+ explicit Bitmap8(ServiceLocator* service_locator);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Bitmap8);
+};
+
+class Bitmap16F : public TypedBitmapUncompressed<uint16> {
+ public:
+ explicit Bitmap16F(ServiceLocator* service_locator);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Bitmap16F);
+};
+
+class Bitmap32F : public TypedBitmapUncompressed<float> {
+ public:
+ explicit Bitmap32F(ServiceLocator* service_locator);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Bitmap32F);
+};
+
+class BitmapCompressed : public Bitmap {
+ public:
+ explicit BitmapCompressed(ServiceLocator* service_locator);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BitmapCompressed);
+};
+
+class BitmapDXT1 : public BitmapCompressed {
+ public:
+ explicit BitmapDXT1(ServiceLocator* service_locator);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BitmapDXT1);
+};
+
+class BitmapDXT3 : public BitmapCompressed {
+ public:
+ explicit BitmapDXT3(ServiceLocator* service_locator);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BitmapDXT3);
+};
+
+class BitmapDXT5 : public BitmapCompressed {
+ public:
+ explicit BitmapDXT5(ServiceLocator* service_locator);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BitmapDXT5);
+};
+
} // namespace o3d
#endif // O3D_CORE_CROSS_BITMAP_H_
diff --git a/o3d/core/cross/bitmap_dds.cc b/o3d/core/cross/bitmap_dds.cc
index a4f9491..b5ad5fa 100644
--- a/o3d/core/cross/bitmap_dds.cc
+++ b/o3d/core/cross/bitmap_dds.cc
@@ -51,17 +51,17 @@ namespace o3d {
// LoadFromDDSFile -------------------------------------------------------------
// A function that flips a DXTC block.
-typedef void (* FlipBlockFunction)(unsigned char *block);
+typedef void (* FlipBlockFunction)(uint8 *block);
// Flips a full DXT1 block in the y direction.
-static void FlipDXT1BlockFull(unsigned char *block) {
+static void FlipDXT1BlockFull(uint8 *block) {
// A DXT1 block layout is:
// [0-1] color0.
// [2-3] color1.
// [4-7] color bitmap, 2 bits per pixel.
// So each of the 4-7 bytes represents one line, flipping a block is just
// flipping those bytes.
- unsigned char tmp = block[4];
+ uint8 tmp = block[4];
block[4] = block[7];
block[7] = tmp;
tmp = block[5];
@@ -70,21 +70,21 @@ static void FlipDXT1BlockFull(unsigned char *block) {
}
// Flips the first 2 lines of a DXT1 block in the y direction.
-static void FlipDXT1BlockHalf(unsigned char *block) {
+static void FlipDXT1BlockHalf(uint8 *block) {
// See layout above.
- unsigned char tmp = block[4];
+ uint8 tmp = block[4];
block[4] = block[5];
block[5] = tmp;
}
// Flips a full DXT3 block in the y direction.
-static void FlipDXT3BlockFull(unsigned char *block) {
+static void FlipDXT3BlockFull(uint8 *block) {
// A DXT3 block layout is:
// [0-7] alpha bitmap, 4 bits per pixel.
// [8-15] a DXT1 block.
// We can flip the alpha bits at the byte level (2 bytes per line).
- unsigned char tmp = block[0];
+ uint8 tmp = block[0];
block[0] = block[6];
block[6] = tmp;
tmp = block[1];
@@ -102,9 +102,9 @@ static void FlipDXT3BlockFull(unsigned char *block) {
}
// Flips the first 2 lines of a DXT3 block in the y direction.
-static void FlipDXT3BlockHalf(unsigned char *block) {
+static void FlipDXT3BlockHalf(uint8 *block) {
// See layout above.
- unsigned char tmp = block[0];
+ uint8 tmp = block[0];
block[0] = block[2];
block[2] = tmp;
tmp = block[1];
@@ -114,7 +114,7 @@ static void FlipDXT3BlockHalf(unsigned char *block) {
}
// Flips a full DXT5 block in the y direction.
-static void FlipDXT5BlockFull(unsigned char *block) {
+static void FlipDXT5BlockFull(uint8 *block) {
// A DXT5 block layout is:
// [0] alpha0.
// [1] alpha1.
@@ -157,7 +157,7 @@ static void FlipDXT5BlockFull(unsigned char *block) {
}
// Flips the first 2 lines of a DXT5 block in the y direction.
-static void FlipDXT5BlockHalf(unsigned char *block) {
+static void FlipDXT5BlockHalf(uint8 *block) {
// See layout above.
unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]);
unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
@@ -173,8 +173,8 @@ static void FlipDXTCImage(unsigned int width,
unsigned int height,
unsigned int levels,
Texture::Format format,
- unsigned char *data) {
- DCHECK(Bitmap::CheckImageDimensions(width, height));
+ uint8 *data) {
+ DCHECK(image::CheckImageDimensions(width, height));
// Height must be a power-of-two.
DCHECK_EQ(height & (height - 1), 0u);
FlipBlockFunction full_block_function = NULL;
@@ -223,10 +223,10 @@ static void FlipDXTCImage(unsigned int width,
// corresponding one in the second half.
// note that this is a no-op if mip_height is 4.
unsigned int row_bytes = block_bytes * blocks_per_row;
- scoped_array<unsigned char> temp_line(new unsigned char[row_bytes]);
+ scoped_array<uint8> temp_line(new uint8[row_bytes]);
for (unsigned int y = 0; y < blocks_per_col / 2; ++y) {
- unsigned char *line1 = data + y * row_bytes;
- unsigned char *line2 = data + (blocks_per_col - y - 1) * row_bytes;
+ uint8 *line1 = data + y * row_bytes;
+ uint8 *line2 = data + (blocks_per_col - y - 1) * row_bytes;
memcpy(temp_line.get(), line1, row_bytes);
memcpy(line1, line2, row_bytes);
memcpy(line2, temp_line.get(), row_bytes);
@@ -244,20 +244,21 @@ static void FlipBGRAImage(unsigned int width,
unsigned int height,
unsigned int levels,
Texture::Format format,
- unsigned char *data) {
- DCHECK(Bitmap::CheckImageDimensions(width, height));
- DCHECK(format == Texture::XRGB8 || format == Texture::ARGB8);
- unsigned int pixel_bytes = 4;
+ uint8 *data) {
+ DCHECK(image::CheckImageDimensions(width, height));
+ DCHECK(format != Texture::DXT1 && format != Texture::DXT3 &&
+ format != Texture::DXT5);
+ unsigned int pixel_bytes = image::ComputeMipChainSize(1, 1, format, 1);
unsigned int mip_width = width;
unsigned int mip_height = height;
// rows are at most as big as the first one.
- scoped_array<unsigned char> temp_line(
- new unsigned char[mip_width * pixel_bytes]);
+ scoped_array<uint8> temp_line(
+ new uint8[mip_width * pixel_bytes]);
for (unsigned int i = 0; i < levels; ++i) {
unsigned int row_bytes = pixel_bytes * mip_width;
for (unsigned int y = 0; y < mip_height / 2; ++y) {
- unsigned char *line1 = data + y * row_bytes;
- unsigned char *line2 = data + (mip_height - y - 1) * row_bytes;
+ uint8 *line1 = data + y * row_bytes;
+ uint8 *line2 = data + (mip_height - y - 1) * row_bytes;
memcpy(temp_line.get(), line1, row_bytes);
memcpy(line1, line2, row_bytes);
memcpy(line2, temp_line.get(), row_bytes);
@@ -269,6 +270,19 @@ static void FlipBGRAImage(unsigned int width,
}
}
+void Bitmap::FlipVertically() {
+ if (!is_cubemap()) {
+ if (format() == Texture::DXT1 ||
+ format() == Texture::DXT3 ||
+ format() == Texture::DXT5) {
+ FlipDXTCImage(width(), height(), num_mipmaps(), format(), image_data());
+ } else {
+ FlipBGRAImage(width(), height(), num_mipmaps(), format(), image_data());
+ }
+ }
+}
+
+
// Load the bitmap data as DXTC compressed data from a DDS stream into the
// Bitmap object. This routine only supports compressed DDS formats DXT1,
// DXT3 and DXT5.
@@ -314,7 +328,7 @@ bool Bitmap::LoadFromDDSStream(MemoryReadStream *stream,
dd_surface_descriptor.dwMipMapCount : 1;
unsigned int dds_width = dd_surface_descriptor.dwWidth;
unsigned int dds_height = dd_surface_descriptor.dwHeight;
- if (!CheckImageDimensions(dds_width, dds_height)) {
+ if (!image::CheckImageDimensions(dds_width, dds_height)) {
DLOG(ERROR) << "Failed to load " << filename
<< ": dimensions are too large (" << dds_width
<< ", " << dds_height << ").";
@@ -376,7 +390,8 @@ bool Bitmap::LoadFromDDSStream(MemoryReadStream *stream,
// Check that the advertised size is correct.
if (dd_surface_descriptor.dwFlags & DDSD_LINEARSIZE) {
- unsigned int expected_size = GetBufferSize(dds_width, dds_height, format);
+ unsigned int expected_size =
+ image::ComputeBufferSize(dds_width, dds_height, format);
if (expected_size != dd_surface_descriptor.dwLinearSize) {
DLOG(ERROR) << "Advertised buffer size in \"" << filename
<< "\" differs from expected size.";
@@ -443,17 +458,18 @@ bool Bitmap::LoadFromDDSStream(MemoryReadStream *stream,
unsigned int num_faces = is_cubemap ? 6 : 1;
// power-of-two dimensions.
unsigned int final_mip_count =
- generate_mipmaps ? GetMipMapCount(dds_width, dds_height) : mip_count;
- unsigned int face_size = GetMipChainSize(dds_width, dds_height, format,
- final_mip_count);
+ generate_mipmaps ? image::ComputeMipMapCount(
+ dds_width, dds_height) : mip_count;
+ unsigned int face_size = image::ComputeMipChainSize(
+ dds_width, dds_height, format, final_mip_count);
unsigned int buffer_size = num_faces * face_size;
// Allocate and load bitmap data.
- scoped_array<unsigned char> image_data(new unsigned char[buffer_size]);
+ scoped_array<uint8> image_data(new uint8[buffer_size]);
- unsigned int disk_face_size = GetMipChainSize(dds_width, dds_height, format,
- mip_count);
+ unsigned int disk_face_size =
+ image::ComputeMipChainSize(dds_width, dds_height, format, mip_count);
if (!is_dxtc) {
// if reading uncompressed RGB, for example, we shouldn't read alpha channel
// NOTE: here we assume that RGB data is packed - it may not be true
@@ -475,25 +491,16 @@ bool Bitmap::LoadFromDDSStream(MemoryReadStream *stream,
DCHECK(components_per_pixel == 3 || components_per_pixel == 4);
unsigned int pixel_count = disk_face_size / components_per_pixel;
for (unsigned int face = 0; face < num_faces; ++face) {
- unsigned char *data = image_data.get() + face_size * face;
+ uint8 *data = image_data.get() + face_size * face;
// convert to four components per pixel if necessary
if (add_filler_alpha) {
DCHECK_EQ(components_per_pixel, 3u);
- XYZToXYZA(data, pixel_count);
+ image::XYZToXYZA(data, pixel_count);
} else {
DCHECK_EQ(components_per_pixel, 4u);
}
if (rgb_to_bgr)
- RGBAToBGRA(data, pixel_count);
- }
- }
-
- if (!is_cubemap) {
- // NOTE: we flip the images to respect max/maya's UV orientation.
- if (is_dxtc) {
- FlipDXTCImage(dds_width, dds_height, mip_count, format, image_data.get());
- } else {
- FlipBGRAImage(dds_width, dds_height, mip_count, format, image_data.get());
+ image::RGBAToBGRA(data, pixel_count);
}
}
@@ -502,11 +509,10 @@ bool Bitmap::LoadFromDDSStream(MemoryReadStream *stream,
// face.
unsigned int base_mip_width = dds_width >> (mip_count - 1);
unsigned int base_mip_height = dds_height >> (mip_count - 1);
- unsigned int base_mip_offset = GetMipChainSize(dds_width, dds_height,
- format, mip_count - 1);
+ unsigned int base_mip_offset = image::ComputeMipChainSize(
+ dds_width, dds_height, format, mip_count - 1);
for (unsigned int face = 0; face < num_faces; ++face) {
- unsigned char *data =
- image_data.get() + face_size * face + base_mip_offset;
+ uint8 *data = image_data.get() + face_size * face + base_mip_offset;
if (!GenerateMipmaps(base_mip_width, base_mip_height, format,
final_mip_count - mip_count, data)) {
DLOG(ERROR) << "mip-map generation failed for \"" << filename << "\"";
diff --git a/o3d/core/cross/bitmap_jpg.cc b/o3d/core/cross/bitmap_jpg.cc
index 565bb97..bbb31d3 100644
--- a/o3d/core/cross/bitmap_jpg.cc
+++ b/o3d/core/cross/bitmap_jpg.cc
@@ -151,7 +151,7 @@ bool Bitmap::LoadFromJPEGStream(MemoryReadStream *stream,
// NOTE: The following smart pointer needs to be declared before the
// setjmp so that it is properly destroyed if we jump back.
- scoped_array<unsigned char> image_data;
+ scoped_array<uint8> image_data;
// Establish the setjmp return context for my_error_exit to use.
if (setjmp(jerr.setjmp_buffer)) {
@@ -182,7 +182,7 @@ bool Bitmap::LoadFromJPEGStream(MemoryReadStream *stream,
// Set the Bitmap member variables from the jpeg_decompress_struct fields.
unsigned int width = cinfo.image_width;
unsigned int height = cinfo.image_height;
- if (!CheckImageDimensions(width, height)) {
+ if (!image::CheckImageDimensions(width, height)) {
DLOG(ERROR) << "Failed to load " << filename
<< ": dimensions are too large (" << width
<< ", " << height << ").";
@@ -199,12 +199,12 @@ bool Bitmap::LoadFromJPEGStream(MemoryReadStream *stream,
}
unsigned int image_components = 4;
unsigned int num_mipmaps =
- generate_mipmaps ? GetMipMapCount(width, height) : 1;
+ generate_mipmaps ? image::ComputeMipMapCount(width, height) : 1;
Texture::Format format = Texture::XRGB8;
// Allocate storage for the pixels.
- unsigned int image_size = GetMipChainSize(width, height, format,
- num_mipmaps);
- image_data.reset(new unsigned char[image_size]);
+ unsigned int image_size =
+ image::ComputeMipChainSize(width, height, format, num_mipmaps);
+ image_data.reset(new uint8[image_size]);
if (image_data.get() == NULL) {
DLOG(ERROR) << "JPEG memory allocation error \"" << filename << "\"";
// Invoke the longjmp() error handler.
@@ -237,6 +237,10 @@ bool Bitmap::LoadFromJPEGStream(MemoryReadStream *stream,
// Use the library's state variable cinfo.output_scanline as the
// loop counter, so that we don't have to keep track ourselves.
while (cinfo.output_scanline < height) {
+ // Initialise the buffer write location.
+ uint8 *image_write_ptr = image_data.get() +
+ cinfo.output_scanline * width * image_components;
+
// jpeg_read_scanlines() expects an array of pointers to scanlines.
// Here we ask for only one scanline to be read into "buffer".
jpeg_read_scanlines(&cinfo, buffer, 1);
@@ -244,11 +248,6 @@ bool Bitmap::LoadFromJPEGStream(MemoryReadStream *stream,
// output_scanline is the numbe of scanlines that have been emitted.
DCHECK_LE(cinfo.output_scanline, height);
- // Initialise the buffer write location.
- // NOTE: we load images bottom to up to respect max/maya's UV
- // orientation.
- unsigned char *image_write_ptr = image_data.get()
- + (height - cinfo.output_scanline) * width * image_components;
// copy the scanline to its final destination
for (unsigned int i = 0; i < width; ++i) {
// RGB -> BGRX
diff --git a/o3d/core/cross/bitmap_png.cc b/o3d/core/cross/bitmap_png.cc
index 38f5afe..770ced0 100644
--- a/o3d/core/cross/bitmap_png.cc
+++ b/o3d/core/cross/bitmap_png.cc
@@ -101,7 +101,7 @@ bool Bitmap::LoadFromPNGStream(MemoryReadStream *stream,
// NOTE: The following smart pointer needs to be declared before the
// setjmp so that it is properly destroyed if we jump back.
- scoped_array<unsigned char> image_data;
+ scoped_array<uint8> image_data;
png_bytepp row_pointers = NULL;
// Set error handling if you are using the setjmp/longjmp method. If any
@@ -139,7 +139,7 @@ bool Bitmap::LoadFromPNGStream(MemoryReadStream *stream,
NULL,
NULL);
- if (!CheckImageDimensions(png_width, png_height)) {
+ if (!image::CheckImageDimensions(png_width, png_height)) {
DLOG(ERROR) << "Failed to load " << filename
<< ": dimensions are too large (" << png_width
<< ", " << png_height << ").";
@@ -209,11 +209,11 @@ bool Bitmap::LoadFromPNGStream(MemoryReadStream *stream,
// Allocate storage for the pixels.
unsigned int num_mipmaps =
- generate_mipmaps ? GetMipMapCount(png_width, png_height) : 1;
+ generate_mipmaps ? image::ComputeMipMapCount(png_width, png_height) : 1;
// Allocate storage for the pixels.
- unsigned int png_image_size = GetMipChainSize(png_width, png_height, format,
- num_mipmaps);
- image_data.reset(new unsigned char[png_image_size]);
+ unsigned int png_image_size =
+ image::ComputeMipChainSize(png_width, png_height, format, num_mipmaps);
+ image_data.reset(new uint8[png_image_size]);
if (image_data.get() == NULL) {
DLOG(ERROR) << "PNG image memory allocation error \"" << filename << "\"";
png_error(png_ptr, "Cannot allocate memory for bitmap");
@@ -231,13 +231,10 @@ bool Bitmap::LoadFromPNGStream(MemoryReadStream *stream,
// Fill the row pointer array.
DCHECK_LE(png_get_rowbytes(png_ptr, info_ptr), png_width * dst_components);
- // NOTE: we load images bottom to up to respect max/maya's UV
- // orientation.
- png_bytep row_ptr = reinterpret_cast<png_bytep>(image_data.get())
- + png_width * dst_components * (png_height - 1);
+ png_bytep row_ptr = reinterpret_cast<png_bytep>(image_data.get());
for (unsigned int i = 0; i < png_height; ++i) {
row_pointers[i] = row_ptr;
- row_ptr -= png_width * dst_components;
+ row_ptr += png_width * dst_components;
}
// Read the image, applying format transforms and de-interlacing as we go.
diff --git a/o3d/core/cross/bitmap_test.cc b/o3d/core/cross/bitmap_test.cc
index 36f474c..4278469 100644
--- a/o3d/core/cross/bitmap_test.cc
+++ b/o3d/core/cross/bitmap_test.cc
@@ -42,7 +42,7 @@ class BitmapTest : public testing::Test {
};
// The first 128 bytes of tga-256x256-24bit.tga, converted to BGRX format.
-static unsigned char ktga256x256_24bit_BGRX[128] = {
+static uint8 ktga256x256_24bit_BGRX[128] = {
0x36, 0x87, 0xbc, 0xff, 0x36, 0x87, 0xbc, 0xff,
0x35, 0x83, 0xb5, 0xff, 0x34, 0x83, 0xb5, 0xff,
0x35, 0x83, 0xb5, 0xff, 0x35, 0x82, 0xb5, 0xff,
@@ -61,7 +61,7 @@ static unsigned char ktga256x256_24bit_BGRX[128] = {
0x1d, 0x8d, 0x96, 0xff, 0x1b, 0x8f, 0x90, 0xff,
};
-static unsigned char ktga256x256_32bit_BGRA[128] = {
+static uint8 ktga256x256_32bit_BGRA[128] = {
0x36, 0x87, 0xbc, 0x7d, 0x36, 0x87, 0xbc, 0x7c,
0x35, 0x83, 0xb5, 0x78, 0x34, 0x83, 0xb5, 0x77,
0x35, 0x83, 0xb5, 0x77, 0x35, 0x82, 0xb5, 0x76,
@@ -80,7 +80,7 @@ static unsigned char ktga256x256_32bit_BGRA[128] = {
0x1d, 0x8d, 0x96, 0x75, 0x1b, 0x8f, 0x90, 0x75,
};
-static unsigned char kjpg256x256_BGRX[128] = {
+static uint8 kjpg256x256_BGRX[128] = {
0x3a, 0x88, 0xbd, 0xff, 0x38, 0x86, 0xbb, 0xff,
0x36, 0x85, 0xb8, 0xff, 0x34, 0x83, 0xb6, 0xff,
0x36, 0x82, 0xb6, 0xff, 0x35, 0x82, 0xb3, 0xff,
@@ -99,7 +99,7 @@ static unsigned char kjpg256x256_BGRX[128] = {
0x21, 0x8d, 0x99, 0xff, 0x1a, 0x8f, 0x8e, 0xff,
};
-static unsigned char kpng256x256_24bit_BGRX[128] = {
+static uint8 kpng256x256_24bit_BGRX[128] = {
0x36, 0x87, 0xbc, 0xff, 0x36, 0x87, 0xbc, 0xff,
0x35, 0x83, 0xb5, 0xff, 0x34, 0x83, 0xb5, 0xff,
0x35, 0x83, 0xb5, 0xff, 0x35, 0x82, 0xb5, 0xff,
@@ -118,7 +118,7 @@ static unsigned char kpng256x256_24bit_BGRX[128] = {
0x1d, 0x8d, 0x96, 0xff, 0x1b, 0x8f, 0x90, 0xff,
};
-static unsigned char kpng256x256_24bit_interlaced_BGRX[128] = {
+static uint8 kpng256x256_24bit_interlaced_BGRX[128] = {
0x36, 0x87, 0xbc, 0xff, 0x36, 0x87, 0xbc, 0xff,
0x35, 0x83, 0xb5, 0xff, 0x34, 0x83, 0xb5, 0xff,
0x35, 0x83, 0xb5, 0xff, 0x35, 0x82, 0xb5, 0xff,
@@ -137,7 +137,7 @@ static unsigned char kpng256x256_24bit_interlaced_BGRX[128] = {
0x1d, 0x8d, 0x96, 0xff, 0x1b, 0x8f, 0x90, 0xff,
};
-static unsigned char kpng256x256_32bit_BGRA[128] = {
+static uint8 kpng256x256_32bit_BGRA[128] = {
0x36, 0x87, 0xbc, 0xd4, 0x36, 0x87, 0xbc, 0xfa,
0x35, 0x83, 0xb5, 0xff, 0x34, 0x83, 0xb5, 0xfe,
0x35, 0x83, 0xb5, 0xf3, 0x35, 0x82, 0xb5, 0xcf,
@@ -156,7 +156,7 @@ static unsigned char kpng256x256_32bit_BGRA[128] = {
0x1d, 0x8d, 0x96, 0xff, 0x1b, 0x8f, 0x90, 0xff,
};
-static unsigned char kpng256x256_8bit_palette_BGRX[128] = {
+static uint8 kpng256x256_8bit_palette_BGRX[128] = {
0x36, 0x89, 0xbb, 0xff, 0x36, 0x89, 0xbb, 0xff,
0x35, 0x81, 0xb5, 0xff, 0x32, 0x84, 0xb5, 0xff,
0x35, 0x81, 0xb5, 0xff, 0x35, 0x81, 0xb5, 0xff,
@@ -175,7 +175,7 @@ static unsigned char kpng256x256_8bit_palette_BGRX[128] = {
0x1f, 0x8d, 0x91, 0xff, 0x1f, 0x8d, 0x91, 0xff,
};
-static unsigned char kpng20x14_4bit_palette_BGRX[128] = {
+static uint8 kpng20x14_4bit_palette_BGRX[128] = {
0xed, 0xed, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -194,7 +194,7 @@ static unsigned char kpng20x14_4bit_palette_BGRX[128] = {
0x54, 0x54, 0x54, 0xff, 0x33, 0x33, 0x33, 0xff,
};
-static unsigned char kdxt1_256x256[128] = {
+static uint8 kdxt1_256x256[128] = {
0x47, 0xbc, 0x06, 0xb4, 0x5a, 0x6a, 0x6a, 0xea,
0x27, 0xb4, 0x06, 0xb4, 0x57, 0x57, 0x57, 0x5e,
0x06, 0xb4, 0x07, 0xb4, 0xaa, 0xaa, 0xaa, 0xaa,
@@ -213,7 +213,7 @@ static unsigned char kdxt1_256x256[128] = {
0x06, 0xb4, 0x45, 0xa4, 0xfd, 0xaf, 0xaf, 0x0a,
};
-static unsigned char kdxt1_256x256_alpha[128] = {
+static uint8 kdxt1_256x256_alpha[128] = {
0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff,
@@ -232,7 +232,7 @@ static unsigned char kdxt1_256x256_alpha[128] = {
0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff,
};
-static unsigned char kdxt1_256x256_mipmap[128] = {
+static uint8 kdxt1_256x256_mipmap[128] = {
0x47, 0xbc, 0x06, 0xb4, 0x5a, 0x6a, 0x6a, 0xea,
0x27, 0xb4, 0x06, 0xb4, 0x57, 0x57, 0x57, 0x5e,
0x06, 0xb4, 0x07, 0xb4, 0xaa, 0xaa, 0xaa, 0xaa,
@@ -251,7 +251,7 @@ static unsigned char kdxt1_256x256_mipmap[128] = {
0x06, 0xb4, 0x45, 0xa4, 0xfd, 0xaf, 0xaf, 0x0a,
};
-static unsigned char kdxt3_256x256_alpha[128] = {
+static uint8 kdxt3_256x256_alpha[128] = {
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
0x47, 0xbc, 0x06, 0xb4, 0x5a, 0x6a, 0x6a, 0xea,
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
@@ -270,7 +270,7 @@ static unsigned char kdxt3_256x256_alpha[128] = {
0x46, 0xac, 0x83, 0x8c, 0xf0, 0x7c, 0x7c, 0x5f,
};
-static unsigned char kdxt3_256x256_mipmap[128] = {
+static uint8 kdxt3_256x256_mipmap[128] = {
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
0x47, 0xbc, 0x06, 0xb4, 0x5a, 0x6a, 0x6a, 0xea,
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
@@ -289,7 +289,7 @@ static unsigned char kdxt3_256x256_mipmap[128] = {
0x46, 0xac, 0x83, 0x8c, 0xf0, 0x7c, 0x7c, 0x5f,
};
-static unsigned char kdxt5_256x256_alpha[128] = {
+static uint8 kdxt5_256x256_alpha[128] = {
0x7e, 0x77, 0xda, 0x23, 0x00, 0x90, 0x0a, 0x00,
0x47, 0xbc, 0x06, 0xb4, 0x5a, 0x6a, 0x6a, 0xea,
0x78, 0x76, 0x4e, 0x02, 0x00, 0x70, 0x02, 0x00,
@@ -308,7 +308,7 @@ static unsigned char kdxt5_256x256_alpha[128] = {
0x46, 0xac, 0x83, 0x8c, 0xf0, 0x7c, 0x7c, 0x5f,
};
-static unsigned char kdxt5_256x256_mipmap[128] = {
+static uint8 kdxt5_256x256_mipmap[128] = {
0x7e, 0x77, 0xda, 0x23, 0x00, 0x90, 0x0a, 0x00,
0x47, 0xbc, 0x06, 0xb4, 0x5a, 0x6a, 0x6a, 0xea,
0x78, 0x76, 0x4e, 0x02, 0x00, 0x70, 0x02, 0x00,
@@ -328,7 +328,7 @@ static unsigned char kdxt5_256x256_mipmap[128] = {
};
// Match the first 128 bytes of a loaded bitmap data againt known values.
-bool TestBitmapData(const Bitmap &bitmap, unsigned char reference[128]) {
+bool TestBitmapData(const Bitmap &bitmap, uint8 reference[128]) {
if (!bitmap.image_data()) return false;
return std::memcmp(bitmap.image_data(), reference, sizeof(reference)) == 0;
}
@@ -336,9 +336,9 @@ bool TestBitmapData(const Bitmap &bitmap, unsigned char reference[128]) {
// Prints the first 128 bytes of a loaded bitmap data. Helper function to
// generate the known data above.
bool PrintBitmapData(const Bitmap &bitmap, const char *name) {
- const unsigned char *data = bitmap.image_data();
+ const uint8 *data = bitmap.image_data();
if (!data) return false;
- printf("static unsigned char %s[128] = {\n", name);
+ printf("static uint8 %s[128] = {\n", name);
for (int i = 0; i < 16; ++i) {
printf(" ");
for (int j = 0; j < 8; ++j) {
@@ -359,7 +359,7 @@ TEST_F(BitmapTest, LoadTGAFile24bit) {
String filename = *g_program_path + "/bitmap_test/tga-256x256-24bit.tga";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::TGA, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::TGA, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::XRGB8, bitmap->format());
@@ -374,7 +374,7 @@ TEST_F(BitmapTest, LoadTGAFile32bit) {
String filename = *g_program_path + "/bitmap_test/tga-256x256-32bit.tga";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::TGA, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::TGA, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::ARGB8, bitmap->format());
@@ -392,7 +392,7 @@ TEST_F(BitmapTest, LoadTGAFileTooLarge) {
String filename = *g_program_path + "/bitmap_test/5kx5k.tga";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_FALSE(bitmap->LoadFromFile(filepath, Bitmap::TGA, false));
+ EXPECT_FALSE(bitmap->LoadFromFile(filepath, image::TGA, false));
EXPECT_TRUE(bitmap->image_data() == NULL);
}
@@ -401,7 +401,7 @@ TEST_F(BitmapTest, LoadJPEGFile) {
String filename = *g_program_path + "/bitmap_test/jpeg-256x256.jpg";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::JPEG, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::JPEG, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::XRGB8, bitmap->format());
@@ -416,7 +416,7 @@ TEST_F(BitmapTest, LoadJPEGFileTooLarge) {
String filename = *g_program_path + "/bitmap_test/5kx5k.jpg";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_FALSE(bitmap->LoadFromFile(filepath, Bitmap::JPEG, false));
+ EXPECT_FALSE(bitmap->LoadFromFile(filepath, image::JPEG, false));
EXPECT_TRUE(bitmap->image_data() == NULL);
}
@@ -425,7 +425,7 @@ TEST_F(BitmapTest, LoadPNGFile24bit) {
String filename = *g_program_path + "/bitmap_test/png-256x256-24bit.png";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::PNG, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::XRGB8, bitmap->format());
@@ -441,7 +441,7 @@ TEST_F(BitmapTest, LoadPNGFile24bitInterlaced) {
"/bitmap_test/png-256x256-24bit-interlaced.png";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::PNG, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::XRGB8, bitmap->format());
@@ -455,7 +455,7 @@ TEST_F(BitmapTest, LoadPNGFile32bit) {
String filename = *g_program_path + "/bitmap_test/png-256x256-32bit.png";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::PNG, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::ARGB8, bitmap->format());
@@ -471,7 +471,7 @@ TEST_F(BitmapTest, LoadPNGFile8bitPalette) {
"/bitmap_test/png-256x256-8bit-palette.png";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::PNG, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::XRGB8, bitmap->format());
@@ -487,7 +487,7 @@ TEST_F(BitmapTest, LoadPNGFile4bitPalette) {
"/bitmap_test/png-20x14-4bit-palette.png";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::PNG, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::XRGB8, bitmap->format());
@@ -503,7 +503,7 @@ TEST_F(BitmapTest, LoadPNGFileTooLarge) {
String filename = *g_program_path + "/bitmap_test/5kx5k.png";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_FALSE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_FALSE(bitmap->LoadFromFile(filepath, image::PNG, false));
EXPECT_TRUE(bitmap->image_data() == NULL);
}
@@ -515,7 +515,7 @@ TEST_F(BitmapTest, LoadPNGFile8bitPaletteAlpha) {
"/bitmap_test/png-256x256-8bit-palette-alpha.png";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::PNG, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::ARGB8, bitmap->format());
@@ -530,7 +530,7 @@ TEST_F(BitmapTest, LoadDDSFileDXT1) {
String filename = *g_program_path + "/bitmap_test/dds-dxt1-256x256.dds";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT1, bitmap->format());
@@ -546,7 +546,7 @@ TEST_F(BitmapTest, LoadDDSFileDXT1Alpha) {
"/bitmap_test/dds-dxt1-256x256-alpha.dds";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT1, bitmap->format());
@@ -562,7 +562,7 @@ TEST_F(BitmapTest, LoadDDSFileDXT1Mipmap) {
"/bitmap_test/dds-dxt1-256x256-mipmap.dds";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT1, bitmap->format());
@@ -581,7 +581,7 @@ TEST_F(BitmapTest, LoadDDSFileDXT3) {
"/bitmap_test/dds-dxt3-256x256-alpha.dds";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT3, bitmap->format());
@@ -597,7 +597,7 @@ TEST_F(BitmapTest, LoadDDSFileDXT3Mipmap) {
"/bitmap_test/dds-dxt3-256x256-mipmap.dds";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT3, bitmap->format());
@@ -616,7 +616,7 @@ TEST_F(BitmapTest, LoadDDSFileDXT5) {
"/bitmap_test/dds-dxt5-256x256-alpha.dds";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT5, bitmap->format());
@@ -632,7 +632,7 @@ TEST_F(BitmapTest, LoadDDSFileDXT5Mipmap) {
"/bitmap_test/dds-dxt5-256x256-mipmap.dds";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
EXPECT_TRUE(bitmap->image_data() != NULL);
EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT5, bitmap->format());
@@ -653,206 +653,11 @@ TEST_F(BitmapTest, LoadDDSFileTooLarge) {
String filename = *g_program_path + "/bitmap_test/5kx5k.dds";
FilePath filepath = UTF8ToFilePath(filename);
Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_FALSE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_FALSE(bitmap->LoadFromFile(filepath, image::DDS, false));
EXPECT_TRUE(bitmap->image_data() == NULL);
}
-
-// NOTE: untested ffile types are:
-// png grayscale textures
-// dds cube maps
-// dds mipmapped cube maps
-// dds 1D textures
-// dds 3D textures
-
-
-static const unsigned char kMipmapDataPOT[] = {
- // This is a 4x4 image
- 0x7D, 0xE4, 0x0F, 0xff, 0x71, 0x7B, 0x9C, 0xff,
- 0xDD, 0xF0, 0x9D, 0xff, 0xFA, 0x08, 0x49, 0xff,
- 0xEA, 0x28, 0xF6, 0xff, 0x73, 0x10, 0x64, 0xff,
- 0x8B, 0x36, 0x58, 0xff, 0x7A, 0x3E, 0x21, 0xff,
- 0x64, 0xCE, 0xB1, 0xff, 0x36, 0x4D, 0xC5, 0xff,
- 0xF3, 0x99, 0x7E, 0xff, 0x5C, 0x56, 0x1E, 0xff,
- 0x59, 0x8C, 0x41, 0xff, 0x39, 0x24, 0x1B, 0xff,
- 0x5D, 0x4D, 0x96, 0xff, 0x5E, 0xF8, 0x8B, 0xff,
- // Followed by its 2x2 mip level
- 0x92, 0x65, 0x81, 0xff, 0xb7, 0x5b, 0x57, 0xff,
- 0x4b, 0x72, 0x74, 0xff, 0x82, 0x8d, 0x6f, 0xff,
- // Followed by its 1x1 mip level
- 0x85, 0x6f, 0x6e, 0xff,
-};
-
-// Generates mip-maps from a known power-of-two image, compare with expected
-// results.
-TEST_F(BitmapTest, GenerateMipmapsPOT) {
- const unsigned int kWidth = 4;
- const unsigned int kHeight = 4;
- const Texture::Format format = Texture::ARGB8;
- unsigned int mipmaps = Bitmap::GetMipMapCount(kWidth, kHeight);
- EXPECT_EQ(3U, mipmaps);
- unsigned int size = Bitmap::GetMipChainSize(kWidth, kHeight, format, mipmaps);
- ASSERT_EQ(sizeof(kMipmapDataPOT), size);
- scoped_array<unsigned char> data(new unsigned char[size]);
- ASSERT_TRUE(data.get() != NULL);
- // Copy first level into the buffer.
- unsigned int base_size = Bitmap::GetMipChainSize(kWidth, kHeight, format, 1);
- memcpy(data.get(), kMipmapDataPOT, base_size);
- Bitmap::GenerateMipmaps(kWidth, kHeight, format, mipmaps, data.get());
- // Check the result.
- EXPECT_EQ(0, memcmp(data.get(), kMipmapDataPOT, size));
-}
-
-static const unsigned char kMipmapDataNPOT[] = {
- // This is a 7x7 image
- 0x0d, 0x16, 0x68, 0x1b, 0xe6, 0x09, 0x89, 0x55,
- 0xda, 0x28, 0x56, 0x55, 0x3e, 0x00, 0x6f, 0x16,
- 0x98, 0x11, 0x50, 0x72, 0xe7, 0x17, 0x24, 0xca,
- 0x05, 0xe9, 0x92, 0x43, 0xd6, 0xc4, 0x57, 0xcd,
- 0x34, 0x9b, 0x86, 0xcf, 0x50, 0x65, 0xc4, 0x83,
- 0xaf, 0xa3, 0xaa, 0xe3, 0x7c, 0xab, 0x5f, 0x08,
- 0xc1, 0x2e, 0xd1, 0xe9, 0xa8, 0x2b, 0x56, 0x64,
- 0x12, 0x74, 0x92, 0x56, 0x30, 0x16, 0xa0, 0x03,
- 0x5a, 0x3a, 0x88, 0xb9, 0xe8, 0xa3, 0xfd, 0xf6,
- 0xa1, 0x3b, 0x7b, 0x2d, 0xfd, 0x71, 0xc0, 0x0b,
- 0x22, 0x31, 0x41, 0x5a, 0x45, 0x6f, 0x6b, 0x1b,
- 0x10, 0x5a, 0x16, 0x6e, 0x02, 0x89, 0x12, 0xb1,
- 0x67, 0xfc, 0x43, 0x78, 0xc0, 0x55, 0x59, 0xa3,
- 0xf8, 0xe2, 0x6b, 0xb7, 0xad, 0x5f, 0x3c, 0x14,
- 0xe1, 0x0e, 0x84, 0x89, 0x25, 0xa7, 0xea, 0xc6,
- 0x63, 0x20, 0xf9, 0x84, 0xa1, 0xcd, 0x62, 0x0f,
- 0x22, 0xab, 0x59, 0xde, 0xbd, 0xfa, 0xab, 0x4d,
- 0xca, 0x07, 0x85, 0xdf, 0x83, 0x23, 0x80, 0x8b,
- 0x5e, 0xe4, 0x57, 0x45, 0x81, 0x34, 0x52, 0x65,
- 0xf0, 0x14, 0x32, 0x33, 0xfe, 0xe4, 0x31, 0x90,
- 0x15, 0x51, 0x57, 0x89, 0xed, 0xcf, 0x88, 0xc9,
- 0x7b, 0xbb, 0xc6, 0x41, 0xd5, 0x93, 0x7c, 0x65,
- 0x39, 0x80, 0x20, 0xa2, 0xe5, 0xca, 0x9b, 0x7e,
- 0xb2, 0x1f, 0x0d, 0xdc, 0x5c, 0xab, 0x6b, 0x5b,
- 0xc5, 0x57, 0xc0, 0xd2,
- // Followed by its 3x3 mip level
- 0x75, 0x58, 0x7b, 0x76, 0x8a, 0x54, 0x85, 0x6f,
- 0x93, 0x56, 0x74, 0x7d, 0x3f, 0x58, 0x7a, 0x64,
- 0x7a, 0x90, 0x75, 0x8f, 0xb4, 0x7c, 0x71, 0x6b,
- 0x84, 0x84, 0x85, 0x6c, 0xb1, 0x73, 0x4f, 0x7c,
- 0x97, 0x87, 0x78, 0xa2,
- // Followed by its 1x1 mip level
- 0x88, 0x6e, 0x75, 0x7a,
-};
-
-// Generates mip-maps from a known non-power-of-two image, compare with expected
-// results.
-TEST_F(BitmapTest, GenerateMipmapsNPOT) {
- const unsigned int kWidth = 7;
- const unsigned int kHeight = 7;
- const Texture::Format format = Texture::ARGB8;
- unsigned int mipmaps = Bitmap::GetMipMapCount(kWidth, kHeight);
- EXPECT_EQ(3U, mipmaps);
- unsigned int size = Bitmap::GetMipChainSize(kWidth, kHeight, format, mipmaps);
- ASSERT_EQ(sizeof(kMipmapDataNPOT), size);
- scoped_array<unsigned char> data(new unsigned char[size]);
- ASSERT_TRUE(data.get() != NULL);
- // Copy first level into the buffer.
- unsigned int base_size = Bitmap::GetMipChainSize(kWidth, kHeight, format, 1);
- memcpy(data.get(), kMipmapDataNPOT, base_size);
- Bitmap::GenerateMipmaps(kWidth, kHeight, format, mipmaps, data.get());
- // Check the result.
- EXPECT_EQ(0, memcmp(data.get(), kMipmapDataNPOT, size));
-}
-
-// Checks that filenames are detected as the correct type.
-TEST_F(BitmapTest, GetFileTypeFromFilename) {
- EXPECT_EQ(Bitmap::TGA, Bitmap::GetFileTypeFromFilename("foo.tga"));
- EXPECT_EQ(Bitmap::TGA, Bitmap::GetFileTypeFromFilename("BAR.TGA"));
- EXPECT_EQ(Bitmap::PNG, Bitmap::GetFileTypeFromFilename("foo.png"));
- EXPECT_EQ(Bitmap::PNG, Bitmap::GetFileTypeFromFilename("BAR.PNG"));
- EXPECT_EQ(Bitmap::JPEG, Bitmap::GetFileTypeFromFilename("foo.jpeg"));
- EXPECT_EQ(Bitmap::JPEG, Bitmap::GetFileTypeFromFilename("BAR.JPEG"));
- EXPECT_EQ(Bitmap::JPEG, Bitmap::GetFileTypeFromFilename("foo.jpg"));
- EXPECT_EQ(Bitmap::JPEG, Bitmap::GetFileTypeFromFilename("BAR.JPG"));
- EXPECT_EQ(Bitmap::JPEG, Bitmap::GetFileTypeFromFilename("foo.jpe"));
- EXPECT_EQ(Bitmap::JPEG, Bitmap::GetFileTypeFromFilename("BAR.JPE"));
- EXPECT_EQ(Bitmap::DDS, Bitmap::GetFileTypeFromFilename("foo.dds"));
- EXPECT_EQ(Bitmap::DDS, Bitmap::GetFileTypeFromFilename("BAR.DDS"));
- EXPECT_EQ(Bitmap::UNKNOWN, Bitmap::GetFileTypeFromFilename("foo.bar"));
- EXPECT_EQ(Bitmap::UNKNOWN, Bitmap::GetFileTypeFromFilename("FOO.BAR"));
-}
-
-// Checks that mime types are detected as the correct type.
-TEST_F(BitmapTest, GetFileTypeFromMimeType) {
- EXPECT_EQ(Bitmap::PNG, Bitmap::GetFileTypeFromMimeType("image/png"));
- EXPECT_EQ(Bitmap::JPEG, Bitmap::GetFileTypeFromMimeType("image/jpeg"));
- EXPECT_EQ(Bitmap::UNKNOWN, Bitmap::GetFileTypeFromFilename("text/plain"));
- EXPECT_EQ(Bitmap::UNKNOWN,
- Bitmap::GetFileTypeFromFilename("application/x-123"));
-}
-
-static const unsigned char kScaleUPDataNPOT[] = {
- // This is a 3x3 image.
- 0x75, 0x58, 0x7b, 0x76,
- 0x8a, 0x54, 0x85, 0x6f,
- 0x93, 0x56, 0x74, 0x7d,
-
- 0x3f, 0x58, 0x7a, 0x64,
- 0x7a, 0x90, 0x75, 0x8f,
- 0xb4, 0x7c, 0x71, 0x6b,
-
- 0x84, 0x84, 0x85, 0x6c,
- 0xb1, 0x73, 0x4f, 0x7c,
- 0x97, 0x87, 0x78, 0xa2,
-};
-
-static const unsigned char kScaleUPDataPOT[] = {
- // This is the 4x4 scaled-up version of the above.
- 0x75, 0x58, 0x7b, 0x76,
- 0x8a, 0x54, 0x85, 0x6f,
- 0x8a, 0x54, 0x85, 0x6f,
- 0x93, 0x56, 0x74, 0x7d,
-
- 0x3f, 0x58, 0x7a, 0x64,
- 0x7a, 0x90, 0x75, 0x8f,
- 0x7a, 0x90, 0x75, 0x8f,
- 0xb4, 0x7c, 0x71, 0x6b,
-
- 0x3f, 0x58, 0x7a, 0x64,
- 0x7a, 0x90, 0x75, 0x8f,
- 0x7a, 0x90, 0x75, 0x8f,
- 0xb4, 0x7c, 0x71, 0x6b,
-
- 0x84, 0x84, 0x85, 0x6c,
- 0xb1, 0x73, 0x4f, 0x7c,
- 0xb1, 0x73, 0x4f, 0x7c,
- 0x97, 0x87, 0x78, 0xa2,
-};
-
-// Scales up a NPOT texture, compare with expected results.
-TEST_F(BitmapTest, ScaleUpToPOT) {
- const unsigned int kWidth = 3;
- const unsigned int kHeight = 3;
- const unsigned int kPOTWidth = Bitmap::GetPOTSize(kWidth);
- ASSERT_EQ(kPOTWidth, 4U);
- const unsigned int kPOTHeight = Bitmap::GetPOTSize(kHeight);
- ASSERT_EQ(kPOTHeight, 4U);
- const Texture::Format format = Texture::ARGB8;
- unsigned int src_size = Bitmap::GetBufferSize(kWidth, kHeight, format);
- ASSERT_EQ(sizeof(kScaleUPDataNPOT), src_size);
- unsigned int dst_size = Bitmap::GetBufferSize(kPOTWidth, kPOTHeight, format);
- ASSERT_EQ(sizeof(kScaleUPDataPOT), dst_size);
- scoped_array<unsigned char> data(new unsigned char[dst_size]);
- ASSERT_TRUE(data.get() != NULL);
- // Check that scaling works when source and destination don't alias
- Bitmap::ScaleUpToPOT(kWidth, kHeight, format, kScaleUPDataNPOT, data.get(),
- 4 * 4);
- EXPECT_EQ(0, memcmp(data.get(), kScaleUPDataPOT, dst_size));
-
- // Check that scaling works when source and destination do alias
- memset(data.get(), 0, dst_size);
- memcpy(data.get(), kScaleUPDataNPOT, src_size);
- Bitmap::ScaleUpToPOT(kWidth, kHeight, format, data.get(), data.get(), 4 * 4);
- EXPECT_EQ(0, memcmp(data.get(), kScaleUPDataPOT, dst_size));
-}
-
-static unsigned char kpng_8x4_drawImage[128] = {
+static uint8 kpng_8x4_drawImage[128] = {
// Raw dest image used in drawimage test.
0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
0x34, 0x68, 0xd0, 0xff, 0x36, 0x6c, 0xd8, 0xff,
@@ -872,7 +677,7 @@ static unsigned char kpng_8x4_drawImage[128] = {
0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
};
-static unsigned char kpng_8x4_drawImage_top_left[128] = {
+static uint8 kpng_8x4_drawImage_top_left[128] = {
// expected result of drawimage on top left corner of dest image.
0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
0x34, 0x68, 0xd0, 0xff, 0x36, 0x6c, 0xd8, 0xff,
@@ -892,7 +697,7 @@ static unsigned char kpng_8x4_drawImage_top_left[128] = {
0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
};
-static unsigned char kpng_8x4_drawImage_top[128] = {
+static uint8 kpng_8x4_drawImage_top[128] = {
// expected result of drawimage on top bound of dest image.
0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
0x34, 0x68, 0xd0, 0xff, 0x36, 0x6c, 0xd8, 0xff,
@@ -912,7 +717,7 @@ static unsigned char kpng_8x4_drawImage_top[128] = {
0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
};
-static unsigned char kpng_8x4_drawImage_top_right[128] = {
+static uint8 kpng_8x4_drawImage_top_right[128] = {
// expected result of drawimage on top right corner of dest image.
0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
0x34, 0x68, 0xd0, 0xff, 0x36, 0x6c, 0xd8, 0xff,
@@ -932,7 +737,7 @@ static unsigned char kpng_8x4_drawImage_top_right[128] = {
0x24, 0x24, 0x24, 0xff, 0x25, 0x25, 0x25, 0xff,
};
-static unsigned char kpng_8x4_drawImage_right[128] = {
+static uint8 kpng_8x4_drawImage_right[128] = {
// expected result of drawimage on right bound of dest image.
0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
0x34, 0x68, 0xd0, 0xff, 0x36, 0x6c, 0xd8, 0xff,
@@ -952,7 +757,7 @@ static unsigned char kpng_8x4_drawImage_right[128] = {
0x20, 0x20, 0x20, 0xff, 0x21, 0x21, 0x21, 0xff,
};
-static unsigned char kpng_8x4_drawImage_bottom_right[128] = {
+static uint8 kpng_8x4_drawImage_bottom_right[128] = {
// expected result of drawimage on bottom right corner of dest image.
0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
0x34, 0x68, 0xd0, 0xff, 0x36, 0x6c, 0xd8, 0xff,
@@ -972,7 +777,7 @@ static unsigned char kpng_8x4_drawImage_bottom_right[128] = {
0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
};
-static unsigned char kpng_8x4_drawImage_bottom[128] = {
+static uint8 kpng_8x4_drawImage_bottom[128] = {
// expected result of drawimage on bottom bound of dest image.
0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
0x27, 0x27, 0x27, 0xff, 0x28, 0x28, 0x28, 0xff,
@@ -992,7 +797,7 @@ static unsigned char kpng_8x4_drawImage_bottom[128] = {
0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
};
-static unsigned char kpng_8x4_drawImage_bottom_left[128] = {
+static uint8 kpng_8x4_drawImage_bottom_left[128] = {
// expected result of drawimage on bottom left corner of dest image.
0x28, 0x28, 0x28, 0xff, 0x29, 0x29, 0x29, 0xff,
0x2a, 0x2a, 0x2a, 0xff, 0x36, 0x6c, 0xd8, 0xff,
@@ -1012,7 +817,7 @@ static unsigned char kpng_8x4_drawImage_bottom_left[128] = {
0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
};
-static unsigned char kpng_8x4_drawImage_left[128] = {
+static uint8 kpng_8x4_drawImage_left[128] = {
// expected result of drawimage on left bound of dest image.
0x2c, 0x2c, 0x2c, 0xff, 0x2d, 0x2d, 0x2d, 0xff,
0x2e, 0x2e, 0x2e, 0xff, 0x36, 0x6c, 0xd8, 0xff,
@@ -1032,7 +837,7 @@ static unsigned char kpng_8x4_drawImage_left[128] = {
0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
};
-static unsigned char kpng_8x4_drawImage_scale_up[128] = {
+static uint8 kpng_8x4_drawImage_scale_up[128] = {
// expected result of scale up from 2x2 to 8x4.
0x38, 0x38, 0x38, 0xff, 0x43, 0x43, 0x43, 0xff,
0x52, 0x52, 0x52, 0xff, 0x63, 0x63, 0x63, 0xff,
@@ -1052,7 +857,7 @@ static unsigned char kpng_8x4_drawImage_scale_up[128] = {
0x11, 0x11, 0x11, 0xff, 0x0e, 0x0e, 0x0e, 0xff,
};
-static unsigned char kpng_8x4_drawImage_scale_down[128] = {
+static uint8 kpng_8x4_drawImage_scale_down[128] = {
// expected result of scale down from 8x8 to 4x4.
0xa0, 0xa0, 0xa0, 0xff, 0xa7, 0xa7, 0xa7, 0xff,
0xad, 0xad, 0xad, 0xff, 0xb3, 0xb3, 0xb3, 0xff,
@@ -1072,7 +877,7 @@ static unsigned char kpng_8x4_drawImage_scale_down[128] = {
0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
};
-static unsigned char kpng_8x4_drawImage_scale_out[128] = {
+static uint8 kpng_8x4_drawImage_scale_out[128] = {
// expected result of scale src image larger than dest image.
0x64, 0x64, 0x64, 0xff, 0x66, 0x66, 0x66, 0xff,
0x68, 0x68, 0x68, 0xff, 0x6a, 0x6a, 0x6a, 0xff,
@@ -1092,7 +897,7 @@ static unsigned char kpng_8x4_drawImage_scale_out[128] = {
0x3f, 0x3f, 0x3f, 0xff, 0x41, 0x41, 0x41, 0xff,
};
-static unsigned char kpng_8x4_drawImage_flip[128] = {
+static uint8 kpng_8x4_drawImage_flip[128] = {
// expected result of flip src image.
0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
0x22, 0x22, 0x22, 0xff, 0x21, 0x21, 0x21, 0xff,
@@ -1112,7 +917,7 @@ static unsigned char kpng_8x4_drawImage_flip[128] = {
0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
};
-static unsigned char kpng_8x4_drawImage_argb8[128] = {
+static uint8 kpng_8x4_drawImage_argb8[128] = {
// expected result of drawimage with rgb8 format.
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xca, 0xca, 0xca, 0x3e, 0xd7, 0xd7, 0xd7, 0x9a,
@@ -1144,112 +949,112 @@ TEST_F(BitmapTest, DrawImage) {
"/bitmap_test/png-2x2-24bit-drawimage-src.png";
Bitmap::Ref bitmap_2x2_src(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_2x2_src->LoadFromFile(UTF8ToFilePath(filename_2x2_src),
- Bitmap::PNG, false));
+ image::PNG, false));
String filename_4x4_src = *g_program_path +
"/bitmap_test/png-4x4-24bit-drawimage-src.png";
Bitmap::Ref bitmap_4x4_src(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_4x4_src->LoadFromFile(UTF8ToFilePath(filename_4x4_src),
- Bitmap::PNG, false));
+ image::PNG, false));
String filename_8x8_src = *g_program_path +
"/bitmap_test/png-8x8-24bit-drawimage-src.png";
Bitmap::Ref bitmap_8x8_src(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_8x8_src->LoadFromFile(UTF8ToFilePath(filename_8x8_src),
- Bitmap::PNG, false));
+ image::PNG, false));
// test draw image on top left boundary.
Bitmap::Ref bitmap_dest_top_left(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_top_left->LoadFromFile(UTF8ToFilePath(fname_dst),
- Bitmap::PNG, false));
+ image::PNG, false));
// test whether the raw image is loaded correctly or not.
EXPECT_TRUE(bitmap_dest_top_left->image_data() != NULL);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_top_left, kpng_8x4_drawImage));
- bitmap_dest_top_left->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, -1, -1, 4, 4);
+ bitmap_dest_top_left->DrawImage(*bitmap_4x4_src, 0, 0, 4, 4, -1, -1, 4, 4);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_top_left,
kpng_8x4_drawImage_top_left));
// test draw image on top boundary.
Bitmap::Ref bitmap_dest_top(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_top->LoadFromFile(UTF8ToFilePath(fname_dst),
- Bitmap::PNG, false));
- bitmap_dest_top->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, 2, -2, 4, 4);
+ image::PNG, false));
+ bitmap_dest_top->DrawImage(*bitmap_4x4_src, 0, 0, 4, 4, 2, -2, 4, 4);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_top, kpng_8x4_drawImage_top));
// test draw image on top right boundary.
Bitmap::Ref bitmap_dest_top_right(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_top_right->LoadFromFile(UTF8ToFilePath(fname_dst),
- Bitmap::PNG, false));
- bitmap_dest_top_right->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, 5, -1, 4, 4);
+ image::PNG, false));
+ bitmap_dest_top_right->DrawImage(*bitmap_4x4_src, 0, 0, 4, 4, 5, -1, 4, 4);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_top_right,
kpng_8x4_drawImage_top_right));
// test draw image on right boundary.
Bitmap::Ref bitmap_dest_right(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_right->LoadFromFile(UTF8ToFilePath(fname_dst),
- Bitmap::PNG, false));
- bitmap_dest_right->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, 5, 0, 4, 4);
+ image::PNG, false));
+ bitmap_dest_right->DrawImage(*bitmap_4x4_src, 0, 0, 4, 4, 5, 0, 4, 4);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_right, kpng_8x4_drawImage_right));
// test draw image on bottom right boundary.
Bitmap::Ref bitmap_dest_bottom_right(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_bottom_right->LoadFromFile(UTF8ToFilePath(fname_dst),
- Bitmap::PNG, false));
- bitmap_dest_bottom_right->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, 5, 1, 4, 4);
+ image::PNG, false));
+ bitmap_dest_bottom_right->DrawImage(*bitmap_4x4_src, 0, 0, 4, 4, 5, 1, 4, 4);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_bottom_right,
kpng_8x4_drawImage_bottom_right));
// test draw image on bottom boundary.
Bitmap::Ref bitmap_dest_bottom(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_bottom->LoadFromFile(UTF8ToFilePath(fname_dst),
- Bitmap::PNG, false));
- bitmap_dest_bottom->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, 2, 1, 4, 4);
+ image::PNG, false));
+ bitmap_dest_bottom->DrawImage(*bitmap_4x4_src, 0, 0, 4, 4, 2, 1, 4, 4);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_bottom, kpng_8x4_drawImage_bottom));
// test draw image on bottom left boundary.
Bitmap::Ref bitmap_dest_bottom_left(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_bottom_left->LoadFromFile(UTF8ToFilePath(fname_dst),
- Bitmap::PNG, false));
- bitmap_dest_bottom_left->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, -1, 1, 4, 4);
+ image::PNG, false));
+ bitmap_dest_bottom_left->DrawImage(*bitmap_4x4_src, 0, 0, 4, 4, -1, 1, 4, 4);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_bottom_left,
kpng_8x4_drawImage_bottom_left));
// test draw image on left boundary.
Bitmap::Ref bitmap_dest_left(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_left->LoadFromFile(UTF8ToFilePath(fname_dst),
- Bitmap::PNG, false));
- bitmap_dest_left->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, -1, 0, 4, 4);
+ image::PNG, false));
+ bitmap_dest_left->DrawImage(*bitmap_4x4_src, 0, 0, 4, 4, -1, 0, 4, 4);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_left, kpng_8x4_drawImage_left));
// test scale up.
Bitmap::Ref bitmap_dest_scale_up(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_scale_up->LoadFromFile(UTF8ToFilePath(fname_dst),
- Bitmap::PNG, false));
- bitmap_dest_scale_up->DrawImage(bitmap_2x2_src, 0, 0, 2, 2, 0, 0, 8, 4);
+ image::PNG, false));
+ bitmap_dest_scale_up->DrawImage(*bitmap_2x2_src, 0, 0, 2, 2, 0, 0, 8, 4);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_scale_up,
kpng_8x4_drawImage_scale_up));
// test scale down.
Bitmap::Ref bitmap_dest_scale_down(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_scale_down->LoadFromFile(UTF8ToFilePath(fname_dst),
- Bitmap::PNG, false));
- bitmap_dest_scale_down->DrawImage(bitmap_8x8_src, 0, 0, 8, 8, 0, 0, 4, 4);
+ image::PNG, false));
+ bitmap_dest_scale_down->DrawImage(*bitmap_8x8_src, 0, 0, 8, 8, 0, 0, 4, 4);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_scale_down,
kpng_8x4_drawImage_scale_down));
// test scale up to a large size.
Bitmap::Ref bitmap_dest_scale_out(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_scale_out->LoadFromFile(UTF8ToFilePath(fname_dst),
- Bitmap::PNG, false));
- bitmap_dest_scale_out->DrawImage(bitmap_8x8_src, 0, 0, 8, 8, -2, -4, 12, 12);
+ image::PNG, false));
+ bitmap_dest_scale_out->DrawImage(*bitmap_8x8_src, 0, 0, 8, 8, -2, -4, 12, 12);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_scale_out,
kpng_8x4_drawImage_scale_out));
// test flip an image on both x and y cooridnates.
Bitmap::Ref bitmap_dest_flip(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_flip->LoadFromFile(UTF8ToFilePath(fname_dst),
- Bitmap::PNG, false));
- bitmap_dest_flip->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, 5, 3, -4, -4);
+ image::PNG, false));
+ bitmap_dest_flip->DrawImage(*bitmap_4x4_src, 0, 0, 4, 4, 5, 3, -4, -4);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_flip, kpng_8x4_drawImage_flip));
// test draw image on argb8 format.
@@ -1258,14 +1063,14 @@ TEST_F(BitmapTest, DrawImage) {
"png-8x4-24bit-drawimage-argb8-dest.png";
Bitmap::Ref bitmap_dest_argb8(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_dest_argb8->LoadFromFile(UTF8ToFilePath(fname_dst_argb8),
- Bitmap::PNG, false));
+ image::PNG, false));
String fname_src_argb8 = *g_program_path +
"/bitmap_test/" +
"png-4x4-24bit-drawimage-argb8-src.png";
Bitmap::Ref bitmap_src_argb8(new Bitmap(g_service_locator));
EXPECT_TRUE(bitmap_src_argb8->LoadFromFile(UTF8ToFilePath(fname_src_argb8),
- Bitmap::PNG, false));
- bitmap_dest_argb8->DrawImage(bitmap_src_argb8, 0, 0, 4, 4, 0, 0, 4, 4);
+ image::PNG, false));
+ bitmap_dest_argb8->DrawImage(*bitmap_src_argb8, 0, 0, 4, 4, 0, 0, 4, 4);
EXPECT_TRUE(TestBitmapData(*bitmap_dest_argb8, kpng_8x4_drawImage_argb8));
}
diff --git a/o3d/core/cross/bitmap_tga.cc b/o3d/core/cross/bitmap_tga.cc
index 97ff4fb..c85cca9 100644
--- a/o3d/core/cross/bitmap_tga.cc
+++ b/o3d/core/cross/bitmap_tga.cc
@@ -55,14 +55,14 @@ bool Bitmap::LoadFromTGAStream(MemoryReadStream *stream,
const String &filename,
bool generate_mipmaps) {
// Read the magic header.
- unsigned char file_magic[12];
+ uint8 file_magic[12];
if (stream->Read(file_magic, sizeof(file_magic)) != sizeof(file_magic)) {
DLOG(ERROR) << "Targa file magic not loaded \"" << filename << "\"";
return false;
}
// Match the first few bytes of the TGA header to confirm we can read this
// format. Multibyte values are stored little endian.
- const unsigned char kTargaMagic[12] = {
+ const uint8 kTargaMagic[12] = {
0, // ID Length (0 = no ID string present)
0, // Color Map Type ( 0 = no color map)
2, // Image Type (2 = Uncompressed True Color)
@@ -76,12 +76,16 @@ bool Bitmap::LoadFromTGAStream(MemoryReadStream *stream,
// MATCHED LATER: Pixel Depth (1 byte)
// MATCHED LATER: Image Descriptor (1 byte, alpha:4bit, origin:2bit)
};
+
+ // TODO(gman): The most common targa format is compressed! We should support
+ // that format or remove targa support completely. If we are keeping targa
+ // format we should also support grayscale, 8bit indexed and 16bit formats.
if (memcmp(kTargaMagic, file_magic, sizeof(kTargaMagic)) != 0) {
DLOG(ERROR) << "Targa file subtype not recognized \"" << filename << "\"";
return false;
}
// Read the image header.
- unsigned char header[6];
+ uint8 header[6];
if (stream->Read(header, sizeof(header)) != sizeof(header)) {
DLOG(ERROR) << "Targa file header not read \"" << filename << "\"";
return false;
@@ -89,7 +93,7 @@ bool Bitmap::LoadFromTGAStream(MemoryReadStream *stream,
// Calculate image width and height, stored as little endian.
unsigned int tga_width = header[1] * 256 + header[0];
unsigned int tga_height = header[3] * 256 + header[2];
- if (!CheckImageDimensions(tga_width, tga_height)) {
+ if (!image::CheckImageDimensions(tga_width, tga_height)) {
DLOG(ERROR) << "Failed to load " << filename
<< ": dimensions are too large (" << tga_width
<< ", " << tga_height << ").";
@@ -106,11 +110,11 @@ bool Bitmap::LoadFromTGAStream(MemoryReadStream *stream,
unsigned int pixel_count = tga_width * tga_height;
// Allocate storage for the pixels.
unsigned int num_mipmaps =
- generate_mipmaps ? GetMipMapCount(tga_width, tga_height) : 1;
+ generate_mipmaps ? image::ComputeMipMapCount(tga_width, tga_height) : 1;
Texture::Format format = components == 3 ? Texture::XRGB8 : Texture::ARGB8;
- unsigned int image_size = GetMipChainSize(tga_width, tga_height, format,
- num_mipmaps);
- scoped_array<unsigned char> image_data(new unsigned char[image_size]);
+ unsigned int image_size =
+ image::ComputeMipChainSize(tga_width, tga_height, format, num_mipmaps);
+ scoped_array<uint8> image_data(new uint8[image_size]);
if (image_data.get() == NULL) {
DLOG(ERROR) << "Targa file memory allocation error \"" << filename << "\"";
return false;
@@ -124,7 +128,7 @@ bool Bitmap::LoadFromTGAStream(MemoryReadStream *stream,
if (components == 3) {
// Fixup the image by inserting an alpha value of 1 (BGR->BGRX).
- XYZToXYZA(image_data.get(), pixel_count);
+ image::XYZToXYZA(image_data.get(), pixel_count);
}
if (generate_mipmaps) {
@@ -141,6 +145,13 @@ bool Bitmap::LoadFromTGAStream(MemoryReadStream *stream,
height_ = tga_height;
format_ = format;
num_mipmaps_ = num_mipmaps;
+
+ // Targas are generally bottom first in memory so flip it.
+ //
+ // TODO(gman): In truth a targa can be any orientation. We should check
+ // that orientation and flip or not flip accordingly.
+ FlipVertically();
+
return true;
}
diff --git a/o3d/core/cross/buffer_test.cc b/o3d/core/cross/buffer_test.cc
index 469df99..7bdddac 100644
--- a/o3d/core/cross/buffer_test.cc
+++ b/o3d/core/cross/buffer_test.cc
@@ -36,6 +36,7 @@
#include "tests/common/win/testing_common.h"
#include "core/cross/error_status.h"
#include "core/cross/buffer.h"
+#include "core/cross/pack.h"
#include "import/cross/memory_buffer.h"
#include "import/cross/memory_stream.h"
#include "import/cross/raw_data.h"
diff --git a/o3d/core/cross/client.h b/o3d/core/cross/client.h
index 07e60e5..b7de85c 100644
--- a/o3d/core/cross/client.h
+++ b/o3d/core/cross/client.h
@@ -52,11 +52,8 @@
#include "core/cross/object_manager.h"
#include "core/cross/semantic_manager.h"
#include "core/cross/transformation_context.h"
-#include "core/cross/pack.h"
-#include "core/cross/bitmap.h"
+#include "core/cross/render_node.h"
#include "core/cross/callback.h"
-#include "core/cross/cursor.h"
-#include "core/cross/draw_list.h"
#include "core/cross/event.h"
#include "core/cross/event_callback.h"
#include "core/cross/event_manager.h"
@@ -65,11 +62,13 @@
#include "core/cross/tick_event.h"
#include "core/cross/timer.h"
#include "core/cross/timingtable.h"
+#include "core/cross/transform.h"
namespace o3d {
class MessageQueue;
class Profiler;
class State;
+class Pack;
// The Client class is the main point of entry to O3D. It defines methods
// for creating and deleting packs and internal use only methods for creating
diff --git a/o3d/core/cross/client_test.cc b/o3d/core/cross/client_test.cc
index ac6e853..49c5d85 100644
--- a/o3d/core/cross/client_test.cc
+++ b/o3d/core/cross/client_test.cc
@@ -34,6 +34,8 @@
#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
+#include "core/cross/pack.h"
+#include "core/cross/buffer.h"
namespace o3d {
diff --git a/o3d/core/cross/command_buffer/texture_cb.cc b/o3d/core/cross/command_buffer/texture_cb.cc
index e9d5e52..88c529b 100644
--- a/o3d/core/cross/command_buffer/texture_cb.cc
+++ b/o3d/core/cross/command_buffer/texture_cb.cc
@@ -112,14 +112,14 @@ void UpdateResourceFromBitmap(RendererCB *renderer,
unsigned int mip_height = std::max(1U, bitmap.height() >> level);
unsigned char *mip_data = bitmap.GetFaceMipData(face, level);
unsigned int mip_size =
- Bitmap::GetBufferSize(mip_width, mip_height, bitmap.format());
+ image::ComputeBufferSize(mip_width, mip_height, bitmap.format());
if (resize_to_pot) {
unsigned int pot_width =
- std::max(1U, Bitmap::GetPOTSize(bitmap.width()) >> level);
+ std::max(1U, image::ComputePOTSize(bitmap.width()) >> level);
unsigned int pot_height =
- std::max(1U, Bitmap::GetPOTSize(bitmap.height()) >> level);
- unsigned int pot_size = Bitmap::GetBufferSize(pot_width, pot_height,
- bitmap.format());
+ std::max(1U, image::ComputePOTSize(bitmap.height()) >> level);
+ unsigned int pot_size = image::ComputeBufferSize(pot_width, pot_height,
+ bitmap.format());
unsigned char *buffer = allocator->AllocTyped<unsigned char>(pot_size);
// This should succeed for practical purposes: we don't store persistent
// data in the transfer buffer, and the maximum texture size 2048x2048
@@ -129,9 +129,9 @@ void UpdateResourceFromBitmap(RendererCB *renderer,
// by bits that fit into an arbitrarily small buffer, but that is complex
// for the NPOT->POT case.
DCHECK(buffer);
- Bitmap::Scale(mip_width, mip_height, bitmap.format(), mip_data,
- pot_width, pot_height, buffer,
- Bitmap::GetMipChainSize(pot_width, 1, bitmap.format(), 1));
+ image::Scale(mip_width, mip_height, bitmap.format(), mip_data,
+ pot_width, pot_height, buffer,
+ image::ComputePitch(bitmap.format(), pot_width));
mip_width = pot_width;
mip_height = pot_height;
mip_size = pot_size;
@@ -143,7 +143,7 @@ void UpdateResourceFromBitmap(RendererCB *renderer,
mip_data = buffer;
}
- unsigned int pitch = Bitmap::GetBufferSize(mip_width, 1, bitmap.format());
+ unsigned int pitch = image::ComputeBufferSize(mip_width, 1, bitmap.format());
CommandBufferEntry args[10];
args[0].value_uint32 = texture_id;
@@ -180,11 +180,11 @@ void CopyBackResourceToBitmap(RendererCB *renderer,
unsigned int mip_width = std::max(1U, bitmap.width() >> level);
unsigned int mip_height = std::max(1U, bitmap.height() >> level);
unsigned int mip_size =
- Bitmap::GetBufferSize(mip_width, mip_height, bitmap.format());
+ image::ComputeBufferSize(mip_width, mip_height, bitmap.format());
unsigned char *buffer = allocator->AllocTyped<unsigned char>(mip_size);
DCHECK(buffer);
- unsigned int pitch = Bitmap::GetBufferSize(mip_width, 1, bitmap.format());
+ unsigned int pitch = image::ComputeBufferSize(mip_width, 1, bitmap.format());
CommandBufferEntry args[10];
args[0].value_uint32 = texture_id;
@@ -276,8 +276,8 @@ Texture2DCB* Texture2DCB::Create(ServiceLocator* service_locator,
unsigned int mip_width = bitmap->width();
unsigned int mip_height = bitmap->height();
if (resize_to_pot) {
- mip_width = Bitmap::GetPOTSize(mip_width);
- mip_height = Bitmap::GetPOTSize(mip_height);
+ mip_width = image::ComputePOTSize(mip_width);
+ mip_height = image::ComputePOTSize(mip_height);
}
ResourceID texture_id = renderer->texture_ids().AllocateID();
@@ -345,10 +345,10 @@ bool Texture2DCB::Lock(int level, void** data, int* pitch) {
backing_bitmap_->Allocate(format(), width(), height(), levels(), false);
}
*data = backing_bitmap_->GetMipData(level);
- unsigned int mip_width = Bitmap::GetMipDimension(level, width());
- unsigned int mip_height = Bitmap::GetMipDimension(level, height());
+ unsigned int mip_width = image::ComputeMipDimension(level, width());
+ unsigned int mip_height = image::ComputeMipDimension(level, height());
if (!IsCompressed()) {
- *pitch = Bitmap::GetMipChainSize(mip_width, 1,format(), 1);
+ *pitch = image::ComputePitch(format(), mip_width);
} else {
unsigned blocks_across = (mip_width + 3) / 4;
unsigned bytes_per_block = format() == Texture::DXT1 ? 8 : 16;
@@ -471,8 +471,8 @@ TextureCUBECB* TextureCUBECB::Create(ServiceLocator* service_locator,
unsigned int mip_width = bitmap->width();
unsigned int mip_height = bitmap->height();
if (resize_to_pot) {
- mip_width = Bitmap::GetPOTSize(mip_width);
- mip_height = Bitmap::GetPOTSize(mip_height);
+ mip_width = image::ComputePOTSize(mip_width);
+ mip_height = image::ComputePOTSize(mip_height);
}
ResourceID texture_id = renderer->texture_ids().AllocateID();
@@ -547,9 +547,9 @@ bool TextureCUBECB::Lock(CubeFace face, int level, void** data, int* pitch) {
levels(), true);
}
*data = backing_bitmap_->GetFaceMipData(face, level);
- unsigned int mip_width = Bitmap::GetMipDimension(level, edge_length());
+ unsigned int mip_width = image::ComputeMipDimension(level, edge_length());
if (!IsCompressed()) {
- *pitch = Bitmap::GetMipChainSize(mip_width, 1,format(), 1);
+ *pitch = image::ComputePitch(format(), mip_width);
} else {
unsigned blocks_across = (mip_width + 3) / 4;
unsigned bytes_per_block = format() == Texture::DXT1 ? 8 : 16;
diff --git a/o3d/core/cross/counter.h b/o3d/core/cross/counter.h
index 117adbe..9faea11 100644
--- a/o3d/core/cross/counter.h
+++ b/o3d/core/cross/counter.h
@@ -39,6 +39,7 @@
#include <vector>
#include "core/cross/callback.h"
#include "core/cross/param_object.h"
+#include "core/cross/pack.h"
namespace o3d {
diff --git a/o3d/core/cross/curve_test.cc b/o3d/core/cross/curve_test.cc
index d1de1f2..ab8c47a 100644
--- a/o3d/core/cross/curve_test.cc
+++ b/o3d/core/cross/curve_test.cc
@@ -33,9 +33,12 @@
// This file implements unit tests for class Curve.
#include <algorithm>
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/curve.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
+#include "core/cross/error_status.h"
+#include "core/cross/object_manager.h"
#include "import/cross/memory_buffer.h"
#include "import/cross/memory_stream.h"
#include "serializer/cross/serializer_binary.h"
diff --git a/o3d/core/cross/draw_element_test.cc b/o3d/core/cross/draw_element_test.cc
index aafd612..535bce6 100644
--- a/o3d/core/cross/draw_element_test.cc
+++ b/o3d/core/cross/draw_element_test.cc
@@ -32,9 +32,11 @@
// This file implements unit tests for class DrawElement.
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/draw_element.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
namespace o3d {
diff --git a/o3d/core/cross/draw_list_test.cc b/o3d/core/cross/draw_list_test.cc
index bff7f84..36ab6e3 100644
--- a/o3d/core/cross/draw_list_test.cc
+++ b/o3d/core/cross/draw_list_test.cc
@@ -32,9 +32,13 @@
// This file implements unit tests for class DrawList.
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/draw_list.h"
+#include "core/cross/draw_list_manager.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
+#include "core/cross/transformation_context.h"
namespace o3d {
diff --git a/o3d/core/cross/effect_test.cc b/o3d/core/cross/effect_test.cc
index b1361fb..2b1ca6c 100644
--- a/o3d/core/cross/effect_test.cc
+++ b/o3d/core/cross/effect_test.cc
@@ -30,13 +30,17 @@
*/
+#include "tests/common/win/testing_common.h"
#include "core/cross/client.h"
#include "core/cross/effect.h"
+#include "core/cross/image_utils.h"
+#include "core/cross/pack.h"
+#include "core/cross/param_array.h"
#include "core/cross/primitive.h"
+#include "core/cross/sampler.h"
#include "core/cross/standard_param.h"
-#include "core/cross/param_array.h"
#include "core/cross/stream.h"
-#include "tests/common/win/testing_common.h"
+#include "core/cross/texture_base.h"
namespace o3d {
@@ -305,7 +309,7 @@ TEST_F(EffectTest, CreateAndDestroyEffect) {
String filepath = *g_program_path + "/unittest_data/rock01.tga";
Texture *texture = pack->CreateTextureFromFile(filepath,
filepath,
- Bitmap::TGA,
+ image::TGA,
true);
EXPECT_TRUE(texture != NULL);
diff --git a/o3d/core/cross/element_test.cc b/o3d/core/cross/element_test.cc
index 954dd8b..fc66b15 100644
--- a/o3d/core/cross/element_test.cc
+++ b/o3d/core/cross/element_test.cc
@@ -33,9 +33,11 @@
// This file implements unit tests for class Element.
#include <algorithm>
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/element.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
#include "core/cross/primitive.h"
namespace o3d {
diff --git a/o3d/core/cross/features.cc b/o3d/core/cross/features.cc
index 75349cc..6a5d967 100644
--- a/o3d/core/cross/features.cc
+++ b/o3d/core/cross/features.cc
@@ -49,6 +49,7 @@ Features::Features(ServiceLocator* service_locator)
large_geometry_(true),
windowless_(false),
not_anti_aliased_(false),
+ flip_textures_(true),
init_status_(Renderer::SUCCESS) {
// NOTE: For backward compatibility floating_point_textures and
// large_geometry default to true. o3djs.util.makeClients before 0.1.35.0
@@ -58,36 +59,59 @@ Features::Features(ServiceLocator* service_locator)
// which sets those to false to start.
}
-void Features::Init(const String& requested_features) {
- large_geometry_ = false;
- floating_point_textures_ = false;
-
- std::vector<std::string> features;
- SplitString(requested_features, ',', &features);
+void Features::ParseFeatures(const std::vector<std::string>& features,
+ bool version_pass) {
for (size_t jj = 0; jj < features.size(); ++jj) {
const std::string& feature_string = features[jj];
std::vector<std::string> arguments;
SplitString(feature_string, '=', &arguments);
const std::string feature(arguments.front());
arguments.erase(arguments.begin());
- if (feature.compare("FloatingPointTextures") == 0) {
- floating_point_textures_ = true;
- } else if (feature.compare("LargeGeometry") == 0) {
- large_geometry_ = true;
- } else if (feature.compare("Windowless") == 0) {
- windowless_ = true;
- } else if (feature.compare("NotAntiAliased") == 0) {
- not_anti_aliased_ = true;
- } else if (feature.compare("MaxCapabilities") == 0) {
- large_geometry_ = true;
- floating_point_textures_ = true;
- } else if (feature.compare("InitStatus") == 0 &&
- !arguments.empty()) {
- int value;
- StringToInt(arguments[0], &value);
- init_status_ = static_cast<Renderer::InitStatus>(value);
+ if (version_pass) {
+ if (feature.compare("APIVersion") == 0 && !arguments.empty()) {
+ int version[4] = { 0, };
+ std::vector<std::string> parts;
+ SplitString(arguments[0], '.', &parts);
+ size_t num_parts = std::min(parts.size(), arraysize(version));
+ for (size_t ii = 0; ii < num_parts; ++ii) {
+ StringToInt(parts[ii], &version[ii]);
+ }
+ if (version[0] >= 0 && version[1] >= 1 && version[2] >= 40) {
+ flip_textures_ = false;
+ }
+ }
+ } else {
+ if (feature.compare("FloatingPointTextures") == 0) {
+ floating_point_textures_ = true;
+ } else if (feature.compare("LargeGeometry") == 0) {
+ large_geometry_ = true;
+ } else if (feature.compare("Windowless") == 0) {
+ windowless_ = true;
+ } else if (feature.compare("NotAntiAliased") == 0) {
+ not_anti_aliased_ = true;
+ } else if (feature.compare("FlipTextures") == 0) {
+ flip_textures_ = true;
+ } else if (feature.compare("MaxCapabilities") == 0) {
+ large_geometry_ = true;
+ floating_point_textures_ = true;
+ } else if (feature.compare("InitStatus") == 0 &&
+ !arguments.empty()) {
+ int value;
+ StringToInt(arguments[0], &value);
+ init_status_ = static_cast<Renderer::InitStatus>(value);
+ }
}
}
}
+void Features::Init(const String& requested_features) {
+ large_geometry_ = false;
+ floating_point_textures_ = false;
+
+ std::vector<std::string> features;
+ SplitString(requested_features, ',', &features);
+ ParseFeatures(features, true);
+ ParseFeatures(features, false);
+}
+
} // namespace o3d
diff --git a/o3d/core/cross/features.h b/o3d/core/cross/features.h
index 003c807..efd3266 100644
--- a/o3d/core/cross/features.h
+++ b/o3d/core/cross/features.h
@@ -35,6 +35,8 @@
#ifndef O3D_CORE_CROSS_FEATURES_H_
#define O3D_CORE_CROSS_FEATURES_H_
+#include <string>
+#include <vector>
#include "core/cross/types.h"
#include "core/cross/service_locator.h"
#include "core/cross/service_implementation.h"
@@ -68,7 +70,11 @@ class Features {
}
bool not_anti_aliased() const {
- return not_anti_aliased_;
+ return not_anti_aliased_;
+ }
+
+ bool flip_textures() const {
+ return flip_textures_;
}
// This can be used to force the renderer to fail for testing.
@@ -77,12 +83,21 @@ class Features {
}
private:
+ // Parses the features strings.
+ // Parameters:
+ // features: vector of feature strings.
+ // version_pass: True = only check for APIVersion, false = check everything
+ // but APIVersion.
+ void ParseFeatures(const std::vector<std::string>& features,
+ bool version_pass);
+
ServiceImplementation<Features> service_;
bool floating_point_textures_;
bool large_geometry_;
bool windowless_;
bool not_anti_aliased_;
+ bool flip_textures_;
Renderer::InitStatus init_status_;
DISALLOW_COPY_AND_ASSIGN(Features);
diff --git a/o3d/core/cross/features_test.cc b/o3d/core/cross/features_test.cc
index bd2e339..e844e5f 100644
--- a/o3d/core/cross/features_test.cc
+++ b/o3d/core/cross/features_test.cc
@@ -71,10 +71,15 @@ TEST_F(FeaturesTest, Basic) {
// Features::Init is not called. o3djs,util.makeClients after and
// including 0.1.35.0 do set o3d_features and therefore Init is called
// which sets those to false to start.
+ //
+ // NOTE: pre 0.1.40.0 flip_textures defaults to true. After it defaults to
+ // false.
+
EXPECT_TRUE(features->floating_point_textures());
EXPECT_TRUE(features->large_geometry());
EXPECT_FALSE(features->windowless());
EXPECT_FALSE(features->not_anti_aliased());
+ EXPECT_TRUE(features->flip_textures());
EXPECT_EQ(features->init_status(), Renderer::SUCCESS);
delete features;
@@ -90,6 +95,39 @@ TEST_F(FeaturesTest, Empty) {
EXPECT_FALSE(features->large_geometry());
EXPECT_FALSE(features->windowless());
EXPECT_FALSE(features->not_anti_aliased());
+ EXPECT_TRUE(features->flip_textures());
+ EXPECT_EQ(features->init_status(), Renderer::SUCCESS);
+
+ delete features;
+}
+
+TEST_F(FeaturesTest, APIVersion0_1_38_0) {
+ Features* features = new Features(service_locator());
+
+ features->Init("APIVersion=0.1.38.0");
+
+ // Check that the features start off as false.
+ EXPECT_FALSE(features->floating_point_textures());
+ EXPECT_FALSE(features->large_geometry());
+ EXPECT_FALSE(features->windowless());
+ EXPECT_FALSE(features->not_anti_aliased());
+ EXPECT_TRUE(features->flip_textures());
+ EXPECT_EQ(features->init_status(), Renderer::SUCCESS);
+
+ delete features;
+}
+
+TEST_F(FeaturesTest, APIVersion0_1_40_0) {
+ Features* features = new Features(service_locator());
+
+ features->Init("APIVersion=0.1.40.0");
+
+ // Check that the features start off as false.
+ EXPECT_FALSE(features->floating_point_textures());
+ EXPECT_FALSE(features->large_geometry());
+ EXPECT_FALSE(features->windowless());
+ EXPECT_FALSE(features->not_anti_aliased());
+ EXPECT_FALSE(features->flip_textures());
EXPECT_EQ(features->init_status(), Renderer::SUCCESS);
delete features;
@@ -104,6 +142,7 @@ TEST_F(FeaturesTest, FloatingPointTextures) {
EXPECT_FALSE(features->large_geometry());
EXPECT_FALSE(features->windowless());
EXPECT_FALSE(features->not_anti_aliased());
+ EXPECT_TRUE(features->flip_textures());
EXPECT_EQ(features->init_status(), Renderer::SUCCESS);
delete features;
@@ -118,6 +157,7 @@ TEST_F(FeaturesTest, LargeGeometry) {
EXPECT_TRUE(features->large_geometry());
EXPECT_FALSE(features->windowless());
EXPECT_FALSE(features->not_anti_aliased());
+ EXPECT_TRUE(features->flip_textures());
EXPECT_EQ(features->init_status(), Renderer::SUCCESS);
delete features;
@@ -132,6 +172,7 @@ TEST_F(FeaturesTest, Windowless) {
EXPECT_FALSE(features->large_geometry());
EXPECT_TRUE(features->windowless());
EXPECT_FALSE(features->not_anti_aliased());
+ EXPECT_TRUE(features->flip_textures());
EXPECT_EQ(features->init_status(), Renderer::SUCCESS);
delete features;
@@ -146,6 +187,22 @@ TEST_F(FeaturesTest, NotAntiAliased) {
EXPECT_FALSE(features->large_geometry());
EXPECT_FALSE(features->windowless());
EXPECT_TRUE(features->not_anti_aliased());
+ EXPECT_TRUE(features->flip_textures());
+ EXPECT_EQ(features->init_status(), Renderer::SUCCESS);
+
+ delete features;
+}
+
+TEST_F(FeaturesTest, FlipTextures) {
+ Features* features = new Features(service_locator());
+
+ features->Init("FlipTextures,APIVersion=0.1.40.0");
+
+ EXPECT_FALSE(features->floating_point_textures());
+ EXPECT_FALSE(features->large_geometry());
+ EXPECT_FALSE(features->windowless());
+ EXPECT_FALSE(features->not_anti_aliased());
+ EXPECT_TRUE(features->flip_textures());
EXPECT_EQ(features->init_status(), Renderer::SUCCESS);
delete features;
@@ -166,6 +223,7 @@ TEST_F(FeaturesTest, InitStatus) {
EXPECT_FALSE(features->large_geometry());
EXPECT_FALSE(features->windowless());
EXPECT_FALSE(features->not_anti_aliased());
+ EXPECT_TRUE(features->flip_textures());
EXPECT_EQ(features->init_status(), statuses[ii]);
delete features;
@@ -181,6 +239,7 @@ TEST_F(FeaturesTest, BadInput) {
EXPECT_FALSE(features->large_geometry());
EXPECT_FALSE(features->windowless());
EXPECT_FALSE(features->not_anti_aliased());
+ EXPECT_TRUE(features->flip_textures());
EXPECT_EQ(features->init_status(), Renderer::SUCCESS);
delete features;
@@ -195,6 +254,7 @@ TEST_F(FeaturesTest, MultipleFeatures) {
EXPECT_FALSE(features->large_geometry());
EXPECT_TRUE(features->windowless());
EXPECT_FALSE(features->not_anti_aliased());
+ EXPECT_TRUE(features->flip_textures());
EXPECT_EQ(features->init_status(), Renderer::SUCCESS);
delete features;
@@ -209,6 +269,7 @@ TEST_F(FeaturesTest, MaxCapabilities) {
EXPECT_TRUE(features->large_geometry());
EXPECT_FALSE(features->windowless());
EXPECT_FALSE(features->not_anti_aliased());
+ EXPECT_TRUE(features->flip_textures());
EXPECT_EQ(features->init_status(), Renderer::SUCCESS);
delete features;
diff --git a/o3d/core/cross/field_test.cc b/o3d/core/cross/field_test.cc
index 0f8afce..6b37426 100644
--- a/o3d/core/cross/field_test.cc
+++ b/o3d/core/cross/field_test.cc
@@ -32,10 +32,13 @@
// Tests Field, FloatField, UInt32Field, UByteNField.
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/error_status.h"
#include "core/cross/field.h"
+#include "core/cross/buffer.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
namespace o3d {
diff --git a/o3d/core/cross/function_test.cc b/o3d/core/cross/function_test.cc
index c53e36f..5407324 100644
--- a/o3d/core/cross/function_test.cc
+++ b/o3d/core/cross/function_test.cc
@@ -32,9 +32,11 @@
// This file implements unit tests for class Function and FunctionEval.
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
+#include "core/cross/error_status.h"
#include "core/cross/function.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
namespace o3d {
diff --git a/o3d/core/cross/gl/renderer_gl.cc b/o3d/core/cross/gl/renderer_gl.cc
index b7197b5..6741453 100644
--- a/o3d/core/cross/gl/renderer_gl.cc
+++ b/o3d/core/cross/gl/renderer_gl.cc
@@ -1567,7 +1567,7 @@ bool RendererGL::SaveScreen(const String& file_name) {
MakeCurrentLazy();
Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
bitmap->Allocate(Texture::ARGB8, width(), height(), 1, false);
-
+
// Note: glReadPixels captures the alpha component of the frame buffer as well
// as the color components, the browser usually ignores the alpha channel when
// drawing to the screen, so unless the alpha is 1, the png image generated
diff --git a/o3d/core/cross/gl/texture_gl.cc b/o3d/core/cross/gl/texture_gl.cc
index 05acd38..559271e 100644
--- a/o3d/core/cross/gl/texture_gl.cc
+++ b/o3d/core/cross/gl/texture_gl.cc
@@ -157,20 +157,20 @@ static bool UpdateGLImageFromBitmap(GLenum target,
unsigned int mip_height = std::max(1U, bitmap.height() >> level);
const unsigned char *mip_data = bitmap.GetFaceMipData(face, level);
unsigned int mip_size =
- Bitmap::GetBufferSize(mip_width, mip_height, bitmap.format());
+ image::ComputeBufferSize(mip_width, mip_height, bitmap.format());
scoped_array<unsigned char> temp_data;
if (resize_to_pot) {
DCHECK(!Texture::IsCompressedFormat(bitmap.format()));
unsigned int pot_width =
- std::max(1U, Bitmap::GetPOTSize(bitmap.width()) >> level);
+ std::max(1U, image::ComputePOTSize(bitmap.width()) >> level);
unsigned int pot_height =
- std::max(1U, Bitmap::GetPOTSize(bitmap.height()) >> level);
- unsigned int pot_size = Bitmap::GetBufferSize(pot_width, pot_height,
- bitmap.format());
+ std::max(1U, image::ComputePOTSize(bitmap.height()) >> level);
+ unsigned int pot_size = image::ComputeBufferSize(pot_width, pot_height,
+ bitmap.format());
temp_data.reset(new unsigned char[pot_size]);
- Bitmap::Scale(mip_width, mip_height, bitmap.format(), mip_data,
- pot_width, pot_height, temp_data.get(),
- Bitmap::GetMipChainSize(pot_width, 1, bitmap.format(), 1));
+ image::Scale(mip_width, mip_height, bitmap.format(), mip_data,
+ pot_width, pot_height, temp_data.get(),
+ image::ComputePitch(bitmap.format(), pot_width));
mip_width = pot_width;
mip_height = pot_height;
mip_size = pot_size;
@@ -202,8 +202,8 @@ static bool CreateGLImagesAndUpload(GLenum target,
unsigned int mip_width = bitmap.width();
unsigned int mip_height = bitmap.height();
if (resize_to_pot) {
- mip_width = Bitmap::GetPOTSize(mip_width);
- mip_height = Bitmap::GetPOTSize(mip_height);
+ mip_width = image::ComputePOTSize(mip_width);
+ mip_height = image::ComputePOTSize(mip_height);
}
// glCompressedTexImage2D does't accept NULL as a parameter, so we need
// to pass in some data. If we can pass in the original pixel data, we'll
@@ -213,8 +213,8 @@ static bool CreateGLImagesAndUpload(GLenum target,
if (!format && (!bitmap.image_data() || resize_to_pot)) {
// Allocate a buffer big enough for the first level which is the biggest
// one.
- unsigned int size = Bitmap::GetBufferSize(mip_width, mip_height,
- bitmap.format());
+ unsigned int size = image::ComputeBufferSize(mip_width, mip_height,
+ bitmap.format());
temp_data.reset(new unsigned char[size]);
memset(temp_data.get(), 0, size);
}
@@ -231,8 +231,8 @@ static bool CreateGLImagesAndUpload(GLenum target,
return false;
}
} else {
- unsigned int mip_size = Bitmap::GetBufferSize(mip_width, mip_height,
- bitmap.format());
+ unsigned int mip_size = image::ComputeBufferSize(mip_width, mip_height,
+ bitmap.format());
DCHECK(data || temp_data.get());
glCompressedTexImage2DARB(target, i, internal_format, mip_width,
mip_height, 0, mip_size,
@@ -398,8 +398,8 @@ void Texture2DGL::SetRect(int level,
return;
}
- unsigned mip_width = Bitmap::GetMipDimension(level, width());
- unsigned mip_height = Bitmap::GetMipDimension(level, height());
+ unsigned mip_width = image::ComputeMipDimension(level, width());
+ unsigned mip_height = image::ComputeMipDimension(level, height());
if (dst_left + src_width > mip_width ||
dst_top + src_height > mip_height) {
@@ -435,8 +435,7 @@ void Texture2DGL::SetRect(int level,
GLenum gl_format = GLFormatFromO3DFormat(format(), &gl_internal_format,
&gl_data_type);
if (gl_format) {
- if ((unsigned)src_pitch == Bitmap::GetMipChainSize(src_width, 1,
- format(), 1)) {
+ if (src_pitch == image::ComputePitch(format(), src_width)) {
glTexSubImage2D(GL_TEXTURE_2D, level,
dst_left, dst_top,
src_width, src_height,
@@ -459,7 +458,7 @@ void Texture2DGL::SetRect(int level,
glCompressedTexSubImage2D(
GL_TEXTURE_2D, level, 0, 0, src_width, src_height,
gl_internal_format,
- Bitmap::GetMipChainSize(src_width, src_height, format(), 1),
+ image::ComputeMipChainSize(src_width, src_height, format(), 1),
src_data);
}
}
@@ -489,10 +488,9 @@ bool Texture2DGL::Lock(int level, void** data, int* pitch) {
backing_bitmap_->Allocate(format(), width(), height(), levels(), false);
}
*data = backing_bitmap_->GetMipData(level);
- unsigned int mip_width = Bitmap::GetMipDimension(level, width());
-
+ unsigned int mip_width = image::ComputeMipDimension(level, width());
if (!IsCompressed()) {
- *pitch = Bitmap::GetMipChainSize(mip_width, 1,format(), 1);
+ *pitch = image::ComputePitch(format(), mip_width);
} else {
unsigned blocks_across = (mip_width + 3) / 4;
unsigned bytes_per_block = format() == Texture::DXT1 ? 8 : 16;
@@ -778,7 +776,7 @@ void TextureCUBEGL::SetRect(TextureCUBE::CubeFace face,
return;
}
- unsigned mip_width = Bitmap::GetMipDimension(level, edge_length());
+ unsigned mip_width = image::ComputeMipDimension(level, edge_length());
unsigned mip_height = mip_width;
if (dst_left + src_width > mip_width ||
@@ -817,8 +815,7 @@ void TextureCUBEGL::SetRect(TextureCUBE::CubeFace face,
&gl_data_type);
int gl_face = kCubemapFaceList[face];
if (gl_format) {
- if (static_cast<unsigned>(src_pitch) ==
- Bitmap::GetMipChainSize(src_width, 1, format(), 1)) {
+ if (src_pitch == image::ComputePitch(format(), src_width)) {
glTexSubImage2D(gl_face, level,
dst_left, dst_top,
src_width, src_height,
@@ -841,7 +838,7 @@ void TextureCUBEGL::SetRect(TextureCUBE::CubeFace face,
glCompressedTexSubImage2D(
GL_TEXTURE_2D, level, 0, 0, src_width, src_height,
gl_internal_format,
- Bitmap::GetMipChainSize(src_width, src_height, format(), 1),
+ image::ComputeMipChainSize(src_width, src_height, format(), 1),
src_data);
}
}
@@ -873,9 +870,9 @@ bool TextureCUBEGL::Lock(CubeFace face, int level, void** data, int* pitch) {
levels(), true);
}
*data = backing_bitmap_->GetFaceMipData(face, level);
- unsigned int mip_width = Bitmap::GetMipDimension(level, edge_length());
+ unsigned int mip_width = image::ComputeMipDimension(level, edge_length());
if (!IsCompressed()) {
- *pitch = Bitmap::GetMipChainSize(mip_width, 1,format(), 1);
+ *pitch = image::ComputePitch(format(), mip_width);
} else {
unsigned blocks_across = (mip_width + 3) / 4;
unsigned bytes_per_block = format() == Texture::DXT1 ? 8 : 16;
diff --git a/o3d/core/cross/gl/texture_gl.h b/o3d/core/cross/gl/texture_gl.h
index 14d0be7..6b97b7f 100644
--- a/o3d/core/cross/gl/texture_gl.h
+++ b/o3d/core/cross/gl/texture_gl.h
@@ -45,11 +45,11 @@
#pragma warning(disable : 4311)
#endif
-#ifdef OS_MACOSX
-#include <OpenGL/gl.h>
-#else
-#include <GL/gl.h>
-#endif
+//#ifdef OS_MACOSX
+//#include <OpenGL/gl.h>
+//#else
+//#include <GL/gl.h>
+//#endif
#include "core/cross/bitmap.h"
#include "core/cross/texture.h"
diff --git a/o3d/core/cross/material_test.cc b/o3d/core/cross/material_test.cc
index b5feb1f..24d7a57 100644
--- a/o3d/core/cross/material_test.cc
+++ b/o3d/core/cross/material_test.cc
@@ -32,9 +32,13 @@
// This file implements unit tests for class Material.
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/material.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/semantic_manager.h"
+#include "core/cross/service_dependency.h"
+#include "core/cross/transformation_context.h"
namespace o3d {
diff --git a/o3d/core/cross/message_queue.cc b/o3d/core/cross/message_queue.cc
index f77d019..7e24767 100644
--- a/o3d/core/cross/message_queue.cc
+++ b/o3d/core/cross/message_queue.cc
@@ -591,13 +591,14 @@ bool MessageQueue::ProcessUpdateTexture2D(ConnectedClient* client,
}
unsigned int mip_width =
- Bitmap::GetMipDimension(level, texture_object->width());
+ image::ComputeMipDimension(level, texture_object->width());
unsigned int mip_height =
- Bitmap::GetMipDimension(level, texture_object->height());
+ image::ComputeMipDimension(level, texture_object->height());
if (static_cast<unsigned>(number_of_bytes) !=
- Bitmap::GetMipChainSize(mip_width, mip_height,
- texture_object->format(), 1)) {
+ image::ComputeMipChainSize(mip_width, mip_height,
+ texture_object->format(),
+ 1)) {
O3D_ERROR(service_locator_)
<< "texture_size does not match size of texture level ("
<< offset << " + " << number_of_bytes << " > " << info->size_;
@@ -608,7 +609,7 @@ bool MessageQueue::ProcessUpdateTexture2D(ConnectedClient* client,
void *target_address = static_cast<char*>(info->mapped_address_) + offset;
texture_object->SetRect(
level, 0, 0, mip_width, mip_height, target_address,
- Bitmap::GetMipChainSize(mip_width, 1, texture_object->format(), 1));
+ image::ComputePitch(texture_object->format(), mip_width));
SendBooleanResponse(client->client_handle(), true);
return true;
diff --git a/o3d/core/cross/message_queue_test.cc b/o3d/core/cross/message_queue_test.cc
index 3cefff0..5a0d30f 100644
--- a/o3d/core/cross/message_queue_test.cc
+++ b/o3d/core/cross/message_queue_test.cc
@@ -33,7 +33,10 @@
// Tests the functionality defined in MessageQueue.cc/h
#include "core/cross/message_queue.h"
-#include "core/cross/client.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
+#include "core/cross/texture.h"
#include "core/cross/types.h"
#include "tests/common/win/testing_common.h"
#include "base/condition_variable.h"
diff --git a/o3d/core/cross/pack.cc b/o3d/core/cross/pack.cc
index dee5b87..eb19e05 100644
--- a/o3d/core/cross/pack.cc
+++ b/o3d/core/cross/pack.cc
@@ -121,7 +121,7 @@ ArchiveRequest *Pack::CreateArchiveRequest() {
// Creates a Texture object from a file in the current render context format.
Texture* Pack::CreateTextureFromFile(const String& uri,
const FilePath& filepath,
- Bitmap::ImageFileType file_type,
+ image::ImageFileType file_type,
bool generate_mipmaps) {
if (!renderer_) {
O3D_ERROR(service_locator()) << "No Render Device Available";
@@ -150,7 +150,7 @@ Texture* Pack::CreateTextureFromFile(const String& uri,
// FilePath argument. The use of this method should be phased out
Texture* Pack::CreateTextureFromFile(const String& uri,
const String& filename,
- Bitmap::ImageFileType file_type,
+ image::ImageFileType file_type,
bool generate_mipmaps) {
FilePath filepath = UTF8ToFilePath(filename);
return CreateTextureFromFile(uri,
@@ -213,7 +213,7 @@ Texture* Pack::CreateTextureFromRawData(RawData *raw_data,
Bitmap::Ref bitmap(new Bitmap(service_locator()));
- if (!bitmap->LoadFromRawData(raw_data, Bitmap::UNKNOWN, generate_mips)) {
+ if (!bitmap->LoadFromRawData(raw_data, image::UNKNOWN, generate_mips)) {
O3D_ERROR(service_locator())
<< "Failed to load bitmap from raw data \"" << uri << "\"";
return NULL;
@@ -225,7 +225,7 @@ Texture* Pack::CreateTextureFromRawData(RawData *raw_data,
// Create a bitmap object.
Bitmap* Pack::CreateBitmap(int width, int height,
Texture::Format format) {
- DCHECK(Bitmap::CheckImageDimensions(width, height));
+ DCHECK(image::CheckImageDimensions(width, height));
Bitmap::Ref bitmap(new Bitmap(service_locator()));
if (bitmap.IsNull()) {
@@ -251,8 +251,7 @@ Bitmap* Pack::CreateBitmapFromRawData(RawData* raw_data) {
<< "Failed to create bitmap object.";
return NULL;
}
- if (!bitmap->LoadFromRawData(raw_data, Bitmap::UNKNOWN,
- false)) {
+ if (!bitmap->LoadFromRawData(raw_data, image::UNKNOWN, false)) {
O3D_ERROR(service_locator())
<< "Failed to load bitmap from raw data.";
return NULL;
@@ -281,8 +280,8 @@ Texture2D* Pack::CreateTexture2D(int width,
}
if (enable_render_surfaces) {
- if (Bitmap::GetPOTSize(width) != static_cast<unsigned int>(width) ||
- Bitmap::GetPOTSize(height) != static_cast<unsigned int>(height)) {
+ if (image::ComputePOTSize(width) != static_cast<unsigned int>(width) ||
+ image::ComputePOTSize(height) != static_cast<unsigned int>(height)) {
O3D_ERROR(service_locator()) <<
"Textures with RenderSurfaces enabled must have power-of-two "
"dimensions.";
@@ -294,8 +293,7 @@ Texture2D* Pack::CreateTexture2D(int width,
width,
height,
format,
- (levels == 0) ? Bitmap::GetMipMapCount(width,
- height) : levels,
+ (levels == 0) ? image::ComputeMipMapCount(width, height) : levels,
enable_render_surfaces);
if (!texture.IsNull()) {
RegisterObject(texture);
@@ -322,7 +320,7 @@ TextureCUBE* Pack::CreateTextureCUBE(int edge_length,
if (enable_render_surfaces) {
- if (Bitmap::GetPOTSize(edge_length) !=
+ if (image::ComputePOTSize(edge_length) !=
static_cast<unsigned int>(edge_length)) {
O3D_ERROR(service_locator()) <<
"Textures with RenderSurfaces enabled must have power-of-two "
@@ -334,8 +332,8 @@ TextureCUBE* Pack::CreateTextureCUBE(int edge_length,
TextureCUBE::Ref texture = renderer_->CreateTextureCUBE(
edge_length,
format,
- (levels == 0) ? Bitmap::GetMipMapCount(edge_length,
- edge_length) : levels,
+ (levels == 0) ? image::ComputeMipMapCount(edge_length,
+ edge_length) : levels,
enable_render_surfaces);
if (!texture.IsNull()) {
RegisterObject(texture);
@@ -359,8 +357,8 @@ RenderDepthStencilSurface* Pack::CreateDepthStencilSurface(int width,
return NULL;
}
- if (Bitmap::GetPOTSize(width) != static_cast<unsigned int>(width) ||
- Bitmap::GetPOTSize(height) != static_cast<unsigned int>(height)) {
+ if (image::ComputePOTSize(width) != static_cast<unsigned int>(width) ||
+ image::ComputePOTSize(height) != static_cast<unsigned int>(height)) {
O3D_ERROR(service_locator()) <<
"Depth-stencil RenderSurfaces must have power-of-two dimensions.";
return NULL;
diff --git a/o3d/core/cross/pack.h b/o3d/core/cross/pack.h
index 8832f02..9ce91d6 100644
--- a/o3d/core/cross/pack.h
+++ b/o3d/core/cross/pack.h
@@ -39,32 +39,34 @@
#include <vector>
#include <set>
-#include "core/cross/bitmap.h"
-#include "core/cross/buffer.h"
-#include "core/cross/effect.h"
#include "core/cross/named_object.h"
-#include "core/cross/sampler.h"
-#include "core/cross/shape.h"
-#include "core/cross/state.h"
#include "core/cross/smart_ptr.h"
-#include "core/cross/texture.h"
#include "core/cross/transform.h"
#include "core/cross/types.h"
-#include "core/cross/render_node.h"
+#include "core/cross/image_utils.h"
-namespace o3d {
-
-// Type definitions ------------------------
+class FilePath;
-// Array of object id's
-typedef std::vector<Id> IdArray;
+namespace o3d {
+class Bitmap;
class ArchiveRequest;
class RawData;
+class Texture;
+class Texture2D;
+class TextureCUBE;
class FileRequest;
class DrawContext;
class IClassManager;
class ObjectManager;
+class RenderDepthStencilSurface;
+
+// Type definitions ------------------------
+
+// Array of object id's
+typedef std::vector<Id> IdArray;
+// Array of Bitmaps.
+typedef std::vector<Bitmap*> BitmapArray;
// A Pack object functions as a container for O3D objects. All objects
// inheriting from ObjectBase must be constructed and assigned a pack. The Pack
@@ -200,14 +202,14 @@ class Pack : public NamedObject {
// A pointer to the texture or NULL if it did not load
Texture* CreateTextureFromFile(const String& uri,
const FilePath& filepath,
- Bitmap::ImageFileType file_type,
+ image::ImageFileType file_type,
bool generate_mipmaps);
// This version takes a String |filename| argument instead of the preferred
// FilePath argument. The use of this method should be phased out.
Texture* CreateTextureFromFile(const String& uri,
const String& filename,
- Bitmap::ImageFileType file_type,
+ image::ImageFileType file_type,
bool generate_mipmaps);
// Creates a new Texture object given a "raw-data" object which must contain
@@ -223,16 +225,13 @@ class Pack : public NamedObject {
// format: The format of the bitmap.
// Returns:
// A pointer to the bitmap obejct.
-
Bitmap* CreateBitmap(int width, int height, Texture::Format format);
// Creates a new Bitmap object from RawData.
// Parameters:
// raw_data: contains the bitmap data in one of the know formats.
- // file_type: the format of the bitmap data. If UNKNOW, the file
- // type would determined from the extension.
// Returns:
- // A pointer to the bitmap object.
+ // An array of pointers to the bitmap objects.
Bitmap* CreateBitmapFromRawData(RawData* raw_data);
// Creates a new Texture2D object of the specified size and format and
diff --git a/o3d/core/cross/pack_test.cc b/o3d/core/cross/pack_test.cc
index 0b4732f..a32e2ea 100644
--- a/o3d/core/cross/pack_test.cc
+++ b/o3d/core/cross/pack_test.cc
@@ -32,8 +32,10 @@
// Tests for functionality in pack.cc/.h.
-#include "core/cross/client.h"
#include "core/cross/pack.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/service_dependency.h"
+#include "core/cross/transform.h"
#include "tests/common/win/testing_common.h"
namespace o3d {
diff --git a/o3d/core/cross/param_array_test.cc b/o3d/core/cross/param_array_test.cc
index 8be5801..8ffa04f 100644
--- a/o3d/core/cross/param_array_test.cc
+++ b/o3d/core/cross/param_array_test.cc
@@ -32,12 +32,15 @@
// Tests functionality of the ParamArray class
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/id_manager.h"
#include "core/cross/error.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
#include "core/cross/param_array.h"
+#include "core/cross/service_dependency.h"
#include "core/cross/standard_param.h"
+#include "core/cross/transformation_context.h"
namespace o3d {
diff --git a/o3d/core/cross/param_object_test.cc b/o3d/core/cross/param_object_test.cc
index 8eb03c0..c302877 100644
--- a/o3d/core/cross/param_object_test.cc
+++ b/o3d/core/cross/param_object_test.cc
@@ -34,9 +34,11 @@
#include <algorithm>
#include "core/cross/param_object.h"
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/error.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
namespace o3d {
diff --git a/o3d/core/cross/param_operation_test.cc b/o3d/core/cross/param_operation_test.cc
index 2abe123..7906c35 100644
--- a/o3d/core/cross/param_operation_test.cc
+++ b/o3d/core/cross/param_operation_test.cc
@@ -32,9 +32,12 @@
// This file implements unit tests for various Param operations.
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/param_operation.h"
+#include "core/cross/error_status.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
namespace o3d {
diff --git a/o3d/core/cross/param_test.cc b/o3d/core/cross/param_test.cc
index 3044acd..433c3d3 100644
--- a/o3d/core/cross/param_test.cc
+++ b/o3d/core/cross/param_test.cc
@@ -59,6 +59,12 @@ class TestTexture : public Texture {
false) {}
void* GetTextureHandle() const { return NULL; }
virtual const RGBASwizzleIndices& GetABGR32FSwizzleIndices();
+ virtual void SetFromBitmap(const Bitmap& bitmap) {
+ DCHECK(false);
+ }
+ virtual void GenerateMips(int source_level, int last_target_level) {
+ DCHECK(false);
+ }
};
const Texture::RGBASwizzleIndices& TestTexture::GetABGR32FSwizzleIndices() {
diff --git a/o3d/core/cross/primitive_test.cc b/o3d/core/cross/primitive_test.cc
index 661e0ab..84765f2 100644
--- a/o3d/core/cross/primitive_test.cc
+++ b/o3d/core/cross/primitive_test.cc
@@ -32,10 +32,12 @@
// This file implements unit tests for class Primitive.
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/primitive.h"
#include "core/cross/fake_vertex_source.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
namespace o3d {
diff --git a/o3d/core/cross/ray_intersection_info_test.cc b/o3d/core/cross/ray_intersection_info_test.cc
index 9c75fb6..2b6955a 100644
--- a/o3d/core/cross/ray_intersection_info_test.cc
+++ b/o3d/core/cross/ray_intersection_info_test.cc
@@ -32,9 +32,11 @@
// This file implements unit tests for class RayIntersectionInfo.
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/ray_intersection_info.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
namespace o3d {
diff --git a/o3d/core/cross/render_node_test.cc b/o3d/core/cross/render_node_test.cc
index 256e3a2..c0ea865 100644
--- a/o3d/core/cross/render_node_test.cc
+++ b/o3d/core/cross/render_node_test.cc
@@ -32,8 +32,12 @@
// Tests functionality defined in render_node.cc/h
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
+#include "core/cross/render_node.h"
+#include "core/cross/error_status.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
namespace o3d {
diff --git a/o3d/core/cross/skin_test.cc b/o3d/core/cross/skin_test.cc
index ef4cd57..3060b1a 100644
--- a/o3d/core/cross/skin_test.cc
+++ b/o3d/core/cross/skin_test.cc
@@ -32,12 +32,15 @@
// Tests functionality of the Skin class
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/error.h"
+#include "core/cross/error_status.h"
#include "core/cross/skin.h"
#include "core/cross/pointer_utils.h"
#include "core/cross/primitive.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
#include "import/cross/memory_buffer.h"
#include "import/cross/memory_stream.h"
#include "serializer/cross/serializer_binary.h"
diff --git a/o3d/core/cross/state_set_test.cc b/o3d/core/cross/state_set_test.cc
index bd98fb8..6d784e5 100644
--- a/o3d/core/cross/state_set_test.cc
+++ b/o3d/core/cross/state_set_test.cc
@@ -32,9 +32,11 @@
// This file implements unit tests for class StateSet.
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/state_set.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
namespace o3d {
diff --git a/o3d/core/cross/state_test.cc b/o3d/core/cross/state_test.cc
index c9ea3d9..5b7faef 100644
--- a/o3d/core/cross/state_test.cc
+++ b/o3d/core/cross/state_test.cc
@@ -32,8 +32,10 @@
// This file implements unit tests for class State.
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
#include "core/cross/state.h"
namespace o3d {
diff --git a/o3d/core/cross/stream_bank_test.cc b/o3d/core/cross/stream_bank_test.cc
index daee4ca..b8bf67b 100644
--- a/o3d/core/cross/stream_bank_test.cc
+++ b/o3d/core/cross/stream_bank_test.cc
@@ -32,9 +32,11 @@
// This file implements unit tests for class StreamBank.
-#include "core/cross/client.h"
#include "core/cross/skin.h"
#include "core/cross/stream_bank.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
#include "core/cross/pointer_utils.h"
#include "core/cross/fake_vertex_source.h"
#include "tests/common/win/testing_common.h"
diff --git a/o3d/core/cross/texture.cc b/o3d/core/cross/texture.cc
index 8f71fd8..2ef6c54 100644
--- a/o3d/core/cross/texture.cc
+++ b/o3d/core/cross/texture.cc
@@ -33,6 +33,7 @@
// This file contains the definition of the Texture2D and TextureCUBE classes.
#include "core/cross/precompile.h"
+#include <cmath>
#include "core/cross/texture.h"
#include "core/cross/bitmap.h"
#include "core/cross/renderer.h"
@@ -70,7 +71,8 @@ Texture2D::Texture2D(ServiceLocator* service_locator,
ClientInfoManager* client_info_manager =
service_locator->GetService<ClientInfoManager>();
client_info_manager->AdjustTextureMemoryUsed(
- static_cast<int>(Bitmap::GetMipChainSize(width, height, format, levels)));
+ static_cast<int>(image::ComputeMipChainSize(
+ width, height, format, levels)));
}
Texture2D::~Texture2D() {
@@ -83,18 +85,22 @@ Texture2D::~Texture2D() {
ClientInfoManager* client_info_manager =
service_locator()->GetService<ClientInfoManager>();
client_info_manager->AdjustTextureMemoryUsed(
- -static_cast<int>(Bitmap::GetMipChainSize(width(),
- height(),
- format(),
- levels())));
+ -static_cast<int>(image::ComputeMipChainSize(width(),
+ height(),
+ format(),
+ levels())));
}
-void Texture2D::DrawImage(Bitmap* src_img,
+void Texture2D::DrawImage(const Bitmap& src_img,
int src_x, int src_y,
int src_width, int src_height,
int dst_x, int dst_y,
int dst_width, int dst_height, int dest_mip) {
- DCHECK(src_img->image_data());
+ DCHECK(src_img.image_data());
+
+ if (dest_mip < 0 || dest_mip >= levels()) {
+ O3D_ERROR(service_locator()) << "Mip out of range";
+ }
unsigned int mip_width = std::max(1, width() >> dest_mip);
unsigned int mip_height = std::max(1, height() >> dest_mip);
@@ -103,18 +109,19 @@ void Texture2D::DrawImage(Bitmap* src_img,
// source and destination bitmaps.
// if src or dest rectangle is out of boundary,
// do nothing and return.
- if (!Bitmap::AdjustDrawImageBoundary(&src_x, &src_y,
- &src_width, &src_height,
- src_img->width(), src_img->height(),
- &dst_x, &dst_y,
- &dst_width, &dst_height,
- mip_width, mip_height))
+ if (!image::AdjustDrawImageBoundary(&src_x, &src_y,
+ &src_width, &src_height,
+ src_img.width(), src_img.height(),
+ &dst_x, &dst_y,
+ &dst_width, &dst_height,
+ mip_width, mip_height)) {
return;
+ }
unsigned int components = 0;
// check formats of source and dest images.
// format of source and dest should be the same.
- if (src_img->format() != format()) {
+ if (src_img.format() != format()) {
O3D_ERROR(service_locator()) << "DrawImage does not support "
<< "different formats.";
return;
@@ -122,22 +129,22 @@ void Texture2D::DrawImage(Bitmap* src_img,
// if src and dest are in the same size and drawImage is copying
// the entire bitmap on dest image, just perform memcpy.
if (src_x == 0 && src_y == 0 && dst_x == 0 && dst_y == 0 &&
- src_img->width() == mip_width && src_img->height() == mip_height &&
- static_cast<unsigned int>(src_width) == src_img->width() &&
- static_cast<unsigned int>(src_height) == src_img->height() &&
+ src_img.width() == mip_width && src_img.height() == mip_height &&
+ static_cast<unsigned int>(src_width) == src_img.width() &&
+ static_cast<unsigned int>(src_height) == src_img.height() &&
static_cast<unsigned int>(dst_width) == mip_width &&
static_cast<unsigned int>(dst_height) == mip_height) {
SetRect(dest_mip, 0, 0, mip_width, mip_height,
- src_img->image_data(),
- Bitmap::GetMipChainSize(src_img->width(), 1, format(), 1));
+ src_img.image_data(),
+ src_img.GetMipPitch(0));
return;
}
- if (src_img->format() == Texture::XRGB8 ||
- src_img->format() == Texture::ARGB8) {
+ if (src_img.format() == Texture::XRGB8 ||
+ src_img.format() == Texture::ARGB8) {
components = 4;
} else {
O3D_ERROR(service_locator()) << "DrawImage does not support format: "
- << src_img->format() << " unless src and "
+ << src_img.format() << " unless src and "
<< "dest images are in the same size and "
<< "copying the entire bitmap";
return;
@@ -149,15 +156,69 @@ void Texture2D::DrawImage(Bitmap* src_img,
return;
}
- uint8* src_img_data = src_img->image_data();
+ uint8* src_img_data = src_img.image_data();
+
+ image::LanczosScale(src_img_data, src_x, src_y,
+ src_width, src_height,
+ src_img.width(), src_img.height(),
+ mip_data, helper.pitch(),
+ dst_x, dst_y,
+ dst_width, dst_height,
+ mip_width, mip_height, components);
+}
+
+void Texture2D::SetFromBitmap(const Bitmap& bitmap) {
+ DCHECK(bitmap.image_data());
+ if (bitmap.width() != width() || bitmap.height() != height() ||
+ bitmap.format() != format() || bitmap.is_cubemap()) {
+ O3D_ERROR(service_locator())
+ << "bitmap must be the same format and dimensions as texture";
+ return;
+ }
+
+ int last_level = std::min<int>(bitmap.num_mipmaps(), levels());
+ for (int level = 0; level < last_level; ++level) {
+ SetRect(level, 0, 0,
+ image::ComputeMipDimension(level, width()),
+ image::ComputeMipDimension(level, height()),
+ bitmap.GetMipData(level),
+ bitmap.GetMipPitch(level));
+ }
+}
- Bitmap::LanczosScale(src_img_data, src_x, src_y,
- src_width, src_height,
- src_img->width(), src_img->height(),
- mip_data, helper.pitch(),
- dst_x, dst_y,
- dst_width, dst_height,
- mip_width, mip_height, components);
+void Texture2D::GenerateMips(int source_level, int num_levels) {
+ if (source_level < 0 || source_level >= levels()) {
+ O3D_ERROR(service_locator()) << "source level out of range";
+ return;
+ }
+ if (source_level + num_levels >= levels()) {
+ O3D_ERROR(service_locator()) << "num levels out of range";
+ return;
+ }
+
+ for (int ii = 0; ii < num_levels; ++ii) {
+ int level = source_level + ii;
+ Texture2D::LockHelper src_helper(this, level);
+ Texture2D::LockHelper dst_helper(this, level + 1);
+ const uint8* src_data = src_helper.GetDataAs<const uint8>();
+ if (!src_data) {
+ O3D_ERROR(service_locator())
+ << "could not lock source texture.";
+ return;
+ }
+ uint8* dst_data = dst_helper.GetDataAs<uint8>();
+ if (!dst_data) {
+ O3D_ERROR(service_locator())
+ << "could not lock destination texture.";
+ return;
+ }
+
+ unsigned int src_width = image::ComputeMipDimension(level, width());
+ unsigned int src_height = image::ComputeMipDimension(level, height());
+ image::GenerateMipmap(src_width, src_height, format(),
+ src_data, src_helper.pitch(),
+ dst_data, dst_helper.pitch());
+ }
}
ObjectBase::Ref Texture2D::Create(ServiceLocator* service_locator) {
@@ -206,10 +267,10 @@ TextureCUBE::TextureCUBE(ServiceLocator* service_locator,
ClientInfoManager* client_info_manager =
service_locator->GetService<ClientInfoManager>();
client_info_manager->AdjustTextureMemoryUsed(
- static_cast<int>(Bitmap::GetMipChainSize(edge_length,
- edge_length,
- format,
- levels)) * 6);
+ static_cast<int>(image::ComputeMipChainSize(edge_length,
+ edge_length,
+ format,
+ levels)) * 6);
}
TextureCUBE::~TextureCUBE() {
@@ -225,23 +286,32 @@ TextureCUBE::~TextureCUBE() {
ClientInfoManager* client_info_manager =
service_locator()->GetService<ClientInfoManager>();
client_info_manager->AdjustTextureMemoryUsed(
- -static_cast<int>(Bitmap::GetMipChainSize(edge_length(),
- edge_length(),
- format(),
- levels()) * 6));
+ -static_cast<int>(image::ComputeMipChainSize(edge_length(),
+ edge_length(),
+ format(),
+ levels()) * 6));
}
ObjectBase::Ref TextureCUBE::Create(ServiceLocator* service_locator) {
return ObjectBase::Ref();
}
-void TextureCUBE::DrawImage(Bitmap* src_img,
+void TextureCUBE::DrawImage(const Bitmap& src_img,
int src_x, int src_y,
int src_width, int src_height,
int dst_x, int dst_y,
int dst_width, int dst_height,
CubeFace dest_face, int dest_mip) {
- DCHECK(src_img->image_data());
+ DCHECK(src_img.image_data());
+
+ if (dest_face >= NUMBER_OF_FACES) {
+ O3D_ERROR(service_locator()) << "Invalid face specification";
+ return;
+ }
+
+ if (dest_mip < 0 || dest_mip >= levels()) {
+ O3D_ERROR(service_locator()) << "Mip out of range";
+ }
unsigned int mip_length = std::max(1, edge_length() >> dest_mip);
@@ -249,18 +319,19 @@ void TextureCUBE::DrawImage(Bitmap* src_img,
// source and destination bitmaps.
// if src or dest rectangle is out of boundary,
// do nothing and return true.
- if (!Bitmap::AdjustDrawImageBoundary(&src_x, &src_y,
- &src_width, &src_height,
- src_img->width(), src_img->height(),
- &dst_x, &dst_y,
- &dst_width, &dst_height,
- mip_length, mip_length))
+ if (!image::AdjustDrawImageBoundary(&src_x, &src_y,
+ &src_width, &src_height,
+ src_img.width(), src_img.height(),
+ &dst_x, &dst_y,
+ &dst_width, &dst_height,
+ mip_length, mip_length)) {
return;
+ }
unsigned int components = 0;
// check formats of source and dest images.
// format of source and dest should be the same.
- if (src_img->format() != format()) {
+ if (src_img.format() != format()) {
O3D_ERROR(service_locator()) << "DrawImage does not support "
<< "different formats.";
return;
@@ -268,22 +339,22 @@ void TextureCUBE::DrawImage(Bitmap* src_img,
// if src and dest are in the same size and drawImage is copying
// the entire bitmap on dest image, just perform memcpy.
if (src_x == 0 && src_y == 0 && dst_x == 0 && dst_y == 0 &&
- src_img->width() == mip_length && src_img->height() == mip_length &&
- static_cast<unsigned int>(src_width) == src_img->width() &&
- static_cast<unsigned int>(src_height) == src_img->height() &&
+ src_img.width() == mip_length && src_img.height() == mip_length &&
+ static_cast<unsigned int>(src_width) == src_img.width() &&
+ static_cast<unsigned int>(src_height) == src_img.height() &&
static_cast<unsigned int>(dst_width) == mip_length &&
static_cast<unsigned int>(dst_height) == mip_length) {
SetRect(dest_face, dest_mip, 0, 0, mip_length, mip_length,
- src_img->image_data(),
- Bitmap::GetMipChainSize(src_img->width(), 1, format(), 1));
+ src_img.image_data(),
+ src_img.GetMipPitch(0));
return;
}
- if (src_img->format() == Texture::XRGB8 ||
- src_img->format() == Texture::ARGB8) {
+ if (src_img.format() == Texture::XRGB8 ||
+ src_img.format() == Texture::ARGB8) {
components = 4;
} else {
O3D_ERROR(service_locator()) << "DrawImage does not support format: "
- << src_img->format() << " unless src and "
+ << src_img.format() << " unless src and "
<< "dest images are in the same size and "
<< "copying the entire bitmap";
return;
@@ -295,15 +366,77 @@ void TextureCUBE::DrawImage(Bitmap* src_img,
return;
}
- uint8* src_img_data = src_img->image_data();
+ uint8* src_img_data = src_img.image_data();
+
+ image::LanczosScale(src_img_data, src_x, src_y,
+ src_width, src_height,
+ src_img.width(), src_img.height(),
+ mip_data, helper.pitch(),
+ dst_x, dst_y,
+ dst_width, dst_height,
+ mip_length, mip_length, components);
+}
+
+void TextureCUBE::SetFromBitmap(const Bitmap& bitmap) {
+ DCHECK(bitmap.image_data());
+ if (bitmap.width() != edge_length() || bitmap.height() != edge_length() ||
+ bitmap.format() != format() || !bitmap.is_cubemap()) {
+ O3D_ERROR(service_locator())
+ << "bitmap must be the same format and dimensions as texture";
+ return;
+ }
- Bitmap::LanczosScale(src_img_data, src_x, src_y,
- src_width, src_height,
- src_img->width(), src_img->height(),
- mip_data, helper.pitch(),
- dst_x, dst_y,
- dst_width, dst_height,
- mip_length, mip_length, components);
+ int last_level = std::min<int>(bitmap.num_mipmaps(), levels());
+ for (int level = 0; level < last_level; ++level) {
+ for (int face = FACE_POSITIVE_X; face < NUMBER_OF_FACES; ++face) {
+ SetRect(static_cast<CubeFace>(face), level, 0, 0,
+ image::ComputeMipDimension(level, edge_length()),
+ image::ComputeMipDimension(level, edge_length()),
+ bitmap.GetFaceMipData(static_cast<CubeFace>(face), level),
+ bitmap.GetMipPitch(level));
+ }
+ }
+}
+
+void TextureCUBE::GenerateMips(int source_level, int num_levels) {
+ if (source_level < 0 || source_level >= levels()) {
+ O3D_ERROR(service_locator()) << "source level out of range";
+ return;
+ }
+ if (source_level + num_levels >= levels()) {
+ O3D_ERROR(service_locator()) << "num levels out of range";
+ return;
+ }
+
+ for (int face = FACE_POSITIVE_X; face < NUMBER_OF_FACES; ++face) {
+ for (int ii = 0; ii < num_levels; ++ii) {
+ int level = source_level + ii;
+ TextureCUBE::LockHelper src_helper(
+ this, static_cast<TextureCUBE::CubeFace>(face), level);
+ TextureCUBE::LockHelper dst_helper(
+ this, static_cast<TextureCUBE::CubeFace>(face), level + 1);
+ const uint8* src_data = src_helper.GetDataAs<const uint8>();
+ if (!src_data) {
+ O3D_ERROR(service_locator())
+ << "could not lock source texture.";
+ return;
+ }
+ uint8* dst_data = dst_helper.GetDataAs<uint8>();
+ if (!dst_data) {
+ O3D_ERROR(service_locator())
+ << "could not lock destination texture.";
+ return;
+ }
+
+ unsigned int src_edge_length =
+ std::max<unsigned int>(1U, edge_length() >> level);
+
+ image::GenerateMipmap(
+ src_edge_length, src_edge_length, format(),
+ src_data, src_helper.pitch(),
+ dst_data, dst_helper.pitch());
+ }
+ }
}
TextureCUBE::LockHelper::LockHelper(
diff --git a/o3d/core/cross/texture.h b/o3d/core/cross/texture.h
index 721a7ec..fdb1b2f 100644
--- a/o3d/core/cross/texture.h
+++ b/o3d/core/cross/texture.h
@@ -104,11 +104,6 @@ class Texture2D : public Texture {
return height_param_->value();
}
- // Sets a rectangular region of this texture.
- // If the texture is a DXT format, the only acceptable values
- // for left, top, width and height are 0, 0, texture->width, texture->height
- //
- // Parameters:
// level: The mipmap level to modify
// dst_left: The left edge of the rectangular area to modify.
// dst_top: The top edge of the rectangular area to modify.
@@ -146,11 +141,17 @@ class Texture2D : public Texture {
// dest_width: width of the dest image.
// dest_height: height of the dest image.
// dest_mip: on which mip level the sourceImg would be drawn.
- void DrawImage(Bitmap* source_img, int source_x, int source_y,
+ void DrawImage(const Bitmap& source_img, int source_x, int source_y,
int source_width, int source_height,
int dest_x, int dest_y,
int dest_width, int dest_height, int dest_mip);
+ // Sets the contents of the texture from a Bitmap.
+ virtual void SetFromBitmap(const Bitmap& bitmap);
+
+ // Generates mips.
+ virtual void GenerateMips(int source_level, int num_levels);
+
protected:
// Returns a pointer to the internal texture data for the given mipmap level.
// Lock must be called before the texture data can be modified.
@@ -307,11 +308,17 @@ class TextureCUBE : public Texture {
// dest_height: height of the dest image.
// face: on which face the sourceImg would be drawn.
// dest_mip: on which mip level the sourceImg would be drawn.
- void DrawImage(Bitmap* source_img, int source_x, int source_y,
+ void DrawImage(const Bitmap& source_img, int source_x, int source_y,
int source_width, int source_height,
int dest_x, int dest_y, int dest_width,
int dest_height, CubeFace face, int dest_mip);
+ // Sets the contents of the texture from a Bitmap.
+ virtual void SetFromBitmap(const Bitmap& bitmap);
+
+ // Generates mips.
+ virtual void GenerateMips(int source_level, int num_levels);
+
protected:
// Returns a pointer to the internal texture data for the given face and
// mipmap level.
diff --git a/o3d/core/cross/texture_base.h b/o3d/core/cross/texture_base.h
index 395480c..b8649b9 100644
--- a/o3d/core/cross/texture_base.h
+++ b/o3d/core/cross/texture_base.h
@@ -40,6 +40,7 @@
namespace o3d {
+class Bitmap;
class Pack;
class Renderer;
class RenderSurface;
@@ -52,8 +53,6 @@ class Texture : public ParamObject {
typedef SmartPointer<Texture> Ref;
typedef WeakPointer<Texture> WeakPointerType;
- enum Type { TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_CUBE };
-
enum Format {
UNKNOWN_FORMAT,
XRGB8, // actual format in memory is B G R X
@@ -115,6 +114,12 @@ class Texture : public ParamObject {
return render_surfaces_enabled_;
}
+ // Sets the contents of the texture from a Bitmap.
+ virtual void SetFromBitmap(const Bitmap& bitmap) = 0;
+
+ // Generates mips.
+ virtual void GenerateMips(int source_level, int num_levels) = 0;
+
// Gets a RGBASwizzleIndices that contains a mapping from
// RGBA to the internal format used by the graphics API.
virtual const RGBASwizzleIndices& GetABGR32FSwizzleIndices() = 0;
diff --git a/o3d/core/cross/texture_base_test.cc b/o3d/core/cross/texture_base_test.cc
index 8b13973..a7780d37 100644
--- a/o3d/core/cross/texture_base_test.cc
+++ b/o3d/core/cross/texture_base_test.cc
@@ -58,11 +58,17 @@ class MockTexture : public Texture {
virtual const RGBASwizzleIndices& GetABGR32FSwizzleIndices() {
return swizzle;
- };
+ }
virtual void* GetTextureHandle() const {
return NULL;
- };
+ }
+
+ virtual void SetFromBitmap(const Bitmap& bitmap) {
+ }
+
+ virtual void GenerateMips(int source_level, int num_levels) {
+ }
private:
DISALLOW_COPY_AND_ASSIGN(MockTexture);
diff --git a/o3d/core/cross/texture_test.cc b/o3d/core/cross/texture_test.cc
index f14c87f..c9cb3ca 100644
--- a/o3d/core/cross/texture_test.cc
+++ b/o3d/core/cross/texture_test.cc
@@ -33,7 +33,7 @@
// This file implements unit tests for class Texture.
#include "tests/common/win/testing_common.h"
-#include "core/cross/texture_base.h"
+#include "core/cross/texture.h"
#include "core/cross/object_manager.h"
#include "core/cross/pack.h"
diff --git a/o3d/core/cross/transform_test.cc b/o3d/core/cross/transform_test.cc
index 7ee4f23..c6fa213 100644
--- a/o3d/core/cross/transform_test.cc
+++ b/o3d/core/cross/transform_test.cc
@@ -34,10 +34,13 @@
#include <algorithm>
-#include "core/cross/client.h"
+#include "core/cross/transform.h"
#include "core/cross/shape.h"
#include "core/cross/primitive.h"
#include "core/cross/material.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
#include "tests/common/win/testing_common.h"
namespace o3d {
diff --git a/o3d/core/cross/tree_traversal_test.cc b/o3d/core/cross/tree_traversal_test.cc
index 8ae0874..1cb1f8b 100644
--- a/o3d/core/cross/tree_traversal_test.cc
+++ b/o3d/core/cross/tree_traversal_test.cc
@@ -32,9 +32,13 @@
// This file implements unit tests for class TreeTraveral.
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "core/cross/tree_traversal.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/service_dependency.h"
+#include "core/cross/transformation_context.h"
+#include "core/cross/draw_list_manager.h"
namespace o3d {
diff --git a/o3d/core/win/d3d9/texture_d3d9.cc b/o3d/core/win/d3d9/texture_d3d9.cc
index 1fb9c4c..5c93f7b 100644
--- a/o3d/core/win/d3d9/texture_d3d9.cc
+++ b/o3d/core/win/d3d9/texture_d3d9.cc
@@ -98,8 +98,8 @@ HRESULT CreateTexture2DD3D9(RendererD3D9* renderer,
*mip_height = bitmap->height();
if (*resize_to_pot) {
- *mip_width = Bitmap::GetPOTSize(*mip_width);
- *mip_height = Bitmap::GetPOTSize(*mip_height);
+ *mip_width = image::ComputePOTSize(*mip_width);
+ *mip_height = image::ComputePOTSize(*mip_height);
}
DWORD usage = (enable_render_surfaces) ? D3DUSAGE_RENDERTARGET : 0;
@@ -135,7 +135,7 @@ HRESULT CreateTextureCUBED3D9(RendererD3D9* renderer,
*resize_to_pot = !renderer->supports_npot() && !bitmap->IsPOT();
*edge_width = bitmap->width();
if (*resize_to_pot) {
- *edge_width = Bitmap::GetPOTSize(*edge_width);
+ *edge_width = image::ComputePOTSize(*edge_width);
}
DWORD usage = (enable_render_surfaces) ? D3DUSAGE_RENDERTARGET : 0;
@@ -220,7 +220,7 @@ void SetTextureRectUncompressed(Texture::Format format,
unsigned src_height,
uint8* dst,
int dst_pitch) {
- size_t bytes_per_line = Bitmap::GetMipChainSize(src_width, 1, format, 1);
+ size_t bytes_per_line = image::ComputePitch(format, src_width);
for (unsigned yy = 0; yy < src_height; ++yy) {
memcpy(dst, src, bytes_per_line);
src += src_pitch;
@@ -406,12 +406,12 @@ void Texture2DD3D9::UpdateBackedMipLevel(unsigned int level) {
DCHECK_EQ(backing_bitmap_->format(), format());
DCHECK_EQ(backing_bitmap_->num_mipmaps(), levels());
- unsigned int mip_width = Bitmap::GetMipDimension(level, width());
- unsigned int mip_height = Bitmap::GetMipDimension(level, height());
+ unsigned int mip_width = image::ComputeMipDimension(level, width());
+ unsigned int mip_height = image::ComputeMipDimension(level, height());
unsigned int rect_width = mip_width;
unsigned int rect_height = mip_height;
- rect_width = std::max(1U, Bitmap::GetPOTSize(width()) >> level);
- rect_height = std::max(1U, Bitmap::GetPOTSize(height()) >> level);
+ rect_width = std::max(1U, image::ComputePOTSize(width()) >> level);
+ rect_height = std::max(1U, image::ComputePOTSize(height()) >> level);
RECT rect = {0, 0, rect_width, rect_height};
D3DLOCKED_RECT out_rect = {0};
@@ -427,15 +427,15 @@ void Texture2DD3D9::UpdateBackedMipLevel(unsigned int level) {
const uint8 *mip_data = backing_bitmap_->GetMipData(level);
if (resize_to_pot_) {
- Bitmap::Scale(mip_width, mip_height, format(), mip_data,
- rect_width, rect_height,
- static_cast<uint8 *>(out_rect.pBits),
- out_rect.Pitch);
+ image::Scale(mip_width, mip_height, format(), mip_data,
+ rect_width, rect_height,
+ static_cast<uint8 *>(out_rect.pBits),
+ out_rect.Pitch);
} else {
if (!IsCompressed()) {
SetTextureRectUncompressed(
format(), mip_data,
- Bitmap::GetMipChainSize(mip_width, 1, format(), 1),
+ image::ComputePitch(format(), mip_width),
mip_width, mip_height,
dst, out_rect.Pitch);
} else {
@@ -500,8 +500,8 @@ void Texture2DD3D9::SetRect(int level,
return;
}
- unsigned mip_width = Bitmap::GetMipDimension(level, width());
- unsigned mip_height = Bitmap::GetMipDimension(level, height());
+ unsigned mip_width = image::ComputeMipDimension(level, width());
+ unsigned mip_height = image::ComputeMipDimension(level, height());
if (dst_left + src_width > mip_width ||
dst_top + src_height > mip_height) {
@@ -569,9 +569,9 @@ bool Texture2DD3D9::Lock(int level, void** texture_data, int* pitch) {
if (resize_to_pot_) {
DCHECK(backing_bitmap_->image_data());
*texture_data = backing_bitmap_->GetMipData(level);
- unsigned int mip_width = Bitmap::GetMipDimension(level, width());
- unsigned int mip_height = Bitmap::GetMipDimension(level, height());
- *pitch = Bitmap::GetMipChainSize(mip_width, 1, format(), 1);
+ unsigned int mip_width = image::ComputeMipDimension(level, width());
+ unsigned int mip_height = image::ComputeMipDimension(level, height());
+ *pitch = image::ComputePitch(format(), mip_width);
locked_levels_ |= 1 << level;
return true;
} else {
@@ -746,7 +746,7 @@ void TextureCUBED3D9::UpdateBackedMipLevel(TextureCUBE::CubeFace face,
unsigned int mip_edge = std::max(1, edge_length() >> level);
unsigned int rect_edge = mip_edge;
if (resize_to_pot_) {
- rect_edge = std::max(1U, Bitmap::GetPOTSize(edge_length()) >> level);
+ rect_edge = std::max(1U, image::ComputePOTSize(edge_length()) >> level);
}
RECT rect = {0, 0, rect_edge, rect_edge};
@@ -764,15 +764,15 @@ void TextureCUBED3D9::UpdateBackedMipLevel(TextureCUBE::CubeFace face,
const uint8 *mip_data = backing_bitmap_->GetFaceMipData(face, level);
if (resize_to_pot_) {
- Bitmap::Scale(mip_edge, mip_edge, format(), mip_data,
- rect_edge, rect_edge,
- static_cast<uint8 *>(out_rect.pBits),
- out_rect.Pitch);
+ image::Scale(mip_edge, mip_edge, format(), mip_data,
+ rect_edge, rect_edge,
+ static_cast<uint8 *>(out_rect.pBits),
+ out_rect.Pitch);
} else {
if (!IsCompressed()) {
SetTextureRectUncompressed(
format(), mip_data,
- Bitmap::GetMipChainSize(mip_edge, 1, format(), 1),
+ image::ComputePitch(format(), mip_edge),
mip_edge, mip_edge,
dst, out_rect.Pitch);
} else {
@@ -847,7 +847,7 @@ void TextureCUBED3D9::SetRect(TextureCUBE::CubeFace face,
return;
}
- unsigned mip_width = Bitmap::GetMipDimension(level, edge_length());
+ unsigned mip_width = image::ComputeMipDimension(level, edge_length());
unsigned mip_height = mip_width;
if (dst_left + src_width > mip_width ||
@@ -918,9 +918,9 @@ bool TextureCUBED3D9::Lock(
if (resize_to_pot_) {
DCHECK(backing_bitmap_->image_data());
*texture_data = backing_bitmap_->GetFaceMipData(face, level);
- unsigned int mip_width = Bitmap::GetMipDimension(level, edge_length());
+ unsigned int mip_width = image::ComputeMipDimension(level, edge_length());
unsigned int mip_height = mip_width;
- *pitch = Bitmap::GetMipChainSize(mip_width, 1, format(), 1);
+ *pitch = image::ComputePitch(format(), mip_width);
locked_levels_[face] |= 1 << level;
return true;
} else {
diff --git a/o3d/import/cross/collada.cc b/o3d/import/cross/collada.cc
index 0e88ae2..e04c32a 100644
--- a/o3d/import/cross/collada.cc
+++ b/o3d/import/cross/collada.cc
@@ -49,6 +49,7 @@
#include "core/cross/pack.h"
#include "core/cross/param_operation.h"
#include "core/cross/primitive.h"
+#include "core/cross/sampler.h"
#include "core/cross/skin.h"
#include "core/cross/stream.h"
#include "import/cross/collada.h"
@@ -1686,7 +1687,7 @@ Texture* Collada::BuildTextureFromImage(FCDImage* image) {
tex = Texture::Ref(
pack_->CreateTextureFromFile(FilePathToUTF8(uri),
file_path,
- Bitmap::UNKNOWN,
+ image::UNKNOWN,
options_.generate_mipmaps));
if (tex) {
const fstring name(image->GetName());
diff --git a/o3d/import/cross/gz_compressor_test.cc b/o3d/import/cross/gz_compressor_test.cc
index cd39499..3ca59d0 100644
--- a/o3d/import/cross/gz_compressor_test.cc
+++ b/o3d/import/cross/gz_compressor_test.cc
@@ -33,7 +33,6 @@
#include <sys/stat.h>
#include <string>
-#include "core/cross/client.h"
#include "import/cross/memory_stream.h"
#include "import/cross/memory_buffer.h"
#include "import/cross/gz_decompressor.h"
diff --git a/o3d/import/cross/gz_decompressor_test.cc b/o3d/import/cross/gz_decompressor_test.cc
index ec79ad9..f2d1212 100644
--- a/o3d/import/cross/gz_decompressor_test.cc
+++ b/o3d/import/cross/gz_decompressor_test.cc
@@ -33,7 +33,6 @@
#include <sys/stat.h>
#include <algorithm>
-#include "core/cross/client.h"
#include "import/cross/gz_decompressor.h"
#include "import/cross/memory_buffer.h"
#include "tests/common/win/testing_common.h"
diff --git a/o3d/import/cross/precompile.h b/o3d/import/cross/precompile.h
index e1daa2b..20671d6 100644
--- a/o3d/import/cross/precompile.h
+++ b/o3d/import/cross/precompile.h
@@ -42,6 +42,13 @@
#ifdef __cplusplus
+#if defined(RENDERER_GL)
+#include <GL/glew.h>
+#if defined(OS_WIN)
+#include <GL/wglew.h>
+#endif
+#endif // defined(RENDERER_GL)
+
#include <Cg/cg.h>
#include <Cg/cgGL.h>
#include <FCollada.h>
diff --git a/o3d/import/cross/raw_data.h b/o3d/import/cross/raw_data.h
index 1929b1a..092c800 100644
--- a/o3d/import/cross/raw_data.h
+++ b/o3d/import/cross/raw_data.h
@@ -46,8 +46,6 @@
#include "core/cross/param.h"
#include "core/cross/types.h"
-class FilePath;
-
namespace o3d {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/o3d/import/cross/raw_data_test.cc b/o3d/import/cross/raw_data_test.cc
index 4399cd9..b4c5f86 100644
--- a/o3d/import/cross/raw_data_test.cc
+++ b/o3d/import/cross/raw_data_test.cc
@@ -32,7 +32,6 @@
// Tests functionality of the RawData class
-#include "core/cross/client.h"
#include "tests/common/win/testing_common.h"
#include "utils/cross/file_path_utils.h"
#include "base/file_path.h"
diff --git a/o3d/import/cross/tar_generator_test.cc b/o3d/import/cross/tar_generator_test.cc
index 5fdec8a..1659e98 100644
--- a/o3d/import/cross/tar_generator_test.cc
+++ b/o3d/import/cross/tar_generator_test.cc
@@ -30,7 +30,6 @@
*/
-#include "core/cross/client.h"
#include "import/cross/memory_buffer.h"
#include "import/cross/memory_stream.h"
#include "import/cross/tar_generator.h"
diff --git a/o3d/import/cross/tar_processor_test.cc b/o3d/import/cross/tar_processor_test.cc
index 2e1f0bd..4da0f97 100644
--- a/o3d/import/cross/tar_processor_test.cc
+++ b/o3d/import/cross/tar_processor_test.cc
@@ -30,7 +30,6 @@
*/
-#include "core/cross/client.h"
#include "import/cross/targz_processor.h"
#include "tests/common/win/testing_common.h"
#include "tests/common/cross/test_utils.h"
diff --git a/o3d/import/cross/targz_generator_test.cc b/o3d/import/cross/targz_generator_test.cc
index 7911387..e3331f3 100644
--- a/o3d/import/cross/targz_generator_test.cc
+++ b/o3d/import/cross/targz_generator_test.cc
@@ -33,7 +33,6 @@
#include <string>
#include "base/file_util.h"
-#include "core/cross/client.h"
#include "import/cross/memory_stream.h"
#include "import/cross/targz_generator.h"
#include "tests/common/cross/test_utils.h"
diff --git a/o3d/import/cross/targz_processor_test.cc b/o3d/import/cross/targz_processor_test.cc
index a351ec8..37d70a4 100644
--- a/o3d/import/cross/targz_processor_test.cc
+++ b/o3d/import/cross/targz_processor_test.cc
@@ -30,7 +30,6 @@
*/
-#include "core/cross/client.h"
#include "import/cross/targz_processor.h"
#include "tests/common/win/testing_common.h"
diff --git a/o3d/plugin/cross/async_loading.cc b/o3d/plugin/cross/async_loading.cc
index f38ef5d..dfcbcfe 100644
--- a/o3d/plugin/cross/async_loading.cc
+++ b/o3d/plugin/cross/async_loading.cc
@@ -90,8 +90,8 @@ class LoadTextureURLCallback : public StreamManager::FinishedCallback {
// Unfortunately, TGA and DDS don't have standard MIME type, so we may
// have to rely on the filename, or let the image loader figure it out by
// itself (by trying every possible type).
- Bitmap::ImageFileType image_type =
- Bitmap::GetFileTypeFromMimeType(mime_type.c_str());
+ o3d::image::ImageFileType image_type =
+ o3d::image::GetFileTypeFromMimeType(mime_type.c_str());
texture = Texture::Ref(
request_->pack()->CreateTextureFromFile(
request_->uri(),
diff --git a/o3d/plugin/cross/o3d_glue.h b/o3d/plugin/cross/o3d_glue.h
index c318ea5..6143db2 100644
--- a/o3d/plugin/cross/o3d_glue.h
+++ b/o3d/plugin/cross/o3d_glue.h
@@ -60,6 +60,7 @@
#include "core/cross/evaluation_counter.h"
#include "core/cross/class_manager.h"
#include "core/cross/client_info.h"
+#include "core/cross/cursor.h"
#include "core/cross/features.h"
#include "core/cross/object_manager.h"
#include "core/cross/error.h"
diff --git a/o3d/plugin/idl/bitmap.idl b/o3d/plugin/idl/bitmap.idl
index 066ca5a..a223f43 100644
--- a/o3d/plugin/idl/bitmap.idl
+++ b/o3d/plugin/idl/bitmap.idl
@@ -33,49 +33,29 @@
namespace o3d {
%[
-Bitmap provides an interface for basic image operations on bitmap,
-including scale and crop. The contents of bitmap can be created from
-RawData via pack.createBitmapFromRawData(), and also can be transfered
-to mip of a Texure2D or a specific face of TextureCUBE via methods
-in Texture.
+ Bitmap provides an interface for basic image operations on bitmap,
+ including scale and crop. The contents of bitmap can be created from
+ RawData via pack.createBitmapFromRawData(), and also can be transfered
+ to mip of a Texure2D or a specific face of TextureCUBE via methods
+ in Texture.
%]
[nocpp, include="core/cross/bitmap.h"]
class Bitmap : ParamObject {
%[
- enum ImageFileType {
- \li UNKNOWN, Image type unknown.
- \li TGA, image in TGA format.
- \li JPEG, image in JPEG format.
- \li PNG, image in PNG format.
- \li DDS, image in DDS format.
- };
+ Flips a bitmap vertically in place.
%]
- enum ImageFileType {
- UNKNOWN,
- TGA,
- JPEG,
- PNG,
- DDS
- };
+ void FlipVertically();
%[
- Copy pixels from source bitmap. Scales if the width and height of source
- and dest do not match.
- \param source_img source bitmap which would be drawn.
- \param source_x x-coordinate of the starting pixel in the source image.
- \param source_y y-coordinate of the starting pixel in the source image.
- \param source_width width of the source image to draw.
- \param source_height Height of the source image to draw.
- \param dest_x x-coordinate of the starting pixel in the dest image.
- \param dest_y y-coordinate of the starting pixel in the dest image.
- \param dest_width width of the dest image to draw.
- \param dest_height height of the dest image to draw.
+ Generates mip maps from the source level to lower levels.
+
+ You can currently only use this on XRGB8 and ARGB8 textures.
+
+ \param source_level The level to use as the source of the mips.
+ \param num_levels The number of levels to generate below the source level.
%]
- void DrawImage(Bitmap source_img, int source_x, int source_y,
- int source_width, int source_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height);
+ void GenerateMips(int source_level, int num_levels);
%[
The width of the bitmap (read only).
@@ -87,6 +67,20 @@ class Bitmap : ParamObject {
%]
[getter] int height_;
+ %[
+ The format of the bitmap (read only).
+ %]
+ [getter] Texture::Format format_;
+
+ %[
+ Number mip-maps (read only)
+ %]
+ [getter] int num_mipmaps_;
+
+ %[
+ Whether or not the bitmap is a cubemap.
+ %]
+ [getter] bool is_cubemap_;
}; // Bitmap
} // namespace o3d
diff --git a/o3d/plugin/idl/texture.idl b/o3d/plugin/idl/texture.idl
index 763518e..54b705c 100644
--- a/o3d/plugin/idl/texture.idl
+++ b/o3d/plugin/idl/texture.idl
@@ -107,6 +107,29 @@ namespace o3d {
True of all the alpha values in the texture are 1.0
%]
[getter, getter, setter] bool alpha_is_one;
+
+ %[
+ Generates Mips.
+ \param source_level the mip to use as the source.
+ \param num_levels the number of mips from the source to generate.
+ %]
+ void GenerateMips(int source_level, int num_levels);
+
+ %[
+ Sets the content of the texture to the content of the bitmap. The texture
+ and the bitmap must be the same dimensions and the same format.
+
+ \param bitmap The bitmap to copy data from.
+ %]
+ [userglue]
+ void SetFromBitmap(Bitmap bitmap);
+
+ [verbatim=cpp_glue] %{
+ void userglue_method_SetFromBitmap(o3d::Texture* self,
+ o3d::Bitmap* bitmap) {
+ self->SetFromBitmap(*bitmap);
+ }
+ %}
}; // Texture
%[
@@ -209,10 +232,25 @@ namespace o3d {
\param dest_height height of the dest image.
\param dest_mip on which mip level the sourceImg would be drawn.
%]
+ [userglue]
void DrawImage(Bitmap source_img, int source_x, int source_y,
int source_width, int source_height,
int dest_x, int dest_y,
int dest_width, int dest_height, int dest_mip);
+
+ [verbatim=cpp_glue] %{
+ void userglue_method_DrawImage(
+ o3d::Texture2D* self,
+ o3d::Bitmap* source_img, int source_x, int source_y,
+ int source_width, int source_height,
+ int dest_x, int dest_y,
+ int dest_width, int dest_height, int dest_mip) {
+ self->DrawImage(*source_img, source_x, source_y,
+ source_width, source_height,
+ dest_x, dest_y,
+ dest_width, dest_height, dest_mip);
+ }
+%}
}; // Texture2D
@@ -317,11 +355,27 @@ namespace o3d {
\param face on which face the sourceImg would be drawn.
\param dest_mip on which mip level the sourceImg would be drawn.
%]
+ [userglue]
void DrawImage(Bitmap source_img, int source_x, int source_y,
int source_width, int source_height,
int dest_x, int dest_y,
int dest_width, int dest_height,
CubeFace face, int dest_mip);
+
+ [verbatim=cpp_glue] %{
+ void userglue_method_DrawImage(
+ o3d::TextureCUBE* self,
+ o3d::Bitmap* source_img, int source_x, int source_y,
+ int source_width, int source_height,
+ int dest_x, int dest_y,
+ int dest_width, int dest_height,
+ o3d::TextureCUBE::CubeFace dest_face, int dest_mip) {
+ self->DrawImage(*source_img, source_x, source_y,
+ source_width, source_height,
+ dest_x, dest_y,
+ dest_width, dest_height, dest_face, dest_mip);
+ }
+ %}
}; // TextureCUBE
} // namespace o3d
diff --git a/o3d/samples/bitmap-draw-image.html b/o3d/samples/bitmap-draw-image.html
index 66471f1..1e3bac0 100644
--- a/o3d/samples/bitmap-draw-image.html
+++ b/o3d/samples/bitmap-draw-image.html
@@ -113,8 +113,6 @@ function makeShape(texture, effect) {
// Make a transform for each quad.
var transform = g_pack.createObject('Transform');
-
- transform.translate(0, 0, 0);
transform.scale(hScale, 1, vScale);
transform.addShape(myShape);
transform.parent = g_client.root;
@@ -184,34 +182,28 @@ function initStep2(clientElements) {
var bitmap2 = g_pack.createBitmapFromRawData(rawdata2);
var rawdata_hi = archiveInfo.getFileByURI('hi.jpg', true);
var bitmap_hi = g_pack.createBitmapFromRawData(rawdata_hi);
- var bitmap = g_pack.createBitmap(300, 300, g_o3d.Texture.XRGB8);
+ var texture = g_pack.createTexture2D(300, 300, g_o3d.Texture.XRGB8, 0,
+ false);
// draw image on bitmap.
// scale down on top left corner.
- bitmap.drawImage(bitmap1, 0, 0, 300, 300, 0, 0, 150, 150);
+ texture.drawImage(bitmap1, 0, 0, 300, 300, 0, 0, 150, 150, 0);
// scale up on top right corner.
- bitmap.drawImage(bitmap1, 0, 0, 100, 100, 150, 0, 150, 150);
+ texture.drawImage(bitmap1, 0, 0, 100, 100, 150, 0, 150, 150, 0);
// flip and draw part of the img on bottom left.
- bitmap.drawImage(bitmap1, 150, 0, 150, 150, 149, 299, -150, -150);
+ texture.drawImage(bitmap1, 150, 0, 150, 150, 149, 299, -150, -150, 0);
// draw out of boundary.
- bitmap.drawImage(bitmap1, 0, 0, 300, 300, 150, 150, 300, 300);
+ texture.drawImage(bitmap1, 0, 0, 300, 300, 150, 150, 300, 300, 0);
// draw o3d.
- bitmap.drawImage(bitmap_hi, 0, 0, 100, 50, 100, 125, 100, 50);
-
- var texture = g_pack.createTexture2D(300, 300, g_o3d.Texture.XRGB8,
- 0, false);
- if (texture) {
- // draw image on texture.
- texture.drawImage(bitmap, 0, 0, 300, 300, 0, 0, 300, 300, 0);
+ texture.drawImage(bitmap_hi, 0, 0, 100, 50, 100, 125, 100, 50, 0);
- // draw image on different mip-maps.
- texture.drawImage(bitmap1, 0, 0, 300, 300, 0, 0, 150, 150, 1);
- texture.drawImage(bitmap2, 0, 0, 2, 2, 0, 0, 75, 75, 2);
+ // draw image on different mip-maps.
+ texture.drawImage(bitmap1, 0, 0, 300, 300, 0, 0, 150, 150, 1);
+ texture.drawImage(bitmap2, 0, 0, 2, 2, 0, 0, 75, 75, 2);
- makeShape(texture, effect);
- }
+ makeShape(texture, effect);
}
}
- o3djs.event.addEventListener(o3dElement, 'wheel', scrollMe);
+ o3djs.event.addEventListener(o3dElement, 'wheel', scrollMe);
}
function scrollMe(e) {
diff --git a/o3d/tests/build.scons b/o3d/tests/build.scons
index c9bc853..706cefd 100644
--- a/o3d/tests/build.scons
+++ b/o3d/tests/build.scons
@@ -203,6 +203,7 @@ tests = [
'core/cross/field_test.cc',
'core/cross/float_n_test.cc',
'core/cross/function_test.cc',
+ 'core/cross/image_utils_test.cc',
'core/cross/material_test.cc',
'core/cross/math_utilities_test.cc',
'core/cross/matrix4_axis_rotation_test.cc',