diff options
author | gman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-06 04:53:24 +0000 |
---|---|---|
committer | gman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-06 04:53:24 +0000 |
commit | 132899b905b0f1794d7e82e28f9fe77ca6a08282 (patch) | |
tree | 47af391191ac78d3b4e02533f74e3575970cebcc /o3d/core/cross/texture.cc | |
parent | 22e037073118aaf90549410b32d66885d39b78a9 (diff) | |
download | chromium_src-132899b905b0f1794d7e82e28f9fe77ca6a08282.zip chromium_src-132899b905b0f1794d7e82e28f9fe77ca6a08282.tar.gz chromium_src-132899b905b0f1794d7e82e28f9fe77ca6a08282.tar.bz2 |
A step in exposing Bitmap to JavaScript.
The plan is to make pack.createBitmapFromRawData
return an array of bitmaps.
1 bitmap if it's a standard 2d image
6 bitmaps if it's a cubemap
N bitmaps if it's a volume map.
The bitmaps will have a semantic so you can look at them and tell
they were from a volumemap, a cubemap or a 2d image.
On the way I'm attempting to clean up the code. Moving
stuff out of Bitmap the did not belong there and
Refactoring Bitmap so there are less If Format =
stuff.
Review URL: http://codereview.chromium.org/164034
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22583 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/core/cross/texture.cc')
-rw-r--r-- | o3d/core/cross/texture.cc | 259 |
1 files changed, 196 insertions, 63 deletions
diff --git a/o3d/core/cross/texture.cc b/o3d/core/cross/texture.cc index 8f71fd8..2ef6c54 100644 --- a/o3d/core/cross/texture.cc +++ b/o3d/core/cross/texture.cc @@ -33,6 +33,7 @@ // This file contains the definition of the Texture2D and TextureCUBE classes. #include "core/cross/precompile.h" +#include <cmath> #include "core/cross/texture.h" #include "core/cross/bitmap.h" #include "core/cross/renderer.h" @@ -70,7 +71,8 @@ Texture2D::Texture2D(ServiceLocator* service_locator, ClientInfoManager* client_info_manager = service_locator->GetService<ClientInfoManager>(); client_info_manager->AdjustTextureMemoryUsed( - static_cast<int>(Bitmap::GetMipChainSize(width, height, format, levels))); + static_cast<int>(image::ComputeMipChainSize( + width, height, format, levels))); } Texture2D::~Texture2D() { @@ -83,18 +85,22 @@ Texture2D::~Texture2D() { ClientInfoManager* client_info_manager = service_locator()->GetService<ClientInfoManager>(); client_info_manager->AdjustTextureMemoryUsed( - -static_cast<int>(Bitmap::GetMipChainSize(width(), - height(), - format(), - levels()))); + -static_cast<int>(image::ComputeMipChainSize(width(), + height(), + format(), + levels()))); } -void Texture2D::DrawImage(Bitmap* src_img, +void Texture2D::DrawImage(const Bitmap& src_img, int src_x, int src_y, int src_width, int src_height, int dst_x, int dst_y, int dst_width, int dst_height, int dest_mip) { - DCHECK(src_img->image_data()); + DCHECK(src_img.image_data()); + + if (dest_mip < 0 || dest_mip >= levels()) { + O3D_ERROR(service_locator()) << "Mip out of range"; + } unsigned int mip_width = std::max(1, width() >> dest_mip); unsigned int mip_height = std::max(1, height() >> dest_mip); @@ -103,18 +109,19 @@ void Texture2D::DrawImage(Bitmap* src_img, // source and destination bitmaps. // if src or dest rectangle is out of boundary, // do nothing and return. - if (!Bitmap::AdjustDrawImageBoundary(&src_x, &src_y, - &src_width, &src_height, - src_img->width(), src_img->height(), - &dst_x, &dst_y, - &dst_width, &dst_height, - mip_width, mip_height)) + if (!image::AdjustDrawImageBoundary(&src_x, &src_y, + &src_width, &src_height, + src_img.width(), src_img.height(), + &dst_x, &dst_y, + &dst_width, &dst_height, + mip_width, mip_height)) { return; + } unsigned int components = 0; // check formats of source and dest images. // format of source and dest should be the same. - if (src_img->format() != format()) { + if (src_img.format() != format()) { O3D_ERROR(service_locator()) << "DrawImage does not support " << "different formats."; return; @@ -122,22 +129,22 @@ void Texture2D::DrawImage(Bitmap* src_img, // if src and dest are in the same size and drawImage is copying // the entire bitmap on dest image, just perform memcpy. if (src_x == 0 && src_y == 0 && dst_x == 0 && dst_y == 0 && - src_img->width() == mip_width && src_img->height() == mip_height && - static_cast<unsigned int>(src_width) == src_img->width() && - static_cast<unsigned int>(src_height) == src_img->height() && + src_img.width() == mip_width && src_img.height() == mip_height && + static_cast<unsigned int>(src_width) == src_img.width() && + static_cast<unsigned int>(src_height) == src_img.height() && static_cast<unsigned int>(dst_width) == mip_width && static_cast<unsigned int>(dst_height) == mip_height) { SetRect(dest_mip, 0, 0, mip_width, mip_height, - src_img->image_data(), - Bitmap::GetMipChainSize(src_img->width(), 1, format(), 1)); + src_img.image_data(), + src_img.GetMipPitch(0)); return; } - if (src_img->format() == Texture::XRGB8 || - src_img->format() == Texture::ARGB8) { + if (src_img.format() == Texture::XRGB8 || + src_img.format() == Texture::ARGB8) { components = 4; } else { O3D_ERROR(service_locator()) << "DrawImage does not support format: " - << src_img->format() << " unless src and " + << src_img.format() << " unless src and " << "dest images are in the same size and " << "copying the entire bitmap"; return; @@ -149,15 +156,69 @@ void Texture2D::DrawImage(Bitmap* src_img, return; } - uint8* src_img_data = src_img->image_data(); + uint8* src_img_data = src_img.image_data(); + + image::LanczosScale(src_img_data, src_x, src_y, + src_width, src_height, + src_img.width(), src_img.height(), + mip_data, helper.pitch(), + dst_x, dst_y, + dst_width, dst_height, + mip_width, mip_height, components); +} + +void Texture2D::SetFromBitmap(const Bitmap& bitmap) { + DCHECK(bitmap.image_data()); + if (bitmap.width() != width() || bitmap.height() != height() || + bitmap.format() != format() || bitmap.is_cubemap()) { + O3D_ERROR(service_locator()) + << "bitmap must be the same format and dimensions as texture"; + return; + } + + int last_level = std::min<int>(bitmap.num_mipmaps(), levels()); + for (int level = 0; level < last_level; ++level) { + SetRect(level, 0, 0, + image::ComputeMipDimension(level, width()), + image::ComputeMipDimension(level, height()), + bitmap.GetMipData(level), + bitmap.GetMipPitch(level)); + } +} - Bitmap::LanczosScale(src_img_data, src_x, src_y, - src_width, src_height, - src_img->width(), src_img->height(), - mip_data, helper.pitch(), - dst_x, dst_y, - dst_width, dst_height, - mip_width, mip_height, components); +void Texture2D::GenerateMips(int source_level, int num_levels) { + if (source_level < 0 || source_level >= levels()) { + O3D_ERROR(service_locator()) << "source level out of range"; + return; + } + if (source_level + num_levels >= levels()) { + O3D_ERROR(service_locator()) << "num levels out of range"; + return; + } + + for (int ii = 0; ii < num_levels; ++ii) { + int level = source_level + ii; + Texture2D::LockHelper src_helper(this, level); + Texture2D::LockHelper dst_helper(this, level + 1); + const uint8* src_data = src_helper.GetDataAs<const uint8>(); + if (!src_data) { + O3D_ERROR(service_locator()) + << "could not lock source texture."; + return; + } + uint8* dst_data = dst_helper.GetDataAs<uint8>(); + if (!dst_data) { + O3D_ERROR(service_locator()) + << "could not lock destination texture."; + return; + } + + unsigned int src_width = image::ComputeMipDimension(level, width()); + unsigned int src_height = image::ComputeMipDimension(level, height()); + image::GenerateMipmap(src_width, src_height, format(), + src_data, src_helper.pitch(), + dst_data, dst_helper.pitch()); + } } ObjectBase::Ref Texture2D::Create(ServiceLocator* service_locator) { @@ -206,10 +267,10 @@ TextureCUBE::TextureCUBE(ServiceLocator* service_locator, ClientInfoManager* client_info_manager = service_locator->GetService<ClientInfoManager>(); client_info_manager->AdjustTextureMemoryUsed( - static_cast<int>(Bitmap::GetMipChainSize(edge_length, - edge_length, - format, - levels)) * 6); + static_cast<int>(image::ComputeMipChainSize(edge_length, + edge_length, + format, + levels)) * 6); } TextureCUBE::~TextureCUBE() { @@ -225,23 +286,32 @@ TextureCUBE::~TextureCUBE() { ClientInfoManager* client_info_manager = service_locator()->GetService<ClientInfoManager>(); client_info_manager->AdjustTextureMemoryUsed( - -static_cast<int>(Bitmap::GetMipChainSize(edge_length(), - edge_length(), - format(), - levels()) * 6)); + -static_cast<int>(image::ComputeMipChainSize(edge_length(), + edge_length(), + format(), + levels()) * 6)); } ObjectBase::Ref TextureCUBE::Create(ServiceLocator* service_locator) { return ObjectBase::Ref(); } -void TextureCUBE::DrawImage(Bitmap* src_img, +void TextureCUBE::DrawImage(const Bitmap& src_img, int src_x, int src_y, int src_width, int src_height, int dst_x, int dst_y, int dst_width, int dst_height, CubeFace dest_face, int dest_mip) { - DCHECK(src_img->image_data()); + DCHECK(src_img.image_data()); + + if (dest_face >= NUMBER_OF_FACES) { + O3D_ERROR(service_locator()) << "Invalid face specification"; + return; + } + + if (dest_mip < 0 || dest_mip >= levels()) { + O3D_ERROR(service_locator()) << "Mip out of range"; + } unsigned int mip_length = std::max(1, edge_length() >> dest_mip); @@ -249,18 +319,19 @@ void TextureCUBE::DrawImage(Bitmap* src_img, // source and destination bitmaps. // if src or dest rectangle is out of boundary, // do nothing and return true. - if (!Bitmap::AdjustDrawImageBoundary(&src_x, &src_y, - &src_width, &src_height, - src_img->width(), src_img->height(), - &dst_x, &dst_y, - &dst_width, &dst_height, - mip_length, mip_length)) + if (!image::AdjustDrawImageBoundary(&src_x, &src_y, + &src_width, &src_height, + src_img.width(), src_img.height(), + &dst_x, &dst_y, + &dst_width, &dst_height, + mip_length, mip_length)) { return; + } unsigned int components = 0; // check formats of source and dest images. // format of source and dest should be the same. - if (src_img->format() != format()) { + if (src_img.format() != format()) { O3D_ERROR(service_locator()) << "DrawImage does not support " << "different formats."; return; @@ -268,22 +339,22 @@ void TextureCUBE::DrawImage(Bitmap* src_img, // if src and dest are in the same size and drawImage is copying // the entire bitmap on dest image, just perform memcpy. if (src_x == 0 && src_y == 0 && dst_x == 0 && dst_y == 0 && - src_img->width() == mip_length && src_img->height() == mip_length && - static_cast<unsigned int>(src_width) == src_img->width() && - static_cast<unsigned int>(src_height) == src_img->height() && + src_img.width() == mip_length && src_img.height() == mip_length && + static_cast<unsigned int>(src_width) == src_img.width() && + static_cast<unsigned int>(src_height) == src_img.height() && static_cast<unsigned int>(dst_width) == mip_length && static_cast<unsigned int>(dst_height) == mip_length) { SetRect(dest_face, dest_mip, 0, 0, mip_length, mip_length, - src_img->image_data(), - Bitmap::GetMipChainSize(src_img->width(), 1, format(), 1)); + src_img.image_data(), + src_img.GetMipPitch(0)); return; } - if (src_img->format() == Texture::XRGB8 || - src_img->format() == Texture::ARGB8) { + if (src_img.format() == Texture::XRGB8 || + src_img.format() == Texture::ARGB8) { components = 4; } else { O3D_ERROR(service_locator()) << "DrawImage does not support format: " - << src_img->format() << " unless src and " + << src_img.format() << " unless src and " << "dest images are in the same size and " << "copying the entire bitmap"; return; @@ -295,15 +366,77 @@ void TextureCUBE::DrawImage(Bitmap* src_img, return; } - uint8* src_img_data = src_img->image_data(); + uint8* src_img_data = src_img.image_data(); + + image::LanczosScale(src_img_data, src_x, src_y, + src_width, src_height, + src_img.width(), src_img.height(), + mip_data, helper.pitch(), + dst_x, dst_y, + dst_width, dst_height, + mip_length, mip_length, components); +} + +void TextureCUBE::SetFromBitmap(const Bitmap& bitmap) { + DCHECK(bitmap.image_data()); + if (bitmap.width() != edge_length() || bitmap.height() != edge_length() || + bitmap.format() != format() || !bitmap.is_cubemap()) { + O3D_ERROR(service_locator()) + << "bitmap must be the same format and dimensions as texture"; + return; + } - Bitmap::LanczosScale(src_img_data, src_x, src_y, - src_width, src_height, - src_img->width(), src_img->height(), - mip_data, helper.pitch(), - dst_x, dst_y, - dst_width, dst_height, - mip_length, mip_length, components); + int last_level = std::min<int>(bitmap.num_mipmaps(), levels()); + for (int level = 0; level < last_level; ++level) { + for (int face = FACE_POSITIVE_X; face < NUMBER_OF_FACES; ++face) { + SetRect(static_cast<CubeFace>(face), level, 0, 0, + image::ComputeMipDimension(level, edge_length()), + image::ComputeMipDimension(level, edge_length()), + bitmap.GetFaceMipData(static_cast<CubeFace>(face), level), + bitmap.GetMipPitch(level)); + } + } +} + +void TextureCUBE::GenerateMips(int source_level, int num_levels) { + if (source_level < 0 || source_level >= levels()) { + O3D_ERROR(service_locator()) << "source level out of range"; + return; + } + if (source_level + num_levels >= levels()) { + O3D_ERROR(service_locator()) << "num levels out of range"; + return; + } + + for (int face = FACE_POSITIVE_X; face < NUMBER_OF_FACES; ++face) { + for (int ii = 0; ii < num_levels; ++ii) { + int level = source_level + ii; + TextureCUBE::LockHelper src_helper( + this, static_cast<TextureCUBE::CubeFace>(face), level); + TextureCUBE::LockHelper dst_helper( + this, static_cast<TextureCUBE::CubeFace>(face), level + 1); + const uint8* src_data = src_helper.GetDataAs<const uint8>(); + if (!src_data) { + O3D_ERROR(service_locator()) + << "could not lock source texture."; + return; + } + uint8* dst_data = dst_helper.GetDataAs<uint8>(); + if (!dst_data) { + O3D_ERROR(service_locator()) + << "could not lock destination texture."; + return; + } + + unsigned int src_edge_length = + std::max<unsigned int>(1U, edge_length() >> level); + + image::GenerateMipmap( + src_edge_length, src_edge_length, format(), + src_data, src_helper.pitch(), + dst_data, dst_helper.pitch()); + } + } } TextureCUBE::LockHelper::LockHelper( |