blob: 9e415e89370589316b78b1857296d73cf2071754 [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 "gpu/command_buffer/service/shared_image_manager.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/task/thread_pool/thread_pool_instance.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/shared_image_backing.h"
#include "gpu/command_buffer/service/shared_image_representation.h"
#include "gpu/command_buffer/service/test_shared_image_backing.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/gmock/include/gmock/gmock.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 {
TEST(SharedImageManagerTest, BasicRefCounting) {
const size_t kSizeBytes = 1024;
SharedImageManager manager;
auto tracker = std::make_unique<MemoryTypeTracker>(nullptr);
auto mailbox = Mailbox::GenerateForSharedImage();
auto format = viz::ResourceFormat::RGBA_8888;
gfx::Size size(256, 256);
auto color_space = gfx::ColorSpace::CreateSRGB();
auto surface_origin = kTopLeft_GrSurfaceOrigin;
auto alpha_type = kPremul_SkAlphaType;
uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
auto backing = std::make_unique<TestSharedImageBacking>(
mailbox, format, size, color_space, surface_origin, alpha_type, usage,
kSizeBytes);
auto factory_ref = manager.Register(std::move(backing), tracker.get());
EXPECT_EQ(kSizeBytes, tracker->GetMemRepresented());
// Taking/releasing an additional ref/representation with the same tracker
// should have no impact.
{
auto gl_representation = manager.ProduceGLTexture(mailbox, tracker.get());
EXPECT_EQ(kSizeBytes, tracker->GetMemRepresented());
}
// Taking/releasing an additional ref/representation with a new tracker should
// also have no impact.
{
auto tracker2 = std::make_unique<MemoryTypeTracker>(nullptr);
auto gl_representation = manager.ProduceGLTexture(mailbox, tracker2.get());
EXPECT_EQ(kSizeBytes, tracker->GetMemRepresented());
EXPECT_EQ(0u, tracker2->GetMemRepresented());
}
factory_ref.reset();
EXPECT_EQ(0u, tracker->GetMemRepresented());
}
TEST(SharedImageManagerTest, TransferRefSameTracker) {
const size_t kSizeBytes = 1024;
SharedImageManager manager;
auto tracker = std::make_unique<MemoryTypeTracker>(nullptr);
auto mailbox = Mailbox::GenerateForSharedImage();
auto format = viz::ResourceFormat::RGBA_8888;
gfx::Size size(256, 256);
auto color_space = gfx::ColorSpace::CreateSRGB();
auto surface_origin = kTopLeft_GrSurfaceOrigin;
auto alpha_type = kPremul_SkAlphaType;
uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
auto backing = std::make_unique<TestSharedImageBacking>(
mailbox, format, size, color_space, surface_origin, alpha_type, usage,
kSizeBytes);
auto factory_ref = manager.Register(std::move(backing), tracker.get());
EXPECT_EQ(kSizeBytes, tracker->GetMemRepresented());
// Take an additional ref/representation.
auto gl_representation = manager.ProduceGLTexture(mailbox, tracker.get());
// Releasing the original ref should have no impact.
factory_ref.reset();
EXPECT_EQ(kSizeBytes, tracker->GetMemRepresented());
gl_representation.reset();
EXPECT_EQ(0u, tracker->GetMemRepresented());
}
TEST(SharedImageManagerTest, TransferRefNewTracker) {
const size_t kSizeBytes = 1024;
SharedImageManager manager;
auto tracker = std::make_unique<MemoryTypeTracker>(nullptr);
auto tracker2 = std::make_unique<MemoryTypeTracker>(nullptr);
auto mailbox = Mailbox::GenerateForSharedImage();
auto format = viz::ResourceFormat::RGBA_8888;
gfx::Size size(256, 256);
auto color_space = gfx::ColorSpace::CreateSRGB();
auto surface_origin = kTopLeft_GrSurfaceOrigin;
auto alpha_type = kPremul_SkAlphaType;
uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
auto backing = std::make_unique<TestSharedImageBacking>(
mailbox, format, size, color_space, surface_origin, alpha_type, usage,
kSizeBytes);
auto factory_ref = manager.Register(std::move(backing), tracker.get());
EXPECT_EQ(kSizeBytes, tracker->GetMemRepresented());
// Take an additional ref/representation with a new tracker. Memory should
// stay accounted to the original tracker.
auto gl_representation = manager.ProduceGLTexture(mailbox, tracker2.get());
EXPECT_EQ(kSizeBytes, tracker->GetMemRepresented());
EXPECT_EQ(0u, tracker2->GetMemRepresented());
// Releasing the original should transfer memory to the new tracker.
factory_ref.reset();
EXPECT_EQ(0u, tracker->GetMemRepresented());
EXPECT_EQ(kSizeBytes, tracker2->GetMemRepresented());
// We can now safely destroy the original tracker.
tracker.reset();
gl_representation.reset();
EXPECT_EQ(0u, tracker2->GetMemRepresented());
}
class SequenceValidatingMemoryTracker : public MemoryTracker {
public:
SequenceValidatingMemoryTracker()
: task_runner_(base::ThreadPool::CreateSequencedTaskRunner({})) {}
~SequenceValidatingMemoryTracker() override { EXPECT_EQ(size_, 0u); }
scoped_refptr<base::SequencedTaskRunner> task_runner() const {
return task_runner_;
}
void TrackMemoryAllocatedChange(int64_t delta) override {
EXPECT_TRUE(task_runner_->RunsTasksInCurrentSequence());
size_ += delta;
}
uint64_t GetSize() const override { return size_; }
int ClientId() const override { return 0; }
uint64_t ClientTracingId() const override { return 0; }
uint64_t ContextGroupTracingId() const override { return 0; }
private:
scoped_refptr<base::SequencedTaskRunner> task_runner_;
int64_t size_ = 0;
};
TEST(SharedImageManagerTest, TransferRefCrossThread) {
const size_t kSizeBytes = 1024;
SharedImageManager manager;
SequenceValidatingMemoryTracker memory_tracker1;
SequenceValidatingMemoryTracker memory_tracker2;
auto memory_type_tracker1 = std::make_unique<MemoryTypeTracker>(
&memory_tracker1, memory_tracker1.task_runner());
auto memory_type_tracker2 = std::make_unique<MemoryTypeTracker>(
&memory_tracker2, memory_tracker2.task_runner());
auto mailbox = Mailbox::GenerateForSharedImage();
auto format = viz::ResourceFormat::RGBA_8888;
gfx::Size size(256, 256);
auto color_space = gfx::ColorSpace::CreateSRGB();
auto surface_origin = kTopLeft_GrSurfaceOrigin;
auto alpha_type = kPremul_SkAlphaType;
uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
auto backing = std::make_unique<TestSharedImageBacking>(
mailbox, format, size, color_space, surface_origin, alpha_type, usage,
kSizeBytes);
auto factory_ref =
manager.Register(std::move(backing), memory_type_tracker1.get());
EXPECT_EQ(kSizeBytes, memory_type_tracker1->GetMemRepresented());
base::ThreadPoolInstance::Get()->FlushForTesting();
EXPECT_EQ(kSizeBytes, memory_tracker1.GetSize());
// Take an additional ref/representation with a new tracker. Memory should
// stay accounted to the original tracker.
auto gl_representation =
manager.ProduceGLTexture(mailbox, memory_type_tracker2.get());
EXPECT_EQ(kSizeBytes, memory_type_tracker1->GetMemRepresented());
EXPECT_EQ(0u, memory_type_tracker2->GetMemRepresented());
base::ThreadPoolInstance::Get()->FlushForTesting();
EXPECT_EQ(kSizeBytes, memory_tracker1.GetSize());
EXPECT_EQ(0u, memory_tracker2.GetSize());
// Releasing the original should transfer memory to the new tracker.
factory_ref.reset();
EXPECT_EQ(0u, memory_type_tracker1->GetMemRepresented());
EXPECT_EQ(kSizeBytes, memory_type_tracker2->GetMemRepresented());
base::ThreadPoolInstance::Get()->FlushForTesting();
EXPECT_EQ(0u, memory_tracker1.GetSize());
EXPECT_EQ(kSizeBytes, memory_tracker2.GetSize());
// We can now safely destroy the original tracker.
memory_type_tracker1.reset();
gl_representation.reset();
EXPECT_EQ(0u, memory_type_tracker2->GetMemRepresented());
base::ThreadPoolInstance::Get()->FlushForTesting();
EXPECT_EQ(0u, memory_tracker2.GetSize());
}
} // anonymous namespace
} // namespace gpu