diff options
Diffstat (limited to 'o3d/core/cross/texture.cc')
-rw-r--r-- | o3d/core/cross/texture.cc | 230 |
1 files changed, 194 insertions, 36 deletions
diff --git a/o3d/core/cross/texture.cc b/o3d/core/cross/texture.cc index 10e1289..560eb6c 100644 --- a/o3d/core/cross/texture.cc +++ b/o3d/core/cross/texture.cc @@ -36,6 +36,7 @@ #include <cmath> #include "core/cross/texture.h" #include "core/cross/bitmap.h" +#include "core/cross/canvas.h" #include "core/cross/renderer.h" #include "core/cross/client_info.h" #include "core/cross/error.h" @@ -89,18 +90,21 @@ Texture2D::~Texture2D() { } void Texture2D::DrawImage(const Bitmap& src_img, + int src_mip, int src_x, int src_y, int src_width, int src_height, + int dst_mip, int dst_x, int dst_y, - int dst_width, int dst_height, int dest_mip) { + int dst_width, int dst_height) { DCHECK(src_img.image_data()); - if (dest_mip < 0 || dest_mip >= levels()) { + if (dst_mip < 0 || dst_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); + if (src_mip < 0 || src_mip >= src_img.num_mipmaps()) { + O3D_ERROR(service_locator()) << "Source Mip out of range"; + } // Clip source and destination rectangles to // source and destination bitmaps. @@ -108,21 +112,25 @@ void Texture2D::DrawImage(const Bitmap& src_img, // do nothing and return. if (!image::AdjustDrawImageBoundary(&src_x, &src_y, &src_width, &src_height, + src_mip, src_img.width(), src_img.height(), &dst_x, &dst_y, &dst_width, &dst_height, - mip_width, mip_height)) { + dst_mip, + width(), height())) { return; } - unsigned int components = 0; // check formats of source and dest images. // format of source and dest should be the same. if (src_img.format() != format()) { - O3D_ERROR(service_locator()) << "DrawImage does not support " - << "different formats."; + O3D_ERROR(service_locator()) << "formats must be the same."; return; } + + unsigned int mip_width = image::ComputeMipDimension(dst_mip, width()); + unsigned int mip_height = image::ComputeMipDimension(dst_mip, height()); + // 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 && @@ -131,15 +139,14 @@ void Texture2D::DrawImage(const Bitmap& src_img, 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(), - src_img.GetMipPitch(0)); + SetRect(dst_mip, 0, 0, mip_width, mip_height, + src_img.GetMipData(src_mip), + src_img.GetMipPitch(src_mip)); return; } - if (src_img.format() == Texture::XRGB8 || - src_img.format() == Texture::ARGB8) { - components = 4; - } else { + + unsigned int components = image::GetNumComponentsForFormat(format()); + if (components == 0) { O3D_ERROR(service_locator()) << "DrawImage does not support format: " << src_img.format() << " unless src and " << "dest images are in the same size and " @@ -147,21 +154,93 @@ void Texture2D::DrawImage(const Bitmap& src_img, return; } - LockHelper helper(this, dest_mip); + int src_pitch = src_img.GetMipPitch(src_mip); + if (image::AdjustForSetRect(&src_y, src_width, src_height, &src_pitch, + &dst_y, dst_width, &dst_height)) { + SetRect(dst_mip, dst_x, dst_y, dst_width, dst_height, + src_img.GetPixelData(src_mip, src_x, src_y), + src_pitch); + return; + } + + LockHelper helper(this, dst_mip); uint8* mip_data = helper.GetDataAs<uint8>(); if (!mip_data) { return; } - uint8* src_img_data = src_img.image_data(); + image::LanczosScale(src_img.format(), + src_img.GetMipData(src_mip), + src_img.GetMipPitch(src_mip), + src_x, src_y, + src_width, src_height, + mip_data, helper.pitch(), + dst_x, dst_y, + dst_width, dst_height, + components); +} + +void Texture2D::DrawImage(const Canvas& src_img, + int src_x, int src_y, + int src_width, int src_height, + int dst_mip, + int dst_x, int dst_y, + int dst_width, int dst_height) { + if (dst_mip < 0 || dst_mip >= levels()) { + O3D_ERROR(service_locator()) << "Mip out of range"; + } - image::LanczosScale(src_img_data, src_x, src_y, + // Clip source and destination rectangles to + // source and destination bitmaps. + // if src or dest rectangle is out of boundary, + // do nothing and return. + if (!image::AdjustDrawImageBoundary(&src_x, &src_y, + &src_width, &src_height, + 0, + src_img.width(), src_img.height(), + &dst_x, &dst_y, + &dst_width, &dst_height, + dst_mip, + width(), height())) { + return; + } + + // check formats of source and dest images. + // format of source and dest should be the same. + if (format() != Texture::ARGB8 && format() != Texture::XRGB8) { + O3D_ERROR(service_locator()) << "format must be ARGB8 or XRGB8."; + return; + } + + unsigned int mip_width = image::ComputeMipDimension(dst_mip, width()); + unsigned int mip_height = image::ComputeMipDimension(dst_mip, height()); + unsigned int components = image::GetNumComponentsForFormat(format()); + DCHECK(components > 0); + + int src_pitch = src_img.GetPitch(); + if (image::AdjustForSetRect(&src_y, src_width, src_height, &src_pitch, + &dst_y, dst_width, &dst_height)) { + SetRect(dst_mip, dst_x, dst_y, dst_width, dst_height, + src_img.GetPixelData(src_x, src_y), + src_pitch); + return; + } + + LockHelper helper(this, dst_mip); + uint8* mip_data = helper.GetDataAs<uint8>(); + if (!mip_data) { + return; + } + + image::LanczosScale(format(), + src_img.GetPixelData(0, 0), + src_img.GetPitch(), + 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); + components); } void Texture2D::SetFromBitmap(const Bitmap& bitmap) { @@ -291,12 +370,12 @@ ObjectBase::Ref TextureCUBE::Create(ServiceLocator* service_locator) { return ObjectBase::Ref(); } -void TextureCUBE::DrawImage(const Bitmap& src_img, +void TextureCUBE::DrawImage(const Bitmap& src_img, int src_mip, int src_x, int src_y, int src_width, int src_height, + CubeFace dest_face, int dest_mip, int dst_x, int dst_y, - int dst_width, int dst_height, - CubeFace dest_face, int dest_mip) { + int dst_width, int dst_height) { DCHECK(src_img.image_data()); if (dest_face >= NUMBER_OF_FACES) { @@ -305,10 +384,12 @@ void TextureCUBE::DrawImage(const Bitmap& src_img, } if (dest_mip < 0 || dest_mip >= levels()) { - O3D_ERROR(service_locator()) << "Mip out of range"; + O3D_ERROR(service_locator()) << "Destination Mip out of range"; } - unsigned int mip_length = std::max(1, edge_length() >> dest_mip); + if (src_mip < 0 || src_mip >= src_img.num_mipmaps()) { + O3D_ERROR(service_locator()) << "Source Mip out of range"; + } // Clip source and destination rectangles to // source and destination bitmaps. @@ -316,14 +397,15 @@ void TextureCUBE::DrawImage(const Bitmap& src_img, // do nothing and return true. if (!image::AdjustDrawImageBoundary(&src_x, &src_y, &src_width, &src_height, + src_mip, src_img.width(), src_img.height(), &dst_x, &dst_y, &dst_width, &dst_height, - mip_length, mip_length)) { + dest_mip, + edge_length(), edge_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()) { @@ -331,6 +413,9 @@ void TextureCUBE::DrawImage(const Bitmap& src_img, << "different formats."; return; } + + unsigned int mip_length = image::ComputeMipDimension(dest_mip, edge_length()); + // 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 && @@ -341,13 +426,12 @@ void TextureCUBE::DrawImage(const Bitmap& src_img, static_cast<unsigned int>(dst_height) == mip_length) { SetRect(dest_face, dest_mip, 0, 0, mip_length, mip_length, src_img.image_data(), - src_img.GetMipPitch(0)); + src_img.GetMipPitch(src_mip)); return; } - if (src_img.format() == Texture::XRGB8 || - src_img.format() == Texture::ARGB8) { - components = 4; - } else { + + unsigned int components = image::GetNumComponentsForFormat(format()); + if (components == 0) { O3D_ERROR(service_locator()) << "DrawImage does not support format: " << src_img.format() << " unless src and " << "dest images are in the same size and " @@ -355,21 +439,95 @@ void TextureCUBE::DrawImage(const Bitmap& src_img, return; } + int src_pitch = src_img.GetMipPitch(src_mip); + if (image::AdjustForSetRect(&src_y, src_width, src_height, &src_pitch, + &dst_y, dst_width, &dst_height)) { + SetRect(dest_face, dest_mip, dst_x, dst_y, dst_width, dst_height, + src_img.GetPixelData(src_mip, src_x, src_y), + src_pitch); + } + LockHelper helper(this, dest_face, dest_mip); uint8* mip_data = helper.GetDataAs<uint8>(); if (!mip_data) { return; } - uint8* src_img_data = src_img.image_data(); + image::LanczosScale(src_img.format(), src_img.GetMipData(src_mip), + src_img.GetMipPitch(src_mip), + src_x, src_y, + src_width, src_height, + mip_data, helper.pitch(), + dst_x, dst_y, + dst_width, dst_height, + components); +} + +void TextureCUBE::DrawImage(const Canvas& src_img, + int src_x, int src_y, + int src_width, int src_height, + CubeFace dest_face, int dest_mip, + int dst_x, int dst_y, + int dst_width, int dst_height) { + 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()) << "Destination Mip out of range"; + } + + // Clip source and destination rectangles to + // source and destination bitmaps. + // if src or dest rectangle is out of boundary, + // do nothing and return true. + if (!image::AdjustDrawImageBoundary(&src_x, &src_y, + &src_width, &src_height, + 0, + src_img.width(), src_img.height(), + &dst_x, &dst_y, + &dst_width, &dst_height, + dest_mip, + edge_length(), edge_length())) { + return; + } + + // check formats of source and dest images. + // format of source and dest should be the same. + if (format() != Texture::ARGB8 && format() != Texture::XRGB8) { + O3D_ERROR(service_locator()) << "format must be ARGB8 or XRGB8."; + return; + } + + unsigned int mip_length = image::ComputeMipDimension(dest_mip, edge_length()); + unsigned int components = image::GetNumComponentsForFormat(format()); + DCHECK(components > 0); + + int src_pitch = src_img.GetPitch(); + if (image::AdjustForSetRect(&src_y, src_width, src_height, &src_pitch, + &dst_y, dst_width, &dst_height)) { + SetRect(dest_face, dest_mip, dst_x, dst_y, dst_width, dst_height, + src_img.GetPixelData(src_x, src_y), + src_pitch); + return; + } + + LockHelper helper(this, dest_face, dest_mip); + uint8* mip_data = helper.GetDataAs<uint8>(); + if (!mip_data) { + return; + } - image::LanczosScale(src_img_data, src_x, src_y, + image::LanczosScale(format(), + src_img.GetPixelData(0, 0), + src_img.GetPitch(), + 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); + components); } void TextureCUBE::SetFromBitmap(CubeFace face, const Bitmap& bitmap) { |