summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--o3d/converter/cross/renderer_stub.cc18
-rw-r--r--o3d/converter/cross/renderer_stub.h3
-rw-r--r--o3d/converter/cross/texture_stub.h4
-rw-r--r--o3d/core/cross/bitmap.cc252
-rw-r--r--o3d/core/cross/bitmap.h189
-rw-r--r--o3d/core/cross/bitmap_dds.cc103
-rw-r--r--o3d/core/cross/bitmap_jpg.cc27
-rw-r--r--o3d/core/cross/bitmap_png.cc32
-rw-r--r--o3d/core/cross/bitmap_test.cc335
-rw-r--r--o3d/core/cross/bitmap_tga.cc31
-rw-r--r--o3d/core/cross/command_buffer/renderer_cb.cc36
-rw-r--r--o3d/core/cross/command_buffer/renderer_cb.h3
-rw-r--r--o3d/core/cross/command_buffer/texture_cb.cc259
-rw-r--r--o3d/core/cross/command_buffer/texture_cb.h25
-rw-r--r--o3d/core/cross/gl/renderer_gl.cc48
-rw-r--r--o3d/core/cross/gl/renderer_gl.h3
-rw-r--r--o3d/core/cross/gl/texture_gl.cc246
-rw-r--r--o3d/core/cross/gl/texture_gl.h31
-rw-r--r--o3d/core/cross/image_utils.cc216
-rw-r--r--o3d/core/cross/image_utils.h20
-rw-r--r--o3d/core/cross/image_utils_test.cc18
-rw-r--r--o3d/core/cross/pack.cc142
-rw-r--r--o3d/core/cross/pack.h10
-rw-r--r--o3d/core/cross/param_test.cc3
-rw-r--r--o3d/core/cross/renderer.cc9
-rw-r--r--o3d/core/cross/renderer.h15
-rw-r--r--o3d/core/cross/renderer_test.cc38
-rw-r--r--o3d/core/cross/texture.cc28
-rw-r--r--o3d/core/cross/texture.h12
-rw-r--r--o3d/core/cross/texture_base.cc5
-rw-r--r--o3d/core/cross/texture_base.h10
-rw-r--r--o3d/core/cross/texture_base_test.cc7
-rw-r--r--o3d/core/win/d3d9/renderer_d3d9.cc48
-rw-r--r--o3d/core/win/d3d9/renderer_d3d9.h3
-rw-r--r--o3d/core/win/d3d9/texture_d3d9.cc179
-rw-r--r--o3d/core/win/d3d9/texture_d3d9.h30
-rw-r--r--o3d/plugin/idl/bitmap.idl37
-rw-r--r--o3d/plugin/idl/pack.idl3
-rw-r--r--o3d/plugin/idl/texture.idl62
39 files changed, 1229 insertions, 1311 deletions
diff --git a/o3d/converter/cross/renderer_stub.cc b/o3d/converter/cross/renderer_stub.cc
index 9f71be6..333f72a 100644
--- a/o3d/converter/cross/renderer_stub.cc
+++ b/o3d/converter/cross/renderer_stub.cc
@@ -141,24 +141,6 @@ Sampler::Ref RendererStub::CreateSampler(void) {
return Sampler::Ref(new SamplerStub(service_locator()));
}
-Texture::Ref RendererStub::CreatePlatformSpecificTextureFromBitmap(
- Bitmap *bitmap) {
- if (bitmap->is_cubemap()) {
- return Texture::Ref(new TextureCUBEStub(service_locator(),
- bitmap->width(),
- bitmap->format(),
- bitmap->num_mipmaps(),
- false));
- } else {
- return Texture::Ref(new Texture2DStub(service_locator(),
- bitmap->width(),
- bitmap->height(),
- bitmap->format(),
- bitmap->num_mipmaps(),
- false));
- }
-}
-
Texture2D::Ref RendererStub::CreatePlatformSpecificTexture2D(
int width,
int height,
diff --git a/o3d/converter/cross/renderer_stub.h b/o3d/converter/cross/renderer_stub.h
index 9ebc860b..e6bd1eb 100644
--- a/o3d/converter/cross/renderer_stub.h
+++ b/o3d/converter/cross/renderer_stub.h
@@ -95,9 +95,6 @@ class RendererStub : public Renderer {
explicit RendererStub(ServiceLocator* service_locator);
// Overridden from Renderer.
- virtual Texture::Ref CreatePlatformSpecificTextureFromBitmap(Bitmap* bitmap);
-
- // Overridden from Renderer.
virtual void SetBackBufferPlatformSpecific();
// Overridden from Renderer.
diff --git a/o3d/converter/cross/texture_stub.h b/o3d/converter/cross/texture_stub.h
index 9ded546..b26107a 100644
--- a/o3d/converter/cross/texture_stub.h
+++ b/o3d/converter/cross/texture_stub.h
@@ -57,8 +57,6 @@ class Texture2DStub : public Texture2D {
height,
format,
levels,
- false,
- false,
enable_render_surfaces) {}
virtual ~Texture2DStub() {}
@@ -119,8 +117,6 @@ class TextureCUBEStub : public TextureCUBE {
edge_length,
format,
levels,
- false,
- false,
enable_render_surfaces) {}
virtual ~TextureCUBEStub() {}
diff --git a/o3d/core/cross/bitmap.cc b/o3d/core/cross/bitmap.cc
index cdccc66..c2709ae 100644
--- a/o3d/core/cross/bitmap.cc
+++ b/o3d/core/cross/bitmap.cc
@@ -65,19 +65,46 @@ Bitmap::Bitmap(ServiceLocator* service_locator)
width_(0),
height_(0),
num_mipmaps_(0),
- is_cubemap_(false) {}
+ semantic_(IMAGE) {
+}
-unsigned int Bitmap::GetMipSize(unsigned int level) const {
+size_t 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::SetContents(Texture::Format format,
+ unsigned int num_mipmaps,
+ unsigned int width,
+ unsigned int height,
+ Bitmap::Semantic semantic,
+ scoped_array<uint8>* image_data) {
+ DCHECK(image_data);
+ image_data_.reset();
+ format_ = format;
+ num_mipmaps_ = num_mipmaps;
+ width_ = width;
+ height_ = height;
+ semantic_ = semantic;
+ image_data_.swap(*image_data);
+}
+
+void Bitmap::SetFrom(Bitmap *source) {
+ DCHECK(source);
+ SetContents(source->format(),
+ source->num_mipmaps(),
+ source->width(),
+ source->height(),
+ source->semantic(),
+ &source->image_data_);
+}
+
void Bitmap::Allocate(Texture::Format format,
unsigned int width,
unsigned int height,
unsigned int num_mipmaps,
- bool cube_map) {
+ Bitmap::Semantic semantic) {
DCHECK(image::CheckImageDimensions(width, height));
switch (format) {
case Texture::XRGB8:
@@ -93,7 +120,6 @@ void Bitmap::Allocate(Texture::Format format,
DLOG(FATAL) << "Trying to allocate a bitmap with invalid format";
break;
}
- DCHECK(!cube_map || (width == height));
DCHECK_LE(num_mipmaps, image::ComputeMipMapCount(width, height));
DCHECK_GT(num_mipmaps, 0u);
@@ -101,30 +127,17 @@ void Bitmap::Allocate(Texture::Format format,
width_ = width;
height_ = height;
num_mipmaps_ = num_mipmaps;
- is_cubemap_ = cube_map;
+ semantic_ = semantic;
AllocateData();
}
uint8 *Bitmap::GetMipData(unsigned int level) const {
DCHECK(level < num_mipmaps_);
- DCHECK(!is_cubemap_);
if (!image_data_.get()) return NULL;
uint8 *data = image_data_.get();
return data + GetMipChainSize(level);
}
-uint8 *Bitmap::GetFaceMipData(TextureCUBE::CubeFace face,
- unsigned int level) const {
- DCHECK(level < num_mipmaps_);
- if (!image_data_.get()) return NULL;
- uint8 *data = image_data_.get();
- if (is_cubemap()) {
- data += (face - TextureCUBE::FACE_POSITIVE_X) *
- GetMipChainSize(num_mipmaps_);
- }
- return data + GetMipChainSize(level);
-}
-
void Bitmap::SetRect(
int level,
unsigned dst_left,
@@ -164,52 +177,14 @@ void Bitmap::SetRect(
}
}
-void Bitmap::SetFaceRect(
- TextureCUBE::CubeFace face,
- int level,
- unsigned dst_left,
- unsigned dst_top,
- unsigned src_width,
- unsigned src_height,
- const void* src_data,
- int src_pitch) {
- DCHECK(src_data);
- DCHECK(level < static_cast<int>(num_mipmaps()) && level >= 0);
- 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());
- bool entire_rect = dst_left == 0 && dst_top == 0 &&
- src_width == mip_width && src_height == mip_height;
- DCHECK(!compressed || entire_rect);
-
- uint8* dst =
- GetFaceMipData(face, level) +
- 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 = 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,
- image::ComputeMipChainSize(mip_width, mip_height, format(), 1));
- }
-}
-
-
-bool Bitmap::LoadFromStream(MemoryReadStream *stream,
+bool Bitmap::LoadFromStream(ServiceLocator* service_locator,
+ MemoryReadStream *stream,
const String &filename,
image::ImageFileType file_type,
- bool generate_mipmaps) {
+ BitmapRefArray* bitmaps) {
+ DCHECK(stream);
+ DCHECK(bitmaps);
+ BitmapRefArray::size_type first = bitmaps->size();
bool success = false;
// If we don't know what type to load, try to detect it based on the file
// name.
@@ -219,16 +194,16 @@ bool Bitmap::LoadFromStream(MemoryReadStream *stream,
switch (file_type) {
case image::TGA:
- success = LoadFromTGAStream(stream, filename, generate_mipmaps);
+ success = LoadFromTGAStream(service_locator, stream, filename, bitmaps);
break;
case image::DDS:
- success = LoadFromDDSStream(stream, filename, generate_mipmaps);
+ success = LoadFromDDSStream(service_locator, stream, filename, bitmaps);
break;
case image::PNG:
- success = LoadFromPNGStream(stream, filename, generate_mipmaps);
+ success = LoadFromPNGStream(service_locator, stream, filename, bitmaps);
break;
case image::JPEG:
- success = LoadFromJPEGStream(stream, filename, generate_mipmaps);
+ success = LoadFromJPEGStream(service_locator, stream, filename, bitmaps);
break;
case image::UNKNOWN:
default:
@@ -243,28 +218,34 @@ bool Bitmap::LoadFromStream(MemoryReadStream *stream,
// 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);
+ success = LoadFromDDSStream(service_locator, stream, filename, bitmaps);
if (!success) {
stream->Seek(0);
- success = LoadFromPNGStream(stream, filename, generate_mipmaps);
+ success = LoadFromPNGStream(service_locator, stream, filename, bitmaps);
}
if (!success) {
stream->Seek(0);
- success = LoadFromJPEGStream(stream, filename, generate_mipmaps);
+ success = LoadFromJPEGStream(service_locator, stream, filename, bitmaps);
}
if (!success) {
stream->Seek(0);
- success = LoadFromTGAStream(stream, filename, generate_mipmaps);
+ success = LoadFromTGAStream(service_locator, stream, filename, bitmaps);
}
}
if (success) {
- Features* features = service_locator()->GetService<Features>();
+ Features* features = service_locator->GetService<Features>();
DCHECK(features);
if (features->flip_textures()) {
- FlipVertically();
+ // Only flip the bitmaps we added.
+ for (BitmapRefArray::size_type ii = first; ii < bitmaps->size(); ++ii) {
+ Bitmap* bitmap = (*bitmaps)[ii].Get();
+ if (bitmap->semantic() == IMAGE) {
+ bitmap->FlipVertically();
+ }
+ }
}
} else {
DLOG(ERROR) << "Failed to load image \"" << filename
@@ -275,9 +256,11 @@ bool Bitmap::LoadFromStream(MemoryReadStream *stream,
// Given an arbitrary bitmap file, load it all into memory and then call our
// stream loader
-bool Bitmap::LoadFromFile(const FilePath &filepath,
+bool Bitmap::LoadFromFile(ServiceLocator* service_locator,
+ const FilePath &filepath,
image::ImageFileType file_type,
- bool generate_mipmaps) {
+ BitmapRefArray* bitmaps) {
+ DCHECK(bitmaps);
// Open the file.
bool result = false;
String filename = FilePathToUTF8(filepath);
@@ -304,8 +287,8 @@ bool Bitmap::LoadFromFile(const FilePath &filepath,
} else {
// And create the bitmap from a memory stream
MemoryReadStream stream(file_contents, file_length);
- result = LoadFromStream(&stream, filename, file_type,
- generate_mipmaps);
+ result = LoadFromStream(service_locator,
+ &stream, filename, file_type, bitmaps);
}
}
}
@@ -319,7 +302,9 @@ bool Bitmap::LoadFromFile(const FilePath &filepath,
// decide which image format it is and call the correct loading function.
bool Bitmap::LoadFromRawData(RawData *raw_data,
image::ImageFileType file_type,
- bool generate_mipmaps) {
+ BitmapRefArray* bitmaps) {
+ DCHECK(raw_data);
+ DCHECK(bitmaps);
String filename = raw_data->uri();
// GetData() returns NULL if it, for example, cannot open the temporary data
@@ -332,7 +317,8 @@ bool Bitmap::LoadFromRawData(RawData *raw_data,
MemoryReadStream stream(data, raw_data->GetLength());
- return LoadFromStream(&stream, filename, file_type, generate_mipmaps);
+ return LoadFromStream(raw_data->service_locator(),
+ &stream, filename, file_type, bitmaps);
}
void Bitmap::DrawImage(const Bitmap& src_img,
@@ -462,48 +448,38 @@ bool Bitmap::CheckAlphaIsOne() const {
case Texture::XRGB8:
return true;
case Texture::ARGB8: {
- int faces = is_cubemap() ? 6 : 1;
- for (int face = 0; face < faces; ++face) {
- for (unsigned int level = 0; level < num_mipmaps(); ++level) {
- const uint8 *data = GetFaceMipData(
- static_cast<TextureCUBE::CubeFace>(face),
- level) + 3;
- const uint8* end = data + image::ComputeBufferSize(
- std::max(1U, width() >> level),
- std::max(1U, height() >> level),
- format());
- while (data < end) {
- if (*data != 255) {
- return false;
- }
- data += 4;
+ for (unsigned int level = 0; level < num_mipmaps(); ++level) {
+ const uint8* data = GetMipData(level) + 3;
+ const uint8* end = data + image::ComputeBufferSize(
+ std::max(1U, width() >> level),
+ std::max(1U, height() >> level),
+ format());
+ while (data < end) {
+ if (*data != 255) {
+ return false;
}
+ data += 4;
}
}
break;
}
case Texture::DXT1: {
- int faces = is_cubemap() ? 6 : 1;
- for (int face = 0; face < faces; ++face) {
- for (unsigned int level = 0; level < num_mipmaps(); ++level) {
- const uint8 *data = GetFaceMipData(
- static_cast<TextureCUBE::CubeFace>(face),
- level);
- const uint8* end = data + image::ComputeBufferSize(
- std::max(1U, width() >> level),
- std::max(1U, height() >> level),
- format());
- DCHECK((end - data) % 8 == 0);
- while (data < end) {
- int color0 = static_cast<int>(data[0]) |
- static_cast<int>(data[1]) << 8;
- int color1 = static_cast<int>(data[2]) |
- static_cast<int>(data[3]) << 8;
- if (color0 < color1) {
- return false;
- }
- data += 8;
+ for (unsigned int level = 0; level < num_mipmaps(); ++level) {
+ const uint8* data = GetMipData(level);
+ const uint8* end = data + image::ComputeBufferSize(
+ std::max(1U, width() >> level),
+ std::max(1U, height() >> level),
+ format());
+ DCHECK((end - data) % 8 == 0);
+ while (data < end) {
+ int color0 = static_cast<int>(data[0]) |
+ static_cast<int>(data[1]) << 8;
+ int color1 = static_cast<int>(data[2]) |
+ static_cast<int>(data[3]) << 8;
+ if (color0 < color1) {
+ return false;
}
+ data += 8;
}
}
break;
@@ -512,22 +488,17 @@ bool Bitmap::CheckAlphaIsOne() const {
case Texture::DXT5:
return false;
case Texture::ABGR16F: {
- int faces = is_cubemap() ? 6 : 1;
- for (int face = 0; face < faces; ++face) {
- for (unsigned int level = 0; level < num_mipmaps(); ++level) {
- const uint8 *data = GetFaceMipData(
- static_cast<TextureCUBE::CubeFace>(face),
- level) + 6;
- const uint8* end = data + image::ComputeBufferSize(
- std::max(1U, width() >> level),
- std::max(1U, height() >> level),
- format());
- while (data < end) {
- if (data[0] != 0x00 || data[1] != 0x3C) {
- return false;
- }
- data += 8;
+ for (unsigned int level = 0; level < num_mipmaps(); ++level) {
+ const uint8* data = GetMipData(level) + 6;
+ const uint8* end = data + image::ComputeBufferSize(
+ std::max(1U, width() >> level),
+ std::max(1U, height() >> level),
+ format());
+ while (data < end) {
+ if (data[0] != 0x00 || data[1] != 0x3C) {
+ return false;
}
+ data += 8;
}
}
break;
@@ -535,22 +506,17 @@ bool Bitmap::CheckAlphaIsOne() const {
case Texture::R32F:
return true;
case Texture::ABGR32F: {
- int faces = is_cubemap() ? 6 : 1;
- for (int face = 0; face < faces; ++face) {
- for (unsigned int level = 0; level < num_mipmaps(); ++level) {
- const uint8* data = GetFaceMipData(
- static_cast<TextureCUBE::CubeFace>(face),
- level) + 12;
- const uint8* end = data + image::ComputeBufferSize(
- std::max(1U, width() >> level),
- std::max(1U, height() >> level),
- format());
- while (data < end) {
- if (*(reinterpret_cast<const float*>(data)) != 1.0f) {
- return false;
- }
- data += 16;
+ for (unsigned int level = 0; level < num_mipmaps(); ++level) {
+ const uint8* data = GetMipData(level) + 12;
+ const uint8* end = data + image::ComputeBufferSize(
+ std::max(1U, width() >> level),
+ std::max(1U, height() >> level),
+ format());
+ while (data < end) {
+ if (*(reinterpret_cast<const float*>(data)) != 1.0f) {
+ return false;
}
+ data += 16;
}
}
break;
diff --git a/o3d/core/cross/bitmap.h b/o3d/core/cross/bitmap.h
index a86b76a..a116ecb 100644
--- a/o3d/core/cross/bitmap.h
+++ b/o3d/core/cross/bitmap.h
@@ -41,7 +41,7 @@
#define O3D_CORE_CROSS_BITMAP_H_
#include <stdlib.h>
-
+#include <vector>
#include "base/cross/bits.h"
#include "core/cross/types.h"
#include "core/cross/texture.h"
@@ -56,27 +56,27 @@ class RawData;
class Pack;
// Bitmap provides an API for basic image operations on bitmap images,
-// including scale and crop. The contents of bitmap can be created from
-// a RawData object via LoadFromRawData(), and also can be transfered
-// to mip of a Texure2D or a specific face of TextureCUBE via methods
-// in Texture.
+// including scale and crop. Bitmaps can be created from a RawData object via
+// LoadFromRawData(), and also can be transfered to mips of a Texure2D or a
+// specific face of TextureCUBE via methods in Texture.
class Bitmap : public ParamObject {
public:
typedef SmartPointer<Bitmap> Ref;
+ typedef std::vector<Bitmap::Ref> BitmapRefArray;
explicit Bitmap(ServiceLocator* service_locator);
virtual ~Bitmap() {}
enum Semantic {
- FACE_POSITIVE_X,
+ FACE_POSITIVE_X, // NOTE: These must match TextureCUBE::CubeFace
FACE_NEGATIVE_X,
FACE_POSITIVE_Y,
FACE_NEGATIVE_Y,
FACE_POSITIVE_Z,
FACE_NEGATIVE_Z,
- NORMAL,
- SLICE,
+ IMAGE, // normal 2d image
+ SLICE, // a slice of a 3d texture.
};
// Returns the pitch of the bitmap for a certain level.
@@ -89,7 +89,7 @@ class Bitmap : public ParamObject {
// source: the source bitmap.
void CopyDeepFrom(const Bitmap &source) {
Allocate(source.format_, source.width_, source.height_,
- source.num_mipmaps_, source.is_cubemap_);
+ source.num_mipmaps_, source.semantic_);
memcpy(image_data(), source.image_data(), GetTotalSize());
}
@@ -97,15 +97,7 @@ class Bitmap : public ParamObject {
// from the source bitmap.
// Parameters:
// source: the source bitmap.
- void SetFrom(Bitmap *source) {
- image_data_.reset();
- format_ = source->format_;
- width_ = source->width_;
- height_ = source->height_;
- num_mipmaps_ = source->num_mipmaps_;
- is_cubemap_ = source->is_cubemap_;
- image_data_.swap(source->image_data_);
- }
+ void SetFrom(Bitmap *source);
// Allocates an uninitialized bitmap with specified parameters.
// Parameters:
@@ -113,12 +105,11 @@ class Bitmap : public ParamObject {
// width: the width of the base image.
// height: the height of the base image.
// num_mipmaps: the number of mip-maps.
- // cube_map: true if creating a cube map.
void Allocate(Texture::Format format,
unsigned int width,
unsigned int height,
unsigned int num_mipmaps,
- bool cube_map);
+ Semantic semantic);
// Allocates a bitmap with initialized parameters.
// data is zero-initialized
@@ -153,31 +144,9 @@ class Bitmap : public ParamObject {
const void* src_data,
int src_pitch);
- // Sets a rectangular region of this bitmap.
- // If the bitmap is a DXT format, the only acceptable values
- // for left, top, width and height are 0, 0, bitmap->width, bitmap->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.
- // width: The width of the rectangular area to modify.
- // height: The of the rectangular area to modify.
- // src_data: The source pixels.
- // src_pitch: If the format is uncompressed this is the number of bytes
- // per row of pixels. If compressed this value is unused.
- void SetFaceRect(TextureCUBE::CubeFace face,
- int level,
- unsigned dst_left,
- unsigned dst_top,
- unsigned width,
- unsigned height,
- const void* src_data,
- int src_pitch);
-
// Gets the total size of the bitmap data, counting all faces and mip levels.
- unsigned int GetTotalSize() const {
- return (is_cubemap_ ? 6 : 1) * GetMipChainSize(num_mipmaps_);
+ size_t GetTotalSize() const {
+ return GetMipChainSize(num_mipmaps_);
}
// Gets the image data for a given mip-map level.
@@ -185,44 +154,34 @@ class Bitmap : public ParamObject {
// level: mip level to get.
uint8 *GetMipData(unsigned int level) const;
- // Gets the image data for a given mip-map level and cube map face.
- // Parameters:
- // 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;
-
// Gets the size of mip.
- unsigned int GetMipSize(unsigned int level) const;
+ size_t GetMipSize(unsigned int level) const;
uint8 *image_data() const { return image_data_.get(); }
Texture::Format format() const { return format_; }
unsigned int width() const { return width_; }
unsigned int height() const { return height_; }
unsigned int num_mipmaps() const { return num_mipmaps_; }
- bool is_cubemap() const { return is_cubemap_; }
+ Semantic semantic() const {
+ return semantic_;
+ }
// Returns whether or not the dimensions of the bitmap are power-of-two.
bool IsPOT() const {
- return ((width_ & (width_ - 1)) == 0) && ((height_ & (height_ - 1)) == 0);
+ return image::IsPOT(width_, height_);
}
- void set_format(Texture::Format format) { format_ = format; }
- void set_width(unsigned int n) { width_ = n; }
- void set_height(unsigned int n) { height_ = n; }
- void set_num_mipmaps(unsigned int n) { num_mipmaps_ = n; }
- void set_is_cubemap(bool is_cubemap) { is_cubemap_ = is_cubemap; }
-
// Loads a bitmap from a file.
// Parameters:
// filename: the name of the file to load.
// file_type: the type of file to load. If UNKNOWN, the file type will be
// determined from the filename extension, 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 LoadFromFile(const FilePath &filepath,
- image::ImageFileType file_type,
- bool generate_mipmaps);
+ // bitmaps: An array to hold references to the loaded bitmaps.
+ static bool LoadFromFile(ServiceLocator* service_locator,
+ const FilePath &filepath,
+ image::ImageFileType file_type,
+ BitmapRefArray* bitmaps);
// Loads a bitmap from a RawData object.
// Parameters:
@@ -231,10 +190,10 @@ class Bitmap : public ParamObject {
// will be determined from the extension from raw_data's uri
// 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 LoadFromRawData(RawData *raw_data,
- image::ImageFileType file_type,
- bool generate_mipmaps);
+ // bitmaps: An array to hold references to the loaded bitmaps.
+ static bool LoadFromRawData(RawData *raw_data,
+ image::ImageFileType file_type,
+ BitmapRefArray* bitmaps);
// Flips a bitmap vertically in place.
// This is needed instead of just using DrawImage because flipping DXT formats
@@ -269,7 +228,7 @@ class Bitmap : public ParamObject {
// 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 {
+ size_t GetMipChainSize(unsigned int num_mipmaps) const {
return image::ComputeMipChainSize(width(), height(), format(), num_mipmaps);
}
@@ -280,20 +239,22 @@ class Bitmap : public ParamObject {
friend class IClassManager;
static ObjectBase::Ref Create(ServiceLocator* service_locator);
- // pointer to the raw bitmap data
- scoped_array<uint8> image_data_;
- // format of the texture this is meant to represent.
- Texture::Format format_;
- // width of the bitmap in pixels.
- int width_;
- // height of the bitmap in pixels.
- int height_;
- // number of mipmap levels in this texture.
- unsigned int num_mipmaps_;
- // is this cube-map data
- bool is_cubemap_;
-
- // Loads a bitmap from a MemoryReadStream.
+ // Sets the contents of a Bitmap replacing any previous contents.
+ // Parameters:
+ // format: Format of the bitmap.
+ // num_mipmaps: The number of mipmaps.
+ // width: width in pixels.
+ // height: height in pixels.
+ // semantic: the semantic of the bitmap
+ // image_data: The image data. The bitmap will take ownership of this data.
+ void SetContents(Texture::Format format,
+ unsigned int num_mipmaps,
+ unsigned int width,
+ unsigned int height,
+ Semantic semantic,
+ scoped_array<uint8>* image_data);
+
+ // Loads bitmaps 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
@@ -302,27 +263,32 @@ class Bitmap : public ParamObject {
// 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);
+ // bitmaps: An array to hold references to the loaded bitmaps.
+ static bool LoadFromStream(ServiceLocator* service_locator,
+ MemoryReadStream *stream,
+ const String &filename,
+ image::ImageFileType file_type,
+ BitmapRefArray* bitmaps);
+
+ static bool LoadFromPNGStream(ServiceLocator* service_locator,
+ MemoryReadStream *stream,
+ const String &filename,
+ BitmapRefArray* bitmaps);
+
+ static bool LoadFromTGAStream(ServiceLocator* service_locator,
+ MemoryReadStream *stream,
+ const String &filename,
+ BitmapRefArray* bitmaps);
+
+ static bool LoadFromDDSStream(ServiceLocator* service_locator,
+ MemoryReadStream *stream,
+ const String &filename,
+ BitmapRefArray* bitmaps);
+
+ static bool LoadFromJPEGStream(ServiceLocator* service_locator,
+ MemoryReadStream *stream,
+ const String &filename,
+ BitmapRefArray* bitmaps);
bool GenerateMipmaps(unsigned int base_width,
unsigned int base_height,
@@ -330,10 +296,25 @@ class Bitmap : public ParamObject {
unsigned int num_mipmaps,
uint8 *data);
+ // pointer to the raw bitmap data
+ scoped_array<uint8> image_data_;
+ // format of the texture this is meant to represent.
+ Texture::Format format_;
+ // width of the bitmap in pixels.
+ int width_;
+ // height of the bitmap in pixels.
+ int height_;
+ // number of mipmap levels in this texture.
+ unsigned int num_mipmaps_;
+ // The purpose of the bitmap
+ Semantic semantic_;
+
O3D_DECL_CLASS(Bitmap, ParamObject);
DISALLOW_COPY_AND_ASSIGN(Bitmap);
};
+typedef Bitmap::BitmapRefArray BitmapRefArray;
+
class BitmapUncompressed : public Bitmap {
public:
explicit BitmapUncompressed(ServiceLocator* service_locator);
diff --git a/o3d/core/cross/bitmap_dds.cc b/o3d/core/cross/bitmap_dds.cc
index b5ad5fa..2c4f8a9 100644
--- a/o3d/core/cross/bitmap_dds.cc
+++ b/o3d/core/cross/bitmap_dds.cc
@@ -248,7 +248,7 @@ static void FlipBGRAImage(unsigned int width,
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);
+ size_t 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.
@@ -271,14 +271,12 @@ 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());
- }
+ 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());
}
}
@@ -286,9 +284,10 @@ void Bitmap::FlipVertically() {
// 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.
-bool Bitmap::LoadFromDDSStream(MemoryReadStream *stream,
+bool Bitmap::LoadFromDDSStream(ServiceLocator* service_locator,
+ MemoryReadStream *stream,
const String &filename,
- bool generate_mipmaps) {
+ BitmapRefArray* bitmaps) {
// Verify the file is a true .dds file
char magic[4];
size_t bytes_read = stream->Read(magic, sizeof(magic));
@@ -297,7 +296,7 @@ bool Bitmap::LoadFromDDSStream(MemoryReadStream *stream,
return false;
}
if (std::strncmp(magic, "DDS ", 4) != 0) {
- DLOG(ERROR) << "DDS magic header not rcognised \"" << filename << "\"";
+ DLOG(ERROR) << "DDS magic header not recognized \"" << filename << "\"";
return false;
}
// Get the DirectDraw Surface Descriptor
@@ -390,7 +389,7 @@ bool Bitmap::LoadFromDDSStream(MemoryReadStream *stream,
// Check that the advertised size is correct.
if (dd_surface_descriptor.dwFlags & DDSD_LINEARSIZE) {
- unsigned int expected_size =
+ size_t expected_size =
image::ComputeBufferSize(dds_width, dds_height, format);
if (expected_size != dd_surface_descriptor.dwLinearSize) {
DLOG(ERROR) << "Advertised buffer size in \"" << filename
@@ -449,26 +448,13 @@ bool Bitmap::LoadFromDDSStream(MemoryReadStream *stream,
format = add_filler_alpha ? Texture::XRGB8 : Texture::ARGB8;
}
- if (is_dxtc && generate_mipmaps) {
- DLOG(WARNING) << "Disabling mip-map generation for DXTC image.";
- generate_mipmaps = false;
- }
-
- // compute buffer size
- unsigned int num_faces = is_cubemap ? 6 : 1;
- // power-of-two dimensions.
- unsigned int 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;
+ unsigned int num_bitmaps = is_cubemap ? 6 : 1;
+ size_t face_size = image::ComputeMipChainSize(
+ dds_width, dds_height, format, mip_count);
+ BitmapRefArray temp_bitmaps;
- // Allocate and load bitmap data.
- scoped_array<uint8> image_data(new uint8[buffer_size]);
-
- unsigned int disk_face_size =
+ size_t 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
@@ -477,57 +463,42 @@ bool Bitmap::LoadFromDDSStream(MemoryReadStream *stream,
disk_face_size = components_per_pixel * disk_face_size / 4;
}
- for (unsigned int face = 0; face < num_faces; ++face) {
- char *data = reinterpret_cast<char*>(image_data.get()) + face_size * face;
+ for (unsigned int face = 0; face < num_bitmaps; ++face) {
+ // Allocate and load bitmap data.
+ scoped_array<uint8> image_data(new uint8[face_size]);
+
+ char *data = reinterpret_cast<char*>(image_data.get());
bytes_read = stream->Read(data, disk_face_size);
if (bytes_read != disk_face_size) {
DLOG(ERROR) << "DDS failed to read image data \"" << filename << "\"";
return false;
}
- }
- // Do pixel conversions on non-DXT images.
- if (!is_dxtc) {
- 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) {
- uint8 *data = image_data.get() + face_size * face;
+ // Do pixel conversions on non-DXT images.
+ if (!is_dxtc) {
+ DCHECK(components_per_pixel == 3 || components_per_pixel == 4);
+ unsigned int pixel_count = disk_face_size / components_per_pixel;
// convert to four components per pixel if necessary
if (add_filler_alpha) {
DCHECK_EQ(components_per_pixel, 3u);
- image::XYZToXYZA(data, pixel_count);
+ image::XYZToXYZA(image_data.get(), pixel_count);
} else {
DCHECK_EQ(components_per_pixel, 4u);
}
- if (rgb_to_bgr)
- image::RGBAToBGRA(data, pixel_count);
- }
- }
-
- if (final_mip_count > mip_count) {
- // Generate the full mip-map chain using the last mip-map read, for each
- // 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 = image::ComputeMipChainSize(
- dds_width, dds_height, format, mip_count - 1);
- for (unsigned int face = 0; face < num_faces; ++face) {
- 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 << "\"";
- return false;
+ if (rgb_to_bgr) {
+ image::RGBAToBGRA(image_data.get(), pixel_count);
}
}
+ Semantic semantic = is_cubemap ? static_cast<Semantic>(face) : IMAGE;
+
+ Bitmap::Ref bitmap(new Bitmap(service_locator));
+ bitmap->SetContents(format, mip_count, dds_width, dds_height, semantic,
+ &image_data);
+ temp_bitmaps.push_back(bitmap);
}
- // Update the Bitmap member variables.
- image_data_.swap(image_data);
- format_ = format;
- width_ = dds_width;
- height_ = dds_height;
- num_mipmaps_ = final_mip_count;
- is_cubemap_ = is_cubemap;
+ // Success.
+ bitmaps->insert(bitmaps->end(), temp_bitmaps.begin(), temp_bitmaps.end());
return true;
}
diff --git a/o3d/core/cross/bitmap_jpg.cc b/o3d/core/cross/bitmap_jpg.cc
index bbb31d3..7b84490 100644
--- a/o3d/core/cross/bitmap_jpg.cc
+++ b/o3d/core/cross/bitmap_jpg.cc
@@ -132,9 +132,10 @@ METHODDEF(void) my_error_exit(j_common_ptr cinfo) {
// Loads the raw RGB bitmap data from a compressed JPEG stream and converts
// the result to 24- or 32-bit bitmap data.
-bool Bitmap::LoadFromJPEGStream(MemoryReadStream *stream,
+bool Bitmap::LoadFromJPEGStream(ServiceLocator* service_locator,
+ MemoryReadStream *stream,
const String &filename,
- bool generate_mipmaps) {
+ BitmapRefArray* bitmaps) {
// Workspace for libjpeg decompression.
struct jpeg_decompress_struct cinfo;
// create our custom error handler.
@@ -198,12 +199,9 @@ bool Bitmap::LoadFromJPEGStream(MemoryReadStream *stream,
ERREXIT(&cinfo, JERR_QUANT_COMPONENTS);
}
unsigned int image_components = 4;
- unsigned int num_mipmaps =
- generate_mipmaps ? image::ComputeMipMapCount(width, height) : 1;
Texture::Format format = Texture::XRGB8;
// Allocate storage for the pixels.
- unsigned int image_size =
- image::ComputeMipChainSize(width, height, format, num_mipmaps);
+ size_t image_size = image::ComputeMipChainSize(width, height, format, 1);
image_data.reset(new uint8[image_size]);
if (image_data.get() == NULL) {
DLOG(ERROR) << "JPEG memory allocation error \"" << filename << "\"";
@@ -270,21 +268,10 @@ bool Bitmap::LoadFromJPEGStream(MemoryReadStream *stream,
// Check for jpeg decompression warnings.
DLOG(WARNING) << "JPEG decompression warnings: " << jerr.pub.num_warnings;
- if (generate_mipmaps) {
- if (!GenerateMipmaps(width, height, format, num_mipmaps,
- image_data.get())) {
- DLOG(ERROR) << "mip-map generation failed for \"" << filename << "\"";
- return false;
- }
- }
-
// Success.
- image_data_.swap(image_data);
- width_ = width;
- height_ = height;
- format_ = format;
- num_mipmaps_ = num_mipmaps;
-
+ Bitmap::Ref bitmap(new Bitmap(service_locator));
+ bitmap->SetContents(format, 1, width, height, IMAGE, &image_data);
+ bitmaps->push_back(bitmap);
return true;
}
diff --git a/o3d/core/cross/bitmap_png.cc b/o3d/core/cross/bitmap_png.cc
index 843bd83..9e30011 100644
--- a/o3d/core/cross/bitmap_png.cc
+++ b/o3d/core/cross/bitmap_png.cc
@@ -79,9 +79,11 @@ void StreamFlush(png_structp png_ptr) {
} // anonymous namespace
// Loads the raw RGB data from a compressed PNG file.
-bool Bitmap::LoadFromPNGStream(MemoryReadStream *stream,
+bool Bitmap::LoadFromPNGStream(ServiceLocator* service_locator,
+ MemoryReadStream *stream,
const String &filename,
- bool generate_mipmaps) {
+ BitmapRefArray* bitmaps) {
+ DCHECK(bitmaps);
// Read the magic header.
char magic[4];
size_t bytes_read = stream->Read(magic, sizeof(magic));
@@ -225,11 +227,8 @@ bool Bitmap::LoadFromPNGStream(MemoryReadStream *stream,
png_read_update_info(png_ptr, info_ptr);
// Allocate storage for the pixels.
- unsigned int num_mipmaps =
- generate_mipmaps ? image::ComputeMipMapCount(png_width, png_height) : 1;
- // Allocate storage for the pixels.
- unsigned int png_image_size =
- image::ComputeMipChainSize(png_width, png_height, format, num_mipmaps);
+ size_t png_image_size =
+ image::ComputeMipChainSize(png_width, png_height, format, 1);
image_data.reset(new uint8[png_image_size]);
if (image_data.get() == NULL) {
DLOG(ERROR) << "PNG image memory allocation error \"" << filename << "\"";
@@ -263,20 +262,10 @@ bool Bitmap::LoadFromPNGStream(MemoryReadStream *stream,
png_free(png_ptr, row_pointers);
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
- if (generate_mipmaps) {
- if (!GenerateMipmaps(png_width, png_height, format, num_mipmaps,
- image_data.get())) {
- DLOG(ERROR) << "Mip-map generation failed for \"" << filename << "\"";
- return false;
- }
- }
-
// Success.
- image_data_.swap(image_data);
- format_ = format;
- width_ = png_width;
- height_ = png_height;
- num_mipmaps_ = num_mipmaps;
+ Bitmap::Ref bitmap(new Bitmap(service_locator));
+ bitmap->SetContents(format, 1, png_width, png_height, IMAGE, &image_data);
+ bitmaps->push_back(bitmap);
return true;
}
@@ -285,7 +274,6 @@ namespace {
bool CreatePNGInUInt8Vector(const Bitmap& bitmap, std::vector<uint8>* buffer) {
DCHECK(bitmap.format() == Texture::ARGB8);
DCHECK(bitmap.num_mipmaps() == 1);
- DCHECK(!bitmap.is_cubemap());
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
NULL, NULL);
@@ -336,7 +324,7 @@ String Bitmap::ToDataURL() {
O3D_ERROR(service_locator()) << "Can only get data URL from ARGB8 images.";
return dataurl::kEmptyDataURL;
}
- if (num_mipmaps_ != 1 || is_cubemap_) {
+ if (num_mipmaps_ != 1) {
O3D_ERROR(service_locator()) <<
"Can only get data URL from 2d images with no mips.";
return dataurl::kEmptyDataURL;
diff --git a/o3d/core/cross/bitmap_test.cc b/o3d/core/cross/bitmap_test.cc
index 4278469..6df10f2 100644
--- a/o3d/core/cross/bitmap_test.cc
+++ b/o3d/core/cross/bitmap_test.cc
@@ -353,15 +353,42 @@ bool PrintBitmapData(const Bitmap &bitmap, const char *name) {
// -----------------------------------------------------------------------------
+TEST_F(BitmapTest, Basic) {
+ EXPECT_EQ(static_cast<int>(Bitmap::FACE_NEGATIVE_X),
+ static_cast<int>(TextureCUBE::FACE_NEGATIVE_X));
+ EXPECT_EQ(static_cast<int>(Bitmap::FACE_NEGATIVE_Y),
+ static_cast<int>(TextureCUBE::FACE_NEGATIVE_Y));
+ EXPECT_EQ(static_cast<int>(Bitmap::FACE_NEGATIVE_Z),
+ static_cast<int>(TextureCUBE::FACE_NEGATIVE_Z));
+ EXPECT_EQ(static_cast<int>(Bitmap::FACE_POSITIVE_X),
+ static_cast<int>(TextureCUBE::FACE_POSITIVE_X));
+ EXPECT_EQ(static_cast<int>(Bitmap::FACE_POSITIVE_Y),
+ static_cast<int>(TextureCUBE::FACE_POSITIVE_Y));
+ EXPECT_EQ(static_cast<int>(Bitmap::FACE_POSITIVE_Z),
+ static_cast<int>(TextureCUBE::FACE_POSITIVE_Z));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ ASSERT_FALSE(bitmap.IsNull());
+ EXPECT_TRUE(bitmap->IsA(Bitmap::GetApparentClass()));
+ EXPECT_TRUE(bitmap->IsA(ParamObject::GetApparentClass()));
+ EXPECT_TRUE(bitmap->image_data() == NULL);
+ EXPECT_EQ(Texture::UNKNOWN_FORMAT, bitmap->format());
+ EXPECT_EQ(0, bitmap->width());
+ EXPECT_EQ(0, bitmap->height());
+ EXPECT_EQ(0, bitmap->num_mipmaps());
+ EXPECT_EQ(Bitmap::IMAGE, bitmap->semantic());
+}
+
// Loads a 24 bit TGA file, checks it against the known data.
TEST_F(BitmapTest, LoadTGAFile24bit) {
// Load the texture object from a file.
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, image::TGA, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::TGA, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::XRGB8, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -373,10 +400,12 @@ TEST_F(BitmapTest, LoadTGAFile24bit) {
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, image::TGA, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::TGA, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::ARGB8, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -391,19 +420,22 @@ TEST_F(BitmapTest, LoadTGAFileTooLarge) {
// but bails before reading the actual image bytes.
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, image::TGA, false));
- EXPECT_TRUE(bitmap->image_data() == NULL);
+ BitmapRefArray bitmaps;
+ EXPECT_FALSE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::TGA, &bitmaps));
+ EXPECT_EQ(0, bitmaps.size());
}
// Loads a JPEG file, checks it against the known data.
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, image::JPEG, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::JPEG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::XRGB8, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -415,19 +447,22 @@ TEST_F(BitmapTest, LoadJPEGFile) {
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, image::JPEG, false));
- EXPECT_TRUE(bitmap->image_data() == NULL);
+ BitmapRefArray bitmaps;
+ EXPECT_FALSE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::JPEG, &bitmaps));
+ EXPECT_EQ(0, bitmaps.size());
}
// Loads a 24 bit PNG file, checks it against the known data.
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, image::PNG, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::XRGB8, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -440,10 +475,12 @@ TEST_F(BitmapTest, LoadPNGFile24bitInterlaced) {
String filename = *g_program_path +
"/bitmap_test/png-256x256-24bit-interlaced.png";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::PNG, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::XRGB8, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -454,10 +491,12 @@ TEST_F(BitmapTest, LoadPNGFile24bitInterlaced) {
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, image::PNG, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::ARGB8, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -470,10 +509,12 @@ TEST_F(BitmapTest, LoadPNGFile8bitPalette) {
String filename = *g_program_path +
"/bitmap_test/png-256x256-8bit-palette.png";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::PNG, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::XRGB8, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -486,10 +527,12 @@ TEST_F(BitmapTest, LoadPNGFile4bitPalette) {
String filename = *g_program_path +
"/bitmap_test/png-20x14-4bit-palette.png";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::PNG, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::XRGB8, bitmap->format());
EXPECT_EQ(20U, bitmap->width());
EXPECT_EQ(14U, bitmap->height());
@@ -502,9 +545,10 @@ TEST_F(BitmapTest, LoadPNGFile4bitPalette) {
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, image::PNG, false));
- EXPECT_TRUE(bitmap->image_data() == NULL);
+ BitmapRefArray bitmaps;
+ EXPECT_FALSE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::PNG, &bitmaps));
+ EXPECT_EQ(0, bitmaps.size());
}
// NOTE: Having trouble recognising the alpha channel in a PNG
@@ -514,10 +558,12 @@ TEST_F(BitmapTest, LoadPNGFile8bitPaletteAlpha) {
String filename = *g_program_path +
"/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, image::PNG, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::ARGB8, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -529,10 +575,12 @@ TEST_F(BitmapTest, LoadPNGFile8bitPaletteAlpha) {
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, image::DDS, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::DDS, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT1, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -545,10 +593,12 @@ TEST_F(BitmapTest, LoadDDSFileDXT1Alpha) {
String filename = *g_program_path +
"/bitmap_test/dds-dxt1-256x256-alpha.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::DDS, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT1, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -561,10 +611,12 @@ TEST_F(BitmapTest, LoadDDSFileDXT1Mipmap) {
String filename = *g_program_path +
"/bitmap_test/dds-dxt1-256x256-mipmap.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::DDS, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT1, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -580,10 +632,12 @@ TEST_F(BitmapTest, LoadDDSFileDXT3) {
String filename = *g_program_path +
"/bitmap_test/dds-dxt3-256x256-alpha.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::DDS, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT3, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -596,10 +650,12 @@ TEST_F(BitmapTest, LoadDDSFileDXT3Mipmap) {
String filename = *g_program_path +
"/bitmap_test/dds-dxt3-256x256-mipmap.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::DDS, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT3, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -615,10 +671,12 @@ TEST_F(BitmapTest, LoadDDSFileDXT5) {
String filename = *g_program_path +
"/bitmap_test/dds-dxt5-256x256-alpha.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::DDS, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT5, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -631,10 +689,12 @@ TEST_F(BitmapTest, LoadDDSFileDXT5Mipmap) {
String filename = *g_program_path +
"/bitmap_test/dds-dxt5-256x256-mipmap.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- EXPECT_TRUE(bitmap->LoadFromFile(filepath, image::DDS, false));
+ BitmapRefArray bitmaps;
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::DDS, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap* bitmap = bitmaps[0].Get();
EXPECT_TRUE(bitmap->image_data() != NULL);
- EXPECT_FALSE(bitmap->is_cubemap());
EXPECT_EQ(Texture::DXT5, bitmap->format());
EXPECT_EQ(256U, bitmap->width());
EXPECT_EQ(256U, bitmap->height());
@@ -652,9 +712,10 @@ TEST_F(BitmapTest, LoadDDSFileTooLarge) {
// but bails before reading the actual image bytes.
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, image::DDS, false));
- EXPECT_TRUE(bitmap->image_data() == NULL);
+ BitmapRefArray bitmaps;
+ EXPECT_FALSE(Bitmap::LoadFromFile(
+ g_service_locator, filepath, image::DDS, &bitmaps));
+ EXPECT_EQ(0, bitmaps.size());
}
static uint8 kpng_8x4_drawImage[128] = {
@@ -943,30 +1004,41 @@ TEST_F(BitmapTest, DrawImage) {
// path of dest image.
String fname_dst = *g_program_path +
"/bitmap_test/png-8x4-24bit-drawimage-dest.png";
-
+ BitmapRefArray bitmaps;
// load three src bitmaps in different sizes from files.
String filename_2x2_src = *g_program_path +
"/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),
- image::PNG, false));
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(filename_2x2_src),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_2x2_src(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(filename_4x4_src),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_4x4_src(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(filename_8x8_src),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_8x8_src(bitmaps[0]);
// 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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_top_left(bitmaps[0]);
// 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));
@@ -975,85 +1047,118 @@ TEST_F(BitmapTest, DrawImage) {
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_top(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_top_right(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_right(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_bottom_right(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_bottom(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_bottom_left(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_left(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_scale_up(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_scale_down(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_scale_out(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_flip(bitmaps[0]);
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));
@@ -1061,15 +1166,21 @@ TEST_F(BitmapTest, DrawImage) {
String fname_dst_argb8 = *g_program_path +
"/bitmap_test/" +
"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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_dst_argb8),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_dest_argb8(bitmaps[0]);
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),
- image::PNG, false));
+ bitmaps.clear();
+ EXPECT_TRUE(Bitmap::LoadFromFile(
+ g_service_locator, UTF8ToFilePath(fname_src_argb8),
+ image::PNG, &bitmaps));
+ ASSERT_EQ(1, bitmaps.size());
+ Bitmap::Ref bitmap_src_argb8(bitmaps[0]);
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 c85cca9..e31736a 100644
--- a/o3d/core/cross/bitmap_tga.cc
+++ b/o3d/core/cross/bitmap_tga.cc
@@ -51,9 +51,10 @@ namespace o3d {
// Loads the header information and raw RGB{A} data from an uncompressed
// 24-bit or 32-bit TGA stream into the Bitmap object.
-bool Bitmap::LoadFromTGAStream(MemoryReadStream *stream,
+bool Bitmap::LoadFromTGAStream(ServiceLocator* service_locator,
+ MemoryReadStream *stream,
const String &filename,
- bool generate_mipmaps) {
+ BitmapRefArray* bitmaps) {
// Read the magic header.
uint8 file_magic[12];
if (stream->Read(file_magic, sizeof(file_magic)) != sizeof(file_magic)) {
@@ -62,7 +63,7 @@ bool Bitmap::LoadFromTGAStream(MemoryReadStream *stream,
}
// Match the first few bytes of the TGA header to confirm we can read this
// format. Multibyte values are stored little endian.
- const uint8 kTargaMagic[12] = {
+ static 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)
@@ -109,11 +110,9 @@ bool Bitmap::LoadFromTGAStream(MemoryReadStream *stream,
// pixels contained in the file.
unsigned int pixel_count = tga_width * tga_height;
// Allocate storage for the pixels.
- unsigned int num_mipmaps =
- generate_mipmaps ? image::ComputeMipMapCount(tga_width, tga_height) : 1;
Texture::Format format = components == 3 ? Texture::XRGB8 : Texture::ARGB8;
- unsigned int image_size =
- image::ComputeMipChainSize(tga_width, tga_height, format, num_mipmaps);
+ size_t image_size =
+ image::ComputeMipChainSize(tga_width, tga_height, format, 1);
scoped_array<uint8> image_data(new uint8[image_size]);
if (image_data.get() == NULL) {
DLOG(ERROR) << "Targa file memory allocation error \"" << filename << "\"";
@@ -131,26 +130,16 @@ bool Bitmap::LoadFromTGAStream(MemoryReadStream *stream,
image::XYZToXYZA(image_data.get(), pixel_count);
}
- if (generate_mipmaps) {
- if (!GenerateMipmaps(tga_width, tga_height, format, num_mipmaps,
- image_data.get())) {
- DLOG(ERROR) << "mip-map generation failed for \"" << filename << "\"";
- return false;
- }
- }
-
// Success.
- image_data_.swap(image_data);
- width_ = tga_width;
- height_ = tga_height;
- format_ = format;
- num_mipmaps_ = num_mipmaps;
+ Bitmap::Ref bitmap(new Bitmap(service_locator));
+ bitmap->SetContents(format, 1, tga_width, tga_height, IMAGE, &image_data);
+ bitmaps->push_back(bitmap);
// 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();
+ bitmap->FlipVertically();
return true;
}
diff --git a/o3d/core/cross/command_buffer/renderer_cb.cc b/o3d/core/cross/command_buffer/renderer_cb.cc
index 9de0617..c5d3641 100644
--- a/o3d/core/cross/command_buffer/renderer_cb.cc
+++ b/o3d/core/cross/command_buffer/renderer_cb.cc
@@ -292,25 +292,6 @@ Effect::Ref RendererCB::CreateEffect() {
return Effect::Ref(new EffectCB(service_locator(), this));
}
-// Attempts to create a Texture with the given bitmap, automatically
-// determining whether the to create a 2D texture, cube texture, etc. If
-// creation fails the method returns NULL.
-// Parameters:
-// bitmap: The bitmap specifying the dimensions, format and content of the
-// new texture. The created texture takes ownership of the bitmap
-// data.
-// Returns:
-// A ref-counted pointer to the texture or NULL if it did not load.
-Texture::Ref RendererCB::CreatePlatformSpecificTextureFromBitmap(
- Bitmap *bitmap) {
- if (bitmap->is_cubemap()) {
- return Texture::Ref(TextureCUBECB::Create(service_locator(), bitmap,
- false));
- } else {
- return Texture::Ref(Texture2DCB::Create(service_locator(), bitmap, false));
- }
-}
-
// Creates and returns a platform-specific Texture2D object. It allocates
// the necessary resources to store texture data for the given image size
// and format.
@@ -320,12 +301,8 @@ Texture2D::Ref RendererCB::CreatePlatformSpecificTexture2D(
Texture::Format format,
int levels,
bool enable_render_surfaces) {
- Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
- bitmap->set_format(format);
- bitmap->set_width(width);
- bitmap->set_height(height);
- bitmap->set_num_mipmaps(levels);
- return Texture2D::Ref(Texture2DCB::Create(service_locator(), bitmap,
+ return Texture2D::Ref(Texture2DCB::Create(service_locator(), format, levels,
+ width, height,
enable_render_surfaces));
}
@@ -337,13 +314,8 @@ TextureCUBE::Ref RendererCB::CreatePlatformSpecificTextureCUBE(
Texture::Format format,
int levels,
bool enable_render_surfaces) {
- Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
- bitmap->set_format(format);
- bitmap->set_width(edge);
- bitmap->set_height(edge);
- bitmap->set_num_mipmaps(levels);
- bitmap->set_is_cubemap(true);
- return TextureCUBE::Ref(TextureCUBECB::Create(service_locator(), bitmap,
+ return TextureCUBE::Ref(TextureCUBECB::Create(service_locator(), format,
+ levels, edge,
enable_render_surfaces));
}
diff --git a/o3d/core/cross/command_buffer/renderer_cb.h b/o3d/core/cross/command_buffer/renderer_cb.h
index e7f8963..5df7936 100644
--- a/o3d/core/cross/command_buffer/renderer_cb.h
+++ b/o3d/core/cross/command_buffer/renderer_cb.h
@@ -212,9 +212,6 @@ class RendererCB : public Renderer {
RenderDepthStencilSurface* depth_surface);
// Overridden from Renderer.
- virtual Texture::Ref CreatePlatformSpecificTextureFromBitmap(Bitmap* bitmap);
-
- // Overridden from Renderer.
virtual Texture2D::Ref CreatePlatformSpecificTexture2D(
int width,
int height,
diff --git a/o3d/core/cross/command_buffer/texture_cb.cc b/o3d/core/cross/command_buffer/texture_cb.cc
index 88c529b..56b7e55 100644
--- a/o3d/core/cross/command_buffer/texture_cb.cc
+++ b/o3d/core/cross/command_buffer/texture_cb.cc
@@ -103,47 +103,21 @@ void UpdateResourceFromBitmap(RendererCB *renderer,
ResourceID texture_id,
unsigned int level,
TextureCUBE::CubeFace face,
- const Bitmap &bitmap,
- bool resize_to_pot) {
+ const Bitmap &bitmap) {
DCHECK(bitmap.image_data());
FencedAllocatorWrapper *allocator = renderer->allocator();
CommandBufferHelper *helper = renderer->helper();
unsigned int mip_width = std::max(1U, bitmap.width() >> level);
unsigned int mip_height = std::max(1U, bitmap.height() >> level);
- unsigned char *mip_data = bitmap.GetFaceMipData(face, level);
- unsigned int mip_size =
+ unsigned char *mip_data = bitmap.GetMipData(level);
+ size_t mip_size =
image::ComputeBufferSize(mip_width, mip_height, bitmap.format());
- if (resize_to_pot) {
- unsigned int pot_width =
- std::max(1U, image::ComputePOTSize(bitmap.width()) >> level);
- unsigned int pot_height =
- 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
- // makes 32MB for ABGR16F (the size of the transfer buffer).
- // TODO: 32MB for the transfer buffer can be big (e.g. if there are
- // multiple renderers). We'll want to implement a way to upload the texture
- // by bits that fit into an arbitrarily small buffer, but that is complex
- // for the NPOT->POT case.
- DCHECK(buffer);
- 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;
- mip_data = buffer;
- } else {
- unsigned char *buffer = allocator->AllocTyped<unsigned char>(mip_size);
- DCHECK(buffer);
- memcpy(buffer, mip_data, mip_size);
- mip_data = buffer;
- }
+ unsigned char *buffer = allocator->AllocTyped<unsigned char>(mip_size);
+ DCHECK(buffer);
+ memcpy(buffer, mip_data, mip_size);
+ mip_data = buffer;
- unsigned int pitch = image::ComputeBufferSize(mip_width, 1, bitmap.format());
+ size_t pitch = image::ComputeBufferSize(mip_width, 1, bitmap.format());
CommandBufferEntry args[10];
args[0].value_uint32 = texture_id;
@@ -179,12 +153,12 @@ void CopyBackResourceToBitmap(RendererCB *renderer,
CommandBufferHelper *helper = renderer->helper();
unsigned int mip_width = std::max(1U, bitmap.width() >> level);
unsigned int mip_height = std::max(1U, bitmap.height() >> level);
- unsigned int mip_size =
+ size_t mip_size =
image::ComputeBufferSize(mip_width, mip_height, bitmap.format());
unsigned char *buffer = allocator->AllocTyped<unsigned char>(mip_size);
DCHECK(buffer);
- unsigned int pitch = image::ComputeBufferSize(mip_width, 1, bitmap.format());
+ size_t pitch = image::ComputeBufferSize(mip_width, 1, bitmap.format());
CommandBufferEntry args[10];
args[0].value_uint32 = texture_id;
@@ -207,7 +181,7 @@ void CopyBackResourceToBitmap(RendererCB *renderer,
args[9].value_uint32 = allocator->GetOffset(buffer);
helper->AddCommand(command_buffer::GET_TEXTURE_DATA, 10, args);
helper->Finish();
- memcpy(bitmap.GetFaceMipData(face, level), buffer, mip_size);
+ memcpy(bitmap.GetMipData(level), buffer, mip_size);
allocator->Free(buffer);
}
@@ -223,23 +197,23 @@ static const unsigned int kMaxTextureSize = 2048;
// exit.
Texture2DCB::Texture2DCB(ServiceLocator* service_locator,
ResourceID resource_id,
- const Bitmap &bitmap,
- bool resize_to_pot,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
bool enable_render_surfaces)
: Texture2D(service_locator,
- bitmap.width(),
- bitmap.height(),
- bitmap.format(),
- bitmap.num_mipmaps(),
- bitmap.CheckAlphaIsOne(),
- resize_to_pot,
+ width,
+ height,
+ format,
+ levels,
enable_render_surfaces),
renderer_(static_cast<RendererCB*>(
service_locator->GetService<Renderer>())),
resource_id_(resource_id),
has_levels_(0),
backing_bitmap_(Bitmap::Ref(new Bitmap(service_locator))) {
- DCHECK_NE(format(), Texture::UNKNOWN_FORMAT);
+ DCHECK_NE(format, Texture::UNKNOWN_FORMAT);
}
Texture2DCB::~Texture2DCB() {
@@ -252,65 +226,42 @@ Texture2DCB::~Texture2DCB() {
// Creates a new texture object from scratch.
Texture2DCB* Texture2DCB::Create(ServiceLocator* service_locator,
- Bitmap *bitmap,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
bool enable_render_surfaces) {
- DCHECK_NE(bitmap->format(), Texture::UNKNOWN_FORMAT);
- DCHECK(!bitmap->is_cubemap());
+ DCHECK_NE(format, Texture::UNKNOWN_FORMAT);
RendererCB *renderer = static_cast<RendererCB *>(
service_locator->GetService<Renderer>());
- texture::Format cb_format = CBFormatFromO3DFormat(bitmap->format());
+ texture::Format cb_format = CBFormatFromO3DFormat(format);
if (cb_format == texture::NUM_FORMATS) {
O3D_ERROR(service_locator)
<< "Unsupported format in Texture2DCB::Create.";
return NULL;
}
- if (bitmap->width() > kMaxTextureSize ||
- bitmap->height() > kMaxTextureSize) {
- O3D_ERROR(service_locator) << "Texture dimensions (" << bitmap->width()
- << ", " << bitmap->height() << ") too big.";
+ if (width > kMaxTextureSize || height > kMaxTextureSize) {
+ O3D_ERROR(service_locator) << "Texture dimensions (" << width
+ << ", " << height << ") too big.";
return NULL;
}
- bool resize_to_pot = !renderer->supports_npot() && !bitmap->IsPOT();
-
- unsigned int mip_width = bitmap->width();
- unsigned int mip_height = bitmap->height();
- if (resize_to_pot) {
- mip_width = image::ComputePOTSize(mip_width);
- mip_height = image::ComputePOTSize(mip_height);
- }
-
ResourceID texture_id = renderer->texture_ids().AllocateID();
CommandBufferEntry args[3];
args[0].value_uint32 = texture_id;
args[1].value_uint32 =
- create_texture_2d_cmd::Width::MakeValue(mip_width) |
- create_texture_2d_cmd::Height::MakeValue(mip_height);
+ create_texture_2d_cmd::Width::MakeValue(width) |
+ create_texture_2d_cmd::Height::MakeValue(height);
args[2].value_uint32 =
- create_texture_2d_cmd::Levels::MakeValue(bitmap->num_mipmaps()) |
+ create_texture_2d_cmd::Levels::MakeValue(levels) |
create_texture_2d_cmd::Format::MakeValue(cb_format) |
create_texture_2d_cmd::Flags::MakeValue(0);
renderer->helper()->AddCommand(command_buffer::CREATE_TEXTURE_2D, 3, args);
- if (bitmap->image_data()) {
- for (unsigned int i = 0; i < bitmap->num_mipmaps(); ++i) {
- UpdateResourceFromBitmap(renderer, texture_id, i,
- TextureCUBE::FACE_POSITIVE_X, *bitmap, true);
- }
- }
Texture2DCB *texture = new Texture2DCB(service_locator, texture_id,
- *bitmap, resize_to_pot,
+ format, levels, width, height,
enable_render_surfaces);
- // Setup the backing bitmap.
- texture->backing_bitmap_->SetFrom(bitmap);
- if (texture->backing_bitmap_->image_data()) {
- if (resize_to_pot) {
- texture->has_levels_ = (1 << bitmap->num_mipmaps()) - 1;
- } else {
- texture->backing_bitmap_->FreeData();
- }
- }
return texture;
}
@@ -342,7 +293,8 @@ bool Texture2DCB::Lock(int level, void** data, int* pitch) {
}
if (!backing_bitmap_->image_data()) {
DCHECK_EQ(has_levels_, 0);
- backing_bitmap_->Allocate(format(), width(), height(), levels(), false);
+ backing_bitmap_->Allocate(format(), width(), height(), levels(),
+ Bitmap::IMAGE);
}
*data = backing_bitmap_->GetMipData(level);
unsigned int mip_width = image::ComputeMipDimension(level, width());
@@ -356,12 +308,10 @@ bool Texture2DCB::Lock(int level, void** data, int* pitch) {
*pitch = bytes_per_row;
}
if (!HasLevel(level)) {
- DCHECK(!resize_to_pot_);
DCHECK_EQ(backing_bitmap_->width(), width());
DCHECK_EQ(backing_bitmap_->height(), height());
DCHECK_EQ(backing_bitmap_->format(), format());
DCHECK_GT(backing_bitmap_->num_mipmaps(), level);
- DCHECK(!backing_bitmap_->is_cubemap());
CopyBackResourceToBitmap(renderer_, resource_id_, level,
TextureCUBE::FACE_POSITIVE_X,
*backing_bitmap_.Get());
@@ -391,13 +341,12 @@ bool Texture2DCB::Unlock(int level) {
DCHECK_EQ(backing_bitmap_->height(), height());
DCHECK_EQ(backing_bitmap_->format(), format());
DCHECK_GT(backing_bitmap_->num_mipmaps(), level);
- DCHECK(!backing_bitmap_->is_cubemap());
DCHECK(HasLevel(level));
UpdateResourceFromBitmap(renderer_, resource_id_, level,
TextureCUBE::FACE_POSITIVE_X,
- *backing_bitmap_.Get(), resize_to_pot_);
+ *backing_bitmap_.Get());
locked_levels_ &= ~(1 << level);
- if (!resize_to_pot_ && (locked_levels_ == 0)) {
+ if (locked_levels_ == 0) {
backing_bitmap_->FreeData();
has_levels_ = 0;
}
@@ -418,22 +367,21 @@ const Texture::RGBASwizzleIndices& Texture2DCB::GetABGR32FSwizzleIndices() {
// Creates a texture from a pre-existing texture resource.
TextureCUBECB::TextureCUBECB(ServiceLocator* service_locator,
ResourceID resource_id,
- const Bitmap &bitmap,
- bool resize_to_pot,
+ Texture::Format format,
+ int levels,
+ int edge_length,
bool enable_render_surfaces)
: TextureCUBE(service_locator,
- bitmap.width(),
- bitmap.format(),
- bitmap.num_mipmaps(),
- bitmap.CheckAlphaIsOne(),
- resize_to_pot,
+ edge_length,
+ format,
+ levels,
enable_render_surfaces),
renderer_(static_cast<RendererCB*>(
service_locator->GetService<Renderer>())),
- resource_id_(resource_id),
- backing_bitmap_(Bitmap::Ref(new Bitmap(service_locator))) {
- for (unsigned int i = 0; i < 6; ++i) {
- has_levels_[i] = 0;
+ resource_id_(resource_id) {
+ for (int ii = 0; ii < static_cast<int>(NUMBER_OF_FACES); ++ii) {
+ backing_bitmaps_[ii] = Bitmap::Ref(new Bitmap(service_locator));
+ has_levels_[ii] = 0;
}
}
@@ -447,67 +395,39 @@ TextureCUBECB::~TextureCUBECB() {
// Create a new Cube texture from scratch.
TextureCUBECB* TextureCUBECB::Create(ServiceLocator* service_locator,
- Bitmap *bitmap,
+ Texture::Format format,
+ int levels,
+ int edge_length,
bool enable_render_surfaces) {
- DCHECK_NE(bitmap->format(), Texture::UNKNOWN_FORMAT);
- DCHECK(bitmap->is_cubemap());
- DCHECK_EQ(bitmap->width(), bitmap->height());
+ DCHECK_NE(format, Texture::UNKNOWN_FORMAT);
RendererCB *renderer = static_cast<RendererCB *>(
service_locator->GetService<Renderer>());
- texture::Format cb_format = CBFormatFromO3DFormat(bitmap->format());
+ texture::Format cb_format = CBFormatFromO3DFormat(format);
if (cb_format == texture::NUM_FORMATS) {
O3D_ERROR(service_locator)
<< "Unsupported format in Texture2DCB::Create.";
return NULL;
}
- if (bitmap->width() > kMaxTextureSize) {
- O3D_ERROR(service_locator) << "Texture dimensions (" << bitmap->width()
- << ", " << bitmap->height() << ") too big.";
+ if (edge_length > kMaxTextureSize) {
+ O3D_ERROR(service_locator) << "Texture dimensions (" << edge_length
+ << ", " << edge_length << ") too big.";
return NULL;
}
- bool resize_to_pot = !renderer->supports_npot() && !bitmap->IsPOT();
-
- unsigned int mip_width = bitmap->width();
- unsigned int mip_height = bitmap->height();
- if (resize_to_pot) {
- mip_width = image::ComputePOTSize(mip_width);
- mip_height = image::ComputePOTSize(mip_height);
- }
-
ResourceID texture_id = renderer->texture_ids().AllocateID();
CommandBufferEntry args[3];
args[0].value_uint32 = texture_id;
- args[1].value_uint32 = create_texture_cube_cmd::Side::MakeValue(mip_width);
+ args[1].value_uint32 = create_texture_cube_cmd::Side::MakeValue(edge_length);
args[2].value_uint32 =
- create_texture_cube_cmd::Levels::MakeValue(bitmap->num_mipmaps()) |
+ create_texture_cube_cmd::Levels::MakeValue(levels) |
create_texture_cube_cmd::Format::MakeValue(cb_format) |
create_texture_cube_cmd::Flags::MakeValue(0);
renderer->helper()->AddCommand(command_buffer::CREATE_TEXTURE_CUBE, 3, args);
- if (bitmap->image_data()) {
- for (unsigned int face = 0; face < 6; ++face) {
- for (unsigned int i = 0; i < bitmap->num_mipmaps(); ++i) {
- UpdateResourceFromBitmap(renderer, texture_id, i,
- static_cast<CubeFace>(face), *bitmap, true);
- }
- }
- }
TextureCUBECB* texture =
- new TextureCUBECB(service_locator, texture_id, *bitmap,
- resize_to_pot, enable_render_surfaces);
-
- // Setup the backing bitmap.
- texture->backing_bitmap_->SetFrom(bitmap);
- if (texture->backing_bitmap_->image_data()) {
- if (resize_to_pot) {
- for (unsigned int face = 0; face < 6; ++face) {
- texture->has_levels_[face] = (1 << bitmap->num_mipmaps()) - 1;
- }
- } else {
- texture->backing_bitmap_->FreeData();
- }
- }
+ new TextureCUBECB(service_locator, texture_id, format, levels,
+ edge_length, enable_render_surfaces);
+
return texture;
}
@@ -539,15 +459,14 @@ bool TextureCUBECB::Lock(CubeFace face, int level, void** data, int* pitch) {
<< "\" is already locked.";
return false;
}
- if (!backing_bitmap_->image_data()) {
- for (unsigned int i = 0; i < 6; ++i) {
- DCHECK_EQ(has_levels_[i], 0);
- }
- backing_bitmap_->Allocate(format(), edge_length(), edge_length(),
- levels(), true);
+ Bitmap* backing_bitmap = backing_bitmaps_[face].Get();
+ if (!backing_bitmap->image_data()) {
+ DCHECK_EQ(has_levels_[face], 0);
+ backing_bitmap->Allocate(format(), edge_length(), edge_length(), levels(),
+ Bitmap::IMAGE);
}
- *data = backing_bitmap_->GetFaceMipData(face, level);
- unsigned int mip_width = image::ComputeMipDimension(level, edge_length());
+ *data = backing_bitmap->GetMipData(level);
+ unsigned int mip_width = image::ComputeMipDimension(level, edge_length());
if (!IsCompressed()) {
*pitch = image::ComputePitch(format(), mip_width);
} else {
@@ -559,15 +478,12 @@ bool TextureCUBECB::Lock(CubeFace face, int level, void** data, int* pitch) {
if (!HasLevel(level, face)) {
// TODO: add some API so we don't have to copy back the data if we
// will rewrite it all.
- DCHECK(!resize_to_pot_);
- DCHECK_EQ(backing_bitmap_->width(), edge_length());
- DCHECK_EQ(backing_bitmap_->height(), edge_length());
- DCHECK_EQ(backing_bitmap_->format(), format());
- DCHECK_GT(backing_bitmap_->num_mipmaps(), level);
- DCHECK(backing_bitmap_->is_cubemap());
+ DCHECK_EQ(backing_bitmap->width(), edge_length());
+ DCHECK_EQ(backing_bitmap->height(), edge_length());
+ DCHECK_EQ(backing_bitmap->format(), format());
+ DCHECK_GT(backing_bitmap->num_mipmaps(), level);
CopyBackResourceToBitmap(renderer_, resource_id_, level,
- TextureCUBE::FACE_POSITIVE_X,
- *backing_bitmap_.Get());
+ TextureCUBE::FACE_POSITIVE_X, *backing_bitmap);
has_levels_[face] |= 1 << level;
}
locked_levels_[face] |= 1 << level;
@@ -589,30 +505,19 @@ bool TextureCUBECB::Unlock(CubeFace face, int level) {
<< "\" is not locked.";
return false;
}
- DCHECK(backing_bitmap_->image_data());
- DCHECK_EQ(backing_bitmap_->width(), edge_length());
- DCHECK_EQ(backing_bitmap_->height(), edge_length());
- DCHECK_EQ(backing_bitmap_->format(), format());
- DCHECK_GT(backing_bitmap_->num_mipmaps(), level);
- DCHECK(backing_bitmap_->is_cubemap());
+ Bitmap* backing_bitmap = backing_bitmaps_[face].Get();
+ DCHECK(backing_bitmap->image_data());
+ DCHECK_EQ(backing_bitmap->width(), edge_length());
+ DCHECK_EQ(backing_bitmap->height(), edge_length());
+ DCHECK_EQ(backing_bitmap->format(), format());
+ DCHECK_GT(backing_bitmap->num_mipmaps(), level);
DCHECK(HasLevel(level, face));
UpdateResourceFromBitmap(renderer_, resource_id_, level, face,
- *backing_bitmap_.Get(), resize_to_pot_);
+ *backing_bitmap);
locked_levels_[face] &= ~(1 << level);
- if (!resize_to_pot_) {
- bool has_locked_level = false;
- for (unsigned int i = 0; i < 6; ++i) {
- if (locked_levels_[i]) {
- has_locked_level = true;
- break;
- }
- }
- if (!has_locked_level) {
- backing_bitmap_->FreeData();
- for (unsigned int i = 0; i < 6; ++i) {
- has_levels_[i] = 0;
- }
- }
+ if (locked_levels_[face] == 0) {
+ backing_bitmap->FreeData();
+ has_levels_[face] = 0;
}
return false;
}
diff --git a/o3d/core/cross/command_buffer/texture_cb.h b/o3d/core/cross/command_buffer/texture_cb.h
index c08cfcd..6ccf9cc 100644
--- a/o3d/core/cross/command_buffer/texture_cb.h
+++ b/o3d/core/cross/command_buffer/texture_cb.h
@@ -61,7 +61,10 @@ class Texture2DCB : public Texture2D {
// created Texture object.
// The created texture takes ownership of the bitmap data.
static Texture2DCB* Create(ServiceLocator* service_locator,
- Bitmap *bitmap,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
bool enable_render_surfaces);
// Overridden from Texture2D
@@ -106,8 +109,10 @@ class Texture2DCB : public Texture2D {
// The texture takes ownership of the bitmap data.
Texture2DCB(ServiceLocator* service_locator,
command_buffer::ResourceID resource_id,
- const Bitmap &bitmap,
- bool resize_npot,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
bool enable_render_surfaces);
// Returns true if the backing bitmap has the data for the level.
@@ -138,7 +143,9 @@ class TextureCUBECB : public TextureCUBE {
// Create a new Cube texture from scratch.
static TextureCUBECB* TextureCUBECB::Create(ServiceLocator* service_locator,
- Bitmap *bitmap,
+ Texture::Format format,
+ int levels,
+ int edge_length,
bool enable_render_surfaces);
// Overridden from TextureCUBE
@@ -187,8 +194,9 @@ class TextureCUBECB : public TextureCUBE {
// Creates a texture from a pre-existing texture resource.
TextureCUBECB(ServiceLocator* service_locator,
command_buffer::ResourceID texture,
- const Bitmap &bitmap,
- bool resize_to_pot,
+ Texture::Format format,
+ int levels,
+ int edge_length,
bool enable_render_surfaces);
@@ -201,9 +209,8 @@ class TextureCUBECB : public TextureCUBE {
RendererCB* renderer_;
command_buffer::ResourceID resource_id_;
- // A bitmap used to back the NPOT textures on POT-only hardware, and to back
- // the pixel buffer for Lock().
- Bitmap::Ref backing_bitmap_;
+ // Bitmaps used to back the NPOT textures on POT-only hardware.
+ Bitmap::Ref backing_bitmaps_[NUMBER_OF_FACES];
// Bitfields that indicates mip levels that are currently stored in the
// backing bitmap, one per face.
diff --git a/o3d/core/cross/gl/renderer_gl.cc b/o3d/core/cross/gl/renderer_gl.cc
index 4a8b215..c4a0a30 100644
--- a/o3d/core/cross/gl/renderer_gl.cc
+++ b/o3d/core/cross/gl/renderer_gl.cc
@@ -692,7 +692,7 @@ Renderer::InitStatus RendererGL::InitCommonGL() {
return GPU_NOT_UP_TO_SPEC;
}
- SetSupportsNPOT(GLEW_ARB_texture_non_power_of_two);
+ SetSupportsNPOT(GLEW_ARB_texture_non_power_of_two != 0);
#ifdef OS_MACOSX
// The Radeon X1600 says it supports NPOT, but in most situations it doesn't.
@@ -1115,7 +1115,7 @@ void RendererGL::Destroy() {
bool RendererGL::MakeCurrent() {
#ifdef OS_WIN
if (!device_context_ || !gl_context_) return false;
- bool result = ::wglMakeCurrent(device_context_, gl_context_);
+ bool result = ::wglMakeCurrent(device_context_, gl_context_) != 0;
if (result) current_renderer_ = this;
return result;
#endif
@@ -1493,28 +1493,6 @@ ParamCache* RendererGL::CreatePlatformSpecificParamCache() {
}
-// Attempts to create a Texture with the given bitmap, automatically
-// determining whether the to create a 2D texture, cube texture, etc. If
-// creation fails the method returns NULL.
-// Parameters:
-// bitmap: The bitmap specifying the dimensions, format and content of the
-// new texture. The created texture takes ownership of the bitmap
-// data.
-// Returns:
-// A ref-counted pointer to the texture or NULL if it did not load.
-Texture::Ref RendererGL::CreatePlatformSpecificTextureFromBitmap(
- Bitmap* bitmap) {
- if (bitmap->is_cubemap()) {
- return Texture::Ref(TextureCUBEGL::Create(service_locator(),
- bitmap,
- false));
- } else {
- return Texture::Ref(Texture2DGL::Create(service_locator(),
- bitmap,
- false));
- }
-}
-
Texture2D::Ref RendererGL::CreatePlatformSpecificTexture2D(
int width,
int height,
@@ -1523,13 +1501,11 @@ Texture2D::Ref RendererGL::CreatePlatformSpecificTexture2D(
bool enable_render_surfaces) {
DLOG(INFO) << "RendererGL CreateTexture2D";
MakeCurrentLazy();
- Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
- bitmap->set_format(format);
- bitmap->set_width(width);
- bitmap->set_height(height);
- bitmap->set_num_mipmaps(levels);
return Texture2D::Ref(Texture2DGL::Create(service_locator(),
- bitmap,
+ format,
+ levels,
+ width,
+ height,
enable_render_surfaces));
}
@@ -1540,14 +1516,10 @@ TextureCUBE::Ref RendererGL::CreatePlatformSpecificTextureCUBE(
bool enable_render_surfaces) {
DLOG(INFO) << "RendererGL CreateTextureCUBE";
MakeCurrentLazy();
- Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
- bitmap->set_format(format);
- bitmap->set_width(edge_length);
- bitmap->set_height(edge_length);
- bitmap->set_num_mipmaps(levels);
- bitmap->set_is_cubemap(true);
return TextureCUBE::Ref(TextureCUBEGL::Create(service_locator(),
- bitmap,
+ format,
+ levels,
+ edge_length,
enable_render_surfaces));
}
@@ -1563,7 +1535,7 @@ RenderDepthStencilSurface::Ref RendererGL::CreateDepthStencilSurface(
Bitmap::Ref RendererGL::TakeScreenshot() {;
MakeCurrentLazy();
Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
- bitmap->Allocate(Texture::ARGB8, width(), height(), 1, false);
+ bitmap->Allocate(Texture::ARGB8, width(), height(), 1, Bitmap::IMAGE);
// Note: glReadPixels captures the alpha component of the frame buffer as well
// as the color components, the browser usually ignores the alpha channel when
diff --git a/o3d/core/cross/gl/renderer_gl.h b/o3d/core/cross/gl/renderer_gl.h
index 534ea9c..2ced616 100644
--- a/o3d/core/cross/gl/renderer_gl.h
+++ b/o3d/core/cross/gl/renderer_gl.h
@@ -204,9 +204,6 @@ class RendererGL : public Renderer {
RenderDepthStencilSurface* depth_surface);
// Overridden from Renderer.
- virtual Texture::Ref CreatePlatformSpecificTextureFromBitmap(Bitmap* bitmap);
-
- // Overridden from Renderer.
virtual Texture2D::Ref CreatePlatformSpecificTexture2D(
int width,
int height,
diff --git a/o3d/core/cross/gl/texture_gl.cc b/o3d/core/cross/gl/texture_gl.cc
index 24208c0..309a59e 100644
--- a/o3d/core/cross/gl/texture_gl.cc
+++ b/o3d/core/cross/gl/texture_gl.cc
@@ -155,8 +155,8 @@ static bool UpdateGLImageFromBitmap(GLenum target,
DCHECK(bitmap.image_data());
unsigned int mip_width = std::max(1U, bitmap.width() >> level);
unsigned int mip_height = std::max(1U, bitmap.height() >> level);
- const uint8 *mip_data = bitmap.GetFaceMipData(face, level);
- unsigned int mip_size =
+ const uint8 *mip_data = bitmap.GetMipData(level);
+ size_t mip_size =
image::ComputeBufferSize(mip_width, mip_height, bitmap.format());
scoped_array<uint8> temp_data;
if (resize_to_pot) {
@@ -165,8 +165,8 @@ static bool UpdateGLImageFromBitmap(GLenum target,
std::max(1U, image::ComputePOTSize(bitmap.width()) >> level);
unsigned int pot_height =
std::max(1U, image::ComputePOTSize(bitmap.height()) >> level);
- unsigned int pot_size = image::ComputeBufferSize(pot_width, pot_height,
- bitmap.format());
+ size_t pot_size = image::ComputeBufferSize(pot_width, pot_height,
+ bitmap.format());
temp_data.reset(new uint8[pot_size]);
image::Scale(mip_width, mip_height, bitmap.format(), mip_data,
pot_width, pot_height, temp_data.get(),
@@ -192,15 +192,18 @@ static bool UpdateGLImageFromBitmap(GLenum target,
// Creates the array of GL images for a particular face and upload the pixel
// data from the bitmap.
-static bool CreateGLImagesAndUpload(GLenum target,
- GLenum internal_format,
- GLenum format,
- GLenum type,
- TextureCUBE::CubeFace face,
- const Bitmap &bitmap,
- bool resize_to_pot) {
- unsigned int mip_width = bitmap.width();
- unsigned int mip_height = bitmap.height();
+static bool CreateGLImages(GLenum target,
+ GLenum internal_format,
+ GLenum gl_format,
+ GLenum type,
+ TextureCUBE::CubeFace face,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
+ bool resize_to_pot) {
+ unsigned int mip_width = width;
+ unsigned int mip_height = height;
if (resize_to_pot) {
mip_width = image::ComputePOTSize(mip_width);
mip_height = image::ComputePOTSize(mip_height);
@@ -210,38 +213,25 @@ static bool CreateGLImagesAndUpload(GLenum target,
// do that, otherwise we'll pass an empty buffer. In that case, prepare it
// here once for all.
scoped_array<uint8> temp_data;
- if (!bitmap.image_data()) {
- unsigned int size = image::ComputeBufferSize(mip_width, mip_height,
- bitmap.format());
- temp_data.reset(new uint8[size]);
- memset(temp_data.get(), 0, size);
- }
- for (unsigned int i = 0; i < bitmap.num_mipmaps(); ++i) {
- if (resize_to_pot && bitmap.image_data()) {
- if (!UpdateGLImageFromBitmap(target, i, face, bitmap, true)) {
- DLOG(ERROR) << "UpdateGLImageFromBitmap failed";
+ size_t size = image::ComputeBufferSize(mip_width, mip_height, format);
+ temp_data.reset(new uint8[size]);
+ memset(temp_data.get(), 0, size);
+
+ for (unsigned int i = 0; i < levels; ++i) {
+ if (gl_format) {
+ glTexImage2D(target, i, internal_format, mip_width, mip_height,
+ 0, format, type, temp_data.get());
+ if (glGetError() != GL_NO_ERROR) {
+ DLOG(ERROR) << "glTexImage2D failed";
return false;
}
} else {
- uint8 *data = resize_to_pot ? NULL : bitmap.GetFaceMipData(face, i);
- data = data ? data : temp_data.get();
- if (format) {
- glTexImage2D(target, i, internal_format, mip_width, mip_height,
- 0, format, type, data);
- if (glGetError() != GL_NO_ERROR) {
- DLOG(ERROR) << "glTexImage2D failed";
- return false;
- }
- } else {
- 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, data);
- if (glGetError() != GL_NO_ERROR) {
- DLOG(ERROR) << "glCompressedTexImage2D failed";
- return false;
- }
+ size_t mip_size = image::ComputeBufferSize(mip_width, mip_height, format);
+ glCompressedTexImage2DARB(target, i, internal_format, mip_width,
+ mip_height, 0, mip_size, temp_data.get());
+ if (glGetError() != GL_NO_ERROR) {
+ DLOG(ERROR) << "glCompressedTexImage2D failed";
+ return false;
}
}
mip_width = std::max(1U, mip_width >> 1);
@@ -256,39 +246,43 @@ static bool CreateGLImagesAndUpload(GLenum target,
// NOTE: the Texture2DGL now owns the GL texture and will destroy it on exit.
Texture2DGL::Texture2DGL(ServiceLocator* service_locator,
GLint texture,
- const Bitmap &bitmap,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
bool resize_to_pot,
bool enable_render_surfaces)
: Texture2D(service_locator,
- bitmap.width(),
- bitmap.height(),
- bitmap.format(),
- bitmap.num_mipmaps(),
- bitmap.CheckAlphaIsOne(),
- resize_to_pot,
+ width,
+ height,
+ format,
+ levels,
enable_render_surfaces),
+ resize_to_pot_(resize_to_pot),
renderer_(static_cast<RendererGL*>(
service_locator->GetService<Renderer>())),
gl_texture_(texture),
backing_bitmap_(Bitmap::Ref(new Bitmap(service_locator))),
has_levels_(0) {
DLOG(INFO) << "Texture2DGL Construct from GLint";
- DCHECK_NE(format(), Texture::UNKNOWN_FORMAT);
+ DCHECK_NE(format, Texture::UNKNOWN_FORMAT);
}
// Creates a new texture object from scratch.
Texture2DGL* Texture2DGL::Create(ServiceLocator* service_locator,
- Bitmap *bitmap,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
bool enable_render_surfaces) {
DLOG(INFO) << "Texture2DGL Create";
- DCHECK_NE(bitmap->format(), Texture::UNKNOWN_FORMAT);
- DCHECK(!bitmap->is_cubemap());
+ DCHECK_NE(format, Texture::UNKNOWN_FORMAT);
RendererGL *renderer = static_cast<RendererGL *>(
service_locator->GetService<Renderer>());
renderer->MakeCurrentLazy();
GLenum gl_internal_format = 0;
GLenum gl_data_type = 0;
- GLenum gl_format = GLFormatFromO3DFormat(bitmap->format(),
+ GLenum gl_format = GLFormatFromO3DFormat(format,
&gl_internal_format,
&gl_data_type);
if (gl_internal_format == 0) {
@@ -296,18 +290,19 @@ Texture2DGL* Texture2DGL::Create(ServiceLocator* service_locator,
return NULL;
}
- bool resize_to_pot = !renderer->supports_npot() && !bitmap->IsPOT();
+ bool resize_to_pot = !renderer->supports_npot() &&
+ !image::IsPOT(width, height);
// Creates the OpenGL texture object, with all the required mip levels.
GLuint gl_texture = 0;
glGenTextures(1, &gl_texture);
glBindTexture(GL_TEXTURE_2D, gl_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL,
- bitmap->num_mipmaps()-1);
+ levels - 1);
- if (!CreateGLImagesAndUpload(GL_TEXTURE_2D, gl_internal_format, gl_format,
- gl_data_type, TextureCUBE::FACE_POSITIVE_X,
- *bitmap, resize_to_pot)) {
+ if (!CreateGLImages(GL_TEXTURE_2D, gl_internal_format, gl_format,
+ gl_data_type, TextureCUBE::FACE_POSITIVE_X,
+ format, levels, width, height, resize_to_pot)) {
DLOG(ERROR) << "Failed to create texture images.";
glDeleteTextures(1, &gl_texture);
return NULL;
@@ -328,26 +323,18 @@ Texture2DGL* Texture2DGL::Create(ServiceLocator* service_locator,
<< ", GLuint=" << gl_texture << ")";
Texture2DGL *texture = new Texture2DGL(service_locator,
gl_texture,
- *bitmap,
+ format,
+ levels,
+ width,
+ height,
resize_to_pot,
enable_render_surfaces);
- // Setup the backing bitmap.
- texture->backing_bitmap_->SetFrom(bitmap);
- if (texture->backing_bitmap_->image_data()) {
- if (resize_to_pot) {
- texture->has_levels_ = (1 << bitmap->num_mipmaps()) - 1;
- } else {
- texture->backing_bitmap_->FreeData();
- }
- } else {
- // If no backing store was provided to the routine, and the hardware does
- // not support npot textures, allocate a 0-initialized mip-chain here
- // for use during Texture2DGL::Lock.
- if (resize_to_pot) {
- texture->backing_bitmap_->AllocateData();
- texture->has_levels_ = (1 << bitmap->num_mipmaps()) - 1;
- }
+ // If the hardware does not support npot textures, allocate a 0-initialized
+ // mip-chain here for use during Texture2DGL::Lock.
+ if (resize_to_pot) {
+ texture->backing_bitmap_->AllocateData();
+ texture->has_levels_ = (1 << levels) - 1;
}
CHECK_GL_ERROR();
return texture;
@@ -481,7 +468,8 @@ bool Texture2DGL::Lock(int level, void** data, int* pitch) {
}
if (!backing_bitmap_->image_data()) {
DCHECK_EQ(has_levels_, 0u);
- backing_bitmap_->Allocate(format(), width(), height(), levels(), false);
+ backing_bitmap_->Allocate(format(), width(), height(), levels(),
+ Bitmap::IMAGE);
}
*data = backing_bitmap_->GetMipData(level);
unsigned int mip_width = image::ComputeMipDimension(level, width());
@@ -579,23 +567,24 @@ const Texture::RGBASwizzleIndices& Texture2DGL::GetABGR32FSwizzleIndices() {
// Creates a texture from a pre-existing GL texture object.
TextureCUBEGL::TextureCUBEGL(ServiceLocator* service_locator,
GLint texture,
- const Bitmap &bitmap,
+ Texture::Format format,
+ int levels,
+ int edge_length,
bool resize_to_pot,
bool enable_render_surfaces)
: TextureCUBE(service_locator,
- bitmap.width(),
- bitmap.format(),
- bitmap.num_mipmaps(),
- bitmap.CheckAlphaIsOne(),
- resize_to_pot,
+ edge_length,
+ format,
+ levels,
enable_render_surfaces),
+ resize_to_pot_(resize_to_pot),
renderer_(static_cast<RendererGL*>(
service_locator->GetService<Renderer>())),
- gl_texture_(texture),
- backing_bitmap_(Bitmap::Ref(new Bitmap(service_locator))) {
+ gl_texture_(texture) {
DLOG(INFO) << "TextureCUBEGL Construct";
- for (unsigned int i = 0; i < 6; ++i) {
- has_levels_[i] = 0;
+ for (int ii = 0; ii < static_cast<int>(NUMBER_OF_FACES); ++ii) {
+ backing_bitmaps_[ii] = Bitmap::Ref(new Bitmap(service_locator));
+ has_levels_[ii] = 0;
}
}
@@ -620,22 +609,23 @@ static const int kCubemapFaceList[] = {
// Create a new Cube texture from scratch.
TextureCUBEGL* TextureCUBEGL::Create(ServiceLocator* service_locator,
- Bitmap *bitmap,
+ Texture::Format format,
+ int levels,
+ int edge_length,
bool enable_render_surfaces) {
DLOG(INFO) << "TextureCUBEGL Create";
CHECK_GL_ERROR();
- DCHECK(bitmap->is_cubemap());
- DCHECK_EQ(bitmap->width(), bitmap->height());
RendererGL *renderer = static_cast<RendererGL *>(
service_locator->GetService<Renderer>());
renderer->MakeCurrentLazy();
- bool resize_to_pot = !renderer->supports_npot() && !bitmap->IsPOT();
+ bool resize_to_pot = !renderer->supports_npot() &&
+ !image::IsPOT(edge_length, edge_length);
// Get gl formats
GLenum gl_internal_format = 0;
GLenum gl_data_type = 0;
- GLenum gl_format = GLFormatFromO3DFormat(bitmap->format(),
+ GLenum gl_format = GLFormatFromO3DFormat(format,
&gl_internal_format,
&gl_data_type);
if (gl_internal_format == 0) {
@@ -648,13 +638,14 @@ TextureCUBEGL* TextureCUBEGL::Create(ServiceLocator* service_locator,
glGenTextures(1, &gl_texture);
glBindTexture(GL_TEXTURE_CUBE_MAP, gl_texture);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL,
- bitmap->num_mipmaps()-1);
+ levels - 1);
- for (int face = 0; face < 6; ++face) {
- CreateGLImagesAndUpload(kCubemapFaceList[face], gl_internal_format,
- gl_format, gl_data_type,
- static_cast<CubeFace>(face), *bitmap,
- resize_to_pot);
+ for (int face = 0; face < static_cast<int>(NUMBER_OF_FACES); ++face) {
+ CreateGLImages(kCubemapFaceList[face], gl_internal_format,
+ gl_format, gl_data_type,
+ static_cast<CubeFace>(face),
+ format, levels, edge_length, edge_length,
+ resize_to_pot);
}
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER,
@@ -667,28 +658,17 @@ TextureCUBEGL* TextureCUBEGL::Create(ServiceLocator* service_locator,
// from the Bitmap information.
TextureCUBEGL* texture = new TextureCUBEGL(service_locator,
gl_texture,
- *bitmap,
+ format,
+ levels,
+ edge_length,
resize_to_pot,
enable_render_surfaces);
- // Setup the backing bitmap, and upload the data if we have any.
- texture->backing_bitmap_->SetFrom(bitmap);
- if (texture->backing_bitmap_->image_data()) {
- if (resize_to_pot) {
- for (unsigned int face = 0; face < 6; ++face) {
- texture->has_levels_[face] = (1 << bitmap->num_mipmaps()) - 1;
- }
- } else {
- texture->backing_bitmap_->FreeData();
- }
- } else {
- // If no backing store was provided to the routine, and the hardware does
- // not support npot textures, allocate a 0-initialized mip-chain here
- // for use during TextureCUBEGL::Lock.
- if (resize_to_pot) {
- texture->backing_bitmap_->AllocateData();
- for (unsigned int face = 0; face < 6; ++face) {
- texture->has_levels_[face] = (1 << bitmap->num_mipmaps()) - 1;
- }
+ // If the hardware does not support npot textures, allocate a 0-initialized
+ // mip-chain here for use during TextureCUBEGL::Lock.
+ if (resize_to_pot) {
+ for (int face = 0; face < static_cast<int>(NUMBER_OF_FACES); ++face) {
+ texture->backing_bitmaps_[face]->AllocateData();
+ texture->has_levels_[face] = (1 << levels) - 1;
}
}
CHECK_GL_ERROR();
@@ -698,17 +678,16 @@ TextureCUBEGL* TextureCUBEGL::Create(ServiceLocator* service_locator,
void TextureCUBEGL::UpdateBackedMipLevel(unsigned int level,
TextureCUBE::CubeFace face) {
+ Bitmap* backing_bitmap = backing_bitmaps_[face].Get();
DCHECK_LT(static_cast<int>(level), levels());
- DCHECK(backing_bitmap_->image_data());
- DCHECK(backing_bitmap_->is_cubemap());
- DCHECK_EQ(backing_bitmap_->width(), static_cast<unsigned int>(edge_length()));
- DCHECK_EQ(backing_bitmap_->height(),
- static_cast<unsigned int>(edge_length()));
- DCHECK_EQ(backing_bitmap_->format(), format());
+ DCHECK(backing_bitmap->image_data());
+ DCHECK_EQ(backing_bitmap->width(), static_cast<unsigned int>(edge_length()));
+ DCHECK_EQ(backing_bitmap->height(), static_cast<unsigned int>(edge_length()));
+ DCHECK_EQ(backing_bitmap->format(), format());
DCHECK(HasLevel(level, face));
glBindTexture(GL_TEXTURE_2D, gl_texture_);
UpdateGLImageFromBitmap(kCubemapFaceList[face], level, face,
- *backing_bitmap_.Get(),
+ *backing_bitmap,
resize_to_pot_);
}
@@ -795,11 +774,12 @@ void TextureCUBEGL::SetRect(TextureCUBE::CubeFace face,
}
if (resize_to_pot_) {
- DCHECK(backing_bitmap_->image_data());
+ Bitmap* backing_bitmap = backing_bitmaps_[face].Get();
+ DCHECK(backing_bitmap->image_data());
DCHECK(!compressed);
// We need to update the backing mipmap and then use that to update the
// texture.
- backing_bitmap_->SetFaceRect(face,
+ backing_bitmap->SetRect(
level, dst_left, dst_top, src_width, src_height, src_data, src_pitch);
UpdateBackedMipLevel(level, face);
} else {
@@ -858,14 +838,15 @@ bool TextureCUBEGL::Lock(CubeFace face, int level, void** data, int* pitch) {
<< "\" is already locked.";
return false;
}
- if (!backing_bitmap_->image_data()) {
+ Bitmap* backing_bitmap = backing_bitmaps_[face].Get();
+ if (!backing_bitmap->image_data()) {
for (unsigned int i = 0; i < 6; ++i) {
DCHECK_EQ(has_levels_[i], 0u);
}
- backing_bitmap_->Allocate(format(), edge_length(), edge_length(),
- levels(), true);
+ backing_bitmap->Allocate(format(), edge_length(), edge_length(), levels(),
+ Bitmap::IMAGE);
}
- *data = backing_bitmap_->GetFaceMipData(face, level);
+ *data = backing_bitmap->GetMipData(level);
unsigned int mip_width = image::ComputeMipDimension(level, edge_length());
if (!IsCompressed()) {
*pitch = image::ComputePitch(format(), mip_width);
@@ -912,6 +893,7 @@ bool TextureCUBEGL::Unlock(CubeFace face, int level) {
return false;
}
UpdateBackedMipLevel(level, face);
+ Bitmap* backing_bitmap = backing_bitmaps_[face].Get();
locked_levels_[face] &= ~(1 << level);
if (!resize_to_pot_) {
bool has_locked_level = false;
@@ -922,7 +904,7 @@ bool TextureCUBEGL::Unlock(CubeFace face, int level) {
}
}
if (!has_locked_level) {
- backing_bitmap_->FreeData();
+ backing_bitmap->FreeData();
for (unsigned int i = 0; i < 6; ++i) {
has_levels_[i] = 0;
}
diff --git a/o3d/core/cross/gl/texture_gl.h b/o3d/core/cross/gl/texture_gl.h
index 567bf2b..a107de6 100644
--- a/o3d/core/cross/gl/texture_gl.h
+++ b/o3d/core/cross/gl/texture_gl.h
@@ -82,7 +82,10 @@ class Texture2DGL : public Texture2D {
// newly created Texture object.
// The created texture takes ownership of the bitmap data.
static Texture2DGL* Create(ServiceLocator* service_locator,
- Bitmap *bitmap,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
bool enable_render_surfaces);
// Returns the implementation-specific texture handle for this texture.
@@ -118,7 +121,10 @@ class Texture2DGL : public Texture2D {
// The texture takes ownership of the bitmap data.
Texture2DGL(ServiceLocator* service_locator,
GLint texture,
- const Bitmap &bitmap,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
bool resize_npot,
bool enable_render_surfaces);
@@ -132,6 +138,10 @@ class Texture2DGL : public Texture2D {
return (has_levels_ & (1 << level)) != 0;
}
+ // Whether or not this texture needs to be resized from NPOT to pot behind
+ // the scenes.
+ bool resize_to_pot_;
+
RendererGL* renderer_;
// The handle of the OpenGL texture object.
@@ -157,7 +167,9 @@ class TextureCUBEGL : public TextureCUBE {
// Create a new Cube texture from scratch.
static TextureCUBEGL* Create(ServiceLocator* service_locator,
- Bitmap *bitmap,
+ Texture::Format format,
+ int levels,
+ int edge_length,
bool enable_render_surfaces);
// Overridden from TextureCUBE
@@ -205,7 +217,9 @@ class TextureCUBEGL : public TextureCUBE {
// Creates a texture from a pre-existing GL texture object.
TextureCUBEGL(ServiceLocator* service_locator,
GLint texture,
- const Bitmap &bitmap,
+ Texture::Format format,
+ int levels,
+ int edge_length,
bool resize_to_pot,
bool enable_render_surfaces);
@@ -219,14 +233,17 @@ class TextureCUBEGL : public TextureCUBE {
return (has_levels_[face] & (1 << level)) != 0;
}
+ // Whether or not this texture needs to be resized from NPOT to pot behind
+ // the scenes.
+ bool resize_to_pot_;
+
RendererGL* renderer_;
// The handle of the OpenGL texture object.
GLuint gl_texture_;
- // A bitmap used to back the NPOT textures on POT-only hardware, and to back
- // the pixel buffer for Lock().
- Bitmap::Ref backing_bitmap_;
+ // Bitmaps used to back the NPOT textures on POT-only hardware.
+ Bitmap::Ref backing_bitmaps_[NUMBER_OF_FACES];
// Bitfields that indicates mip levels that are currently stored in the
// backing bitmap, one per face.
diff --git a/o3d/core/cross/image_utils.cc b/o3d/core/cross/image_utils.cc
index 3e96634..5570d2b 100644
--- a/o3d/core/cross/image_utils.cc
+++ b/o3d/core/cross/image_utils.cc
@@ -37,15 +37,17 @@
#include "core/cross/precompile.h"
#include "core/cross/image_utils.h"
+#include "core/cross/pointer_utils.h"
+#include "core/cross/math_utilities.h"
namespace o3d {
namespace image {
// Computes the size of the buffer containing a an image, given its width,
// height and format.
-unsigned int ComputeBufferSize(unsigned int width,
- unsigned int height,
- Texture::Format format) {
+size_t ComputeBufferSize(unsigned int width,
+ unsigned int height,
+ Texture::Format format) {
DCHECK(CheckImageDimensions(width, height));
unsigned int pixels = width * height;
switch (format) {
@@ -75,12 +77,12 @@ unsigned int ComputeBufferSize(unsigned int width,
// 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 ComputeMipChainSize(unsigned int base_width,
- unsigned int base_height,
- Texture::Format format,
- unsigned int num_mipmaps) {
+size_t ComputeMipChainSize(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;
+ size_t total_size = 0;
unsigned int mip_width = base_width;
unsigned int mip_height = base_height;
for (unsigned int i = 0; i < num_mipmaps; ++i) {
@@ -122,22 +124,21 @@ bool ScaleUpToPOT(unsigned int width,
}
unsigned int GetNumComponentsForFormat(o3d::Texture::Format format) {
- unsigned int components = 0;
switch (format) {
case o3d::Texture::XRGB8:
case o3d::Texture::ARGB8:
- components = 4;
- break;
case o3d::Texture::ABGR16F:
- case o3d::Texture::R32F:
case o3d::Texture::ABGR32F:
+ return 4;
+ case o3d::Texture::R32F:
+ return 1;
case o3d::Texture::DXT1:
case o3d::Texture::DXT3:
case o3d::Texture::DXT5:
case o3d::Texture::UNKNOWN_FORMAT:
break;
}
- return components;
+ return 0;
}
namespace {
@@ -400,15 +401,19 @@ void LanczosResize1D(const uint8* src, int src_x, int src_y,
// src_height: height of the source image
// src_data: address of the source image data
// components: number of components in the image.
+template <typename OriginalType,
+ typename WorkType,
+ WorkType convert_to_work(OriginalType value),
+ OriginalType convert_to_original(WorkType)>
void FilterTexel(unsigned int x,
unsigned int y,
unsigned int dst_width,
unsigned int dst_height,
- uint8 *dst_data,
+ void *dst_data,
int dst_pitch,
unsigned int src_width,
unsigned int src_height,
- const uint8 *src_data,
+ const void *src_data,
int src_pitch,
unsigned int components) {
DCHECK(image::CheckImageDimensions(src_width, src_height));
@@ -420,6 +425,12 @@ void FilterTexel(unsigned int x,
DCHECK_LE(static_cast<int>(src_width), src_pitch);
DCHECK_LE(static_cast<int>(dst_width), dst_pitch);
+ const OriginalType* src = static_cast<const OriginalType*>(src_data);
+ OriginalType* dst = static_cast<OriginalType*>(dst_data);
+
+ DCHECK_EQ(src_pitch % (components * sizeof(*src)), 0);
+ DCHECK_EQ(dst_pitch % (components * sizeof(*dst)), 0);
+
src_pitch /= components;
dst_pitch /= components;
// the texel at (x, y) represents the square of texture coordinates
@@ -429,10 +440,12 @@ void FilterTexel(unsigned int x,
// 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;
+ 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
@@ -446,7 +459,7 @@ void FilterTexel(unsigned int x,
// 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};
+ WorkType 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
@@ -480,21 +493,119 @@ void FilterTexel(unsigned int x,
}
DCHECK(y_contrib > 0);
DCHECK(y_contrib <= dst_height);
- unsigned int contrib = x_contrib * y_contrib;
+ WorkType contrib = static_cast<WorkType>(x_contrib * y_contrib);
for (unsigned int c = 0; c < components; ++c) {
- accum[c] +=
- contrib * src_data[(src_y * src_pitch + src_x) * components + c];
+ accum[c] += contrib *
+ convert_to_work(src[(src_y * src_pitch + 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_pitch + x) * components + c] =
- static_cast<uint8>(value);
+ WorkType value = accum[c] / static_cast<WorkType>(src_height * src_width);
+ dst[(y * dst_pitch + x) * components + c] = convert_to_original(value);
+ }
+}
+
+template <typename OriginalType,
+ typename WorkType,
+ typename FilterType,
+ WorkType convert_to_work(OriginalType value),
+ OriginalType convert_from_work(WorkType),
+ FilterType convert_to_filter(OriginalType value),
+ OriginalType convert_from_filter(FilterType)>
+void GenerateMip(unsigned int components,
+ unsigned int src_width,
+ unsigned int src_height,
+ const void *src_data,
+ int src_pitch,
+ void *dst_data,
+ int dst_pitch) {
+ unsigned int mip_width = std::max(1U, src_width >> 1);
+ unsigned int mip_height = std::max(1U, src_height >> 1);
+
+ const OriginalType* src = static_cast<const OriginalType*>(src_data);
+ OriginalType* dst = static_cast<OriginalType*>(dst_data);
+
+ if (mip_width * 2 == src_width && mip_height * 2 == src_height) {
+ DCHECK_EQ(src_pitch % (components * sizeof(*src)), 0);
+ DCHECK_EQ(dst_pitch % (components * sizeof(*dst)), 0);
+ src_pitch /= components;
+ dst_pitch /= components;
+ // 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 * src_pitch + x * 2) * components + c;
+ WorkType value = convert_to_work(src[offset]); // (2x, 2y)
+ value += convert_to_work(src[offset + components]); // (2x+1, 2y)
+ value += convert_to_work(src[offset + src_width * components]);
+ // (2x, 2y+1)
+ value += convert_to_work(src[offset + (src_width + 1) * components]);
+ // (2x+1, 2y+1)
+ dst[(y * dst_pitch + x) * components + c] =
+ convert_from_work(value / static_cast<WorkType>(4));
+ }
+ }
+ }
+ } else {
+ for (unsigned int y = 0; y < mip_height; ++y) {
+ for (unsigned int x = 0; x < mip_width; ++x) {
+ FilterTexel<OriginalType,
+ FilterType,
+ convert_to_filter,
+ convert_from_filter>(
+ x, y, mip_width, mip_height, dst_data, dst_pitch,
+ src_width, src_height, src_data, src_pitch, components);
+ }
+ }
}
}
+uint32 UInt8ToUInt32(uint8 value) {
+ return static_cast<uint32>(value);
+};
+
+uint8 UInt32ToUInt8(uint32 value) {
+ return static_cast<uint8>(value);
+};
+
+uint64 UInt8ToUInt64(uint8 value) {
+ return static_cast<uint64>(value);
+};
+
+uint8 UInt64ToUInt8(uint64 value) {
+ return static_cast<uint8>(value);
+};
+
+float FloatToFloat(float value) {
+ return value;
+}
+
+double FloatToDouble(float value) {
+ return static_cast<double>(value);
+}
+
+float DoubleToFloat(double value) {
+ return static_cast<float>(value);
+}
+
+float HalfToFloat(uint16 value) {
+ return Vectormath::Aos::HalfToFloat(value);
+}
+
+uint16 FloatToHalf(float value) {
+ return Vectormath::Aos::FloatToHalf(value);
+}
+
+double HalfToDouble(uint16 value) {
+ return static_cast<double>(Vectormath::Aos::HalfToFloat(value));
+}
+
+uint16 DoubleToHalf(double value) {
+ return Vectormath::Aos::FloatToHalf(static_cast<float>(value));
+}
+
} // anonymous namespace
// Adjust boundaries when using DrawImage function in bitmap or texture.
@@ -595,34 +706,31 @@ bool GenerateMipmap(unsigned int src_width,
DLOG(ERROR) << "Mip-map generation not supported for format: " << format;
return false;
}
- unsigned int mip_width = std::max(1U, src_width >> 1);
- unsigned int mip_height = std::max(1U, src_height >> 1);
- if (mip_width * 2 == src_width && mip_height * 2 == src_height) {
- src_pitch /= components;
- dst_pitch /= components;
- // 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 * src_pitch + x * 2) * components + c;
- unsigned int value = src_data[offset]; // (2x, 2y)
- value += src_data[offset + components]; // (2x+1, 2y)
- value += src_data[offset + src_width * components]; // (2x, 2y+1)
- value +=
- src_data[offset + (src_width + 1) * components]; // (2x+1, 2y+1)
- dst_data[(y * dst_pitch + 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, dst_data, dst_pitch,
- src_width, src_height, src_data, src_pitch, components);
- }
- }
+ switch (format) {
+ case Texture::ARGB8:
+ case Texture::XRGB8:
+ GenerateMip<uint8, uint32, uint64,
+ UInt8ToUInt32, UInt32ToUInt8,
+ UInt8ToUInt64, UInt64ToUInt8>(
+ components, src_width, src_height, src_data, src_pitch,
+ dst_data, dst_pitch);
+ break;
+ case Texture::ABGR16F:
+ GenerateMip<uint16, float, double,
+ HalfToFloat, FloatToHalf,
+ HalfToDouble, DoubleToHalf>(
+ components, src_width, src_height, src_data, src_pitch,
+ dst_data, dst_pitch);
+ break;
+ case Texture::ABGR32F:
+ case Texture::R32F:
+ GenerateMip<float, float, double,
+ FloatToFloat, FloatToFloat,
+ FloatToDouble, DoubleToFloat>(
+ components, src_width, src_height, src_data, src_pitch,
+ dst_data, dst_pitch);
+ break;
}
return true;
}
diff --git a/o3d/core/cross/image_utils.h b/o3d/core/cross/image_utils.h
index 2b6212e..e37d8eb 100644
--- a/o3d/core/cross/image_utils.h
+++ b/o3d/core/cross/image_utils.h
@@ -58,6 +58,10 @@ enum ImageFileType {
unsigned int GetNumComponentsForFormat(Texture::Format format);
+inline bool IsPOT(unsigned width, unsigned height) {
+ return ((width & (width - 1)) == 0) && ((height & (height - 1)) == 0);
+}
+
inline bool CheckImageDimensions(unsigned int width, unsigned int height) {
return width <= kMaxImageDimension && height <= kMaxImageDimension;
}
@@ -83,10 +87,10 @@ inline unsigned ComputeMipDimension(int level, unsigned dimension) {
// Computes the size of the buffer containing a mip-map chain, given its base
// width, height, format and number of mip-map levels.
-unsigned int ComputeMipChainSize(unsigned int base_width,
- unsigned int base_height,
- Texture::Format format,
- unsigned int num_mipmaps);
+size_t ComputeMipChainSize(unsigned int base_width,
+ unsigned int base_height,
+ Texture::Format format,
+ unsigned int num_mipmaps);
inline int ComputePitch(Texture::Format format, unsigned width) {
if (Texture::IsCompressedFormat(format)) {
@@ -94,7 +98,7 @@ inline int ComputePitch(Texture::Format format, unsigned width) {
unsigned bytes_per_block = format == Texture::DXT1 ? 8u : 16u;
return bytes_per_block * blocks_across;
} else {
- return ComputeMipChainSize(width, 1u, format, 1u);
+ return static_cast<int>(ComputeMipChainSize(width, 1u, format, 1u));
}
}
@@ -107,9 +111,9 @@ inline int ComputeMipPitch(Texture::Format format,
}
// Computes the number of bytes of a bitmap pixel buffer.
-unsigned int ComputeBufferSize(unsigned int width,
- unsigned int height,
- Texture::Format format);
+size_t ComputeBufferSize(unsigned int width,
+ unsigned int height,
+ Texture::Format format);
// Crop part of an image from src, scale it to an arbitrary size
// and paste in dest image. Utility function for all DrawImage
diff --git a/o3d/core/cross/image_utils_test.cc b/o3d/core/cross/image_utils_test.cc
index 4f6a1c3..b7ca6f6 100644
--- a/o3d/core/cross/image_utils_test.cc
+++ b/o3d/core/cross/image_utils_test.cc
@@ -119,11 +119,9 @@ TEST_F(ImageTest, ScaleUpToPOT) {
const unsigned int kPOTHeight = image::ComputePOTSize(kHeight);
ASSERT_EQ(kPOTHeight, 4u);
const Texture::Format format = Texture::ARGB8;
- unsigned int src_size =
- image::ComputeBufferSize(kWidth, kHeight, format);
+ size_t src_size = image::ComputeBufferSize(kWidth, kHeight, format);
ASSERT_EQ(sizeof(kScaleUPDataNPOT), src_size);
- unsigned int dst_size =
- image::ComputeBufferSize(kPOTWidth, kPOTHeight, format);
+ size_t dst_size = image::ComputeBufferSize(kPOTWidth, kPOTHeight, format);
ASSERT_EQ(sizeof(kScaleUPDataPOT), dst_size);
scoped_array<uint8> data(new uint8[dst_size]);
ASSERT_TRUE(data.get() != NULL);
@@ -173,14 +171,12 @@ TEST_F(ImageTest, GenerateMipmapsPOT) {
const Texture::Format format = Texture::ARGB8;
unsigned int mipmaps = image::ComputeMipMapCount(kWidth, kHeight);
EXPECT_EQ(3u, mipmaps);
- unsigned int size =
- image::ComputeMipChainSize(kWidth, kHeight, format, mipmaps);
+ size_t size = image::ComputeMipChainSize(kWidth, kHeight, format, mipmaps);
ASSERT_EQ(sizeof(kMipmapDataPOT), size);
scoped_array<uint8> data(new uint8[size]);
ASSERT_TRUE(data.get() != NULL);
// Copy first level into the buffer.
- unsigned int base_size =
- image::ComputeMipChainSize(kWidth, kHeight, format, 1);
+ size_t base_size = image::ComputeMipChainSize(kWidth, kHeight, format, 1);
memcpy(data.get(), kMipmapDataPOT, base_size);
image::GenerateMipmap(
kWidth, kHeight, format,
@@ -244,14 +240,12 @@ TEST_F(ImageTest, GenerateMipmapsNPOT) {
const Texture::Format format = Texture::ARGB8;
unsigned int mipmaps = image::ComputeMipMapCount(kWidth, kHeight);
EXPECT_EQ(3u, mipmaps);
- unsigned int size =
- image::ComputeMipChainSize(kWidth, kHeight, format, mipmaps);
+ size_t size = image::ComputeMipChainSize(kWidth, kHeight, format, mipmaps);
ASSERT_EQ(sizeof(kMipmapDataNPOT), size);
scoped_array<uint8> data(new uint8[size]);
ASSERT_TRUE(data.get() != NULL);
// Copy first level into the buffer.
- unsigned int base_size =
- image::ComputeMipChainSize(kWidth, kHeight, format, 1);
+ size_t base_size = image::ComputeMipChainSize(kWidth, kHeight, format, 1);
memcpy(data.get(), kMipmapDataNPOT, base_size);
image::GenerateMipmap(
kWidth, kHeight, format,
diff --git a/o3d/core/cross/pack.cc b/o3d/core/cross/pack.cc
index eb19e05..a874c02 100644
--- a/o3d/core/cross/pack.cc
+++ b/o3d/core/cross/pack.cc
@@ -42,6 +42,7 @@
#include "import/cross/memory_buffer.h"
#include "import/cross/memory_stream.h"
#include "core/cross/file_request.h"
+#include "core/cross/image_utils.h"
#include "core/cross/render_node.h"
#include "core/cross/iclass_manager.h"
#include "core/cross/object_manager.h"
@@ -123,26 +124,20 @@ Texture* Pack::CreateTextureFromFile(const String& uri,
const FilePath& filepath,
image::ImageFileType file_type,
bool generate_mipmaps) {
- if (!renderer_) {
- O3D_ERROR(service_locator()) << "No Render Device Available";
- return NULL;
- }
-
String filename = FilePathToUTF8(filepath);
DLOG(INFO) << "CreateTextureFromFile(uri='" << uri
<< "', filename='" << filename << "')";
- // TODO: Add support for volume texture when we have code to load
- // them
- Bitmap::Ref bitmap(new Bitmap(service_locator()));
- if (!bitmap->LoadFromFile(filepath, file_type, generate_mipmaps)) {
+ // TODO(gman): Add support for volume texture when we have code to load them.
+ BitmapRefArray bitmaps;
+ if (!Bitmap::LoadFromFile(service_locator(), filepath, file_type, &bitmaps)) {
O3D_ERROR(service_locator())
<< "Failed to load bitmap file \"" << uri << "\"";
return NULL;
}
- return CreateTextureFromBitmap(bitmap, uri);
+ return CreateTextureFromBitmaps(bitmaps, uri, generate_mipmaps);
}
// Creates a Texture object from a file in the current render context format.
@@ -160,28 +155,87 @@ Texture* Pack::CreateTextureFromFile(const String& uri,
}
// Creates a Texture object from a bitmap in the current render context format.
-Texture* Pack::CreateTextureFromBitmap(Bitmap *bitmap, const String& uri) {
- DCHECK(bitmap);
-
- if (!renderer_) {
- O3D_ERROR(service_locator()) << "No Render Device Available";
+Texture* Pack::CreateTextureFromBitmaps(
+ const BitmapRefArray& bitmaps, const String& uri, bool generate_mipmaps) {
+ if (bitmaps.empty()) {
return NULL;
}
-
- if (bitmap->width() > static_cast<unsigned int>(Texture::MAX_DIMENSION) ||
- bitmap->height() > static_cast<unsigned int>(Texture::MAX_DIMENSION)) {
- O3D_ERROR(service_locator())
- << "Texture (uri='" << uri
- << "', size=" << bitmap->width() << "x" << bitmap->height()
- << ", mips=" << bitmap->num_mipmaps()<< ") is larger than the "
- << "maximum texture size which is (" << Texture::MAX_DIMENSION
- << "x" << Texture::MAX_DIMENSION << ")";
- return NULL;
+ unsigned width = bitmaps[0]->width();
+ unsigned height = bitmaps[0]->height();
+
+ BitmapRefArray temp_bitmaps;
+ for (BitmapRefArray::size_type ii = 0; ii < bitmaps.size(); ++ii) {
+ temp_bitmaps.push_back(bitmaps[ii]);
+ Bitmap* bitmap = temp_bitmaps[ii].Get();
+ if (bitmap->width() > static_cast<unsigned int>(Texture::MAX_DIMENSION) ||
+ bitmap->height() > static_cast<unsigned int>(Texture::MAX_DIMENSION)) {
+ O3D_ERROR(service_locator())
+ << "Bitmap (uri='" << uri
+ << "', size=" << bitmap->width() << "x" << bitmap->height()
+ << ", mips=" << bitmap->num_mipmaps()<< ") is larger than the "
+ << "maximum texture size which is (" << Texture::MAX_DIMENSION
+ << "x" << Texture::MAX_DIMENSION << ")";
+ return NULL;
+ }
+ if (bitmap->width() != width || bitmap->height() != height) {
+ O3D_ERROR(service_locator()) << "Bitmaps are not all the same dimensions";
+ return NULL;
+ }
+ if (generate_mipmaps) {
+ unsigned total_mips = image::ComputeMipMapCount(
+ bitmap->width(), bitmap->height());
+ // If we don't already have mips and we could use them then make them.
+ if (bitmap->num_mipmaps() == 1 && total_mips > 1) {
+ // Create a new Bitmap with mips
+ Bitmap::Ref new_bitmap(new Bitmap(service_locator()));
+ new_bitmap->Allocate(bitmap->format(),
+ bitmap->width(),
+ bitmap->height(),
+ total_mips,
+ bitmap->semantic());
+ new_bitmap->SetRect(0, 0, 0, bitmap->width(), bitmap->height(),
+ bitmap->GetMipData(0), bitmap->GetMipPitch(0));
+ new_bitmap->GenerateMips(0, total_mips - 1);
+ temp_bitmaps[ii] = new_bitmap;
+ }
+ }
}
- Texture::Ref texture = renderer_->CreateTextureFromBitmap(bitmap);
+ // Figure out what kind of texture to make.
+ // TODO(gman): Refactor to check semantics to distinguish between CUBE and
+ // VOLUME textures.
+ Texture::Ref texture;
+ if (temp_bitmaps.size() == 1) {
+ Bitmap* bitmap = temp_bitmaps[0].Get();
+ Texture2D::Ref texture_2d = renderer_->CreateTexture2D(
+ bitmap->width(),
+ bitmap->height(),
+ bitmap->format(),
+ bitmap->num_mipmaps(),
+ false);
+ if (!texture_2d.IsNull()) {
+ texture = Texture::Ref(texture_2d.Get());
+ texture_2d->SetFromBitmap(*bitmap);
+ }
+ } else if (temp_bitmaps.size() == 6) {
+ Bitmap* bitmap = temp_bitmaps[0].Get();
+ TextureCUBE::Ref texture_cube = renderer_->CreateTextureCUBE(
+ bitmap->width(),
+ bitmap->format(),
+ bitmap->num_mipmaps(),
+ false);
+ if (!texture_cube.IsNull()) {
+ texture = Texture::Ref(texture_cube.Get());
+ for (unsigned ii = 0; ii < 6; ++ii) {
+ texture_cube->SetFromBitmap(static_cast<TextureCUBE::CubeFace>(ii),
+ *temp_bitmaps[ii].Get());
+ }
+ }
+ }
if (!texture.IsNull()) {
+ // TODO(gman): remove this. Maybe set the name? or make uri an offical
+ // Texture param.
ParamString* param = texture->CreateParam<ParamString>(
O3D_STRING_CONSTANT("uri"));
DCHECK(param != NULL);
@@ -191,8 +245,8 @@ Texture* Pack::CreateTextureFromBitmap(Bitmap *bitmap, const String& uri) {
} else {
O3D_ERROR(service_locator())
<< "Unable to create texture (uri='" << uri
- << "', size=" << bitmap->width() << "x" << bitmap->height()
- << ", mips=" << bitmap->num_mipmaps()<< ")";
+ << "', size=" << width << "x" << height
+ << ", mips=" << temp_bitmaps[0]->num_mipmaps() << ")";
}
return texture.Get();
@@ -211,20 +265,18 @@ Texture* Pack::CreateTextureFromRawData(RawData *raw_data,
DLOG(INFO) << "CreateTextureFromRawData(uri='" << uri << "')";
-
- Bitmap::Ref bitmap(new Bitmap(service_locator()));
- if (!bitmap->LoadFromRawData(raw_data, image::UNKNOWN, generate_mips)) {
+ BitmapRefArray bitmap_refs;
+ if (!Bitmap::LoadFromRawData(raw_data, image::UNKNOWN, &bitmap_refs)) {
O3D_ERROR(service_locator())
<< "Failed to load bitmap from raw data \"" << uri << "\"";
return NULL;
}
- return CreateTextureFromBitmap(bitmap, uri);
+ return CreateTextureFromBitmaps(bitmap_refs, uri, generate_mips);
}
// Create a bitmap object.
-Bitmap* Pack::CreateBitmap(int width, int height,
- Texture::Format format) {
+Bitmap* Pack::CreateBitmap(int width, int height, Texture::Format format) {
DCHECK(image::CheckImageDimensions(width, height));
Bitmap::Ref bitmap(new Bitmap(service_locator()));
@@ -233,7 +285,7 @@ Bitmap* Pack::CreateBitmap(int width, int height,
<< "Failed to create bitmap object.";
return NULL;
}
- bitmap->Allocate(format, width, height, 1, false);
+ bitmap->Allocate(format, width, height, 1, Bitmap::IMAGE);
if (!bitmap->image_data()) {
O3D_ERROR(service_locator())
<< "Failed to allocate memory for bitmap.";
@@ -244,20 +296,18 @@ Bitmap* Pack::CreateBitmap(int width, int height,
}
// Create a new bitmap object from rawdata.
-Bitmap* Pack::CreateBitmapFromRawData(RawData* raw_data) {
- Bitmap::Ref bitmap(new Bitmap(service_locator()));
- if (bitmap.IsNull()) {
- O3D_ERROR(service_locator())
- << "Failed to create bitmap object.";
- return NULL;
- }
- if (!bitmap->LoadFromRawData(raw_data, image::UNKNOWN, false)) {
+std::vector<Bitmap*> Pack::CreateBitmapsFromRawData(RawData* raw_data) {
+ BitmapRefArray bitmap_refs;
+ if (!Bitmap::LoadFromRawData(raw_data, image::UNKNOWN, &bitmap_refs)) {
O3D_ERROR(service_locator())
<< "Failed to load bitmap from raw data.";
- return NULL;
}
- RegisterObject(bitmap);
- return bitmap.Get();
+ std::vector<Bitmap*> bitmaps(bitmap_refs.size(), NULL);
+ for (BitmapRefArray::size_type ii = 0; ii < bitmap_refs.size(); ++ii) {
+ RegisterObject(bitmap_refs[ii]);
+ bitmaps[ii] = bitmap_refs[ii].Get();
+ }
+ return bitmaps;
}
// Creates a Texture2D object and allocates the necessary resources for it.
diff --git a/o3d/core/cross/pack.h b/o3d/core/cross/pack.h
index 9ce91d6..753dce8 100644
--- a/o3d/core/cross/pack.h
+++ b/o3d/core/cross/pack.h
@@ -44,6 +44,7 @@
#include "core/cross/transform.h"
#include "core/cross/types.h"
#include "core/cross/image_utils.h"
+#include "core/cross/bitmap.h"
class FilePath;
@@ -227,12 +228,12 @@ class Pack : public NamedObject {
// A pointer to the bitmap obejct.
Bitmap* CreateBitmap(int width, int height, Texture::Format format);
- // Creates a new Bitmap object from RawData.
+ // Creates a new Bitmaps from RawData.
// Parameters:
// raw_data: contains the bitmap data in one of the know formats.
// Returns:
- // An array of pointers to the bitmap objects.
- Bitmap* CreateBitmapFromRawData(RawData* raw_data);
+ // bitmaps: A vector of pointers to bitmaps. If empty there was an error.
+ std::vector<Bitmap*> Pack::CreateBitmapsFromRawData(RawData* raw_data);
// Creates a new Texture2D object of the specified size and format and
// reserves the necessary resources for it.
@@ -428,7 +429,8 @@ class Pack : public NamedObject {
Renderer* renderer_;
// helper function
- Texture* CreateTextureFromBitmap(Bitmap *bitmap, const String& uri);
+ Texture* CreateTextureFromBitmaps(
+ const BitmapRefArray& bitmaps, const String& uri, bool generate_mips);
// The set of objects owned by the pack. This container contains all of the
// references that force the lifespan of the contained objects to match
diff --git a/o3d/core/cross/param_test.cc b/o3d/core/cross/param_test.cc
index 433c3d3..551655d 100644
--- a/o3d/core/cross/param_test.cc
+++ b/o3d/core/cross/param_test.cc
@@ -55,8 +55,7 @@ namespace {
class TestTexture : public Texture {
public:
explicit TestTexture(ServiceLocator* service_locator)
- : Texture(service_locator, UNKNOWN_FORMAT, 1, true, false,
- false) {}
+ : Texture(service_locator, UNKNOWN_FORMAT, 1, false) { }
void* GetTextureHandle() const { return NULL; }
virtual const RGBASwizzleIndices& GetABGR32FSwizzleIndices();
virtual void SetFromBitmap(const Bitmap& bitmap) {
diff --git a/o3d/core/cross/renderer.cc b/o3d/core/cross/renderer.cc
index 24c1e4a..48c9c05 100644
--- a/o3d/core/cross/renderer.cc
+++ b/o3d/core/cross/renderer.cc
@@ -310,15 +310,6 @@ void Renderer::SetViewport(const Float4& rectangle, const Float2& depth_range) {
depth_range[1]);
}
-Texture::Ref Renderer::CreateTextureFromBitmap(Bitmap* bitmap) {
- if (!IsSupportedTextureFormat(bitmap->format(),
- features_.Get(),
- service_locator())) {
- return Texture::Ref(NULL);
- }
- return CreatePlatformSpecificTextureFromBitmap(bitmap);
-}
-
Texture2D::Ref Renderer::CreateTexture2D(int width,
int height,
Texture::Format format,
diff --git a/o3d/core/cross/renderer.h b/o3d/core/cross/renderer.h
index d766b24..d07d10e 100644
--- a/o3d/core/cross/renderer.h
+++ b/o3d/core/cross/renderer.h
@@ -314,17 +314,6 @@ class Renderer {
// Frees a Param Cache.
void FreeParamCache(ParamCache* param_cache);
- // Attempts to create a Texture with the given bitmap, automatically
- // determining whether the to create a 2D texture, cube texture, etc. If
- // creation fails the method returns NULL.
- // Parameters:
- // bitmap: The bitmap specifying the dimensions, format and content of the
- // new texture. The created texture takes ownership of the bitmap
- // data.
- // Returns:
- // A ref-counted pointer to the texture or NULL if it did not load.
- Texture::Ref CreateTextureFromBitmap(Bitmap* bitmap);
-
// Creates and returns a platform specific Texture2D object. It allocates
// the necessary resources to store texture data for the given image size
// and format.
@@ -534,10 +523,6 @@ class Renderer {
// Creates a platform specific ParamCache.
virtual ParamCache* CreatePlatformSpecificParamCache() = 0;
- // Platform specific version of CreateTextureFromBitmap.
- virtual Texture::Ref CreatePlatformSpecificTextureFromBitmap(
- Bitmap* bitmap) = 0;
-
// Platform specific version of CreateTexture2D
virtual Texture2D::Ref CreatePlatformSpecificTexture2D(
int width,
diff --git a/o3d/core/cross/renderer_test.cc b/o3d/core/cross/renderer_test.cc
index 9982d12..e0b35d8 100644
--- a/o3d/core/cross/renderer_test.cc
+++ b/o3d/core/cross/renderer_test.cc
@@ -120,44 +120,6 @@ TEST_F(RendererTest, OffScreen) {
}
#endif
-// TODO: add InitAndDestroyGL and InitAndDestroyMock
-TEST_F(RendererTest, Creates2DTextureFromBitmap) {
- Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- bitmap->Allocate(Texture::ARGB8, 16, 32, 2, false);
- memset(bitmap->image_data(), 0x34, bitmap->GetTotalSize());
-
- Client client(g_service_locator);
- client.Init();
-
- Texture::Ref texture = g_renderer->CreateTextureFromBitmap(bitmap);
- ASSERT_TRUE(NULL != texture);
- EXPECT_EQ(Texture::ARGB8, texture->format());
- EXPECT_EQ(2, texture->levels());
-
- Texture2D::Ref texture2D(down_cast<Texture2D*>(texture.Get()));
- ASSERT_TRUE(NULL != texture2D);
- EXPECT_EQ(16, texture2D->width());
- EXPECT_EQ(32, texture2D->height());
-}
-
-TEST_F(RendererTest, CreatesCubeTextureFromBitmap) {
- Bitmap::Ref bitmap(new Bitmap(g_service_locator));
- bitmap->Allocate(Texture::ARGB8, 16, 16, 2, true);
- memset(bitmap->image_data(), 0x34, bitmap->GetTotalSize());
-
- Client client(g_service_locator);
- client.Init();
-
- Texture::Ref texture = g_renderer->CreateTextureFromBitmap(bitmap);
- ASSERT_TRUE(NULL != texture);
- EXPECT_EQ(Texture::ARGB8, texture->format());
- EXPECT_EQ(2, texture->levels());
-
- TextureCUBE::Ref textureCube(down_cast<TextureCUBE*>(texture.Get()));
- ASSERT_TRUE(NULL != textureCube);
- EXPECT_EQ(16, textureCube->edge_length());
-}
-
// Tests SetViewport
TEST_F(RendererTest, SetViewport) {
ErrorStatus error_status(g_service_locator);
diff --git a/o3d/core/cross/texture.cc b/o3d/core/cross/texture.cc
index 837817f..10e1289 100644
--- a/o3d/core/cross/texture.cc
+++ b/o3d/core/cross/texture.cc
@@ -57,11 +57,8 @@ Texture2D::Texture2D(ServiceLocator* service_locator,
int height,
Format format,
int levels,
- bool alpha_is_one,
- bool resize_to_pot,
bool enable_render_surfaces)
- : Texture(service_locator, format, levels, alpha_is_one,
- resize_to_pot, enable_render_surfaces),
+ : Texture(service_locator, format, levels, enable_render_surfaces),
locked_levels_(0) {
RegisterReadOnlyParamRef(kWidthParamName, &width_param_);
RegisterReadOnlyParamRef(kHeightParamName, &height_param_);
@@ -171,7 +168,7 @@ void Texture2D::SetFromBitmap(const Bitmap& bitmap) {
DCHECK(bitmap.image_data());
if (bitmap.width() != static_cast<unsigned>(width()) ||
bitmap.height() != static_cast<unsigned>(height()) ||
- bitmap.format() != format() || bitmap.is_cubemap()) {
+ bitmap.format() != format()) {
O3D_ERROR(service_locator())
<< "bitmap must be the same format and dimensions as texture";
return;
@@ -254,11 +251,8 @@ TextureCUBE::TextureCUBE(ServiceLocator* service_locator,
int edge_length,
Format format,
int levels,
- bool alpha_is_one,
- bool resize_to_pot,
bool enable_render_surfaces)
- : Texture(service_locator, format, levels, alpha_is_one,
- resize_to_pot, enable_render_surfaces) {
+ : Texture(service_locator, format, levels, enable_render_surfaces) {
for (unsigned int i = 0; i < 6; ++i) {
locked_levels_[i] = 0;
}
@@ -378,11 +372,11 @@ void TextureCUBE::DrawImage(const Bitmap& src_img,
mip_length, mip_length, components);
}
-void TextureCUBE::SetFromBitmap(const Bitmap& bitmap) {
+void TextureCUBE::SetFromBitmap(CubeFace face, const Bitmap& bitmap) {
DCHECK(bitmap.image_data());
if (bitmap.width() != static_cast<unsigned>(edge_length()) ||
bitmap.height() != static_cast<unsigned>(edge_length()) ||
- bitmap.format() != format() || !bitmap.is_cubemap()) {
+ bitmap.format() != format()) {
O3D_ERROR(service_locator())
<< "bitmap must be the same format and dimensions as texture";
return;
@@ -390,13 +384,11 @@ void TextureCUBE::SetFromBitmap(const Bitmap& bitmap) {
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));
- }
+ SetRect(face, level, 0, 0,
+ image::ComputeMipDimension(level, edge_length()),
+ image::ComputeMipDimension(level, edge_length()),
+ bitmap.GetMipData(level),
+ bitmap.GetMipPitch(level));
}
}
diff --git a/o3d/core/cross/texture.h b/o3d/core/cross/texture.h
index fdb1b2f..c16c884 100644
--- a/o3d/core/cross/texture.h
+++ b/o3d/core/cross/texture.h
@@ -88,8 +88,6 @@ class Texture2D : public Texture {
int height,
Format format,
int levels,
- bool alpha_is_one,
- bool resize_to_pot,
bool enable_render_surfaces);
virtual ~Texture2D();
@@ -147,9 +145,9 @@ class Texture2D : public Texture {
int dest_width, int dest_height, int dest_mip);
// Sets the contents of the texture from a Bitmap.
- virtual void SetFromBitmap(const Bitmap& bitmap);
+ void SetFromBitmap(const Bitmap& bitmap);
- // Generates mips.
+ // Overridden from Texture.
virtual void GenerateMips(int source_level, int num_levels);
protected:
@@ -250,8 +248,6 @@ class TextureCUBE : public Texture {
int edge_length,
Format format,
int levels,
- bool alpha_is_one,
- bool resize_to_pot,
bool enable_render_surfaces);
virtual ~TextureCUBE();
@@ -314,9 +310,9 @@ class TextureCUBE : public Texture {
int dest_height, CubeFace face, int dest_mip);
// Sets the contents of the texture from a Bitmap.
- virtual void SetFromBitmap(const Bitmap& bitmap);
+ void SetFromBitmap(CubeFace face, const Bitmap& bitmap);
- // Generates mips.
+ // Overridden from Texture.
virtual void GenerateMips(int source_level, int num_levels);
protected:
diff --git a/o3d/core/cross/texture_base.cc b/o3d/core/cross/texture_base.cc
index b416ae5..f9825fb 100644
--- a/o3d/core/cross/texture_base.cc
+++ b/o3d/core/cross/texture_base.cc
@@ -48,12 +48,9 @@ const char* Texture::kLevelsParamName =
Texture::Texture(ServiceLocator* service_locator,
Format format,
int levels,
- bool alpha_is_one,
- bool resize_to_pot,
bool enable_render_surfaces)
: ParamObject(service_locator),
- resize_to_pot_(resize_to_pot),
- alpha_is_one_(alpha_is_one),
+ alpha_is_one_(false),
format_(format),
weak_pointer_manager_(this),
render_surfaces_enabled_(enable_render_surfaces) {
diff --git a/o3d/core/cross/texture_base.h b/o3d/core/cross/texture_base.h
index b8649b9..1c40d55 100644
--- a/o3d/core/cross/texture_base.h
+++ b/o3d/core/cross/texture_base.h
@@ -79,8 +79,6 @@ class Texture : public ParamObject {
Texture(ServiceLocator* service_locator,
Format format,
int levels,
- bool alpha_is_one,
- bool resize_to_pot,
bool enable_render_surfaces);
virtual ~Texture() {}
@@ -114,9 +112,6 @@ 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;
@@ -138,11 +133,6 @@ class Texture : public ParamObject {
format_ = format;
}
- // Whether or not to resize NPOT textures to POT when passing to the
- // underlying graphics API. This should only be true in the if the texture
- // is not POT and if it is not compressed.
- bool resize_to_pot_;
-
static void RegisterSurface(RenderSurface* surface, Pack* pack);
private:
diff --git a/o3d/core/cross/texture_base_test.cc b/o3d/core/cross/texture_base_test.cc
index a7780d37..5f11c8f 100644
--- a/o3d/core/cross/texture_base_test.cc
+++ b/o3d/core/cross/texture_base_test.cc
@@ -49,11 +49,8 @@ class MockTexture : public Texture {
MockTexture(ServiceLocator* service_locator,
Texture::Format format,
int levels,
- bool alpha_is_one,
- bool resize_to_pot,
bool enable_render_surfaces)
- : Texture(service_locator, format, levels, alpha_is_one, resize_to_pot,
- enable_render_surfaces) {
+ : Texture(service_locator, format, levels, enable_render_surfaces) {
}
virtual const RGBASwizzleIndices& GetABGR32FSwizzleIndices() {
@@ -92,8 +89,6 @@ TEST_F(TextureTest, Basic) {
g_service_locator,
Texture::XRGB8,
1,
- false,
- false,
false));
ASSERT_TRUE(texture != NULL);
EXPECT_EQ(texture->format(), Texture::XRGB8);
diff --git a/o3d/core/win/d3d9/renderer_d3d9.cc b/o3d/core/win/d3d9/renderer_d3d9.cc
index 035f615..29142eb 100644
--- a/o3d/core/win/d3d9/renderer_d3d9.cc
+++ b/o3d/core/win/d3d9/renderer_d3d9.cc
@@ -1606,30 +1606,6 @@ ParamCache* RendererD3D9::CreatePlatformSpecificParamCache() {
return new ParamCacheD3D9(service_locator());
}
-// Attempts to create a Texture with the given bitmap, automatically
-// determining whether the to create a 2D texture, cube texture, etc. If
-// creation fails the method returns NULL.
-// Parameters:
-// bitmap: The bitmap specifying the dimensions, format and content of the
-// new texture. The created texture takes ownership of the bitmap
-// data.
-// Returns:
-// A ref-counted pointer to the texture or NULL if it did not load.
-Texture::Ref RendererD3D9::CreatePlatformSpecificTextureFromBitmap(
- Bitmap* bitmap) {
- if (bitmap->is_cubemap()) {
- return Texture::Ref(TextureCUBED3D9::Create(service_locator(),
- bitmap,
- this,
- false));
- } else {
- return Texture::Ref(Texture2DD3D9::Create(service_locator(),
- bitmap,
- this,
- false));
- }
-}
-
// Attempts to create a Texture2D with the given specs. If creation fails
// then the method returns NULL.
Texture2D::Ref RendererD3D9::CreatePlatformSpecificTexture2D(
@@ -1638,32 +1614,26 @@ Texture2D::Ref RendererD3D9::CreatePlatformSpecificTexture2D(
Texture::Format format,
int levels,
bool enable_render_surfaces) {
- Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
- bitmap->set_format(format);
- bitmap->set_width(width);
- bitmap->set_height(height);
- bitmap->set_num_mipmaps(levels);
return Texture2D::Ref(Texture2DD3D9::Create(service_locator(),
- bitmap,
+ format,
+ levels,
+ width,
+ height,
this,
enable_render_surfaces));
}
-// Attempts to create a Texture2D with the given specs. If creation fails
+// Attempts to create a TextureCUBE with the given specs. If creation fails
// then the method returns NULL.
TextureCUBE::Ref RendererD3D9::CreatePlatformSpecificTextureCUBE(
int edge_length,
Texture::Format format,
int levels,
bool enable_render_surfaces) {
- Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
- bitmap->set_format(format);
- bitmap->set_width(edge_length);
- bitmap->set_height(edge_length);
- bitmap->set_num_mipmaps(levels);
- bitmap->set_is_cubemap(true);
return TextureCUBE::Ref(TextureCUBED3D9::Create(service_locator(),
- bitmap,
+ format,
+ levels,
+ edge_length,
this,
enable_render_surfaces));
}
@@ -1744,7 +1714,7 @@ Bitmap::Ref RendererD3D9::TakeScreenshot() {
surface_description.Width,
surface_description.Height,
1,
- false);
+ Bitmap::IMAGE);
bitmap->SetRect(0, 0, 0,
surface_description.Width,
surface_description.Height,
diff --git a/o3d/core/win/d3d9/renderer_d3d9.h b/o3d/core/win/d3d9/renderer_d3d9.h
index f81a6c7..7d6f9bb 100644
--- a/o3d/core/win/d3d9/renderer_d3d9.h
+++ b/o3d/core/win/d3d9/renderer_d3d9.h
@@ -194,9 +194,6 @@ class RendererD3D9 : public Renderer {
float max_z);
// Overridden from Renderer.
- virtual Texture::Ref CreatePlatformSpecificTextureFromBitmap(Bitmap* bitmap);
-
- // Overridden from Renderer.
virtual Texture2D::Ref CreatePlatformSpecificTexture2D(
int width,
int height,
diff --git a/o3d/core/win/d3d9/texture_d3d9.cc b/o3d/core/win/d3d9/texture_d3d9.cc
index 5c93f7b..13c3d3b 100644
--- a/o3d/core/win/d3d9/texture_d3d9.cc
+++ b/o3d/core/win/d3d9/texture_d3d9.cc
@@ -82,20 +82,23 @@ static D3DCUBEMAP_FACES DX9CubeFace(TextureCUBE::CubeFace face) {
return D3DCUBEMAP_FACE_FORCE_DWORD;
}
-// Constructs an Direct3D texture object. Out variable return the status of
+// Constructs an Direct3D texture object. Out variable returns the status of
// the constructed texture including if resize to POT is required, and the
// actual mip dimensions used.
HRESULT CreateTexture2DD3D9(RendererD3D9* renderer,
- Bitmap* bitmap,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
bool enable_render_surfaces,
bool* resize_to_pot,
unsigned int* mip_width,
unsigned int* mip_height,
IDirect3DTexture9** d3d_texture) {
IDirect3DDevice9 *d3d_device = renderer->d3d_device();
- *resize_to_pot = !renderer->supports_npot() && !bitmap->IsPOT();
- *mip_width = bitmap->width();
- *mip_height = bitmap->height();
+ *resize_to_pot = !renderer->supports_npot() && !image::IsPOT(width, height);
+ *mip_width = width;
+ *mip_height = height;
if (*resize_to_pot) {
*mip_width = image::ComputePOTSize(*mip_width);
@@ -104,56 +107,59 @@ HRESULT CreateTexture2DD3D9(RendererD3D9* renderer,
DWORD usage = (enable_render_surfaces) ? D3DUSAGE_RENDERTARGET : 0;
D3DPOOL pool = (enable_render_surfaces) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
- D3DFORMAT format = DX9Format(bitmap->format());
+ D3DFORMAT d3d_format = DX9Format(format);
HRESULT tex_result = d3d_device->CreateTexture(*mip_width,
*mip_height,
- bitmap->num_mipmaps(),
+ levels,
usage,
- format,
+ d3d_format,
pool,
d3d_texture,
NULL);
if (!HR(tex_result)) {
DLOG(ERROR) << "2D texture creation failed with the following parameters: "
<< "(" << *mip_width << " x " << *mip_height << ") x "
- << bitmap->num_mipmaps() << "; format = " << format;
+ << levels << "; format = " << format;
}
return tex_result;
}
-// Constructs an Direct3D cube texture object. Out variable return the
+// Constructs an Direct3D cube texture object. Out variable returns the
// status of the constructed texture including if resize to POT is required,
// and the actual mip edge length used.
HRESULT CreateTextureCUBED3D9(RendererD3D9* renderer,
- Bitmap* bitmap,
+ int edge_length,
+ Texture::Format format,
+ int levels,
bool enable_render_surfaces,
bool* resize_to_pot,
unsigned int* edge_width,
IDirect3DCubeTexture9** d3d_texture) {
IDirect3DDevice9 *d3d_device = renderer->d3d_device();
- *resize_to_pot = !renderer->supports_npot() && !bitmap->IsPOT();
- *edge_width = bitmap->width();
+ *resize_to_pot = !renderer->supports_npot() &&
+ !image::IsPOT(edge_length, edge_length);
+ *edge_width = edge_length;
if (*resize_to_pot) {
*edge_width = image::ComputePOTSize(*edge_width);
}
DWORD usage = (enable_render_surfaces) ? D3DUSAGE_RENDERTARGET : 0;
D3DPOOL pool = (enable_render_surfaces) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
- D3DFORMAT format = DX9Format(bitmap->format());
+ D3DFORMAT d3d_format = DX9Format(format);
HRESULT tex_result = d3d_device->CreateCubeTexture(*edge_width,
- bitmap->num_mipmaps(),
+ levels,
usage,
- format,
+ d3d_format,
pool,
d3d_texture,
NULL);
if (!HR(tex_result)) {
DLOG(ERROR) << "CUBE texture creation failed with the following "
<< "parameters: "
- << "(" << edge_width << " x " << edge_width << ") x "
- << bitmap->num_mipmaps() << "; format = " << format;
+ << "(" << *edge_width << " x " << *edge_width << ") x "
+ << levels << "; format = " << format;
}
return tex_result;
@@ -329,17 +335,19 @@ void SetTextureFaceRect(
// Constructs a 2D texture object from the given (existing) D3D 2D texture.
Texture2DD3D9::Texture2DD3D9(ServiceLocator* service_locator,
IDirect3DTexture9* tex,
- const Bitmap &bitmap,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
bool resize_to_pot,
bool enable_render_surfaces)
: Texture2D(service_locator,
- bitmap.width(),
- bitmap.height(),
- bitmap.format(),
- bitmap.num_mipmaps(),
- bitmap.CheckAlphaIsOne(),
- resize_to_pot,
+ width,
+ height,
+ format,
+ levels,
enable_render_surfaces),
+ resize_to_pot_(resize_to_pot),
d3d_texture_(tex),
backing_bitmap_(Bitmap::Ref(new Bitmap(service_locator))) {
DCHECK(tex);
@@ -350,16 +358,21 @@ Texture2DD3D9::Texture2DD3D9(ServiceLocator* service_locator,
// returns it. This is the safe way to create a Texture2DD3D9 object that
// contains a valid D3D9 texture.
Texture2DD3D9* Texture2DD3D9::Create(ServiceLocator* service_locator,
- Bitmap* bitmap,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
RendererD3D9* renderer,
bool enable_render_surfaces) {
- DCHECK_NE(bitmap->format(), Texture::UNKNOWN_FORMAT);
- DCHECK(!bitmap->is_cubemap());
+ DCHECK_NE(format, Texture::UNKNOWN_FORMAT);
CComPtr<IDirect3DTexture9> d3d_texture;
bool resize_to_pot;
unsigned int mip_width, mip_height;
if (!HR(CreateTexture2DD3D9(renderer,
- bitmap,
+ format,
+ levels,
+ width,
+ height,
enable_render_surfaces,
&resize_to_pot,
&mip_width,
@@ -371,23 +384,14 @@ Texture2DD3D9* Texture2DD3D9::Create(ServiceLocator* service_locator,
Texture2DD3D9 *texture = new Texture2DD3D9(service_locator,
d3d_texture,
- *bitmap,
+ format,
+ levels,
+ width,
+ height,
resize_to_pot,
enable_render_surfaces);
-
- texture->backing_bitmap_->SetFrom(bitmap);
- if (texture->backing_bitmap_->image_data()) {
- for (unsigned int i = 0; i < bitmap->num_mipmaps(); ++i) {
- texture->UpdateBackedMipLevel(i);
- mip_width = std::max(1U, mip_width >> 1);
- mip_height = std::max(1U, mip_height >> 1);
- }
- if (!resize_to_pot)
- texture->backing_bitmap_->FreeData();
- } else {
- if (resize_to_pot) {
- texture->backing_bitmap_->AllocateData();
- }
+ if (resize_to_pot) {
+ texture->backing_bitmap_->AllocateData();
}
return texture;
@@ -637,7 +641,10 @@ bool Texture2DD3D9::OnResetDevice() {
bool resize_to_pot;
unsigned int mip_width, mip_height;
return HR(CreateTexture2DD3D9(renderer_d3d9,
- backing_bitmap_,
+ format(),
+ levels(),
+ width(),
+ height(),
render_surfaces_enabled(),
&resize_to_pot,
&mip_width,
@@ -654,36 +661,42 @@ const Texture::RGBASwizzleIndices& Texture2DD3D9::GetABGR32FSwizzleIndices() {
// Constructs a cube texture object from the given (existing) D3D Cube texture.
TextureCUBED3D9::TextureCUBED3D9(ServiceLocator* service_locator,
IDirect3DCubeTexture9* tex,
- const Bitmap& bitmap,
+ int edge_length,
+ Texture::Format format,
+ int levels,
bool resize_to_pot,
bool enable_render_surfaces)
: TextureCUBE(service_locator,
- bitmap.width(),
- bitmap.format(),
- bitmap.num_mipmaps(),
- bitmap.CheckAlphaIsOne(),
- resize_to_pot,
+ edge_length,
+ format,
+ levels,
enable_render_surfaces),
- d3d_cube_texture_(tex),
- backing_bitmap_(Bitmap::Ref(new Bitmap(service_locator))) {
+ resize_to_pot_(resize_to_pot),
+ d3d_cube_texture_(tex) {
+ for (int ii = 0; ii < static_cast<int>(NUMBER_OF_FACES); ++ii) {
+ backing_bitmaps_[ii] = Bitmap::Ref(new Bitmap(service_locator));
+ }
}
// Attempts to create a D3D9 CubeTexture with the given specs. If creation
// fails the method returns NULL. Otherwise, it wraps around the newly created
// texture a TextureCUBED3D9 object and returns a pointer to it.
TextureCUBED3D9* TextureCUBED3D9::Create(ServiceLocator* service_locator,
- Bitmap *bitmap,
+ Texture::Format format,
+ int levels,
+ int edge_length,
RendererD3D9 *renderer,
bool enable_render_surfaces) {
- DCHECK_NE(bitmap->format(), Texture::UNKNOWN_FORMAT);
- DCHECK(bitmap->is_cubemap());
- DCHECK_EQ(bitmap->width(), bitmap->height());
+ DCHECK_NE(format, Texture::UNKNOWN_FORMAT);
+ DCHECK_GE(levels, 1);
CComPtr<IDirect3DCubeTexture9> d3d_texture;
bool resize_to_pot;
unsigned int edge;
if (!HR(CreateTextureCUBED3D9(renderer,
- bitmap,
+ edge_length,
+ format,
+ levels,
enable_render_surfaces,
&resize_to_pot,
&edge,
@@ -694,24 +707,14 @@ TextureCUBED3D9* TextureCUBED3D9::Create(ServiceLocator* service_locator,
TextureCUBED3D9 *texture = new TextureCUBED3D9(service_locator,
d3d_texture,
- *bitmap,
+ edge_length,
+ format,
+ levels,
resize_to_pot,
enable_render_surfaces);
-
- texture->backing_bitmap_->SetFrom(bitmap);
- if (texture->backing_bitmap_->image_data()) {
- for (int face = 0; face < 6; ++face) {
- unsigned int mip_edge = edge;
- for (unsigned int i = 0; i < bitmap->num_mipmaps(); ++i) {
- texture->UpdateBackedMipLevel(static_cast<CubeFace>(face), i);
- mip_edge = std::max(1U, mip_edge >> 1);
- }
- }
- if (!resize_to_pot)
- texture->backing_bitmap_->FreeData();
- } else {
- if (resize_to_pot) {
- texture->backing_bitmap_->AllocateData();
+ if (resize_to_pot) {
+ for (int ii = 0; ii < static_cast<int>(NUMBER_OF_FACES); ++ii) {
+ texture->backing_bitmaps_[ii]->AllocateData();
}
}
@@ -735,13 +738,13 @@ TextureCUBED3D9::~TextureCUBED3D9() {
void TextureCUBED3D9::UpdateBackedMipLevel(TextureCUBE::CubeFace face,
unsigned int level) {
+ Bitmap* backing_bitmap = backing_bitmaps_[face].Get();
DCHECK_LT(level, static_cast<unsigned int>(levels()));
- DCHECK(backing_bitmap_->image_data());
- DCHECK(backing_bitmap_->is_cubemap());
- DCHECK_EQ(backing_bitmap_->width(), edge_length());
- DCHECK_EQ(backing_bitmap_->height(), edge_length());
- DCHECK_EQ(backing_bitmap_->format(), format());
- DCHECK_EQ(backing_bitmap_->num_mipmaps(), levels());
+ DCHECK(backing_bitmap->image_data());
+ DCHECK_EQ(backing_bitmap->width(), edge_length());
+ DCHECK_EQ(backing_bitmap->height(), edge_length());
+ DCHECK_EQ(backing_bitmap->format(), format());
+ DCHECK_EQ(backing_bitmap->num_mipmaps(), levels());
unsigned int mip_edge = std::max(1, edge_length() >> level);
unsigned int rect_edge = mip_edge;
@@ -762,7 +765,7 @@ void TextureCUBED3D9::UpdateBackedMipLevel(TextureCUBE::CubeFace face,
DCHECK(out_rect.pBits);
uint8* dst = static_cast<uint8*>(out_rect.pBits);
- const uint8 *mip_data = backing_bitmap_->GetFaceMipData(face, level);
+ const uint8 *mip_data = backing_bitmap->GetMipData(level);
if (resize_to_pot_) {
image::Scale(mip_edge, mip_edge, format(), mip_data,
rect_edge, rect_edge,
@@ -870,11 +873,12 @@ void TextureCUBED3D9::SetRect(TextureCUBE::CubeFace face,
}
if (resize_to_pot_) {
- DCHECK(backing_bitmap_->image_data());
+ Bitmap* backing_bitmap = backing_bitmaps_[face].Get();
+ DCHECK(backing_bitmap->image_data());
DCHECK(!compressed);
// We need to update the backing mipmap and then use that to update the
// texture.
- backing_bitmap_->SetFaceRect(face,
+ backing_bitmap->SetRect(
level, dst_left, dst_top, src_width, src_height, src_data, src_pitch);
UpdateBackedMipLevel(face, level);
} else {
@@ -916,8 +920,9 @@ bool TextureCUBED3D9::Lock(
return false;
}
if (resize_to_pot_) {
- DCHECK(backing_bitmap_->image_data());
- *texture_data = backing_bitmap_->GetFaceMipData(face, level);
+ Bitmap* backing_bitmap = backing_bitmaps_[face].Get();
+ DCHECK(backing_bitmap->image_data());
+ *texture_data = backing_bitmap->GetMipData(level);
unsigned int mip_width = image::ComputeMipDimension(level, edge_length());
unsigned int mip_height = mip_width;
*pitch = image::ComputePitch(format(), mip_width);
@@ -988,7 +993,9 @@ bool TextureCUBED3D9::OnResetDevice() {
bool resize_to_pot;
unsigned int mip_edge;
return HR(CreateTextureCUBED3D9(renderer_d3d9,
- backing_bitmap_,
+ edge_length(),
+ format(),
+ levels(),
render_surfaces_enabled(),
&resize_to_pot,
&mip_edge,
diff --git a/o3d/core/win/d3d9/texture_d3d9.h b/o3d/core/win/d3d9/texture_d3d9.h
index 5f10951..311f096 100644
--- a/o3d/core/win/d3d9/texture_d3d9.h
+++ b/o3d/core/win/d3d9/texture_d3d9.h
@@ -59,7 +59,10 @@ class Texture2DD3D9 : public Texture2D {
// creation fails then it returns NULL otherwise it returns a pointer to the
// newly created Texture object.
static Texture2DD3D9* Create(ServiceLocator* service_locator,
- Bitmap* bitmap,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
RendererD3D9* renderer,
bool enable_render_surfaces);
@@ -106,7 +109,10 @@ class Texture2DD3D9 : public Texture2D {
// Initializes the Texture2DD3D9 from a DX9 texture.
Texture2DD3D9(ServiceLocator* service_locator,
IDirect3DTexture9* tex,
- const Bitmap& bitmap,
+ Texture::Format format,
+ int levels,
+ int width,
+ int height,
bool resize_to_pot,
bool enable_render_surfaces);
@@ -114,6 +120,10 @@ class Texture2DD3D9 : public Texture2D {
// rescaling it if resize_to_pot_ is set.
void UpdateBackedMipLevel(unsigned int level);
+ // Whether or not this texture needs to be resized from NPOT to pot behind
+ // the scenes.
+ bool resize_to_pot_;
+
// A pointer to the Direct3D 2D texture object containing this texture.
CComPtr<IDirect3DTexture9> d3d_texture_;
@@ -132,7 +142,9 @@ class TextureCUBED3D9 : public TextureCUBE {
// creation fails then it returns NULL otherwise it returns a pointer to the
// newly created Texture object.
static TextureCUBED3D9* Create(ServiceLocator* service_locator,
- Bitmap* bitmap,
+ Texture::Format format,
+ int levels,
+ int edge_length,
RendererD3D9* renderer,
bool enable_render_surfaces);
@@ -183,10 +195,16 @@ class TextureCUBED3D9 : public TextureCUBE {
private:
TextureCUBED3D9(ServiceLocator* service_locator,
IDirect3DCubeTexture9* tex,
- const Bitmap& bitmap,
+ int edge_length,
+ Texture::Format format,
+ int levels,
bool resize_to_pot,
bool enable_render_surfaces);
+ // Whether or not this texture needs to be resized from NPOT to pot behind
+ // the scenes.
+ bool resize_to_pot_;
+
// Updates a mip level, sending it from the backing bitmap to Direct3D,
// rescaling it if resize_to_pot_ is set.
void UpdateBackedMipLevel(CubeFace face, unsigned int level);
@@ -194,8 +212,8 @@ class TextureCUBED3D9 : public TextureCUBE {
// A pointer to the Direct3D cube texture object containing this texture.
CComPtr<IDirect3DCubeTexture9> d3d_cube_texture_;
- // A bitmap used to back the NPOT textures on POT-only hardware.
- Bitmap::Ref backing_bitmap_;
+ // Bitmaps used to back the NPOT textures on POT-only hardware.
+ Bitmap::Ref backing_bitmaps_[NUMBER_OF_FACES];
DISALLOW_COPY_AND_ASSIGN(TextureCUBED3D9);
};
diff --git a/o3d/plugin/idl/bitmap.idl b/o3d/plugin/idl/bitmap.idl
index a223f43..76cca4c 100644
--- a/o3d/plugin/idl/bitmap.idl
+++ b/o3d/plugin/idl/bitmap.idl
@@ -34,15 +34,40 @@ 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.
+ including scale and crop. A Bitmap can be created from RawData via
+ pack.createBitmapsFromRawData(), and also can be transferred to mip of a
+ Texure2D or a specific face of TextureCUBE via methods in Texture.
%]
[nocpp, include="core/cross/bitmap.h"]
class Bitmap : ParamObject {
%[
+ After loading an array of Bitmaps with pack.createBitmapsFromRawData
+ you can inspect their semantic to see what they were intended for. This is
+ mostly to distinguish between 6 bitmaps that are faces of a cubemap and 6
+ bitmaps that are slices of a 3d texture.
+
+ \li FACE_POSITIVE_X, 1 face of a cubemap
+ \li FACE_NEGATIVE_X, 1 face of a cubemap
+ \li FACE_POSITIVE_Y, 1 face of a cubemap
+ \li FACE_NEGATIVE_Y, 1 face of a cubemap
+ \li FACE_POSITIVE_Z, 1 face of a cubemap
+ \li FACE_NEGATIVE_Z, 1 face of a cubemap
+ \li IMAGE, normal 2d image
+ \li SLICE, a slice of a 3d texture.
+ %]
+ enum Semantic {
+ FACE_POSITIVE_X,
+ FACE_NEGATIVE_X,
+ FACE_POSITIVE_Y,
+ FACE_NEGATIVE_Y,
+ FACE_POSITIVE_Z,
+ FACE_NEGATIVE_Z,
+ IMAGE,
+ SLICE
+ };
+
+ %[
Flips a bitmap vertically in place.
%]
void FlipVertically();
@@ -78,9 +103,9 @@ class Bitmap : ParamObject {
[getter] int num_mipmaps_;
%[
- Whether or not the bitmap is a cubemap.
+ The Semantic of the bitmap.
%]
- [getter] bool is_cubemap_;
+ [getter] Semantic semantic_;
}; // Bitmap
} // namespace o3d
diff --git a/o3d/plugin/idl/pack.idl b/o3d/plugin/idl/pack.idl
index a6a46aa..6880aed 100644
--- a/o3d/plugin/idl/pack.idl
+++ b/o3d/plugin/idl/pack.idl
@@ -322,8 +322,7 @@ typedef Bitmap[] BitmapArray;
\param raw_data contains the bitmap data in a supported format.
\return An Array of Bitmaps object.
%]
- //BitmapArray CreateBitmapsFromRawData(RawData raw_data);
- Bitmap CreateBitmapFromRawData(RawData raw_data);
+ BitmapArray CreateBitmapsFromRawData(RawData raw_data);
}; // Pack
} // namespace o3d
diff --git a/o3d/plugin/idl/texture.idl b/o3d/plugin/idl/texture.idl
index d74a386..dcaf4e7 100644
--- a/o3d/plugin/idl/texture.idl
+++ b/o3d/plugin/idl/texture.idl
@@ -115,21 +115,6 @@ namespace o3d {
%]
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
%[
@@ -238,6 +223,22 @@ namespace o3d {
int height);
%[
+ 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::Texture2D* self,
+ o3d::Bitmap* bitmap) {
+ self->SetFromBitmap(*bitmap);
+ }
+ %}
+
+ %[
Copy pixels from source bitmap to certain mip level.
Scales if the width and height of source and dest do not match.
@@ -294,12 +295,13 @@ namespace o3d {
The names of each of the six faces of a cube map texture.
%]
- enum CubeFace { FACE_POSITIVE_X,
- FACE_NEGATIVE_X,
- FACE_POSITIVE_Y,
- FACE_NEGATIVE_Y,
- FACE_POSITIVE_Z,
- FACE_NEGATIVE_Z };
+ enum CubeFace {
+ FACE_POSITIVE_X,
+ FACE_NEGATIVE_X,
+ FACE_POSITIVE_Y,
+ FACE_NEGATIVE_Y,
+ FACE_POSITIVE_Z,
+ FACE_NEGATIVE_Z };
%[
The length of each edge of the cube, in texels.
@@ -382,6 +384,24 @@ namespace o3d {
int height);
%[
+ Sets the content of a face of the texture to the content of the bitmap. The
+ texture and the bitmap must be the same dimensions and the same format.
+
+ \param face The face to set.
+ \param bitmap The bitmap to copy data from.
+ %]
+ [userglue]
+ void SetFromBitmap(CubeFace face, Bitmap bitmap);
+
+ [verbatim=cpp_glue] %{
+ void userglue_method_SetFromBitmap(o3d::TextureCUBE* self,
+ o3d::TextureCUBE::CubeFace face,
+ o3d::Bitmap* bitmap) {
+ self->SetFromBitmap(face, *bitmap);
+ }
+ %}
+
+ %[
Copy pixels from source bitmap to certain mip level.
Scales if the width and height of source and dest do not match.