Commit 827d7ca4 authored by Antoine Labour's avatar Antoine Labour Committed by Commit Bot

Add GpuMemoryBuffer import in SharedImageInterface

This adds 2 entrypoints:
- CreateSharedImage, which takes a GpuMemoryBuffer to wrap into a shared
image (equivalent to CreateImageCHROMIUM+BindTexImage2DCHROMIUM)
- UpdateSharedImage, which updates the binding after CPU/external writes
to the GMB (equivalent to ReleaseTexImage2DCHROMIUM+BindTexImage2DCHROMIUM).

This is only plumbed to SharedImageBackingFactoryGLTexture in this CL.

Bug: 870116
Change-Id: Ie7645b65649b0f34d5431fc00f62da9d5661c570
Reviewed-on: https://chromium-review.googlesource.com/c/1316250Reviewed-by: default avatarChris Palmer <palmer@chromium.org>
Reviewed-by: default avatarEric Karl <ericrk@chromium.org>
Commit-Queue: Antoine Labour <piman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#605832}
parent a925cbb5
...@@ -122,6 +122,17 @@ class TestSharedImageInterface : public gpu::SharedImageInterface { ...@@ -122,6 +122,17 @@ class TestSharedImageInterface : public gpu::SharedImageInterface {
return gpu::Mailbox::Generate(); return gpu::Mailbox::Generate();
} }
gpu::Mailbox CreateSharedImage(
gfx::GpuMemoryBuffer* gpu_memory_buffer,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
const gfx::ColorSpace& color_space,
uint32_t usage) override {
return gpu::Mailbox::Generate();
}
void UpdateSharedImage(const gpu::SyncToken& sync_token,
const gpu::Mailbox& mailbox) override {}
void DestroySharedImage(const gpu::SyncToken& sync_token, void DestroySharedImage(const gpu::SyncToken& sync_token,
const gpu::Mailbox& mailbox) override {} const gpu::Mailbox& mailbox) override {}
......
...@@ -11,11 +11,13 @@ ...@@ -11,11 +11,13 @@
#include "gpu/command_buffer/common/sync_token.h" #include "gpu/command_buffer/common/sync_token.h"
namespace gfx { namespace gfx {
class Size;
class ColorSpace; class ColorSpace;
class GpuMemoryBuffer;
class Size;
} // namespace gfx } // namespace gfx
namespace gpu { namespace gpu {
class GpuMemoryBufferManager;
// An interface to create shared images that can be imported into other APIs. // An interface to create shared images that can be imported into other APIs.
// This interface is thread-safe and (essentially) stateless. It is asynchronous // This interface is thread-safe and (essentially) stateless. It is asynchronous
...@@ -30,8 +32,9 @@ class SharedImageInterface { ...@@ -30,8 +32,9 @@ class SharedImageInterface {
// |usage| is a combination of |SharedImageUsage| bits that describes which // |usage| is a combination of |SharedImageUsage| bits that describes which
// API(s) the image will be used with. // API(s) the image will be used with.
// Returns a mailbox that can be imported into said APIs using their // Returns a mailbox that can be imported into said APIs using their
// corresponding mailbox functions (e.g. // corresponding shared image functions (e.g.
// RasterInterface::CreateAndConsumeTexture or // GLES2Interface::CreateAndTexStorage2DSharedImageCHROMIUM) or (deprecated)
// mailbox functions (e.g. RasterInterface::CreateAndConsumeTexture or
// GLES2Interface::CreateAndConsumeTextureCHROMIUM). // GLES2Interface::CreateAndConsumeTextureCHROMIUM).
// The |SharedImageInterface| keeps ownership of the image until // The |SharedImageInterface| keeps ownership of the image until
// |DestroySharedImage| is called or the interface itself is destroyed (e.g. // |DestroySharedImage| is called or the interface itself is destroyed (e.g.
...@@ -41,6 +44,31 @@ class SharedImageInterface { ...@@ -41,6 +44,31 @@ class SharedImageInterface {
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
uint32_t usage) = 0; uint32_t usage) = 0;
// Creates a shared image out of a GpuMemoryBuffer, using |color_space|.
// |usage| is a combination of |SharedImageUsage| bits that describes which
// API(s) the image will be used with. Format and size are derived from the
// GpuMemoryBuffer. |gpu_memory_buffer_manager| is the manager that created
// |gpu_memory_buffer|. If valid, |color_space| will be applied to the shared
// image (possibly overwriting the one set on the GpuMemoryBuffer).
// Returns a mailbox that can be imported into said APIs using their
// corresponding shared image functions (e.g.
// GLES2Interface::CreateAndTexStorage2DSharedImageCHROMIUM) or (deprecated)
// mailbox functions (e.g. RasterInterface::CreateAndConsumeTexture or
// GLES2Interface::CreateAndConsumeTextureCHROMIUM).
// The |SharedImageInterface| keeps ownership of the image until
// |DestroySharedImage| is called or the interface itself is destroyed (e.g.
// the GPU channel is lost).
virtual Mailbox CreateSharedImage(
gfx::GpuMemoryBuffer* gpu_memory_buffer,
GpuMemoryBufferManager* gpu_memory_buffer_manager,
const gfx::ColorSpace& color_space,
uint32_t usage) = 0;
// Updates a shared image after its GpuMemoryBuffer (if any) was modified on
// the CPU or through external devices, after |sync_token| has been released.
virtual void UpdateSharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) = 0;
// Destroys the shared image, unregistering its mailbox, after |sync_token| // Destroys the shared image, unregistering its mailbox, after |sync_token|
// has been released. After this call, the mailbox can't be used to reference // has been released. After this call, the mailbox can't be used to reference
// the image any more, however if the image was imported into other APIs, // the image any more, however if the image was imported into other APIs,
......
...@@ -56,6 +56,8 @@ class TestSharedImageBackingPassthrough : public SharedImageBacking { ...@@ -56,6 +56,8 @@ class TestSharedImageBackingPassthrough : public SharedImageBacking {
void SetCleared() override {} void SetCleared() override {}
void Update() override {}
bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override { bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override {
return false; return false;
} }
......
...@@ -3225,6 +3225,8 @@ class TestSharedImageBacking : public SharedImageBacking { ...@@ -3225,6 +3225,8 @@ class TestSharedImageBacking : public SharedImageBacking {
void SetCleared() override {} void SetCleared() override {}
void Update() override {}
bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override { bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override {
return false; return false;
} }
......
...@@ -63,6 +63,8 @@ class GPU_GLES2_EXPORT SharedImageBacking { ...@@ -63,6 +63,8 @@ class GPU_GLES2_EXPORT SharedImageBacking {
// unintiailized pixels. // unintiailized pixels.
virtual void SetCleared() = 0; virtual void SetCleared() = 0;
virtual void Update() = 0;
// Destroys the underlying backing. Must be called before destruction. // Destroys the underlying backing. Must be called before destruction.
virtual void Destroy() = 0; virtual void Destroy() = 0;
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
#include <memory> #include <memory>
#include "components/viz/common/resources/resource_format.h" #include "components/viz/common/resources/resource_format.h"
#include "gpu/ipc/common/surface_handle.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/gpu_memory_buffer.h"
namespace gfx { namespace gfx {
class Size; class Size;
...@@ -27,6 +30,15 @@ class SharedImageBackingFactory { ...@@ -27,6 +30,15 @@ class SharedImageBackingFactory {
const gfx::Size& size, const gfx::Size& size,
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
uint32_t usage) = 0; uint32_t usage) = 0;
virtual std::unique_ptr<SharedImageBacking> CreateSharedImage(
const Mailbox& mailbox,
int client_id,
gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat format,
SurfaceHandle surface_handle,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) = 0;
}; };
} // namespace gpu } // namespace gpu
......
...@@ -87,6 +87,8 @@ class SharedImageBackingAHardwareBuffer : public SharedImageBacking { ...@@ -87,6 +87,8 @@ class SharedImageBackingAHardwareBuffer : public SharedImageBacking {
is_cleared_ = true; is_cleared_ = true;
} }
void Update() override {}
bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override { bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override {
DCHECK(hardware_buffer_handle_.is_valid()); DCHECK(hardware_buffer_handle_.is_valid());
if (!GenGLTexture()) if (!GenGLTexture())
...@@ -363,4 +365,18 @@ SharedImageBackingFactoryAHardwareBuffer::CreateSharedImage( ...@@ -363,4 +365,18 @@ SharedImageBackingFactoryAHardwareBuffer::CreateSharedImage(
SharedImageBackingFactoryAHardwareBuffer::FormatInfo::FormatInfo() = default; SharedImageBackingFactoryAHardwareBuffer::FormatInfo::FormatInfo() = default;
SharedImageBackingFactoryAHardwareBuffer::FormatInfo::~FormatInfo() = default; SharedImageBackingFactoryAHardwareBuffer::FormatInfo::~FormatInfo() = default;
std::unique_ptr<SharedImageBacking>
SharedImageBackingFactoryAHardwareBuffer::CreateSharedImage(
const Mailbox& mailbox,
int client_id,
gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat buffer_format,
SurfaceHandle surface_handle,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) {
NOTIMPLEMENTED();
return nullptr;
}
} // namespace gpu } // namespace gpu
...@@ -39,6 +39,15 @@ class GPU_GLES2_EXPORT SharedImageBackingFactoryAHardwareBuffer ...@@ -39,6 +39,15 @@ class GPU_GLES2_EXPORT SharedImageBackingFactoryAHardwareBuffer
const gfx::Size& size, const gfx::Size& size,
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
uint32_t usage) override; uint32_t usage) override;
std::unique_ptr<SharedImageBacking> CreateSharedImage(
const Mailbox& mailbox,
int client_id,
gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat format,
SurfaceHandle surface_handle,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) override;
private: private:
struct FormatInfo { struct FormatInfo {
......
...@@ -48,8 +48,37 @@ class GPU_GLES2_EXPORT SharedImageBackingFactoryGLTexture ...@@ -48,8 +48,37 @@ class GPU_GLES2_EXPORT SharedImageBackingFactoryGLTexture
const gfx::Size& size, const gfx::Size& size,
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
uint32_t usage) override; uint32_t usage) override;
std::unique_ptr<SharedImageBacking> CreateSharedImage(
const Mailbox& mailbox,
int client_id,
gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat format,
SurfaceHandle surface_handle,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) override;
private: private:
scoped_refptr<gl::GLImage> MakeGLImage(int client_id,
gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat format,
SurfaceHandle surface_handle,
const gfx::Size& size);
std::unique_ptr<SharedImageBacking> MakeBacking(
const Mailbox& mailbox,
GLenum target,
GLuint service_id,
scoped_refptr<gl::GLImage> image,
gles2::Texture::ImageState image_state,
GLuint internal_format,
GLuint gl_format,
GLuint gl_type,
const gles2::Texture::CompatibilitySwizzle* swizzle,
bool is_cleared,
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage);
struct FormatInfo { struct FormatInfo {
FormatInfo(); FormatInfo();
~FormatInfo(); ~FormatInfo();
...@@ -89,6 +118,7 @@ class GPU_GLES2_EXPORT SharedImageBackingFactoryGLTexture ...@@ -89,6 +118,7 @@ class GPU_GLES2_EXPORT SharedImageBackingFactoryGLTexture
ImageFactory* image_factory_ = nullptr; ImageFactory* image_factory_ = nullptr;
FormatInfo format_info_[viz::RESOURCE_FORMAT_MAX + 1]; FormatInfo format_info_[viz::RESOURCE_FORMAT_MAX + 1];
GpuMemoryBufferFormatSet gpu_memory_buffer_formats_;
int32_t max_texture_size_ = 0; int32_t max_texture_size_ = 0;
bool texture_usage_angle_ = false; bool texture_usage_angle_ = false;
bool es3_capable_ = false; bool es3_capable_ = false;
......
...@@ -22,19 +22,23 @@ ...@@ -22,19 +22,23 @@
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/color_space.h" #include "ui/gfx/color_space.h"
#include "ui/gl/gl_bindings.h" #include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h" #include "ui/gl/gl_context.h"
#include "ui/gl/gl_image_shared_memory.h"
#include "ui/gl/gl_image_stub.h"
#include "ui/gl/gl_surface.h" #include "ui/gl/gl_surface.h"
#include "ui/gl/init/gl_factory.h" #include "ui/gl/init/gl_factory.h"
namespace gpu { namespace gpu {
namespace { namespace {
class SharedImageBackingFactoryGLTextureTest class SharedImageBackingFactoryGLTextureTestBase
: public testing::TestWithParam<bool> { : public testing::TestWithParam<bool> {
public: public:
void SetUp() override { void SetUpBase(const GpuDriverBugWorkarounds& workarounds,
ImageFactory* factory) {
surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size()); surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
ASSERT_TRUE(surface_); ASSERT_TRUE(surface_);
context_ = gl::init::CreateGLContext(nullptr, surface_.get(), context_ = gl::init::CreateGLContext(nullptr, surface_.get(),
...@@ -45,10 +49,8 @@ class SharedImageBackingFactoryGLTextureTest ...@@ -45,10 +49,8 @@ class SharedImageBackingFactoryGLTextureTest
GpuPreferences preferences; GpuPreferences preferences;
preferences.use_passthrough_cmd_decoder = use_passthrough(); preferences.use_passthrough_cmd_decoder = use_passthrough();
GpuDriverBugWorkarounds workarounds;
workarounds.max_texture_size = INT_MAX - 1;
backing_factory_ = std::make_unique<SharedImageBackingFactoryGLTexture>( backing_factory_ = std::make_unique<SharedImageBackingFactoryGLTexture>(
preferences, workarounds, GpuFeatureInfo(), &image_factory_); preferences, workarounds, GpuFeatureInfo(), factory);
scoped_refptr<gl::GLShareGroup> share_group = new gl::GLShareGroup(); scoped_refptr<gl::GLShareGroup> share_group = new gl::GLShareGroup();
context_state_ = new raster::RasterDecoderContextState( context_state_ = new raster::RasterDecoderContextState(
...@@ -72,7 +74,6 @@ class SharedImageBackingFactoryGLTextureTest ...@@ -72,7 +74,6 @@ class SharedImageBackingFactoryGLTextureTest
scoped_refptr<gl::GLSurface> surface_; scoped_refptr<gl::GLSurface> surface_;
scoped_refptr<gl::GLContext> context_; scoped_refptr<gl::GLContext> context_;
scoped_refptr<raster::RasterDecoderContextState> context_state_; scoped_refptr<raster::RasterDecoderContextState> context_state_;
TextureImageFactory image_factory_;
std::unique_ptr<SharedImageBackingFactoryGLTexture> backing_factory_; std::unique_ptr<SharedImageBackingFactoryGLTexture> backing_factory_;
gles2::MailboxManagerImpl mailbox_manager_; gles2::MailboxManagerImpl mailbox_manager_;
SharedImageManager shared_image_manager_; SharedImageManager shared_image_manager_;
...@@ -81,6 +82,19 @@ class SharedImageBackingFactoryGLTextureTest ...@@ -81,6 +82,19 @@ class SharedImageBackingFactoryGLTextureTest
shared_image_representation_factory_; shared_image_representation_factory_;
}; };
class SharedImageBackingFactoryGLTextureTest
: public SharedImageBackingFactoryGLTextureTestBase {
public:
void SetUp() override {
GpuDriverBugWorkarounds workarounds;
workarounds.max_texture_size = INT_MAX - 1;
SetUpBase(workarounds, &image_factory_);
}
protected:
TextureImageFactory image_factory_;
};
TEST_P(SharedImageBackingFactoryGLTextureTest, Basic) { TEST_P(SharedImageBackingFactoryGLTextureTest, Basic) {
auto mailbox = Mailbox::Generate(); auto mailbox = Mailbox::Generate();
auto format = viz::ResourceFormat::RGBA_8888; auto format = viz::ResourceFormat::RGBA_8888;
...@@ -330,9 +344,160 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, EstimatedSize) { ...@@ -330,9 +344,160 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, EstimatedSize) {
shared_image.reset(); shared_image.reset();
} }
class StubImage : public gl::GLImageStub {
public:
StubImage(const gfx::Size& size, gfx::BufferFormat format)
: size_(size), format_(format) {}
gfx::Size GetSize() override { return size_; }
unsigned GetInternalFormat() override {
return InternalFormatForGpuMemoryBufferFormat(format_);
}
bool BindTexImage(unsigned target) override {
if (!bound_) {
bound_ = true;
++update_counter_;
}
return true;
};
void ReleaseTexImage(unsigned target) override { bound_ = false; }
bool bound() const { return bound_; }
int update_counter() const { return update_counter_; }
private:
~StubImage() override = default;
gfx::Size size_;
gfx::BufferFormat format_;
bool bound_ = false;
int update_counter_ = 0;
};
class SharedImageBackingFactoryGLTextureWithGMBTest
: public SharedImageBackingFactoryGLTextureTestBase,
public gpu::ImageFactory {
public:
void SetUp() override { SetUpBase(GpuDriverBugWorkarounds(), this); }
scoped_refptr<gl::GLImage> GetImageFromMailbox(Mailbox mailbox) {
if (!use_passthrough()) {
auto representation =
shared_image_representation_factory_->ProduceGLTexture(mailbox);
DCHECK(representation);
return representation->GetTexture()->GetLevelImage(GL_TEXTURE_2D, 0);
} else {
auto representation =
shared_image_representation_factory_->ProduceGLTexturePassthrough(
mailbox);
DCHECK(representation);
return representation->GetTexturePassthrough()->GetLevelImage(
GL_TEXTURE_2D, 0);
}
}
protected:
// gpu::ImageFactory implementation.
scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer(
gfx::GpuMemoryBufferHandle handle,
const gfx::Size& size,
gfx::BufferFormat format,
int client_id,
gpu::SurfaceHandle surface_handle) override {
// pretend to handle NATIVE_PIXMAP types.
if (handle.type != gfx::NATIVE_PIXMAP)
return nullptr;
if (client_id != kClientId)
return nullptr;
return base::MakeRefCounted<StubImage>(size, format);
}
static constexpr int kClientId = 3;
};
TEST_P(SharedImageBackingFactoryGLTextureWithGMBTest,
GpuMemoryBufferImportEmpty) {
auto mailbox = Mailbox::Generate();
gfx::Size size(256, 256);
gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888;
auto color_space = gfx::ColorSpace::CreateSRGB();
uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
gfx::GpuMemoryBufferHandle handle;
auto backing = backing_factory_->CreateSharedImage(
mailbox, kClientId, std::move(handle), format, kNullSurfaceHandle, size,
color_space, usage);
EXPECT_FALSE(backing);
}
TEST_P(SharedImageBackingFactoryGLTextureWithGMBTest,
GpuMemoryBufferImportNative) {
auto mailbox = Mailbox::Generate();
gfx::Size size(256, 256);
gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888;
auto color_space = gfx::ColorSpace::CreateSRGB();
uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::NATIVE_PIXMAP;
auto backing = backing_factory_->CreateSharedImage(
mailbox, kClientId, std::move(handle), format, kNullSurfaceHandle, size,
color_space, usage);
ASSERT_TRUE(backing);
std::unique_ptr<SharedImageRepresentationFactoryRef> ref =
shared_image_manager_.Register(std::move(backing),
memory_type_tracker_.get());
scoped_refptr<gl::GLImage> image = GetImageFromMailbox(mailbox);
ASSERT_EQ(image->GetType(), gl::GLImage::Type::NONE);
auto* stub_image = static_cast<StubImage*>(image.get());
EXPECT_TRUE(stub_image->bound());
int update_counter = stub_image->update_counter();
ref->Update();
EXPECT_TRUE(stub_image->bound());
EXPECT_GT(stub_image->update_counter(), update_counter);
}
TEST_P(SharedImageBackingFactoryGLTextureWithGMBTest,
GpuMemoryBufferImportSharedMemory) {
auto mailbox = Mailbox::Generate();
gfx::Size size(256, 256);
gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888;
auto color_space = gfx::ColorSpace::CreateSRGB();
uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
size_t shm_size = 0u;
ASSERT_TRUE(gfx::BufferSizeForBufferFormatChecked(size, format, &shm_size));
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::SHARED_MEMORY_BUFFER;
handle.region = base::UnsafeSharedMemoryRegion::Create(shm_size);
ASSERT_TRUE(handle.region.IsValid());
handle.offset = 0;
handle.stride = static_cast<int32_t>(
gfx::RowSizeForBufferFormat(size.width(), format, 0));
auto backing = backing_factory_->CreateSharedImage(
mailbox, kClientId, std::move(handle), format, kNullSurfaceHandle, size,
color_space, usage);
ASSERT_TRUE(backing);
std::unique_ptr<SharedImageRepresentationFactoryRef> ref =
shared_image_manager_.Register(std::move(backing),
memory_type_tracker_.get());
scoped_refptr<gl::GLImage> image = GetImageFromMailbox(mailbox);
ASSERT_EQ(image->GetType(), gl::GLImage::Type::MEMORY);
auto* shm_image = static_cast<gl::GLImageSharedMemory*>(image.get());
EXPECT_EQ(size, shm_image->GetSize());
EXPECT_EQ(format, shm_image->format());
}
INSTANTIATE_TEST_CASE_P(Service, INSTANTIATE_TEST_CASE_P(Service,
SharedImageBackingFactoryGLTextureTest, SharedImageBackingFactoryGLTextureTest,
::testing::Bool()); ::testing::Bool());
INSTANTIATE_TEST_CASE_P(Service,
SharedImageBackingFactoryGLTextureWithGMBTest,
::testing::Bool());
} // anonymous namespace } // anonymous namespace
} // namespace gpu } // namespace gpu
...@@ -74,12 +74,6 @@ bool SharedImageFactory::CreateSharedImage(const Mailbox& mailbox, ...@@ -74,12 +74,6 @@ bool SharedImageFactory::CreateSharedImage(const Mailbox& mailbox,
const gfx::Size& size, const gfx::Size& size,
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
uint32_t usage) { uint32_t usage) {
if (shared_image_manager_->IsSharedImage(mailbox)) {
LOG(ERROR) << "CreateSharedImage: mailbox is already associated with a "
"SharedImage";
return false;
}
std::unique_ptr<SharedImageBacking> backing; std::unique_ptr<SharedImageBacking> backing;
bool using_wrapped_sk_image = wrapped_sk_image_factory_ && bool using_wrapped_sk_image = wrapped_sk_image_factory_ &&
(usage & SHARED_IMAGE_USAGE_OOP_RASTERIZATION); (usage & SHARED_IMAGE_USAGE_OOP_RASTERIZATION);
...@@ -91,31 +85,40 @@ bool SharedImageFactory::CreateSharedImage(const Mailbox& mailbox, ...@@ -91,31 +85,40 @@ bool SharedImageFactory::CreateSharedImage(const Mailbox& mailbox,
color_space, usage); color_space, usage);
} }
if (!backing) { return RegisterBacking(std::move(backing), !using_wrapped_sk_image);
LOG(ERROR) << "CreateSharedImage: could not create backing."; }
return false;
}
std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image = bool SharedImageFactory::CreateSharedImage(const Mailbox& mailbox,
shared_image_manager_->Register(std::move(backing), int client_id,
memory_tracker_.get()); gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat format,
SurfaceHandle surface_handle,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) {
// TODO(piman): depending on handle.type, choose platform-specific backing
// factory, e.g. SharedImageBackingFactoryAHardwareBuffer.
std::unique_ptr<SharedImageBacking> backing =
backing_factory_->CreateSharedImage(mailbox, client_id, std::move(handle),
format, surface_handle, size,
color_space, usage);
return RegisterBacking(std::move(backing), true);
}
// TODO(ericrk): Remove this once no legacy cases remain. bool SharedImageFactory::UpdateSharedImage(const Mailbox& mailbox) {
if (!using_wrapped_sk_image && auto it = shared_images_.find(mailbox);
!shared_image->ProduceLegacyMailbox(mailbox_manager_)) { if (it == shared_images_.end()) {
LOG(ERROR) << "CreateSharedImage: could not convert shared_image to legacy " LOG(ERROR) << "UpdateSharedImage: Could not find shared image mailbox";
"mailbox.";
return false; return false;
} }
(*it)->Update();
shared_images_.emplace(std::move(shared_image));
return true; return true;
} }
bool SharedImageFactory::DestroySharedImage(const Mailbox& mailbox) { bool SharedImageFactory::DestroySharedImage(const Mailbox& mailbox) {
auto it = shared_images_.find(mailbox); auto it = shared_images_.find(mailbox);
if (it == shared_images_.end()) { if (it == shared_images_.end()) {
LOG(ERROR) << "Could not find shared image mailbox"; LOG(ERROR) << "DestroySharedImage: Could not find shared image mailbox";
return false; return false;
} }
shared_images_.erase(it); shared_images_.erase(it);
...@@ -144,6 +147,37 @@ bool SharedImageFactory::OnMemoryDump( ...@@ -144,6 +147,37 @@ bool SharedImageFactory::OnMemoryDump(
return true; return true;
} }
bool SharedImageFactory::RegisterBacking(
std::unique_ptr<SharedImageBacking> backing,
bool legacy_mailbox) {
if (!backing) {
LOG(ERROR) << "CreateSharedImage: could not create backing.";
return false;
}
Mailbox mailbox = backing->mailbox();
if (shared_image_manager_->IsSharedImage(mailbox)) {
LOG(ERROR) << "CreateSharedImage: mailbox is already associated with a "
"SharedImage";
backing->Destroy();
return false;
}
std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
shared_image_manager_->Register(std::move(backing),
memory_tracker_.get());
// TODO(ericrk): Remove this once no legacy cases remain.
if (legacy_mailbox && !shared_image->ProduceLegacyMailbox(mailbox_manager_)) {
LOG(ERROR) << "CreateSharedImage: could not convert shared_image to legacy "
"mailbox.";
return false;
}
shared_images_.emplace(std::move(shared_image));
return true;
}
SharedImageRepresentationFactory::SharedImageRepresentationFactory( SharedImageRepresentationFactory::SharedImageRepresentationFactory(
SharedImageManager* manager, SharedImageManager* manager,
MemoryTracker* tracker) MemoryTracker* tracker)
......
...@@ -14,7 +14,9 @@ ...@@ -14,7 +14,9 @@
#include "gpu/command_buffer/service/shared_image_manager.h" #include "gpu/command_buffer/service/shared_image_manager.h"
#include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/gpu_gles2_export.h" #include "gpu/gpu_gles2_export.h"
#include "gpu/ipc/common/surface_handle.h"
#include "ui/gfx/buffer_types.h" #include "ui/gfx/buffer_types.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gl/gl_bindings.h" #include "ui/gl/gl_bindings.h"
namespace gpu { namespace gpu {
...@@ -50,6 +52,15 @@ class GPU_GLES2_EXPORT SharedImageFactory { ...@@ -50,6 +52,15 @@ class GPU_GLES2_EXPORT SharedImageFactory {
const gfx::Size& size, const gfx::Size& size,
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
uint32_t usage); uint32_t usage);
bool CreateSharedImage(const Mailbox& mailbox,
int client_id,
gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat format,
SurfaceHandle surface_handle,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage);
bool UpdateSharedImage(const Mailbox& mailbox);
bool DestroySharedImage(const Mailbox& mailbox); bool DestroySharedImage(const Mailbox& mailbox);
bool HasImages() const { return !shared_images_.empty(); } bool HasImages() const { return !shared_images_.empty(); }
void DestroyAllSharedImages(bool have_context); void DestroyAllSharedImages(bool have_context);
...@@ -59,6 +70,8 @@ class GPU_GLES2_EXPORT SharedImageFactory { ...@@ -59,6 +70,8 @@ class GPU_GLES2_EXPORT SharedImageFactory {
uint64_t client_tracing_id); uint64_t client_tracing_id);
private: private:
bool RegisterBacking(std::unique_ptr<SharedImageBacking> backing,
bool legacy_mailbox);
MailboxManager* mailbox_manager_; MailboxManager* mailbox_manager_;
SharedImageManager* shared_image_manager_; SharedImageManager* shared_image_manager_;
std::unique_ptr<MemoryTypeTracker> memory_tracker_; std::unique_ptr<MemoryTypeTracker> memory_tracker_;
......
...@@ -58,6 +58,7 @@ class MockSharedImageBacking : public SharedImageBacking { ...@@ -58,6 +58,7 @@ class MockSharedImageBacking : public SharedImageBacking {
MOCK_CONST_METHOD0(IsCleared, bool()); MOCK_CONST_METHOD0(IsCleared, bool());
MOCK_METHOD0(SetCleared, void()); MOCK_METHOD0(SetCleared, void());
MOCK_METHOD0(Update, void());
MOCK_METHOD0(Destroy, void()); MOCK_METHOD0(Destroy, void());
MOCK_METHOD1(ProduceLegacyMailbox, bool(MailboxManager*)); MOCK_METHOD1(ProduceLegacyMailbox, bool(MailboxManager*));
......
...@@ -60,6 +60,7 @@ class SharedImageRepresentationFactoryRef : public SharedImageRepresentation { ...@@ -60,6 +60,7 @@ class SharedImageRepresentationFactoryRef : public SharedImageRepresentation {
: SharedImageRepresentation(manager, backing, tracker) {} : SharedImageRepresentation(manager, backing, tracker) {}
const Mailbox& mailbox() const { return backing()->mailbox(); } const Mailbox& mailbox() const { return backing()->mailbox(); }
void Update() { backing()->Update(); }
bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) { bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) {
return backing()->ProduceLegacyMailbox(mailbox_manager); return backing()->ProduceLegacyMailbox(mailbox_manager);
} }
......
...@@ -50,6 +50,8 @@ class WrappedSkImage : public SharedImageBacking { ...@@ -50,6 +50,8 @@ class WrappedSkImage : public SharedImageBacking {
void SetCleared() override { cleared_ = true; } void SetCleared() override { cleared_ = true; }
void Update() override {}
void OnMemoryDump(const std::string& dump_name, void OnMemoryDump(const std::string& dump_name,
base::trace_event::MemoryAllocatorDump* dump, base::trace_event::MemoryAllocatorDump* dump,
base::trace_event::ProcessMemoryDump* pmd, base::trace_event::ProcessMemoryDump* pmd,
...@@ -233,6 +235,19 @@ std::unique_ptr<SharedImageBacking> WrappedSkImageFactory::CreateSharedImage( ...@@ -233,6 +235,19 @@ std::unique_ptr<SharedImageBacking> WrappedSkImageFactory::CreateSharedImage(
return texture; return texture;
} }
std::unique_ptr<SharedImageBacking> WrappedSkImageFactory::CreateSharedImage(
const Mailbox& mailbox,
int client_id,
gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat buffer_format,
SurfaceHandle surface_handle,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) {
NOTREACHED();
return nullptr;
}
std::unique_ptr<SharedImageRepresentationSkia> WrappedSkImage::ProduceSkia( std::unique_ptr<SharedImageRepresentationSkia> WrappedSkImage::ProduceSkia(
SharedImageManager* manager, SharedImageManager* manager,
MemoryTypeTracker* tracker) { MemoryTypeTracker* tracker) {
......
...@@ -33,6 +33,15 @@ class GPU_GLES2_EXPORT WrappedSkImageFactory ...@@ -33,6 +33,15 @@ class GPU_GLES2_EXPORT WrappedSkImageFactory
const gfx::Size& size, const gfx::Size& size,
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
uint32_t usage) override; uint32_t usage) override;
std::unique_ptr<SharedImageBacking> CreateSharedImage(
const Mailbox& mailbox,
int client_id,
gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat format,
SurfaceHandle surface_handle,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) override;
private: private:
RasterDecoderContextState* const context_state_; RasterDecoderContextState* const context_state_;
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "gpu/ipc/client/shared_image_interface_proxy.h" #include "gpu/ipc/client/shared_image_interface_proxy.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/ipc/client/gpu_channel_host.h" #include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/common/command_buffer_id.h" #include "gpu/ipc/common/command_buffer_id.h"
#include "gpu/ipc/common/gpu_messages.h" #include "gpu/ipc/common/gpu_messages.h"
...@@ -32,25 +34,102 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage( ...@@ -32,25 +34,102 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage(
params.release_id = ++next_release_id_; params.release_id = ++next_release_id_;
// Note: we enqueue the IPC under the lock to guarantee monotonicity of the // Note: we enqueue the IPC under the lock to guarantee monotonicity of the
// release ids as seen by the service. // release ids as seen by the service.
host_->EnqueueDeferredMessage( last_flush_id_ = host_->EnqueueDeferredMessage(
GpuChannelMsg_CreateSharedImage(route_id_, params)); GpuChannelMsg_CreateSharedImage(route_id_, params));
} }
return params.mailbox; return params.mailbox;
} }
Mailbox SharedImageInterfaceProxy::CreateSharedImage(
gfx::GpuMemoryBuffer* gpu_memory_buffer,
GpuMemoryBufferManager* gpu_memory_buffer_manager,
const gfx::ColorSpace& color_space,
uint32_t usage) {
DCHECK(gpu_memory_buffer_manager);
GpuChannelMsg_CreateGMBSharedImage_Params params;
params.mailbox = Mailbox::Generate();
params.handle = gpu_memory_buffer->CloneHandle();
params.size = gpu_memory_buffer->GetSize();
params.format = gpu_memory_buffer->GetFormat();
params.color_space = color_space;
params.usage = usage;
// TODO(piman): DCHECK GMB format support.
DCHECK(gpu::IsImageSizeValidForGpuMemoryBufferFormat(params.size,
params.format));
bool requires_sync_token = params.handle.type == gfx::IO_SURFACE_BUFFER;
{
base::AutoLock lock(lock_);
params.release_id = ++next_release_id_;
// Note: we send the IPC under the lock, after flushing previous work (if
// any) to guarantee monotonicity of the release ids as seen by the service.
// Although we don't strictly need to for correctness, we also flush
// DestroySharedImage messages, so that we get a chance to delete resources
// before creating new ones.
// TODO(piman): support messages with handles in EnqueueDeferredMessage.
host_->EnsureFlush(last_flush_id_);
host_->Send(
new GpuChannelMsg_CreateGMBSharedImage(route_id_, std::move(params)));
}
if (requires_sync_token) {
gpu::SyncToken sync_token = GenUnverifiedSyncToken();
// Force a synchronous IPC to validate sync token.
host_->VerifyFlush(UINT32_MAX);
sync_token.SetVerifyFlush();
gpu_memory_buffer_manager->SetDestructionSyncToken(gpu_memory_buffer,
sync_token);
}
return params.mailbox;
}
void SharedImageInterfaceProxy::UpdateSharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) {
std::vector<SyncToken> dependencies;
if (sync_token.HasData()) {
dependencies.push_back(sync_token);
SyncToken& new_token = dependencies.back();
if (!new_token.verified_flush()) {
// Only allow unverified sync tokens for the same channel.
DCHECK_EQ(sync_token.namespace_id(), gpu::CommandBufferNamespace::GPU_IO);
int sync_token_channel_id =
ChannelIdFromCommandBufferId(sync_token.command_buffer_id());
DCHECK_EQ(sync_token_channel_id, host_->channel_id());
new_token.SetVerifyFlush();
}
}
{
base::AutoLock lock(lock_);
last_flush_id_ = host_->EnqueueDeferredMessage(
GpuChannelMsg_UpdateSharedImage(route_id_, mailbox, ++next_release_id_),
std::move(dependencies));
}
}
void SharedImageInterfaceProxy::DestroySharedImage(const SyncToken& sync_token, void SharedImageInterfaceProxy::DestroySharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) { const Mailbox& mailbox) {
SyncToken new_token = sync_token; std::vector<SyncToken> dependencies;
if (!new_token.verified_flush()) { if (sync_token.HasData()) {
// Only allow unverified sync tokens for the same channel. dependencies.push_back(sync_token);
DCHECK_EQ(sync_token.namespace_id(), gpu::CommandBufferNamespace::GPU_IO); SyncToken& new_token = dependencies.back();
int sync_token_channel_id = if (!new_token.verified_flush()) {
ChannelIdFromCommandBufferId(sync_token.command_buffer_id()); // Only allow unverified sync tokens for the same channel.
DCHECK_EQ(sync_token_channel_id, host_->channel_id()); DCHECK_EQ(sync_token.namespace_id(), gpu::CommandBufferNamespace::GPU_IO);
new_token.SetVerifyFlush(); int sync_token_channel_id =
ChannelIdFromCommandBufferId(sync_token.command_buffer_id());
DCHECK_EQ(sync_token_channel_id, host_->channel_id());
new_token.SetVerifyFlush();
}
}
uint32_t flush_id = host_->EnqueueDeferredMessage(
GpuChannelMsg_DestroySharedImage(route_id_, mailbox),
std::move(dependencies));
{
base::AutoLock lock(lock_);
last_flush_id_ = flush_id;
} }
host_->EnqueueDeferredMessage(
GpuChannelMsg_DestroySharedImage(route_id_, mailbox), {new_token});
} }
SyncToken SharedImageInterfaceProxy::GenUnverifiedSyncToken() { SyncToken SharedImageInterfaceProxy::GenUnverifiedSyncToken() {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define GPU_IPC_CLIENT_SHARED_IMAGE_INTERFACE_PROXY_H_ #define GPU_IPC_CLIENT_SHARED_IMAGE_INTERFACE_PROXY_H_
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "gpu/command_buffer/client/shared_image_interface.h" #include "gpu/command_buffer/client/shared_image_interface.h"
namespace gpu { namespace gpu {
...@@ -21,6 +22,13 @@ class SharedImageInterfaceProxy : public SharedImageInterface { ...@@ -21,6 +22,13 @@ class SharedImageInterfaceProxy : public SharedImageInterface {
const gfx::Size& size, const gfx::Size& size,
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
uint32_t usage) override; uint32_t usage) override;
Mailbox CreateSharedImage(gfx::GpuMemoryBuffer* gpu_memory_buffer,
GpuMemoryBufferManager* gpu_memory_buffer_manager,
const gfx::ColorSpace& color_space,
uint32_t usage) override;
void UpdateSharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) override;
void DestroySharedImage(const SyncToken& sync_token, void DestroySharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) override; const Mailbox& mailbox) override;
SyncToken GenUnverifiedSyncToken() override; SyncToken GenUnverifiedSyncToken() override;
...@@ -28,9 +36,9 @@ class SharedImageInterfaceProxy : public SharedImageInterface { ...@@ -28,9 +36,9 @@ class SharedImageInterfaceProxy : public SharedImageInterface {
private: private:
GpuChannelHost* const host_; GpuChannelHost* const host_;
const int32_t route_id_; const int32_t route_id_;
// Protects next_release_id_.
base::Lock lock_; base::Lock lock_;
uint32_t next_release_id_ = 0; uint32_t next_release_id_ GUARDED_BY(lock_) = 0;
uint32_t last_flush_id_ GUARDED_BY(lock_) = 0;
}; };
} // namespace gpu } // namespace gpu
......
...@@ -83,6 +83,16 @@ IPC_STRUCT_BEGIN(GpuChannelMsg_CreateSharedImage_Params) ...@@ -83,6 +83,16 @@ IPC_STRUCT_BEGIN(GpuChannelMsg_CreateSharedImage_Params)
IPC_STRUCT_MEMBER(uint32_t, release_id) IPC_STRUCT_MEMBER(uint32_t, release_id)
IPC_STRUCT_END() IPC_STRUCT_END()
IPC_STRUCT_BEGIN(GpuChannelMsg_CreateGMBSharedImage_Params)
IPC_STRUCT_MEMBER(gpu::Mailbox, mailbox)
IPC_STRUCT_MEMBER(gfx::GpuMemoryBufferHandle, handle)
IPC_STRUCT_MEMBER(gfx::Size, size)
IPC_STRUCT_MEMBER(gfx::BufferFormat, format)
IPC_STRUCT_MEMBER(gfx::ColorSpace, color_space)
IPC_STRUCT_MEMBER(uint32_t, usage)
IPC_STRUCT_MEMBER(uint32_t, release_id)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(GpuChannelMsg_ScheduleImageDecode_Params) IPC_STRUCT_BEGIN(GpuChannelMsg_ScheduleImageDecode_Params)
IPC_STRUCT_MEMBER(std::vector<uint8_t>, encoded_data) IPC_STRUCT_MEMBER(std::vector<uint8_t>, encoded_data)
IPC_STRUCT_MEMBER(gfx::Size, output_size) IPC_STRUCT_MEMBER(gfx::Size, output_size)
...@@ -126,6 +136,11 @@ IPC_MESSAGE_CONTROL1(GpuChannelMsg_FlushDeferredMessages, ...@@ -126,6 +136,11 @@ IPC_MESSAGE_CONTROL1(GpuChannelMsg_FlushDeferredMessages,
IPC_MESSAGE_ROUTED1(GpuChannelMsg_CreateSharedImage, IPC_MESSAGE_ROUTED1(GpuChannelMsg_CreateSharedImage,
GpuChannelMsg_CreateSharedImage_Params /* params */) GpuChannelMsg_CreateSharedImage_Params /* params */)
IPC_MESSAGE_ROUTED1(GpuChannelMsg_CreateGMBSharedImage,
GpuChannelMsg_CreateGMBSharedImage_Params /* params */)
IPC_MESSAGE_ROUTED2(GpuChannelMsg_UpdateSharedImage,
gpu::Mailbox /* id */,
uint32_t /* release_id */)
IPC_MESSAGE_ROUTED1(GpuChannelMsg_DestroySharedImage, gpu::Mailbox /* id */) IPC_MESSAGE_ROUTED1(GpuChannelMsg_DestroySharedImage, gpu::Mailbox /* id */)
// Schedules a hardware-accelerated image decode in the GPU process. Renderers // Schedules a hardware-accelerated image decode in the GPU process. Renderers
......
...@@ -145,6 +145,55 @@ class InProcessCommandBuffer::SharedImageInterface ...@@ -145,6 +145,55 @@ class InProcessCommandBuffer::SharedImageInterface
return mailbox; return mailbox;
} }
Mailbox CreateSharedImage(gfx::GpuMemoryBuffer* gpu_memory_buffer,
GpuMemoryBufferManager* gpu_memory_buffer_manager,
const gfx::ColorSpace& color_space,
uint32_t usage) override {
DCHECK(gpu_memory_buffer_manager);
// TODO(piman): DCHECK GMB format support.
DCHECK(gpu::IsImageSizeValidForGpuMemoryBufferFormat(
gpu_memory_buffer->GetSize(), gpu_memory_buffer->GetFormat()));
auto mailbox = Mailbox::Generate();
gfx::GpuMemoryBufferHandle handle = gpu_memory_buffer->CloneHandle();
bool requires_sync_token = handle.type == gfx::IO_SURFACE_BUFFER;
SyncToken sync_token;
{
base::AutoLock lock(lock_);
sync_token = MakeSyncToken(next_fence_sync_release_++);
// Note: we enqueue the task under the lock to guarantee monotonicity of
// the release ids as seen by the service. Unretained is safe because
// InProcessCommandBuffer synchronizes with the GPU thread at destruction
// time, cancelling tasks, before |this| is destroyed.
parent_->ScheduleGpuTask(base::BindOnce(
&InProcessCommandBuffer::CreateGMBSharedImageOnGpuThread,
parent_->gpu_thread_weak_ptr_factory_.GetWeakPtr(), mailbox,
std::move(handle), gpu_memory_buffer->GetFormat(),
gpu_memory_buffer->GetSize(), color_space, usage, sync_token));
}
if (requires_sync_token) {
sync_token.SetVerifyFlush();
gpu_memory_buffer_manager->SetDestructionSyncToken(gpu_memory_buffer,
sync_token);
}
return mailbox;
}
void UpdateSharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) override {
base::AutoLock lock(lock_);
// Note: we enqueue the task under the lock to guarantee monotonicity of
// the release ids as seen by the service. Unretained is safe because
// InProcessCommandBuffer synchronizes with the GPU thread at destruction
// time, cancelling tasks, before |this| is destroyed.
parent_->ScheduleGpuTask(
base::BindOnce(&InProcessCommandBuffer::UpdateSharedImageOnGpuThread,
parent_->gpu_thread_weak_ptr_factory_.GetWeakPtr(),
mailbox, MakeSyncToken(next_fence_sync_release_++)),
{sync_token});
}
void DestroySharedImage(const SyncToken& sync_token, void DestroySharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) override { const Mailbox& mailbox) override {
// Use sync token dependency to ensure that the destroy task does not run // Use sync token dependency to ensure that the destroy task does not run
...@@ -1241,6 +1290,17 @@ void InProcessCommandBuffer::GetGpuFenceOnGpuThread( ...@@ -1241,6 +1290,17 @@ void InProcessCommandBuffer::GetGpuFenceOnGpuThread(
base::BindOnce(std::move(callback), std::move(gpu_fence))); base::BindOnce(std::move(callback), std::move(gpu_fence)));
} }
void InProcessCommandBuffer::LazyCreateSharedImageFactory() {
if (shared_image_factory_)
return;
shared_image_factory_ = std::make_unique<SharedImageFactory>(
GetGpuPreferences(), context_group_->feature_info()->workarounds(),
GetGpuFeatureInfo(), context_state_.get(),
context_group_->mailbox_manager(), task_executor_->shared_image_manager(),
image_factory_, nullptr);
}
void InProcessCommandBuffer::CreateSharedImageOnGpuThread( void InProcessCommandBuffer::CreateSharedImageOnGpuThread(
const Mailbox& mailbox, const Mailbox& mailbox,
viz::ResourceFormat format, viz::ResourceFormat format,
...@@ -1251,13 +1311,7 @@ void InProcessCommandBuffer::CreateSharedImageOnGpuThread( ...@@ -1251,13 +1311,7 @@ void InProcessCommandBuffer::CreateSharedImageOnGpuThread(
DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
if (!MakeCurrent()) if (!MakeCurrent())
return; return;
if (!shared_image_factory_) { LazyCreateSharedImageFactory();
shared_image_factory_ = std::make_unique<SharedImageFactory>(
GetGpuPreferences(), context_group_->feature_info()->workarounds(),
GetGpuFeatureInfo(), context_state_.get(),
context_group_->mailbox_manager(),
task_executor_->shared_image_manager(), image_factory_, nullptr);
}
if (!shared_image_factory_->CreateSharedImage(mailbox, format, size, if (!shared_image_factory_->CreateSharedImage(mailbox, format, size,
color_space, usage)) { color_space, usage)) {
// Signal errors by losing the command buffer. // Signal errors by losing the command buffer.
...@@ -1268,6 +1322,47 @@ void InProcessCommandBuffer::CreateSharedImageOnGpuThread( ...@@ -1268,6 +1322,47 @@ void InProcessCommandBuffer::CreateSharedImageOnGpuThread(
shared_image_client_state_->ReleaseFenceSync(sync_token.release_count()); shared_image_client_state_->ReleaseFenceSync(sync_token.release_count());
} }
void InProcessCommandBuffer::CreateGMBSharedImageOnGpuThread(
const Mailbox& mailbox,
gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage,
const SyncToken& sync_token) {
DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
if (!MakeCurrent())
return;
LazyCreateSharedImageFactory();
// TODO(piman): add support for SurfaceHandle (for backbuffers for ozone/drm).
SurfaceHandle surface_handle = kNullSurfaceHandle;
if (!shared_image_factory_->CreateSharedImage(
mailbox, kInProcessCommandBufferClientId, std::move(handle), format,
surface_handle, size, color_space, usage)) {
// Signal errors by losing the command buffer.
command_buffer_->SetParseError(error::kLostContext);
return;
}
context_group_->mailbox_manager()->PushTextureUpdates(sync_token);
shared_image_client_state_->ReleaseFenceSync(sync_token.release_count());
}
void InProcessCommandBuffer::UpdateSharedImageOnGpuThread(
const Mailbox& mailbox,
const SyncToken& sync_token) {
DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
if (!MakeCurrent())
return;
if (!shared_image_factory_ ||
!shared_image_factory_->UpdateSharedImage(mailbox)) {
// Signal errors by losing the command buffer.
command_buffer_->SetParseError(error::kLostContext);
return;
}
context_group_->mailbox_manager()->PushTextureUpdates(sync_token);
shared_image_client_state_->ReleaseFenceSync(sync_token.release_count());
}
void InProcessCommandBuffer::DestroySharedImageOnGpuThread( void InProcessCommandBuffer::DestroySharedImageOnGpuThread(
const Mailbox& mailbox) { const Mailbox& mailbox) {
DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
......
...@@ -268,12 +268,22 @@ class GL_IN_PROCESS_CONTEXT_EXPORT InProcessCommandBuffer ...@@ -268,12 +268,22 @@ class GL_IN_PROCESS_CONTEXT_EXPORT InProcessCommandBuffer
void GetGpuFenceOnGpuThread( void GetGpuFenceOnGpuThread(
uint32_t gpu_fence_id, uint32_t gpu_fence_id,
base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback); base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback);
void LazyCreateSharedImageFactory();
void CreateSharedImageOnGpuThread(const Mailbox& mailbox, void CreateSharedImageOnGpuThread(const Mailbox& mailbox,
viz::ResourceFormat format, viz::ResourceFormat format,
const gfx::Size& size, const gfx::Size& size,
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
uint32_t usage, uint32_t usage,
const SyncToken& sync_token); const SyncToken& sync_token);
void CreateGMBSharedImageOnGpuThread(const Mailbox& mailbox,
gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage,
const SyncToken& sync_token);
void UpdateSharedImageOnGpuThread(const Mailbox& mailbox,
const SyncToken& sync_token);
void DestroySharedImageOnGpuThread(const Mailbox& mailbox); void DestroySharedImageOnGpuThread(const Mailbox& mailbox);
// Callbacks on the gpu thread. // Callbacks on the gpu thread.
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include "gpu/command_buffer/service/scheduler.h" #include "gpu/command_buffer/service/scheduler.h"
#include "gpu/command_buffer/service/shared_image_factory.h" #include "gpu/command_buffer/service/shared_image_factory.h"
#include "gpu/ipc/common/command_buffer_id.h" #include "gpu/ipc/common/command_buffer_id.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "gpu/ipc/service/gpu_channel.h" #include "gpu/ipc/service/gpu_channel.h"
#include "gpu/ipc/service/gpu_channel_manager.h" #include "gpu/ipc/service/gpu_channel_manager.h"
#include "gpu/ipc/service/gpu_memory_buffer_factory.h" #include "gpu/ipc/service/gpu_memory_buffer_factory.h"
...@@ -48,6 +47,9 @@ bool SharedImageStub::OnMessageReceived(const IPC::Message& msg) { ...@@ -48,6 +47,9 @@ bool SharedImageStub::OnMessageReceived(const IPC::Message& msg) {
bool handled = true; bool handled = true;
IPC_BEGIN_MESSAGE_MAP(SharedImageStub, msg) IPC_BEGIN_MESSAGE_MAP(SharedImageStub, msg)
IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateSharedImage, OnCreateSharedImage) IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateSharedImage, OnCreateSharedImage)
IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateGMBSharedImage,
OnCreateGMBSharedImage)
IPC_MESSAGE_HANDLER(GpuChannelMsg_UpdateSharedImage, OnUpdateSharedImage)
IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroySharedImage, OnDestroySharedImage) IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroySharedImage, OnDestroySharedImage)
IPC_MESSAGE_UNHANDLED(handled = false) IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP() IPC_END_MESSAGE_MAP()
...@@ -78,6 +80,56 @@ void SharedImageStub::OnCreateSharedImage( ...@@ -78,6 +80,56 @@ void SharedImageStub::OnCreateSharedImage(
sync_point_client_state_->ReleaseFenceSync(params.release_id); sync_point_client_state_->ReleaseFenceSync(params.release_id);
} }
void SharedImageStub::OnCreateGMBSharedImage(
GpuChannelMsg_CreateGMBSharedImage_Params params) {
TRACE_EVENT2("gpu", "SharedImageStub::OnCreateSharedImage", "width",
params.size.width(), "height", params.size.height());
if (!MakeContextCurrentAndCreateFactory()) {
OnError();
return;
}
// TODO(piman): add support for SurfaceHandle (for backbuffers for ozone/drm).
SurfaceHandle surface_handle = kNullSurfaceHandle;
if (!factory_->CreateSharedImage(params.mailbox, channel_->client_id(),
std::move(params.handle), params.format,
surface_handle, params.size,
params.color_space, params.usage)) {
LOG(ERROR) << "SharedImageStub: Unable to create shared image";
OnError();
return;
}
SyncToken sync_token(sync_point_client_state_->namespace_id(),
sync_point_client_state_->command_buffer_id(),
params.release_id);
auto* mailbox_manager = channel_->gpu_channel_manager()->mailbox_manager();
mailbox_manager->PushTextureUpdates(sync_token);
sync_point_client_state_->ReleaseFenceSync(params.release_id);
}
void SharedImageStub::OnUpdateSharedImage(const Mailbox& mailbox,
uint32_t release_id) {
TRACE_EVENT0("gpu", "SharedImageStub::OnDestroySharedImage");
if (!MakeContextCurrentAndCreateFactory()) {
OnError();
return;
}
if (!factory_->UpdateSharedImage(mailbox)) {
LOG(ERROR) << "SharedImageStub: Unable to destroy shared image";
OnError();
return;
}
SyncToken sync_token(sync_point_client_state_->namespace_id(),
sync_point_client_state_->command_buffer_id(),
release_id);
auto* mailbox_manager = channel_->gpu_channel_manager()->mailbox_manager();
mailbox_manager->PushTextureUpdates(sync_token);
sync_point_client_state_->ReleaseFenceSync(release_id);
}
void SharedImageStub::OnDestroySharedImage(const Mailbox& mailbox) { void SharedImageStub::OnDestroySharedImage(const Mailbox& mailbox) {
TRACE_EVENT0("gpu", "SharedImageStub::OnDestroySharedImage"); TRACE_EVENT0("gpu", "SharedImageStub::OnDestroySharedImage");
if (!MakeContextCurrentAndCreateFactory()) { if (!MakeContextCurrentAndCreateFactory()) {
......
...@@ -9,10 +9,9 @@ ...@@ -9,10 +9,9 @@
#include "components/viz/common/resources/resource_format.h" #include "components/viz/common/resources/resource_format.h"
#include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/sync_point_manager.h" #include "gpu/command_buffer/service/sync_point_manager.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "ipc/ipc_listener.h" #include "ipc/ipc_listener.h"
struct GpuChannelMsg_CreateSharedImage_Params;
namespace gpu { namespace gpu {
struct Mailbox; struct Mailbox;
class GpuChannel; class GpuChannel;
...@@ -48,6 +47,8 @@ class SharedImageStub : public IPC::Listener, ...@@ -48,6 +47,8 @@ class SharedImageStub : public IPC::Listener,
private: private:
void OnCreateSharedImage( void OnCreateSharedImage(
const GpuChannelMsg_CreateSharedImage_Params& params); const GpuChannelMsg_CreateSharedImage_Params& params);
void OnCreateGMBSharedImage(GpuChannelMsg_CreateGMBSharedImage_Params params);
void OnUpdateSharedImage(const Mailbox& mailbox, uint32_t release_id);
void OnDestroySharedImage(const Mailbox& mailbox); void OnDestroySharedImage(const Mailbox& mailbox);
bool MakeContextCurrentAndCreateFactory(); bool MakeContextCurrentAndCreateFactory();
void OnError(); void OnError();
......
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