diff options
Diffstat (limited to 'o3d/core/cross/texture.cc')
-rw-r--r-- | o3d/core/cross/texture.cc | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/o3d/core/cross/texture.cc b/o3d/core/cross/texture.cc index 058dbb4..88897c3 100644 --- a/o3d/core/cross/texture.cc +++ b/o3d/core/cross/texture.cc @@ -89,6 +89,82 @@ Texture2D::~Texture2D() { levels()))); } +void Texture2D::DrawImage(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()); + + int mip_width = std::max(1, width() >> dest_mip); + int mip_height = std::max(1, height() >> dest_mip); + + // Clip source and destination rectangles to + // 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)) + 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."; + return; + } + // 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 && + src_width == src_img->width() && src_height == src_img->height() && + dst_width == mip_width && dst_height == mip_height) { + void* data = NULL; + if (!Lock(dest_mip, &data)) + return; + + uint8* mip_data = static_cast<uint8*>(data); + unsigned int size = Bitmap::GetMipChainSize(mip_width, mip_height, + format(), 1); + memcpy(mip_data, src_img->image_data(), size); + this->Unlock(dest_mip); + + return; + } + 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 " + << "dest images are in the same size and " + << "copying the entire bitmap"; + return; + } + + void* data = NULL; + if (!Lock(dest_mip, &data)) + return; + + uint8* src_img_data = src_img->image_data(); + uint8* mip_data = static_cast<uint8*>(data); + + Bitmap::BilinearInterpolateScale(src_img_data, src_x, src_y, + src_width, src_height, + src_img->width(), src_img->height(), + mip_data, dst_x, dst_y, + dst_width, dst_height, + mip_width, mip_height, components); + + this->Unlock(dest_mip); +} + ObjectBase::Ref Texture2D::Create(ServiceLocator* service_locator) { return ObjectBase::Ref(); } @@ -164,4 +240,82 @@ ObjectBase::Ref TextureCUBE::Create(ServiceLocator* service_locator) { return ObjectBase::Ref(); } +void TextureCUBE::DrawImage(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()); + + int mip_length = std::max(1, edge_length() >> dest_mip); + + // 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 (!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)) + 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."; + return; + } + // 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 && + src_width == src_img->width() && src_height == src_img->height() && + dst_width == mip_length && dst_height == mip_length) { + // get mip data by lock method. + void* data = NULL; + if (!Lock(dest_face, dest_mip, &data)) + return; + + uint8* mip_data = static_cast<uint8*>(data); + unsigned int size = Bitmap::GetMipChainSize(mip_length, mip_length, + format(), 1); + memcpy(mip_data, src_img->image_data(), size); + this->Unlock(dest_face, dest_mip); + + return; + } + 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 " + << "dest images are in the same size and " + << "copying the entire bitmap"; + return; + } + + void* data = NULL; + if (!Lock(dest_face, dest_mip, &data)) { + return; + } + + uint8* src_img_data = src_img->image_data(); + uint8* mip_data = static_cast<uint8*>(data); + + Bitmap::BilinearInterpolateScale(src_img_data, src_x, src_y, + src_width, src_height, + src_img->width(), src_img->height(), + mip_data, dst_x, dst_y, + dst_width, dst_height, + mip_length, mip_length, components); + + this->Unlock(dest_face, dest_mip); +} + } // namespace o3d |