blob: 25f4583fabedacaa87e46f9baaddf8d9ec0d134d [file] [log] [blame]
// Copyright 2018 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/common/gpu/texture_allocation.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/common/resources/resource_sizes.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size.h"
namespace viz {
// static
TextureAllocation TextureAllocation::MakeTextureId(
gpu::gles2::GLES2Interface* gl,
const gpu::Capabilities& caps,
ResourceFormat format,
bool use_gpu_memory_buffer_resources,
bool for_framebuffer_attachment) {
uint32_t texture_target = GL_TEXTURE_2D;
bool overlay_candidate = use_gpu_memory_buffer_resources &&
caps.texture_storage_image &&
IsGpuMemoryBufferFormatSupported(format);
if (overlay_candidate) {
texture_target = gpu::GetBufferTextureTarget(gfx::BufferUsage::SCANOUT,
BufferFormat(format), caps);
}
uint32_t texture_id;
gl->GenTextures(1, &texture_id);
gl->BindTexture(texture_target, texture_id);
gl->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gl->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (for_framebuffer_attachment && caps.texture_usage) {
// Set GL_FRAMEBUFFER_ATTACHMENT_ANGLE since we'll be binding these
// textures as a framebuffer for drawing directly to them on the gpu.
gl->TexParameteri(texture_target, GL_TEXTURE_USAGE_ANGLE,
GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
}
gl->BindTexture(texture_target, 0);
return {texture_id, texture_target, overlay_candidate};
}
// static
void TextureAllocation::AllocateStorage(gpu::gles2::GLES2Interface* gl,
const gpu::Capabilities& caps,
ResourceFormat format,
const gfx::Size& size,
const TextureAllocation& alloc,
const gfx::ColorSpace& color_space) {
gl->BindTexture(alloc.texture_target, alloc.texture_id);
// Allocate backing storage for the texture. The best choice is to use
// GpuMemoryBuffers if we can use the texture as an overlay and its asked
// for by the caller. Else we try to make the texture have immutable
// storage, and finally fall back to standard storage if we must.
if (alloc.overlay_candidate) {
// |overlay_candidate| was only set when these were true, and
// |use_gpu_memory_buffer_resources| was specified by the caller.
DCHECK(caps.texture_storage_image);
DCHECK(IsGpuMemoryBufferFormatSupported(format));
gl->TexStorage2DImageCHROMIUM(
alloc.texture_target, TextureStorageFormat(format), GL_SCANOUT_CHROMIUM,
size.width(), size.height());
if (color_space.IsValid()) {
gl->SetColorSpaceMetadataCHROMIUM(
alloc.texture_id, reinterpret_cast<GLColorSpace>(
const_cast<gfx::ColorSpace*>(&color_space)));
}
} else if (caps.texture_storage) {
gl->TexStorage2DEXT(alloc.texture_target, 1, TextureStorageFormat(format),
size.width(), size.height());
} else {
gl->TexImage2D(alloc.texture_target, 0, GLInternalFormat(format),
size.width(), size.height(), 0, GLDataFormat(format),
GLDataType(format), nullptr);
}
}
} // namespace viz