summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authorgman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-11 18:12:50 +0000
committergman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-11 18:12:50 +0000
commited97932b6ec58d01baea6948d5506503247f2986 (patch)
tree19ae1cfc4de8ce29ba75ab0386d1f56a1bacf57a /o3d
parentf963b1d5006ed35450befe042bf58810d9d36bea (diff)
downloadchromium_src-ed97932b6ec58d01baea6948d5506503247f2986.zip
chromium_src-ed97932b6ec58d01baea6948d5506503247f2986.tar.gz
chromium_src-ed97932b6ec58d01baea6948d5506503247f2986.tar.bz2
Changes to Bitmap before exposing to JavaScript
This CL changes Bitmap to no longer be a cubemap. Instead there is a function, Pack::CreateBitmapsFromRawData that returns an array of bitmaps. For a 2D image 1 bitmap is returned For a cubemap 6 bitmaps are returned eventually for a volumemap N bitmaps will be returned. To distinguish between 6 bitmaps that are a cubemap and 6 bitmaps that are slices of a volumemap there is a Bitmap::semantic which tells what the bitmap is intended for. In a previous CL I had started to break Bitmap into classes like Bitmap8, BitmapFloat, BitmapDXT1. These were not intended to be exposed to JavaScript, only to make the internal code get rid of lots of if format == or case(format) stuff. But given that it's working as is and there are more pressing things I'm not planning to do that right now. I can delete the classes if you think I should. Note: This is still not 100% done. I still need to deal with the flipping issues or at least test. I probably need to add more tests as well. I also got rid of any mention of resize_to_pot in the command buffer version. Client side command buffer should not have to deal with POT/NPOT issues. I also moved the pot/npot stuff out of generic code and into the platform specific code. The generic code is not supposed to care. This is slower than the old way but it feels cleaner. A few issues I'm looking for input on. There's a function, Bitmap::GenerateMips(source_level, num_levels). It generates mips as long as they 8Bit textures. I can easily add half and float but not DXT. Right now if you call it on DXT in debug it prints a LOG message but otherwise it does nothing. Should I error for DXT? On the one hand it would be good to know that it failed so a user will not be wondering "I called it, why are there no mips?" On the otherhand, from JavaScript failing would mean you'd need to check the format before calling it which also seems less then ideal. The other is that currently it doesn't ADD mips, it just replaces the ones that are there. That means if you load a 2d image and want mips you have to allocate a new bitmap with the number of mips you want, copy level 0 from the old bitmap to the new bitmap and then generate mips Should I make generate mips effectively do that for you? Basically, if you call it to generate mips on levels that don't yet exist in the bitmap it would realloc itself and then generate them. Is that better? Also, I started down the path of taking out alpha_is_one. I'm trying to decide what to do with it. Part of me wants to take it out completely but since it's already there maybe I can't. If I leave it in I was thinking of making it check every time it's called. First I'd just make it slow. Then later if we want I could add a dirty flag and only recheck when it's dirty. That would be a lot of work though. It would mean wrapping Lock and SetRect and maybe a few other things so that we could catch any writes to the texture. It might also mean changing Lock to take read/write flags. I think those are good changes but again, it's not important right now. So, the question is what to do now. I can 1) Remove alpha_is_one. That might break something out there 2) Leave it in but just have it always false. 3) Make it check every time it's accessed. 4) Do the dirty flag thing. Preference? I'm for 2 or 3 I think. Review URL: http://codereview.chromium.org/164235 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23051 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-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.