blob: 844189b9adc266d34de592ae09175b7b19ec9e7e [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/viz/service/display/scoped_render_pass_texture.h"
#include <algorithm>
#include "base/bits.h"
#include "base/check.h"
#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
namespace viz {
ScopedRenderPassTexture::ScopedRenderPassTexture() = default;
ScopedRenderPassTexture::ScopedRenderPassTexture(
ContextProvider* context_provider,
const gfx::Size& size,
ResourceFormat format,
const gfx::ColorSpace& color_space,
bool mipmap)
: context_provider_(context_provider),
size_(size),
mipmap_(mipmap),
color_space_(color_space) {
DCHECK(context_provider_);
gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
const gpu::Capabilities& caps = context_provider_->ContextCapabilities();
gl->GenTextures(1, &gl_id_);
gl->BindTexture(GL_TEXTURE_2D, gl_id_);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// This texture will be bound as a framebuffer, so optimize for that.
if (caps.texture_usage) {
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE,
GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
}
if (caps.texture_storage) {
GLint levels = 1;
if (caps.texture_npot && mipmap_)
levels += base::bits::Log2Floor(std::max(size_.width(), size_.height()));
gl->TexStorage2DEXT(GL_TEXTURE_2D, levels, TextureStorageFormat(format),
size_.width(), size_.height());
} else {
DCHECK(GLSupportsFormat(format));
gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format), size_.width(),
size_.height(), 0, GLDataFormat(format), GLDataType(format),
nullptr);
}
}
ScopedRenderPassTexture::~ScopedRenderPassTexture() {
Free();
}
ScopedRenderPassTexture::ScopedRenderPassTexture(
ScopedRenderPassTexture&& other) {
context_provider_ = other.context_provider_;
size_ = other.size_;
mipmap_ = other.mipmap_;
color_space_ = other.color_space_;
gl_id_ = other.gl_id_;
mipmap_state_ = other.mipmap_state_;
// When being moved, other will no longer hold this gl_id_.
other.gl_id_ = 0;
}
ScopedRenderPassTexture& ScopedRenderPassTexture::operator=(
ScopedRenderPassTexture&& other) {
if (this != &other) {
Free();
context_provider_ = other.context_provider_;
size_ = other.size_;
mipmap_ = other.mipmap_;
color_space_ = other.color_space_;
gl_id_ = other.gl_id_;
mipmap_state_ = other.mipmap_state_;
// When being moved, other will no longer hold this gl_id_.
other.gl_id_ = 0;
}
return *this;
}
void ScopedRenderPassTexture::Free() {
if (!gl_id_)
return;
gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
gl->DeleteTextures(1, &gl_id_);
gl_id_ = 0;
}
void ScopedRenderPassTexture::BindForSampling() {
gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
gl->BindTexture(GL_TEXTURE_2D, gl_id_);
switch (mipmap_state_) {
case INVALID:
break;
case GENERATE:
// TODO(crbug.com/803286): npot texture always return false on ubuntu
// desktop. The npot texture check is probably failing on desktop GL.
DCHECK(context_provider_->ContextCapabilities().texture_npot);
gl->GenerateMipmap(GL_TEXTURE_2D);
mipmap_state_ = VALID;
FALLTHROUGH;
case VALID:
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
break;
}
}
} // namespace viz