summaryrefslogtreecommitdiffstats
path: root/o3d/core/cross/texture.cc
diff options
context:
space:
mode:
authorgman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-06 04:53:24 +0000
committergman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-06 04:53:24 +0000
commit132899b905b0f1794d7e82e28f9fe77ca6a08282 (patch)
tree47af391191ac78d3b4e02533f74e3575970cebcc /o3d/core/cross/texture.cc
parent22e037073118aaf90549410b32d66885d39b78a9 (diff)
downloadchromium_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.cc259
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(