| Index: gpu/command_buffer/service/texture_manager.cc
|
| diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
|
| index 48b41c05511206835d60362f56dad766953c9844..abe56a84b037647af1e24f30365289da54a9d5cd 100644
|
| --- a/gpu/command_buffer/service/texture_manager.cc
|
| +++ b/gpu/command_buffer/service/texture_manager.cc
|
| @@ -422,6 +422,18 @@ MemoryTypeTracker* Texture::GetMemTracker() {
|
| return memory_tracking_ref_->manager()->GetMemTracker();
|
| }
|
|
|
| +Texture::LayerInfo::LayerInfo()
|
| + : image_state(UNBOUND),
|
| + layer(0) {}
|
| +
|
| +Texture::LayerInfo::LayerInfo(const LayerInfo& rhs)
|
| + : image(rhs.image),
|
| + image_state(rhs.image_state),
|
| + layer(rhs.layer) {}
|
| +
|
| +Texture::LayerInfo::~LayerInfo() {
|
| +}
|
| +
|
| Texture::LevelInfo::LevelInfo()
|
| : target(0),
|
| level(-1),
|
| @@ -432,13 +444,12 @@ Texture::LevelInfo::LevelInfo()
|
| border(0),
|
| format(0),
|
| type(0),
|
| - image_state(UNBOUND),
|
| estimated_size(0),
|
| - internal_workaround(false) {}
|
| + internal_workaround(false),
|
| + num_uncleared_layers(0) {}
|
|
|
| Texture::LevelInfo::LevelInfo(const LevelInfo& rhs)
|
| - : cleared_rect(rhs.cleared_rect),
|
| - target(rhs.target),
|
| + : target(rhs.target),
|
| level(rhs.level),
|
| internal_format(rhs.internal_format),
|
| width(rhs.width),
|
| @@ -447,10 +458,17 @@ Texture::LevelInfo::LevelInfo(const LevelInfo& rhs)
|
| border(rhs.border),
|
| format(rhs.format),
|
| type(rhs.type),
|
| - image(rhs.image),
|
| - image_state(rhs.image_state),
|
| estimated_size(rhs.estimated_size),
|
| - internal_workaround(rhs.internal_workaround) {}
|
| + internal_workaround(rhs.internal_workaround),
|
| + num_uncleared_layers(rhs.num_uncleared_layers) {
|
| + GLint layers = rhs.layer_infos.size();
|
| + layer_infos.resize(layers);
|
| + for (int jj = 0; jj < layers; ++jj) {
|
| + layer_infos[jj].cleared_rect = rhs.layer_infos[jj].cleared_rect;
|
| + layer_infos[jj].image = rhs.layer_infos[jj].image;
|
| + layer_infos[jj].image_state = rhs.layer_infos[jj].image_state;
|
| + }
|
| +}
|
|
|
| Texture::LevelInfo::~LevelInfo() {
|
| }
|
| @@ -564,6 +582,7 @@ void Texture::AddToSignature(
|
| const FeatureInfo* feature_info,
|
| GLenum target,
|
| GLint level,
|
| + GLint layer,
|
| std::string* signature) const {
|
| DCHECK(feature_info);
|
| DCHECK(signature);
|
| @@ -573,24 +592,27 @@ void Texture::AddToSignature(
|
| face_infos_.size());
|
| DCHECK_LT(static_cast<size_t>(level),
|
| face_infos_[face_index].level_infos.size());
|
| + DCHECK_LT(static_cast<size_t>(layer),
|
| + face_infos_[face_index].level_infos[level].layer_infos.size());
|
|
|
| - const Texture::LevelInfo& info =
|
| + const Texture::LevelInfo& level_info =
|
| face_infos_[face_index].level_infos[level];
|
| + const Texture::LayerInfo& layer_info = level_info.layer_infos[layer];
|
|
|
| TextureSignature signature_data(target,
|
| level,
|
| sampler_state_,
|
| usage_,
|
| - info.internal_format,
|
| - info.width,
|
| - info.height,
|
| - info.depth,
|
| + level_info.internal_format,
|
| + level_info.width,
|
| + level_info.height,
|
| + level_info.depth,
|
| base_level_,
|
| - info.border,
|
| + level_info.border,
|
| max_level_,
|
| - info.format,
|
| - info.type,
|
| - info.image.get() != NULL,
|
| + level_info.format,
|
| + level_info.type,
|
| + layer_info.image.get() != NULL,
|
| CanRender(feature_info),
|
| CanRenderTo(feature_info, level),
|
| npot_,
|
| @@ -629,13 +651,20 @@ void Texture::MarkMipmapsGenerated() {
|
| }
|
| }
|
|
|
| -void Texture::SetTarget(GLenum target, GLint max_levels) {
|
| +void Texture::SetTarget(GLenum target, GLint max_levels, GLint layers) {
|
| DCHECK_EQ(0u, target_); // you can only set this once.
|
| target_ = target;
|
| size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
|
| face_infos_.resize(num_faces);
|
| for (size_t ii = 0; ii < num_faces; ++ii) {
|
| face_infos_[ii].level_infos.resize(max_levels);
|
| + for (int jj = 0; jj < max_levels; ++jj) {
|
| + Texture::LevelInfo& level_info = face_infos_[ii].level_infos[jj];
|
| + level_info.layer_infos.resize(layers);
|
| + level_info.num_uncleared_layers = 0;
|
| + for (int kk = 0; kk < layers; ++kk)
|
| + level_info.layer_infos[kk].image_state = UNBOUND;
|
| + }
|
| }
|
|
|
| if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) {
|
| @@ -676,13 +705,17 @@ bool Texture::CanGenerateMipmaps(const FeatureInfo* feature_info) const {
|
| }
|
|
|
| for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
|
| - const LevelInfo& info = face_infos_[ii].level_infos[base_level_];
|
| - if ((info.target == 0) ||
|
| + const LevelInfo& level_info = face_infos_[ii].level_infos[base_level_];
|
| + if ((level_info.target == 0) ||
|
| feature_info->validators()->compressed_texture_format.IsValid(
|
| - info.internal_format) ||
|
| - info.image.get()) {
|
| + level_info.internal_format)) {
|
| return false;
|
| }
|
| + for (size_t jj = 0; jj < level_info.layer_infos.size(); ++jj) {
|
| + if ( level_info.layer_infos[jj].image.get()) {
|
| + return false;
|
| + }
|
| + }
|
| }
|
| if (face_infos_.size() == 6 && !cube_complete_) {
|
| return false;
|
| @@ -779,28 +812,37 @@ bool Texture::TextureFilterable(const FeatureInfo* feature_info,
|
|
|
| void Texture::SetLevelClearedRect(GLenum target,
|
| GLint level,
|
| + GLint layer,
|
| const gfx::Rect& cleared_rect) {
|
| DCHECK_GE(level, 0);
|
| + DCHECK_GE(layer, 0);
|
| size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
|
| DCHECK_LT(static_cast<size_t>(face_index),
|
| face_infos_.size());
|
| DCHECK_LT(static_cast<size_t>(level),
|
| face_infos_[face_index].level_infos.size());
|
| + DCHECK_LT(static_cast<size_t>(layer),
|
| + face_infos_[face_index].level_infos[level].layer_infos.size());
|
| Texture::LevelInfo& info =
|
| face_infos_[face_index].level_infos[level];
|
| - UpdateMipCleared(&info, info.width, info.height, cleared_rect);
|
| + UpdateMipCleared(&info, info.width, info.height, cleared_rect, layer);
|
| UpdateCleared();
|
| }
|
|
|
| -void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) {
|
| +void Texture::SetLevelCleared(GLenum target,
|
| + GLint level,
|
| + GLint layer,
|
| + bool cleared) {
|
| DCHECK_GE(level, 0);
|
| + DCHECK_GE(layer, 0);
|
| size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
|
| DCHECK_LT(static_cast<size_t>(face_index), face_infos_.size());
|
| DCHECK_LT(static_cast<size_t>(level),
|
| face_infos_[face_index].level_infos.size());
|
| Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
|
| UpdateMipCleared(&info, info.width, info.height,
|
| - cleared ? gfx::Rect(info.width, info.height) : gfx::Rect());
|
| + cleared ? gfx::Rect(info.width, info.height) : gfx::Rect(),
|
| + layer);
|
| UpdateCleared();
|
| }
|
|
|
| @@ -829,21 +871,36 @@ void Texture::UpdateSafeToRenderFrom(bool cleared) {
|
| (*it)->manager()->UpdateSafeToRenderFrom(delta);
|
| }
|
|
|
| +void Texture::UpdateMipClearedHelper(LevelInfo* info) {
|
| + int layers = info->layer_infos.size();
|
| + const gfx::Rect cleared_rect = info->layer_infos[0].cleared_rect;
|
| + for (int ii = 1; ii < layers; ++ii) {
|
| + info->layer_infos[ii].cleared_rect = cleared_rect;
|
| + }
|
| +}
|
| +
|
| void Texture::UpdateMipCleared(LevelInfo* info,
|
| GLsizei width,
|
| GLsizei height,
|
| - const gfx::Rect& cleared_rect) {
|
| - bool was_cleared = info->cleared_rect == gfx::Rect(info->width, info->height);
|
| + const gfx::Rect& cleared_rect,
|
| + GLint layer) {
|
| + bool was_cleared = info->layer_infos[layer].cleared_rect ==
|
| + gfx::Rect(info->width, info->height);
|
| info->width = width;
|
| info->height = height;
|
| - info->cleared_rect = cleared_rect;
|
| - bool cleared = info->cleared_rect == gfx::Rect(info->width, info->height);
|
| + info->layer_infos[layer].cleared_rect = cleared_rect;
|
| + bool cleared = info->layer_infos[layer].cleared_rect ==
|
| + gfx::Rect(info->width, info->height);
|
| if (cleared == was_cleared)
|
| return;
|
| int delta = cleared ? -1 : +1;
|
| - num_uncleared_mips_ += delta;
|
| - for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
|
| - (*it)->manager()->UpdateUnclearedMips(delta);
|
| + if (info->num_uncleared_layers == 0 ||
|
| + info->num_uncleared_layers + delta == 0) {
|
| + num_uncleared_mips_ += delta;
|
| + for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
|
| + (*it)->manager()->UpdateUnclearedMips(delta);
|
| + }
|
| + info->num_uncleared_layers += delta;
|
| }
|
|
|
| void Texture::UpdateCanRenderCondition() {
|
| @@ -857,10 +914,12 @@ void Texture::UpdateHasImages() {
|
| bool has_images = false;
|
| for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
|
| for (size_t jj = 0; jj < face_infos_[ii].level_infos.size(); ++jj) {
|
| - const Texture::LevelInfo& info = face_infos_[ii].level_infos[jj];
|
| - if (info.image.get() != NULL) {
|
| - has_images = true;
|
| - break;
|
| + const Texture::LevelInfo& level_info = face_infos_[ii].level_infos[jj];
|
| + for (size_t kk = 0; kk < level_info.layer_infos.size(); ++kk) {
|
| + if (level_info.layer_infos[kk].image.get() != NULL) {
|
| + has_images = true;
|
| + break;
|
| + }
|
| }
|
| }
|
| }
|
| @@ -876,9 +935,11 @@ void Texture::UpdateHasImages() {
|
| void Texture::UpdateEmulatingRGB() {
|
| for (const FaceInfo& face_info : face_infos_) {
|
| for (const LevelInfo& level_info : face_info.level_infos) {
|
| - if (level_info.image && level_info.image->EmulatingRGB()) {
|
| - emulating_rgb_ = true;
|
| - return;
|
| + for (const LayerInfo& layer_info : level_info.layer_infos) {
|
| + if (layer_info.image && layer_info.image->EmulatingRGB()) {
|
| + emulating_rgb_ = true;
|
| + return;
|
| + }
|
| }
|
| }
|
| }
|
| @@ -942,6 +1003,8 @@ void Texture::SetLevelInfo(GLenum target,
|
| face_infos_.size());
|
| DCHECK_LT(static_cast<size_t>(level),
|
| face_infos_[face_index].level_infos.size());
|
| + DCHECK_LE(static_cast<size_t>(depth),
|
| + face_infos_[face_index].level_infos[level].layer_infos.size());
|
| DCHECK_GE(width, 0);
|
| DCHECK_GE(height, 0);
|
| DCHECK_GE(depth, 0);
|
| @@ -982,12 +1045,19 @@ void Texture::SetLevelInfo(GLenum target,
|
| info.border = border;
|
| info.format = format;
|
| info.type = type;
|
| - info.image = 0;
|
| - info.stream_texture_image = 0;
|
| - info.image_state = UNBOUND;
|
| + info.layer_infos[depth - 1].image = 0;
|
| + info.layer_infos[depth - 1].stream_texture_image = 0;
|
| + info.layer_infos[depth - 1].image_state = UNBOUND;
|
| info.internal_workaround = false;
|
|
|
| - UpdateMipCleared(&info, width, height, cleared_rect);
|
| + // UpdateMipCleared(&info, width, height, cleared_rect, depth - 1);
|
| + UpdateMipCleared(&info, width, height, cleared_rect, 0);
|
| + if (target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY) {
|
| + // UpdateMipClearedHelper(&info);
|
| + for (int i = 1; i < depth; ++i) {
|
| + UpdateMipCleared(&info, width, height, cleared_rect, i);
|
| + }
|
| + }
|
|
|
| estimated_size_ -= info.estimated_size;
|
| GLES2Util::ComputeImageDataSizes(
|
| @@ -1356,7 +1426,7 @@ bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) {
|
| jj < base_level_ + face_info.num_mip_levels; ++jj) {
|
| const Texture::LevelInfo& info = face_info.level_infos[jj];
|
| if (info.target != 0) {
|
| - if (!ClearLevel(decoder, info.target, jj)) {
|
| + if (!ClearLevel(decoder, info.target, jj, 0)) {
|
| return false;
|
| }
|
| }
|
| @@ -1381,39 +1451,52 @@ GLint Texture::GetImmutableLevels() const {
|
| return levels;
|
| }
|
|
|
| -gfx::Rect Texture::GetLevelClearedRect(GLenum target, GLint level) const {
|
| +gfx::Rect Texture::GetLevelClearedRect(GLenum target,
|
| + GLint level,
|
| + GLint layer) const {
|
| size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
|
| if (face_index >= face_infos_.size() ||
|
| - level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) {
|
| + level >= static_cast<GLint>(face_infos_[face_index].level_infos.size()) ||
|
| + layer >= static_cast<GLint>(face_infos_[face_index].
|
| + level_infos[level].layer_infos.size())) {
|
| return gfx::Rect();
|
| }
|
|
|
| - const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
|
| + const Texture::LayerInfo& layer_info =
|
| + face_infos_[face_index].level_infos[level].layer_infos[layer];
|
|
|
| - return info.cleared_rect;
|
| + return layer_info.cleared_rect;
|
| }
|
|
|
| -bool Texture::IsLevelCleared(GLenum target, GLint level) const {
|
| +bool Texture::IsLevelCleared(GLenum target, GLint level, GLint layer) const {
|
| size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
|
| if (face_index >= face_infos_.size() ||
|
| level < 0 ||
|
| level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) {
|
| return true;
|
| }
|
| - const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
|
| - return info.cleared_rect == gfx::Rect(info.width, info.height);
|
| + const Texture::LevelInfo& level_info =
|
| + face_infos_[face_index].level_infos[level];
|
| + const Texture::LayerInfo& layer_info = level_info.layer_infos[layer];
|
| + return layer_info.cleared_rect ==
|
| + gfx::Rect(level_info.width, level_info.height);
|
| }
|
|
|
| -bool Texture::IsLevelPartiallyCleared(GLenum target, GLint level) const {
|
| +bool Texture::IsLevelPartiallyCleared(GLenum target,
|
| + GLint level,
|
| + GLint layer) const {
|
| size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
|
| if (face_index >= face_infos_.size() ||
|
| level < 0 ||
|
| level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) {
|
| return false;
|
| }
|
| - const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
|
| - return (info.cleared_rect != gfx::Rect(info.width, info.height) &&
|
| - info.cleared_rect != gfx::Rect());
|
| + const Texture::LevelInfo& level_info =
|
| + face_infos_[face_index].level_infos[level];
|
| + const Texture::LayerInfo& layer_info = level_info.layer_infos[layer];
|
| + return (layer_info.cleared_rect !=
|
| + gfx::Rect(level_info.width, level_info.height) &&
|
| + layer_info.cleared_rect != gfx::Rect());
|
| }
|
|
|
| void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) {
|
| @@ -1425,7 +1508,7 @@ void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) {
|
| }
|
|
|
| bool Texture::ClearLevel(
|
| - GLES2Decoder* decoder, GLenum target, GLint level) {
|
| + GLES2Decoder* decoder, GLenum target, GLint level, GLint layer) {
|
| DCHECK(decoder);
|
| size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
|
| if (face_index >= face_infos_.size() || level < 0 ||
|
| @@ -1433,44 +1516,51 @@ bool Texture::ClearLevel(
|
| return true;
|
| }
|
|
|
| - Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
|
| + Texture::LevelInfo& level_info = face_infos_[face_index].level_infos[level];
|
| + Texture::LayerInfo& layer_info = level_info.layer_infos[layer];
|
|
|
| - DCHECK(target == info.target);
|
| + DCHECK(target == level_info.target);
|
|
|
| - if (info.target == 0 ||
|
| - info.cleared_rect == gfx::Rect(info.width, info.height) ||
|
| - info.width == 0 || info.height == 0 || info.depth == 0) {
|
| + if (level_info.target == 0 ||
|
| + layer_info.cleared_rect ==
|
| + gfx::Rect(level_info.width, level_info.height) ||
|
| + level_info.width == 0 ||
|
| + level_info.height == 0 ||
|
| + level_info.depth == 0) {
|
| return true;
|
| }
|
|
|
| - if (info.target == GL_TEXTURE_3D || info.target == GL_TEXTURE_2D_ARRAY) {
|
| + if (level_info.target == GL_TEXTURE_3D ||
|
| + level_info.target == GL_TEXTURE_2D_ARRAY) {
|
| // For 3D textures, we always clear the entire texture.
|
| - DCHECK(info.cleared_rect == gfx::Rect());
|
| + DCHECK(layer_info.cleared_rect == gfx::Rect());
|
| bool cleared = decoder->ClearLevel3D(
|
| - this, info.target, info.level, info.format, info.type,
|
| - info.width, info.height, info.depth);
|
| + this, level_info.target, level_info.level, level_info.format,
|
| + level_info.type, level_info.width, level_info.height, level_info.depth);
|
| if (!cleared)
|
| return false;
|
| } else {
|
| - if (decoder->IsCompressedTextureFormat(info.internal_format)) {
|
| + if (decoder->IsCompressedTextureFormat(level_info.internal_format)) {
|
| // An uncleared level of a compressed texture can only occur when
|
| // allocating the texture with TexStorage2D. In this case the level
|
| // is cleared just before a call to CompressedTexSubImage2D, to avoid
|
| // having to clear a sub-rectangle of a compressed texture, which
|
| // would be problematic.
|
| DCHECK(IsImmutable());
|
| - DCHECK(info.cleared_rect == gfx::Rect());
|
| + DCHECK(layer_info.cleared_rect == gfx::Rect());
|
| bool cleared = decoder->ClearCompressedTextureLevel(
|
| - this, info.target, info.level, info.internal_format,
|
| - info.width, info.height);
|
| + this, level_info.target, level_info.level, level_info.internal_format,
|
| + level_info.width, level_info.height);
|
| if (!cleared)
|
| return false;
|
| } else {
|
| // Clear all remaining sub regions.
|
| const int x[] = {
|
| - 0, info.cleared_rect.x(), info.cleared_rect.right(), info.width};
|
| + 0, layer_info.cleared_rect.x(),
|
| + layer_info.cleared_rect.right(), level_info.width};
|
| const int y[] = {
|
| - 0, info.cleared_rect.y(), info.cleared_rect.bottom(), info.height};
|
| + 0, layer_info.cleared_rect.y(),
|
| + layer_info.cleared_rect.bottom(), level_info.height};
|
|
|
| for (size_t j = 0; j < 3; ++j) {
|
| for (size_t i = 0; i < 3; ++i) {
|
| @@ -1486,8 +1576,8 @@ bool Texture::ClearLevel(
|
| // but only the decoder knows all the state (like unpack_alignment_)
|
| // that's needed to be able to call GL correctly.
|
| bool cleared = decoder->ClearLevel(
|
| - this, info.target, info.level, info.format, info.type,
|
| - rect.x(), rect.y(), rect.width(), rect.height());
|
| + this, level_info.target, level_info.level, level_info.format,
|
| + level_info.type, rect.x(), rect.y(), rect.width(), rect.height());
|
| if (!cleared)
|
| return false;
|
| }
|
| @@ -1495,13 +1585,21 @@ bool Texture::ClearLevel(
|
| }
|
| }
|
|
|
| - UpdateMipCleared(&info, info.width, info.height,
|
| - gfx::Rect(info.width, info.height));
|
| + UpdateMipCleared(&level_info, level_info.width, level_info.height,
|
| + gfx::Rect(level_info.width, level_info.height), 0);
|
| + if (level_info.target == GL_TEXTURE_3D ||
|
| + level_info.target == GL_TEXTURE_2D_ARRAY) {
|
| + for (int i = 1; i < level_info.depth; ++i) {
|
| + UpdateMipCleared(&level_info, level_info.width, level_info.height,
|
| + gfx::Rect(level_info.width, level_info.height), i);
|
| + }
|
| + }
|
| return true;
|
| }
|
|
|
| void Texture::SetLevelImageInternal(GLenum target,
|
| GLint level,
|
| + GLint layer,
|
| gl::GLImage* image,
|
| GLStreamTextureImage* stream_texture_image,
|
| ImageState state) {
|
| @@ -1511,12 +1609,16 @@ void Texture::SetLevelImageInternal(GLenum target,
|
| DCHECK_LT(static_cast<size_t>(face_index), face_infos_.size());
|
| DCHECK_LT(static_cast<size_t>(level),
|
| face_infos_[face_index].level_infos.size());
|
| - Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
|
| - DCHECK_EQ(info.target, target);
|
| - DCHECK_EQ(info.level, level);
|
| - info.image = image;
|
| - info.stream_texture_image = stream_texture_image;
|
| - info.image_state = state;
|
| + DCHECK_LT(static_cast<size_t>(layer),
|
| + face_infos_[face_index].level_infos[level].layer_infos.size());
|
| + Texture::LevelInfo& level_info = face_infos_[face_index].level_infos[level];
|
| + DCHECK_EQ(level_info.target, target);
|
| + DCHECK_EQ(level_info.level, level);
|
| +
|
| + Texture::LayerInfo& layer_info = level_info.layer_infos[layer];
|
| + layer_info.image = image;
|
| + layer_info.stream_texture_image = stream_texture_image;
|
| + layer_info.image_state = state;
|
|
|
| UpdateCanRenderCondition();
|
| UpdateHasImages();
|
| @@ -1525,35 +1627,44 @@ void Texture::SetLevelImageInternal(GLenum target,
|
|
|
| void Texture::SetLevelImage(GLenum target,
|
| GLint level,
|
| + GLint layer,
|
| gl::GLImage* image,
|
| ImageState state) {
|
| SetStreamTextureServiceId(0);
|
| - SetLevelImageInternal(target, level, image, nullptr, state);
|
| + SetLevelImageInternal(target, level, layer, image, nullptr, state);
|
| }
|
|
|
| void Texture::SetLevelStreamTextureImage(GLenum target,
|
| GLint level,
|
| + GLint layer,
|
| GLStreamTextureImage* image,
|
| ImageState state,
|
| GLuint service_id) {
|
| SetStreamTextureServiceId(service_id);
|
| - SetLevelImageInternal(target, level, image, image, state);
|
| + SetLevelImageInternal(target, level, layer, image, image, state);
|
| }
|
|
|
| -void Texture::SetLevelImageState(GLenum target, GLint level, ImageState state) {
|
| +void Texture::SetLevelImageState(GLenum target,
|
| + GLint level,
|
| + GLint layer,
|
| + ImageState state) {
|
| DCHECK_GE(level, 0);
|
| size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
|
| DCHECK_LT(static_cast<size_t>(face_index), face_infos_.size());
|
| DCHECK_LT(static_cast<size_t>(level),
|
| face_infos_[face_index].level_infos.size());
|
| - Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
|
| - DCHECK_EQ(info.target, target);
|
| - DCHECK_EQ(info.level, level);
|
| - info.image_state = state;
|
| + DCHECK_LT(static_cast<size_t>(layer),
|
| + face_infos_[face_index].level_infos[level].layer_infos.size());
|
| + Texture::LevelInfo& level_info = face_infos_[face_index].level_infos[level];
|
| + DCHECK_EQ(level_info.target, target);
|
| + DCHECK_EQ(level_info.level, level);
|
| + Texture::LayerInfo& layer_info = level_info.layer_infos[layer];
|
| + layer_info.image_state = state;
|
| }
|
|
|
| const Texture::LevelInfo* Texture::GetLevelInfo(GLint target,
|
| GLint level) const {
|
| + // TODO(yunchao): add TEXTURE_3D and TEXTURE_2D_ARRAY
|
| if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES &&
|
| target != GL_TEXTURE_RECTANGLE_ARB) {
|
| return NULL;
|
| @@ -1571,27 +1682,37 @@ const Texture::LevelInfo* Texture::GetLevelInfo(GLint target,
|
|
|
| gl::GLImage* Texture::GetLevelImage(GLint target,
|
| GLint level,
|
| + GLint layer,
|
| ImageState* state) const {
|
| - const LevelInfo* info = GetLevelInfo(target, level);
|
| - if (!info)
|
| + const LevelInfo* level_info = GetLevelInfo(target, level);
|
| + if (!level_info)
|
| + return nullptr;
|
| + if (static_cast<size_t>(layer) >= level_info->layer_infos.size())
|
| return nullptr;
|
| + const LayerInfo& layer_info = level_info->layer_infos[layer];
|
|
|
| if (state)
|
| - *state = info->image_state;
|
| - return info->image.get();
|
| + *state = layer_info.image_state;
|
| + return layer_info.image.get();
|
| }
|
|
|
| -gl::GLImage* Texture::GetLevelImage(GLint target, GLint level) const {
|
| - return GetLevelImage(target, level, nullptr);
|
| +gl::GLImage* Texture::GetLevelImage(GLint target,
|
| + GLint level,
|
| + GLint layer) const {
|
| + return GetLevelImage(target, level, layer, nullptr);
|
| }
|
|
|
| GLStreamTextureImage* Texture::GetLevelStreamTextureImage(GLint target,
|
| - GLint level) const {
|
| - const LevelInfo* info = GetLevelInfo(target, level);
|
| - if (!info)
|
| + GLint level,
|
| + GLint layer) const {
|
| + const LevelInfo* level_info = GetLevelInfo(target, level);
|
| + if (!level_info)
|
| + return nullptr;
|
| + if (static_cast<size_t>(layer) >= level_info->layer_infos.size())
|
| return nullptr;
|
| + const LayerInfo& layer_info = level_info->layer_infos[layer];
|
|
|
| - return info->stream_texture_image.get();
|
| + return layer_info.stream_texture_image.get();
|
| }
|
|
|
| void Texture::DumpLevelMemory(base::trace_event::ProcessMemoryDump* pmd,
|
| @@ -1606,26 +1727,33 @@ void Texture::DumpLevelMemory(base::trace_event::ProcessMemoryDump* pmd,
|
| if (!level_infos[level_index].estimated_size)
|
| continue;
|
|
|
| - // If a level has a GLImage, ask the GLImage to dump itself.
|
| - if (level_infos[level_index].image) {
|
| - level_infos[level_index].image->OnMemoryDump(
|
| - pmd, client_tracing_id,
|
| - base::StringPrintf("%s/face_%d/level_%d", dump_name.c_str(),
|
| - face_index, level_index));
|
| - }
|
| + for (uint32_t layer_index = 0;
|
| + layer_index < level_infos[level_index].layer_infos.size();
|
| + ++layer_index) {
|
| + // If a level has a GLImage, ask the GLImage to dump itself.
|
| + if (level_infos[level_index].layer_infos[layer_index].image) {
|
| + level_infos[level_index].layer_infos[layer_index].image->OnMemoryDump(
|
| + pmd, client_tracing_id,
|
| + base::StringPrintf("%s/face_%d/level_%d/layer_%d",
|
| + dump_name.c_str(),
|
| + face_index, level_index, layer_index));
|
| + }
|
|
|
| // If a level does not have a GLImage bound to it, then dump the
|
| // texture allocation also as the storage is not provided by the
|
| // GLImage in that case.
|
| - if (level_infos[level_index].image_state != BOUND) {
|
| + if (level_infos[level_index].layer_infos[layer_index].image_state
|
| + != BOUND) {
|
| base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(
|
| - base::StringPrintf("%s/face_%d/level_%d", dump_name.c_str(),
|
| - face_index, level_index));
|
| + base::StringPrintf("%s/face_%d/level_%d/layer_%d",
|
| + dump_name.c_str(),
|
| + face_index, level_index, layer_index));
|
| dump->AddScalar(
|
| base::trace_event::MemoryAllocatorDump::kNameSize,
|
| base::trace_event::MemoryAllocatorDump::kUnitsBytes,
|
| static_cast<uint64_t>(level_infos[level_index].estimated_size));
|
| }
|
| + }
|
| }
|
| }
|
| }
|
| @@ -1889,23 +2017,36 @@ bool TextureManager::ValidForTarget(
|
|
|
| void TextureManager::SetTarget(TextureRef* ref, GLenum target) {
|
| DCHECK(ref);
|
| - ref->texture()->SetTarget(target, MaxLevelsForTarget(target));
|
| + GLint layers;
|
| + switch (target) {
|
| + case GL_TEXTURE_3D:
|
| + layers = max_3d_texture_size();
|
| + break;
|
| + case GL_TEXTURE_2D_ARRAY:
|
| + layers = max_array_texture_layers();
|
| + break;
|
| + default:
|
| + layers = 1;
|
| + }
|
| + ref->texture()->SetTarget(target, MaxLevelsForTarget(target), layers);
|
| }
|
|
|
| void TextureManager::SetLevelClearedRect(TextureRef* ref,
|
| GLenum target,
|
| GLint level,
|
| + GLint layer,
|
| const gfx::Rect& cleared_rect) {
|
| DCHECK(ref);
|
| - ref->texture()->SetLevelClearedRect(target, level, cleared_rect);
|
| + ref->texture()->SetLevelClearedRect(target, level, layer, cleared_rect);
|
| }
|
|
|
| void TextureManager::SetLevelCleared(TextureRef* ref,
|
| GLenum target,
|
| GLint level,
|
| + GLint layer,
|
| bool cleared) {
|
| DCHECK(ref);
|
| - ref->texture()->SetLevelCleared(target, level, cleared);
|
| + ref->texture()->SetLevelCleared(target, level, layer, cleared);
|
| }
|
|
|
| bool TextureManager::ClearRenderableLevels(
|
| @@ -1922,7 +2063,7 @@ bool TextureManager::ClearTextureLevel(
|
| if (texture->num_uncleared_mips() == 0) {
|
| return true;
|
| }
|
| - bool result = texture->ClearLevel(decoder, target, level);
|
| + bool result = texture->ClearLevel(decoder, target, level, 0);
|
| texture->UpdateCleared();
|
| return result;
|
| }
|
| @@ -2114,29 +2255,32 @@ GLsizei TextureManager::ComputeMipMapCount(GLenum target,
|
| void TextureManager::SetLevelImage(TextureRef* ref,
|
| GLenum target,
|
| GLint level,
|
| + GLint layer,
|
| gl::GLImage* image,
|
| Texture::ImageState state) {
|
| DCHECK(ref);
|
| - ref->texture()->SetLevelImage(target, level, image, state);
|
| + ref->texture()->SetLevelImage(target, level, layer, image, state);
|
| }
|
|
|
| void TextureManager::SetLevelStreamTextureImage(TextureRef* ref,
|
| GLenum target,
|
| GLint level,
|
| + GLint layer,
|
| GLStreamTextureImage* image,
|
| Texture::ImageState state,
|
| GLuint service_id) {
|
| DCHECK(ref);
|
| - ref->texture()->SetLevelStreamTextureImage(target, level, image, state,
|
| + ref->texture()->SetLevelStreamTextureImage(target, level, layer, image, state,
|
| service_id);
|
| }
|
|
|
| void TextureManager::SetLevelImageState(TextureRef* ref,
|
| GLenum target,
|
| GLint level,
|
| + GLint layer,
|
| Texture::ImageState state) {
|
| DCHECK(ref);
|
| - ref->texture()->SetLevelImageState(target, level, state);
|
| + ref->texture()->SetLevelImageState(target, level, layer, state);
|
| }
|
|
|
| size_t TextureManager::GetSignatureSize() const {
|
| @@ -2147,8 +2291,10 @@ void TextureManager::AddToSignature(
|
| TextureRef* ref,
|
| GLenum target,
|
| GLint level,
|
| + GLint layer,
|
| std::string* signature) const {
|
| - ref->texture()->AddToSignature(feature_info_.get(), target, level, signature);
|
| + ref->texture()->AddToSignature(feature_info_.get(), target,
|
| + level, layer, signature);
|
| }
|
|
|
| void TextureManager::UpdateSafeToRenderFrom(int delta) {
|
| @@ -2453,7 +2599,8 @@ void TextureManager::ValidateAndDoTexImage(
|
| DoTexSubImageRowByRowWorkaround(texture_state, state, sub_args,
|
| unpack_params);
|
|
|
| - SetLevelCleared(texture_ref, args.target, args.level, true);
|
| + SetLevelCleared(texture_ref, args.target,
|
| + args.level, args.depth - 1, true);
|
| return;
|
| }
|
| }
|
| @@ -2474,7 +2621,8 @@ void TextureManager::ValidateAndDoTexImage(
|
| DoTexSubImageArguments::kTexSubImage2D};
|
| DoTexSubImageWithAlignmentWorkaround(texture_state, state, sub_args);
|
|
|
| - SetLevelCleared(texture_ref, args.target, args.level, true);
|
| + SetLevelCleared(texture_ref, args.target,
|
| + args.level, args.depth - 1, true);
|
| return;
|
| }
|
| }
|
| @@ -2625,14 +2773,17 @@ void TextureManager::ValidateAndDoTexSubImage(
|
| gfx::Rect cleared_rect;
|
| if (args.command_type == DoTexSubImageArguments::kTexSubImage2D &&
|
| CombineAdjacentRects(
|
| - texture->GetLevelClearedRect(args.target, args.level),
|
| + texture->GetLevelClearedRect(args.target, args.level,
|
| + args.depth - 1),
|
| gfx::Rect(args.xoffset, args.yoffset, args.width, args.height),
|
| &cleared_rect)) {
|
| DCHECK_GE(cleared_rect.size().GetArea(),
|
| - texture->GetLevelClearedRect(args.target, args.level)
|
| + texture->GetLevelClearedRect(args.target, args.level,
|
| + args.depth - 1)
|
| .size()
|
| .GetArea());
|
| - SetLevelClearedRect(texture_ref, args.target, args.level, cleared_rect);
|
| + SetLevelClearedRect(texture_ref, args.target,
|
| + args.level, args.depth - 1, cleared_rect);
|
| } else {
|
| // Otherwise clear part of texture level that is not already cleared.
|
| if (!ClearTextureLevel(decoder, texture_ref, args.target, args.level)) {
|
| @@ -2643,7 +2794,8 @@ void TextureManager::ValidateAndDoTexSubImage(
|
| }
|
| full_image = false;
|
| } else {
|
| - SetLevelCleared(texture_ref, args.target, args.level, true);
|
| + SetLevelCleared(texture_ref, args.target,
|
| + args.level, args.depth - 1, true);
|
| full_image = true;
|
| }
|
|
|
|
|