mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
WIP on replacing texture contents.
This commit is contained in:
parent
cc57340c5e
commit
5110652812
@ -10,6 +10,7 @@
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/fml/mapping.h"
|
||||
#include "impeller/compositor/texture_descriptor.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
@ -46,6 +47,7 @@ enum class StorageMode {
|
||||
|
||||
class Context;
|
||||
class DeviceBuffer;
|
||||
class Texture;
|
||||
|
||||
class Allocator {
|
||||
public:
|
||||
@ -55,6 +57,9 @@ class Allocator {
|
||||
|
||||
std::shared_ptr<DeviceBuffer> CreateBuffer(StorageMode mode, size_t length);
|
||||
|
||||
std::shared_ptr<Texture> CreateTexture(StorageMode mode,
|
||||
const TextureDescriptor& desc);
|
||||
|
||||
std::shared_ptr<DeviceBuffer> CreateBufferWithCopy(const uint8_t* buffer,
|
||||
size_t length);
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "flutter/fml/logging.h"
|
||||
#include "impeller/compositor/buffer.h"
|
||||
#include "impeller/compositor/device_buffer.h"
|
||||
#include "impeller/compositor/formats_metal.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
@ -26,11 +27,11 @@ bool Allocator::IsValid() const {
|
||||
return is_valid_;
|
||||
}
|
||||
|
||||
static MTLResourceOptions ResourceOptionsFromStorageType(StorageMode type) {
|
||||
static MTLResourceOptions ToMTLResourceOptions(StorageMode type) {
|
||||
switch (type) {
|
||||
case StorageMode::kHostVisible:
|
||||
#if OS_IOS
|
||||
return MTLStorageModeShared;
|
||||
return MTLResourceStorageModeShared;
|
||||
#else
|
||||
return MTLResourceStorageModeManaged;
|
||||
#endif
|
||||
@ -38,11 +39,33 @@ static MTLResourceOptions ResourceOptionsFromStorageType(StorageMode type) {
|
||||
return MTLResourceStorageModePrivate;
|
||||
case StorageMode::kDeviceTransient:
|
||||
#if OS_IOS
|
||||
return MTLStorageModeMemoryless;
|
||||
return MTLResourceStorageModeMemoryless;
|
||||
#else
|
||||
return MTLResourceStorageModePrivate;
|
||||
#endif
|
||||
}
|
||||
|
||||
return MTLResourceStorageModePrivate;
|
||||
}
|
||||
|
||||
static MTLStorageMode ToMTLStorageMode(StorageMode mode) {
|
||||
switch (mode) {
|
||||
case StorageMode::kHostVisible:
|
||||
#if OS_IOS
|
||||
return MTLStorageModeShared;
|
||||
#else
|
||||
return MTLStorageModeManaged;
|
||||
#endif
|
||||
case StorageMode::kDevicePrivate:
|
||||
return MTLStorageModePrivate;
|
||||
case StorageMode::kDeviceTransient:
|
||||
#if OS_IOS
|
||||
return MTLStorageModeMemoryless;
|
||||
#else
|
||||
return MTLStorageModePrivate;
|
||||
#endif
|
||||
}
|
||||
return MTLStorageModeShared;
|
||||
}
|
||||
|
||||
bool Allocator::RequiresExplicitHostSynchronization(StorageMode mode) {
|
||||
@ -59,6 +82,16 @@ bool Allocator::RequiresExplicitHostSynchronization(StorageMode mode) {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::shared_ptr<DeviceBuffer> Allocator::CreateBuffer(StorageMode mode,
|
||||
size_t length) {
|
||||
auto buffer = [device_ newBufferWithLength:length
|
||||
options:ToMTLResourceOptions(mode)];
|
||||
if (!buffer) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::shared_ptr<DeviceBuffer>(new DeviceBuffer(buffer, length, mode));
|
||||
}
|
||||
|
||||
std::shared_ptr<DeviceBuffer> Allocator::CreateBufferWithCopy(
|
||||
const uint8_t* buffer,
|
||||
size_t length) {
|
||||
@ -82,15 +115,20 @@ std::shared_ptr<DeviceBuffer> Allocator::CreateBufferWithCopy(
|
||||
return CreateBufferWithCopy(mapping.GetMapping(), mapping.GetSize());
|
||||
}
|
||||
|
||||
std::shared_ptr<DeviceBuffer> Allocator::CreateBuffer(StorageMode mode,
|
||||
size_t length) {
|
||||
auto buffer =
|
||||
[device_ newBufferWithLength:length
|
||||
options:ResourceOptionsFromStorageType(mode)];
|
||||
if (!buffer) {
|
||||
std::shared_ptr<Texture> Allocator::CreateTexture(
|
||||
StorageMode mode,
|
||||
const TextureDescriptor& desc) {
|
||||
if (!IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::shared_ptr<DeviceBuffer>(new DeviceBuffer(buffer, length, mode));
|
||||
|
||||
auto mtl_texture_desc = ToMTLTextureDescriptor(desc);
|
||||
mtl_texture_desc.storageMode = ToMTLStorageMode(mode);
|
||||
auto texture = [device_ newTextureWithDescriptor:mtl_texture_desc];
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_shared<Texture>(desc, texture);
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@ -30,20 +30,14 @@ std::shared_ptr<Texture> DeviceBuffer::MakeTexture(TextureDescriptor desc,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto mtl_desc = [[MTLTextureDescriptor alloc] init];
|
||||
mtl_desc.pixelFormat = ToMTLPixelFormat(desc.format);
|
||||
mtl_desc.width = desc.size.width;
|
||||
mtl_desc.height = desc.size.height;
|
||||
mtl_desc.mipmapLevelCount = desc.mip_count;
|
||||
|
||||
auto texture = [buffer_ newTextureWithDescriptor:mtl_desc
|
||||
auto texture = [buffer_ newTextureWithDescriptor:ToMTLTextureDescriptor(desc)
|
||||
offset:offset
|
||||
bytesPerRow:desc.GetBytesPerRow()];
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_shared<Texture>(texture);
|
||||
return std::make_shared<Texture>(desc, texture);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool DeviceBuffer::CopyHostBuffer(const uint8_t* source,
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "impeller/compositor/formats.h"
|
||||
#include "impeller/compositor/texture_descriptor.h"
|
||||
#include "impeller/geometry/color.h"
|
||||
|
||||
namespace impeller {
|
||||
@ -244,8 +245,6 @@ constexpr MTLClearColor ToMTLClearColor(const Color& color) {
|
||||
return MTLClearColorMake(color.red, color.green, color.blue, color.alpha);
|
||||
}
|
||||
|
||||
RenderPassDescriptor FromMTLRenderPassDescriptor(MTLRenderPassDescriptor*);
|
||||
|
||||
MTLRenderPipelineColorAttachmentDescriptor*
|
||||
ToMTLRenderPipelineColorAttachmentDescriptor(
|
||||
ColorAttachmentDescriptor descriptor);
|
||||
@ -255,4 +254,6 @@ MTLDepthStencilDescriptor* ToMTLDepthStencilDescriptor(
|
||||
std::optional<StencilAttachmentDescriptor> front,
|
||||
std::optional<StencilAttachmentDescriptor> back);
|
||||
|
||||
MTLTextureDescriptor* ToMTLTextureDescriptor(const TextureDescriptor& desc);
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@ -77,61 +77,13 @@ MTLDepthStencilDescriptor* ToMTLDepthStencilDescriptor(
|
||||
return des;
|
||||
}
|
||||
|
||||
static bool ConfigureRenderPassAttachment(
|
||||
RenderPassAttachment& attachment,
|
||||
MTLRenderPassAttachmentDescriptor* desc) {
|
||||
attachment.texture = std::make_shared<Texture>(desc.texture);
|
||||
attachment.load_action = FromMTLLoadAction(desc.loadAction);
|
||||
attachment.store_action = FromMTLStoreAction(desc.storeAction);
|
||||
return attachment;
|
||||
}
|
||||
|
||||
static ColorRenderPassAttachment FromMTLRenderPassColorAttachmentDescriptor(
|
||||
MTLRenderPassColorAttachmentDescriptor* desc) {
|
||||
ColorRenderPassAttachment attachment;
|
||||
ConfigureRenderPassAttachment(attachment, desc);
|
||||
auto clear = desc.clearColor;
|
||||
attachment.clear_color =
|
||||
Color{static_cast<Scalar>(clear.red), static_cast<Scalar>(clear.green),
|
||||
static_cast<Scalar>(clear.blue), static_cast<Scalar>(clear.alpha)};
|
||||
return attachment;
|
||||
}
|
||||
|
||||
static DepthRenderPassAttachment FromMTLRenderPassDepthAttachmentDescriptor(
|
||||
MTLRenderPassDepthAttachmentDescriptor* desc) {
|
||||
DepthRenderPassAttachment attachment;
|
||||
ConfigureRenderPassAttachment(attachment, desc);
|
||||
attachment.clear_depth = desc.clearDepth;
|
||||
return attachment;
|
||||
}
|
||||
|
||||
static StencilRenderPassAttachment FromMTLRenderPassStencilAttachmentDescriptor(
|
||||
MTLRenderPassStencilAttachmentDescriptor* desc) {
|
||||
StencilRenderPassAttachment attachment;
|
||||
ConfigureRenderPassAttachment(attachment, desc);
|
||||
attachment.clear_stencil = desc.clearStencil;
|
||||
return attachment;
|
||||
}
|
||||
|
||||
RenderPassDescriptor FromMTLRenderPassDescriptor(
|
||||
MTLRenderPassDescriptor* desc) {
|
||||
RenderPassDescriptor result;
|
||||
if (!desc) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// From https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
|
||||
constexpr size_t kMaxPossibleColorAttachments = 8u;
|
||||
for (size_t i = 0; i < kMaxPossibleColorAttachments; i++) {
|
||||
result.SetColorAttachment(
|
||||
FromMTLRenderPassColorAttachmentDescriptor(desc.colorAttachments[i]),
|
||||
i);
|
||||
}
|
||||
result.SetDepthAttachment(
|
||||
FromMTLRenderPassDepthAttachmentDescriptor(desc.depthAttachment));
|
||||
result.SetStencilAttachment(
|
||||
FromMTLRenderPassStencilAttachmentDescriptor(desc.stencilAttachment));
|
||||
return result;
|
||||
MTLTextureDescriptor* ToMTLTextureDescriptor(const TextureDescriptor& desc) {
|
||||
auto mtl_desc = [[MTLTextureDescriptor alloc] init];
|
||||
mtl_desc.pixelFormat = ToMTLPixelFormat(desc.format);
|
||||
mtl_desc.width = desc.size.width;
|
||||
mtl_desc.height = desc.size.height;
|
||||
mtl_desc.mipmapLevelCount = desc.mip_count;
|
||||
return mtl_desc;
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@ -49,7 +49,7 @@ class RenderPassDescriptor {
|
||||
|
||||
bool HasColorAttachment(size_t index) const;
|
||||
|
||||
std::optional<Size> GetColorAttachmentSize(size_t index) const;
|
||||
std::optional<ISize> GetColorAttachmentSize(size_t index) const;
|
||||
|
||||
RenderPassDescriptor& SetColorAttachment(ColorRenderPassAttachment attachment,
|
||||
size_t index);
|
||||
|
||||
@ -25,7 +25,7 @@ bool RenderPassDescriptor::HasColorAttachment(size_t index) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::optional<Size> RenderPassDescriptor::GetColorAttachmentSize(
|
||||
std::optional<ISize> RenderPassDescriptor::GetColorAttachmentSize(
|
||||
size_t index) const {
|
||||
auto found = colors_.find(index);
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ class Surface {
|
||||
|
||||
~Surface();
|
||||
|
||||
const Size& GetSize() const;
|
||||
const ISize& GetSize() const;
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
@ -29,7 +29,7 @@ class Surface {
|
||||
|
||||
private:
|
||||
RenderPassDescriptor desc_;
|
||||
Size size_;
|
||||
ISize size_;
|
||||
|
||||
bool is_valid_ = false;
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ Surface::Surface(RenderPassDescriptor target_desc)
|
||||
|
||||
Surface::~Surface() = default;
|
||||
|
||||
const Size& Surface::GetSize() const {
|
||||
const ISize& Surface::GetSize() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <Metal/Metal.h>
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
@ -15,18 +17,26 @@ namespace impeller {
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
Texture(id<MTLTexture> texture);
|
||||
Texture(TextureDescriptor desc, id<MTLTexture> texture);
|
||||
|
||||
~Texture();
|
||||
|
||||
void SetLabel(const std::string_view& label);
|
||||
|
||||
[[nodiscard]] bool SetContents(const uint8_t* contents,
|
||||
size_t length,
|
||||
size_t mip_level = 0u);
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
Size GetSize() const;
|
||||
ISize GetSize() const;
|
||||
|
||||
id<MTLTexture> GetMTLTexture() const;
|
||||
|
||||
private:
|
||||
id<MTLTexture> texture_;
|
||||
const TextureDescriptor desc_;
|
||||
id<MTLTexture> texture_ = nullptr;
|
||||
bool is_valid_ = false;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(Texture);
|
||||
};
|
||||
|
||||
@ -6,13 +6,39 @@
|
||||
|
||||
namespace impeller {
|
||||
|
||||
Texture::Texture(id<MTLTexture> texture) : texture_(texture) {}
|
||||
Texture::Texture(TextureDescriptor desc, id<MTLTexture> texture)
|
||||
: desc_(std::move(desc)), texture_(texture) {
|
||||
if (!desc_.IsValid() || !texture_) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_valid_ = true;
|
||||
}
|
||||
|
||||
Texture::~Texture() = default;
|
||||
|
||||
Size Texture::GetSize() const {
|
||||
return {static_cast<Scalar>(texture_.width),
|
||||
static_cast<Scalar>(texture_.height)};
|
||||
bool Texture::SetContents(const uint8_t* contents,
|
||||
size_t length,
|
||||
size_t mip_level) {
|
||||
if (!IsValid() || !contents) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FML_CHECK(false);
|
||||
return false;
|
||||
|
||||
// MTLRegionMake2D(NSUInteger x, NSUInteger y, NSUInteger width,
|
||||
// NSUInteger height)
|
||||
|
||||
// [texture_ replaceRegion:(MTLRegion)
|
||||
// mipmapLevel:(NSUInteger)withBytes:(nonnull const
|
||||
// void*)bytesPerRow
|
||||
// :(NSUInteger)];
|
||||
}
|
||||
|
||||
ISize Texture::GetSize() const {
|
||||
return {static_cast<ISize::Type>(texture_.width),
|
||||
static_cast<ISize::Type>(texture_.height)};
|
||||
}
|
||||
|
||||
id<MTLTexture> Texture::GetMTLTexture() const {
|
||||
@ -20,7 +46,7 @@ id<MTLTexture> Texture::GetMTLTexture() const {
|
||||
}
|
||||
|
||||
bool Texture::IsValid() const {
|
||||
return texture_;
|
||||
return is_valid_;
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@ -269,9 +269,9 @@ struct Matrix {
|
||||
|
||||
Matrix operator+(const Matrix& m) const;
|
||||
|
||||
static constexpr Matrix MakeOrthographic(const Size& size) {
|
||||
static constexpr Matrix MakeOrthographic(Scalar width, Scalar height) {
|
||||
// Per assumptions about NDC documented above.
|
||||
const auto scale = MakeScale({1.0f / size.width, -1.0f / size.height, 1.0});
|
||||
const auto scale = MakeScale({1.0f / width, -1.0f / height, 1.0});
|
||||
const auto translate = MakeTranslation({-1.0, 1.0, 0.5});
|
||||
return translate * scale;
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "flutter/fml/paths.h"
|
||||
#include "flutter/testing/testing.h"
|
||||
#include "impeller/compositor/context.h"
|
||||
#include "impeller/compositor/formats_metal.h"
|
||||
#include "impeller/compositor/render_pass.h"
|
||||
#include "impeller/compositor/renderer.h"
|
||||
#include "impeller/compositor/surface.h"
|
||||
@ -108,8 +109,15 @@ bool Playground::OpenPlaygroundHere(Renderer::RenderCallback render_callback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TextureDescriptor color0_desc;
|
||||
color0_desc.format = PixelFormat::kPixelFormat_B8G8R8A8_UNormInt;
|
||||
color0_desc.size = {
|
||||
static_cast<ISize::Type>(current_drawable.texture.width),
|
||||
static_cast<ISize::Type>(current_drawable.texture.height)};
|
||||
|
||||
ColorRenderPassAttachment color0;
|
||||
color0.texture = std::make_shared<Texture>(current_drawable.texture);
|
||||
color0.texture =
|
||||
std::make_shared<Texture>(color0_desc, current_drawable.texture);
|
||||
color0.clear_color = Color::SkyBlue();
|
||||
color0.load_action = LoadAction::kClear;
|
||||
color0.store_action = StoreAction::kStore;
|
||||
|
||||
@ -50,23 +50,20 @@ TEST_F(PrimitivesTest, CanCreateBoxPrimitive) {
|
||||
Image image(flutter::testing::OpenFixtureAsMapping("image.png"));
|
||||
auto result = image.Decode();
|
||||
ASSERT_TRUE(result.IsValid());
|
||||
auto device_image_allocation =
|
||||
context->GetPermanentsAllocator()->CreateBufferWithCopy(
|
||||
*result.GetAllocation());
|
||||
device_image_allocation->SetLabel("Bay Bridge");
|
||||
ASSERT_TRUE(device_image_allocation);
|
||||
auto texture_descriptor = TextureDescriptor::MakeFromImageResult(result);
|
||||
ASSERT_TRUE(texture_descriptor.has_value());
|
||||
auto texture =
|
||||
device_image_allocation->MakeTexture(texture_descriptor.value());
|
||||
auto texture = context->GetPermanentsAllocator()->CreateTexture(
|
||||
StorageMode::kHostVisible, texture_descriptor.value());
|
||||
ASSERT_TRUE(texture);
|
||||
auto uploaded = texture->SetContents(result.GetAllocation()->GetMapping(),
|
||||
result.GetAllocation()->GetSize());
|
||||
ASSERT_TRUE(uploaded);
|
||||
|
||||
Renderer::RenderCallback callback = [&](const Surface& surface,
|
||||
RenderPass& pass) {
|
||||
BoxVertexShader::UniformBuffer uniforms;
|
||||
|
||||
uniforms.mvp = Matrix::MakeOrthographic(surface.GetSize());
|
||||
|
||||
uniforms.mvp = Matrix::MakeOrthographic(surface.GetSize().width,
|
||||
surface.GetSize().height);
|
||||
Command cmd;
|
||||
cmd.label = "Box";
|
||||
cmd.pipeline = box_pipeline;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user