Commit a36c7238 authored by Antoine Labour's avatar Antoine Labour Committed by Commit Bot

gpu: Introduce SharedImageFactory

This is a servce-side class that can create shared images in the form of
mailboxes. This is the service-side implementation of the upcoming
SharedImageInterface, which is a stateless and thread-safe API to create
such shared images from the client side (introduced in a follow-up).

Bug: 870116

Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: Id0db4300a57e02ccbd46b5b328b534d8cd3f2dc8
Reviewed-on: https://chromium-review.googlesource.com/1159384Reviewed-by: default avatarVictor Miura <vmiura@chromium.org>
Commit-Queue: Antoine Labour <piman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580065}
parent f4a65172
...@@ -173,6 +173,7 @@ static_library("test_support") { ...@@ -173,6 +173,7 @@ static_library("test_support") {
test("gl_tests") { test("gl_tests") {
sources = [ sources = [
"command_buffer/service/shared_image_factory_unittest.cc",
"command_buffer/tests/compressed_texture_test.cc", "command_buffer/tests/compressed_texture_test.cc",
"command_buffer/tests/es3_misc_functions_unittest.cc", "command_buffer/tests/es3_misc_functions_unittest.cc",
"command_buffer/tests/gl_apply_screen_space_antialiasing_CHROMIUM_unittest.cc", "command_buffer/tests/gl_apply_screen_space_antialiasing_CHROMIUM_unittest.cc",
......
...@@ -79,6 +79,7 @@ source_set("common_sources") { ...@@ -79,6 +79,7 @@ source_set("common_sources") {
"mailbox_holder.h", "mailbox_holder.h",
"scheduling_priority.cc", "scheduling_priority.cc",
"scheduling_priority.h", "scheduling_priority.h",
"shared_image_usage.h",
"swap_buffers_complete_params.cc", "swap_buffers_complete_params.cc",
"swap_buffers_complete_params.h", "swap_buffers_complete_params.h",
"swap_buffers_flags.h", "swap_buffers_flags.h",
......
// 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.
#ifndef GPU_COMMAND_BUFFER_COMMON_SHARED_IMAGE_USAGE_H_
#define GPU_COMMAND_BUFFER_COMMON_SHARED_IMAGE_USAGE_H_
#include <stdint.h>
namespace gpu {
enum SharedImageUsage : uint32_t {
// Image will be used in GLES2Interface
SHARED_IMAGE_USAGE_GLES2 = 1 << 0,
// Image will be used as a framebuffer (hint)
SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT = 1 << 1,
// Image will be used in RasterInterface
SHARED_IMAGE_USAGE_RASTER = 1 << 2,
// Image will be used in Display
SHARED_IMAGE_USAGE_DISPLAY = 1 << 3,
// Image will be used as a scanout buffer (overlay)
SHARED_IMAGE_USAGE_SCANOUT = 1 << 4,
};
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_COMMON_SHARED_IMAGE_USAGE_H_
...@@ -216,6 +216,8 @@ target(link_target_type, "gles2_sources") { ...@@ -216,6 +216,8 @@ target(link_target_type, "gles2_sources") {
"shader_translator.h", "shader_translator.h",
"shader_translator_cache.cc", "shader_translator_cache.cc",
"shader_translator_cache.h", "shader_translator_cache.h",
"shared_image_factory.cc",
"shared_image_factory.h",
"texture_definition.cc", "texture_definition.cc",
"texture_definition.h", "texture_definition.h",
"texture_manager.cc", "texture_manager.cc",
......
This diff is collapsed.
// 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.
#ifndef GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_FACTORY_H_
#define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_FACTORY_H_
#include <memory>
#include "base/containers/flat_set.h"
#include "base/memory/scoped_refptr.h"
#include "components/viz/common/resources/resource_format.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/gpu_gles2_export.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gl/gl_bindings.h"
namespace gfx {
class Size;
class ColorSpace;
} // namespace gfx
namespace gpu {
class GpuDriverBugWorkarounds;
struct GpuFeatureInfo;
struct GpuPreferences;
class ImageFactory;
class MailboxManager;
namespace gles2 {
class MemoryTracker;
class MemoryTypeTracker;
class TexturePassthrough;
}; // namespace gles2
class GPU_GLES2_EXPORT SharedImageFactory {
public:
SharedImageFactory(const GpuPreferences& gpu_preferences,
const GpuDriverBugWorkarounds& workarounds,
const GpuFeatureInfo& gpu_feature_info,
MailboxManager* mailbox_manager,
ImageFactory* image_factory,
gles2::MemoryTracker* tracker);
~SharedImageFactory();
bool CreateSharedImage(const Mailbox& mailbox,
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage);
bool DestroySharedImage(const Mailbox& mailbox);
bool HasImages() const { return !mailboxes_.empty(); }
void DestroyAllSharedImages(bool have_context);
private:
struct FormatInfo {
FormatInfo();
~FormatInfo();
// Whether this format is supported.
bool enabled = false;
// Whether to use glTexStorage2D or glTexImage2D.
bool use_storage = false;
// Whether to allow SHARED_IMAGE_USAGE_SCANOUT.
bool allow_scanout = false;
// GL internal_format/format/type triplet.
GLuint internal_format = 0;
GLenum gl_format = 0;
GLenum gl_type = 0;
const gles2::Texture::CompatibilitySwizzle* swizzle = nullptr;
GLuint adjusted_internal_format = 0;
GLenum adjusted_format = 0;
// GL target to use for scanout images.
GLenum target_for_scanout = GL_TEXTURE_2D;
// BufferFormat for scanout images.
gfx::BufferFormat buffer_format = gfx::BufferFormat::RGBA_8888;
};
bool use_passthrough_;
MailboxManager* mailbox_manager_;
ImageFactory* image_factory_;
std::unique_ptr<gles2::MemoryTypeTracker> memory_tracker_;
FormatInfo format_info_[viz::RESOURCE_FORMAT_MAX + 1];
int32_t max_texture_size_ = 0;
bool texture_usage_angle_ = false;
bool es3_capable_ = false;
// Mailboxes that have been created by the SharedImageFactory. If not using
// passthrough, the textures pointed to by these mailboxes are kept alive with
// a lightweight ref.
base::flat_set<Mailbox> mailboxes_;
// Textures created by the SharedImageFactory, if using passthrough, to keep
// them alive.
base::flat_set<scoped_refptr<gles2::TexturePassthrough>>
passthrough_textures_;
};
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_FACTORY_H_
// 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 "gpu/command_buffer/service/shared_image_factory.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "gpu/command_buffer/service/service_utils.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/command_buffer/tests/texture_image_factory.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_preferences.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/color_space.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/init/gl_factory.h"
namespace gpu {
namespace {
class SharedImageFactoryTest : public testing::TestWithParam<bool> {
public:
void SetUp() override {
surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
ASSERT_TRUE(surface_);
context_ = gl::init::CreateGLContext(nullptr, surface_.get(),
gl::GLContextAttribs());
ASSERT_TRUE(context_);
bool result = context_->MakeCurrent(surface_.get());
ASSERT_TRUE(result);
GpuPreferences preferences;
preferences.use_passthrough_cmd_decoder = use_passthrough();
GpuDriverBugWorkarounds workarounds;
workarounds.max_texture_size = INT_MAX - 1;
factory_ = std::make_unique<SharedImageFactory>(
preferences, workarounds, GpuFeatureInfo(), &mailbox_manager_,
&image_factory_, nullptr);
}
void TearDown() override {
factory_->DestroyAllSharedImages(true);
factory_.reset();
}
bool use_passthrough() {
return GetParam() && gles2::PassthroughCommandDecoderSupported();
}
protected:
scoped_refptr<gl::GLSurface> surface_;
scoped_refptr<gl::GLContext> context_;
gles2::MailboxManagerImpl mailbox_manager_;
TextureImageFactory image_factory_;
std::unique_ptr<SharedImageFactory> factory_;
};
TEST_P(SharedImageFactoryTest, Basic) {
auto mailbox = Mailbox::Generate();
auto format = viz::ResourceFormat::RGBA_8888;
gfx::Size size(256, 256);
auto color_space = gfx::ColorSpace::CreateSRGB();
uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
EXPECT_TRUE(
factory_->CreateSharedImage(mailbox, format, size, color_space, usage));
TextureBase* texture_base = mailbox_manager_.ConsumeTexture(mailbox);
ASSERT_TRUE(texture_base);
GLenum expected_target = GL_TEXTURE_2D;
EXPECT_EQ(texture_base->target(), expected_target);
if (!use_passthrough()) {
auto* texture = static_cast<gles2::Texture*>(texture_base);
EXPECT_TRUE(texture->IsImmutable());
int width, height, depth;
bool has_level =
texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height, &depth);
EXPECT_TRUE(has_level);
EXPECT_EQ(width, size.width());
EXPECT_EQ(height, size.height());
}
EXPECT_TRUE(factory_->DestroySharedImage(mailbox));
EXPECT_FALSE(mailbox_manager_.ConsumeTexture(mailbox));
}
TEST_P(SharedImageFactoryTest, Image) {
auto mailbox = Mailbox::Generate();
auto format = viz::ResourceFormat::RGBA_8888;
gfx::Size size(256, 256);
auto color_space = gfx::ColorSpace::CreateSRGB();
uint32_t usage = SHARED_IMAGE_USAGE_SCANOUT;
EXPECT_TRUE(
factory_->CreateSharedImage(mailbox, format, size, color_space, usage));
TextureBase* texture_base = mailbox_manager_.ConsumeTexture(mailbox);
ASSERT_TRUE(texture_base);
GLenum target = texture_base->target();
scoped_refptr<gl::GLImage> image;
if (use_passthrough()) {
auto* texture = static_cast<gles2::TexturePassthrough*>(texture_base);
image = texture->GetLevelImage(target, 0);
} else {
auto* texture = static_cast<gles2::Texture*>(texture_base);
image = texture->GetLevelImage(target, 0);
}
ASSERT_TRUE(image);
EXPECT_EQ(size, image->GetSize());
}
TEST_P(SharedImageFactoryTest, DuplicateMailbox) {
auto mailbox = Mailbox::Generate();
auto format = viz::ResourceFormat::RGBA_8888;
gfx::Size size(256, 256);
auto color_space = gfx::ColorSpace::CreateSRGB();
uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
EXPECT_TRUE(
factory_->CreateSharedImage(mailbox, format, size, color_space, usage));
EXPECT_FALSE(
factory_->CreateSharedImage(mailbox, format, size, color_space, usage));
}
TEST_P(SharedImageFactoryTest, DestroyInexistentMailbox) {
auto mailbox = Mailbox::Generate();
EXPECT_FALSE(factory_->DestroySharedImage(mailbox));
}
TEST_P(SharedImageFactoryTest, InvalidFormat) {
auto mailbox = Mailbox::Generate();
auto format = viz::ResourceFormat::UYVY_422;
gfx::Size size(256, 256);
auto color_space = gfx::ColorSpace::CreateSRGB();
uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
EXPECT_FALSE(
factory_->CreateSharedImage(mailbox, format, size, color_space, usage));
}
TEST_P(SharedImageFactoryTest, InvalidSize) {
auto mailbox = Mailbox::Generate();
auto format = viz::ResourceFormat::RGBA_8888;
gfx::Size size(0, 0);
auto color_space = gfx::ColorSpace::CreateSRGB();
uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
EXPECT_FALSE(
factory_->CreateSharedImage(mailbox, format, size, color_space, usage));
size = gfx::Size(INT_MAX, INT_MAX);
EXPECT_FALSE(
factory_->CreateSharedImage(mailbox, format, size, color_space, usage));
}
INSTANTIATE_TEST_CASE_P(Service, SharedImageFactoryTest, ::testing::Bool());
} // anonymous namespace
} // namespace gpu
...@@ -309,8 +309,8 @@ static const Texture::CompatibilitySwizzle kSwizzledFormats[] = { ...@@ -309,8 +309,8 @@ static const Texture::CompatibilitySwizzle kSwizzledFormats[] = {
{GL_LUMINANCE_ALPHA, GL_RG, GL_RED, GL_RED, GL_RED, GL_GREEN}, {GL_LUMINANCE_ALPHA, GL_RG, GL_RED, GL_RED, GL_RED, GL_GREEN},
}; };
// static const Texture::CompatibilitySwizzle* GetCompatibilitySwizzleInternal(
const Texture::CompatibilitySwizzle* GetCompatibilitySwizzle(GLenum format) { GLenum format) {
size_t count = arraysize(kSwizzledFormats); size_t count = arraysize(kSwizzledFormats);
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
if (kSwizzledFormats[i].format == format) if (kSwizzledFormats[i].format == format)
...@@ -1922,7 +1922,7 @@ void Texture::ApplyFormatWorkarounds(FeatureInfo* feature_info) { ...@@ -1922,7 +1922,7 @@ void Texture::ApplyFormatWorkarounds(FeatureInfo* feature_info) {
if (static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size()) if (static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size())
return; return;
const Texture::LevelInfo& info = face_infos_[0].level_infos[base_level_]; const Texture::LevelInfo& info = face_infos_[0].level_infos[base_level_];
SetCompatibilitySwizzle(GetCompatibilitySwizzle(info.format)); SetCompatibilitySwizzle(GetCompatibilitySwizzleInternal(info.format));
} }
} }
...@@ -3302,13 +3302,24 @@ void TextureManager::DoTexSubImageLayerByLayerWorkaround( ...@@ -3302,13 +3302,24 @@ void TextureManager::DoTexSubImageLayerByLayerWorkaround(
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, unpack_params.image_height); glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, unpack_params.image_height);
} }
// static
const Texture::CompatibilitySwizzle* TextureManager::GetCompatibilitySwizzle(
const gles2::FeatureInfo* feature_info,
GLenum format) {
if (feature_info->gl_version_info().is_desktop_core_profile) {
return GetCompatibilitySwizzleInternal(format);
} else {
return nullptr;
}
}
// static // static
GLenum TextureManager::AdjustTexInternalFormat( GLenum TextureManager::AdjustTexInternalFormat(
const gles2::FeatureInfo* feature_info, const gles2::FeatureInfo* feature_info,
GLenum format) { GLenum format) {
if (feature_info->gl_version_info().is_desktop_core_profile) { if (feature_info->gl_version_info().is_desktop_core_profile) {
const Texture::CompatibilitySwizzle* swizzle = const Texture::CompatibilitySwizzle* swizzle =
GetCompatibilitySwizzle(format); GetCompatibilitySwizzleInternal(format);
if (swizzle) if (swizzle)
return swizzle->dest_format; return swizzle->dest_format;
} }
...@@ -3328,7 +3339,7 @@ GLenum TextureManager::AdjustTexFormat(const gles2::FeatureInfo* feature_info, ...@@ -3328,7 +3339,7 @@ GLenum TextureManager::AdjustTexFormat(const gles2::FeatureInfo* feature_info,
} }
if (feature_info->gl_version_info().is_desktop_core_profile) { if (feature_info->gl_version_info().is_desktop_core_profile) {
const Texture::CompatibilitySwizzle* swizzle = const Texture::CompatibilitySwizzle* swizzle =
GetCompatibilitySwizzle(format); GetCompatibilitySwizzleInternal(format);
if (swizzle) if (swizzle)
return swizzle->dest_format; return swizzle->dest_format;
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
namespace gpu { namespace gpu {
class DecoderContext; class DecoderContext;
class ServiceDiscardableManager; class ServiceDiscardableManager;
class SharedImageFactory;
namespace gles2 { namespace gles2 {
class GLStreamTextureImage; class GLStreamTextureImage;
...@@ -46,7 +47,7 @@ class TextureRef; ...@@ -46,7 +47,7 @@ class TextureRef;
// A ref-counted version of the TextureBase class that deletes the texture after // A ref-counted version of the TextureBase class that deletes the texture after
// all references have been released. // all references have been released.
class TexturePassthrough final class GPU_GLES2_EXPORT TexturePassthrough final
: public TextureBase, : public TextureBase,
public base::RefCounted<TexturePassthrough>, public base::RefCounted<TexturePassthrough>,
public base::SupportsWeakPtr<TexturePassthrough> { public base::SupportsWeakPtr<TexturePassthrough> {
...@@ -327,6 +328,7 @@ class GPU_GLES2_EXPORT Texture final : public TextureBase { ...@@ -327,6 +328,7 @@ class GPU_GLES2_EXPORT Texture final : public TextureBase {
private: private:
friend class MailboxManagerSync; friend class MailboxManagerSync;
friend class MailboxManagerTest; friend class MailboxManagerTest;
friend class gpu::SharedImageFactory;
friend class TextureDefinition; friend class TextureDefinition;
friend class TextureManager; friend class TextureManager;
friend class TextureRef; friend class TextureRef;
...@@ -1104,6 +1106,9 @@ class GPU_GLES2_EXPORT TextureManager ...@@ -1104,6 +1106,9 @@ class GPU_GLES2_EXPORT TextureManager
uint32_t GetServiceIdGeneration() const; uint32_t GetServiceIdGeneration() const;
void IncrementServiceIdGeneration(); void IncrementServiceIdGeneration();
static const Texture::CompatibilitySwizzle* GetCompatibilitySwizzle(
const gles2::FeatureInfo* feature_info,
GLenum format);
static GLenum AdjustTexInternalFormat(const gles2::FeatureInfo* feature_info, static GLenum AdjustTexInternalFormat(const gles2::FeatureInfo* feature_info,
GLenum format); GLenum format);
static GLenum AdjustTexFormat(const gles2::FeatureInfo* feature_info, static GLenum AdjustTexFormat(const gles2::FeatureInfo* feature_info,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment