Skip to content

Commit

Permalink
Allow Canvas draw a raw texture
Browse files Browse the repository at this point in the history
  • Loading branch information
floppyhammer committed Jan 10, 2025
1 parent b368ab7 commit d612503
Show file tree
Hide file tree
Showing 23 changed files with 185 additions and 81 deletions.
1 change: 1 addition & 0 deletions pathfinder/common/logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class Logger {
Info,
Warn,
Error,
Silence,
} level;

static void set_level(Level _level) {
Expand Down
5 changes: 5 additions & 0 deletions pathfinder/common/math/rect.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ struct Rect {
return {left * v.x, top * v.y, right * v.x, bottom * v.y};
}

template <typename U>
Rect operator*(U v) const {
return {left * v, top * v, right * v, bottom * v};
}

template <typename U>
void operator+=(const Vec2<U> &v) {
left += v.x;
Expand Down
10 changes: 7 additions & 3 deletions pathfinder/common/math/vec2.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ struct Vec2 {

Vec2() = default;

explicit Vec2(T s) : x(s), y(s){};
explicit Vec2(T s) : x(s), y(s) {};

Vec2(T x, T y) : x(x), y(y){};
Vec2(T x, T y) : x(x), y(y) {};

Vec2<int32_t> floor() const {
return {(int32_t)std::floor(x), (int32_t)std::floor(y)};
Expand Down Expand Up @@ -73,10 +73,14 @@ struct Vec2 {
return {std::sqrt(x), std::sqrt(y)};
}

bool is_zero() const {
bool is_all_zero() const {
return x == 0 && y == 0;
}

bool is_any_zero() const {
return x == 0 || y == 0;
}

T area() const {
return x * y;
}
Expand Down
21 changes: 21 additions & 0 deletions pathfinder/core/canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,27 @@ void Canvas::draw_sub_render_target(const RenderTargetId &render_target_id,
current_state.fill_paint = old_fill_paint;
}

void Canvas::draw_raw_texture(std::shared_ptr<Texture> texture, const RectF &dst_rect) {
auto src_rect = RectF({}, texture->get_size().to_f32());

auto dst_size = dst_rect.size();
auto scale = dst_size / src_rect.size();
auto offset = dst_rect.origin() - src_rect.origin() * scale;
auto transform = Transform2::from_scale(scale).translate(offset);

auto pattern = Pattern::from_raw_texture(texture);
pattern.apply_transform(current_state.transform * transform);

// Save the current fill paint.
auto old_fill_paint = current_state.fill_paint;

current_state.fill_paint = Paint::from_pattern(pattern);
fill_rect(dst_rect);

// Restore the previous fill paint.
current_state.fill_paint = old_fill_paint;
}

std::shared_ptr<Scene> Canvas::get_scene() const {
return scene;
}
Expand Down
3 changes: 2 additions & 1 deletion pathfinder/core/canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ class Canvas {

void draw_sub_render_target(const RenderTargetId &render_target_id, const RectF &src_rect, const RectF &dst_rect);

void draw_raw_texture(std::shared_ptr<Texture> texture, const RectF &dst_rect);

/// Set the inner scene's view box.
void set_size(const Vec2I &size);

Expand Down Expand Up @@ -183,7 +185,6 @@ class Canvas {
*/
void push_path(Outline &outline, PathOp path_op, FillRule fill_rule);

private:
/// Brush state management.
BrushState current_state;
std::vector<BrushState> saved_states;
Expand Down
53 changes: 23 additions & 30 deletions pathfinder/core/d3d9/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,8 @@ RendererD3D9::RendererD3D9(const std::shared_ptr<Device> &_device, const std::sh
quad_vertex_buffer_id = allocator->allocate_buffer(quad_vertex_data_size, BufferType::Vertex, "quad vertex buffer");

auto encoder = device->create_command_encoder("upload quad vertex data");
encoder->write_buffer(allocator->get_buffer(quad_vertex_buffer_id),
0,
quad_vertex_data_size,
QUAD_VERTEX_POSITIONS);
encoder->write_buffer(
allocator->get_buffer(quad_vertex_buffer_id), 0, quad_vertex_data_size, QUAD_VERTEX_POSITIONS);

queue->submit_and_wait(encoder);
}
Expand Down Expand Up @@ -183,11 +181,8 @@ void RendererD3D9::set_up_pipelines() {
allocator->get_texture(dummy_texture_id),
get_default_sampler()),
// Unused binding.
Descriptor::sampled(6,
ShaderStage::Fragment,
"uGammaLUT",
allocator->get_texture(dummy_texture_id),
get_default_sampler()),
Descriptor::sampled(
6, ShaderStage::Fragment, "uGammaLUT", allocator->get_texture(dummy_texture_id), get_default_sampler()),
});

auto tile_vert_shader = device->create_shader_module(tile_vert_source, ShaderStage::Vertex, "tile vert");
Expand Down Expand Up @@ -497,11 +492,8 @@ void RendererD3D9::clip_tiles(const ClipBufferInfo &clip_buffer_info, const std:
auto clip_vertex_buffer = allocator->get_buffer(clip_buffer_info.clip_buffer_id);

tile_clip_copy_descriptor_set->add_or_update({
Descriptor::sampled(1,
ShaderStage::Fragment,
"uSrc",
allocator->get_texture(*mask_storage.texture_id),
get_default_sampler()),
Descriptor::sampled(
1, ShaderStage::Fragment, "uSrc", allocator->get_texture(*mask_storage.texture_id), get_default_sampler()),
});

// Copy out tiles.
Expand Down Expand Up @@ -558,9 +550,8 @@ void RendererD3D9::draw_tiles(uint64_t tile_vertex_buffer_id,
// If no specific RenderTarget is given, we render to the dst framebuffer.
if (render_target_id == nullptr) {
// Check if we should clear the dst framebuffer.
encoder->begin_render_pass(clear_dest_texture ? dest_render_pass_clear : dest_render_pass_load,
dest_texture,
ColorF());
encoder->begin_render_pass(
clear_dest_texture ? dest_render_pass_clear : dest_render_pass_load, dest_texture, ColorF());

target_texture = dest_texture;

Expand Down Expand Up @@ -607,15 +598,20 @@ void RendererD3D9::draw_tiles(uint64_t tile_vertex_buffer_id,
tile_uniform.z_buffer_size = z_buffer_texture->get_size().to_f32();

if (color_texture_info) {
auto color_texture_page = pattern_texture_pages[color_texture_info->page_id];
if (color_texture_page) {
color_texture = allocator->get_texture(color_texture_page->texture_id_);
color_texture_sampler = get_or_create_sampler(color_texture_info->sampling_flags);

if (color_texture == nullptr) {
Logger::error("Failed to obtain color texture!", "RendererD3D9");
return;
if (color_texture_info->raw_texture.expired()) {
auto color_texture_page = pattern_texture_pages[color_texture_info->page_id];
if (color_texture_page) {
color_texture = allocator->get_texture(color_texture_page->texture_id_);
color_texture_sampler = get_or_create_sampler(color_texture_info->sampling_flags);

if (color_texture == nullptr) {
Logger::error("Failed to obtain color texture!", "RendererD3D9");
return;
}
}
} else {
color_texture = color_texture_info->raw_texture.lock();
color_texture_sampler = get_or_create_sampler(color_texture_info->sampling_flags);
}
}

Expand All @@ -628,11 +624,8 @@ void RendererD3D9::draw_tiles(uint64_t tile_vertex_buffer_id,

// Update descriptor set.
tile_descriptor_set->add_or_update({
Descriptor::sampled(0,
ShaderStage::Vertex,
"uTextureMetadata",
allocator->get_texture(metadata_texture_id),
default_sampler),
Descriptor::sampled(
0, ShaderStage::Vertex, "uTextureMetadata", allocator->get_texture(metadata_texture_id), default_sampler),
Descriptor::sampled(1, ShaderStage::Vertex, "uZBuffer", z_buffer_texture, default_sampler),
Descriptor::sampled(3, ShaderStage::Fragment, "uColorTexture0", color_texture, color_texture_sampler),
Descriptor::sampled(4,
Expand Down
2 changes: 1 addition & 1 deletion pathfinder/core/data/line_segment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ bool LineSegmentF::intersection_t(const LineSegmentF &other, float &output) cons
}

LineSegmentF LineSegmentF::offset(float distance) const {
if (vector().is_zero()) {
if (vector().is_all_zero()) {
return *this;
} else {
return *this + vector().yx().normalize() * Vec2F(-distance, distance);
Expand Down
1 change: 1 addition & 0 deletions pathfinder/core/paint/paint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ std::shared_ptr<TileBatchTextureInfo> PaintMetadata::tile_batch_texture_info() c
info->page_id = color_texture_metadata->location.page;
info->sampling_flags = color_texture_metadata->sampling_flags;
info->composite_op = color_texture_metadata->composite_op;
info->raw_texture = color_texture_metadata->raw_texture;
return info;
}

Expand Down
31 changes: 23 additions & 8 deletions pathfinder/core/paint/paint.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,27 @@ enum class PaintCompositeOp {
};

struct TileBatchTextureInfo {
// Only for Image & RenderTarget.
uint32_t page_id;

// Only for Texture.
std::weak_ptr<Texture> raw_texture;

TextureSamplingFlags sampling_flags;
PaintCompositeOp composite_op;

inline bool operator==(const TileBatchTextureInfo &rhs) const {
return page_id == rhs.page_id && sampling_flags == rhs.sampling_flags && composite_op == rhs.composite_op;
bool operator==(const TileBatchTextureInfo &rhs) const {
bool r = page_id == rhs.page_id && sampling_flags == rhs.sampling_flags && composite_op == rhs.composite_op;

if (!raw_texture.expired() || !rhs.raw_texture.expired()) {
if (!raw_texture.expired() && !rhs.raw_texture.expired()) {
r = r && raw_texture.lock().get() == rhs.raw_texture.lock().get();
}
}
return r;
}

inline bool operator!=(const TileBatchTextureInfo &rhs) const {
bool operator!=(const TileBatchTextureInfo &rhs) const {
return !(*this == rhs);
}
};
Expand All @@ -50,7 +62,7 @@ struct PaintContents {
Pattern pattern;

// For being used as key in ordered maps.
inline bool operator<(const PaintContents &rhs) const {
bool operator<(const PaintContents &rhs) const {
if (type == rhs.type) {
if (type == PaintContents::Type::Gradient) {
return gradient < rhs.gradient;
Expand Down Expand Up @@ -83,14 +95,14 @@ struct Paint {

public:
/// Creates a simple paint from a single base color.
inline static Paint from_color(const ColorU &color) {
static Paint from_color(const ColorU &color) {
Paint paint;
paint.base_color = color;
return paint;
}

/// Creates a paint from a gradient.
inline static Paint from_gradient(const Gradient &gradient) {
static Paint from_gradient(const Gradient &gradient) {
PaintContents contents;
contents.type = PaintContents::Type::Gradient;
contents.gradient = gradient;
Expand All @@ -106,7 +118,7 @@ struct Paint {
}

/// Creates a paint from a raster pattern.
inline static Paint from_pattern(const Pattern &pattern) {
static Paint from_pattern(const Pattern &pattern) {
PaintContents contents;
contents.type = PaintContents::Type::Pattern;
contents.pattern = pattern;
Expand Down Expand Up @@ -135,7 +147,7 @@ struct Paint {

/// In order to use Paint as Map keys.
/// See https://stackoverflow.com/questions/1102392/how-can-i-use-stdmaps-with-user-defined-types-as-key.
inline bool operator<(const Paint &rhs) const {
bool operator<(const Paint &rhs) const {
if (overlay && rhs.overlay) {
return overlay->contents < rhs.overlay->contents;
} else if (overlay && !rhs.overlay) {
Expand Down Expand Up @@ -186,6 +198,9 @@ struct PaintColorTextureMetadata {
///
/// The border ensures clamp-to-edge yields the right result.
Vec2I border;

/// Only for raw texture.
std::weak_ptr<Texture> raw_texture;
};

/// Built from paints.
Expand Down
12 changes: 10 additions & 2 deletions pathfinder/core/paint/palette.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ PaintLocationsInfo Palette::assign_paint_locations(const std::shared_ptr<PaintTe
location = render_target_metadata[index];
}
// Image
else {
else if (pattern.source.type == PatternSource::Type::Image) {
auto image = pattern.source.image;

// TODO(pcwalton): We should be able to use tile cleverness to
Expand Down Expand Up @@ -326,8 +326,16 @@ PaintLocationsInfo Palette::assign_paint_locations(const std::shared_ptr<PaintTe
paint_filter.pattern_filter = *pattern.filter;
}

// Texture
if (pattern.source.type == PatternSource::Type::Texture) {
color_texture_metadata->raw_texture = pattern.source.texture;
location.rect = RectI({}, pattern.source.texture.lock()->get_size());
// No page info for raw textures.
} else {
color_texture_metadata->page_scale = allocator.page_scale(location.page);
}

color_texture_metadata->location = location;
color_texture_metadata->page_scale = allocator.page_scale(location.page);
color_texture_metadata->sampling_flags = sampling_flags;
color_texture_metadata->filter = paint_filter;
color_texture_metadata->transform = Transform2::from_translation(border.to_f32());
Expand Down
8 changes: 8 additions & 0 deletions pathfinder/core/paint/palette.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ const int32_t TEXTURE_METADATA_ENTRIES_PER_ROW = 128;
const int32_t TEXTURE_METADATA_TEXTURE_WIDTH = TEXTURE_METADATA_ENTRIES_PER_ROW * 10;
const int32_t TEXTURE_METADATA_TEXTURE_HEIGHT = 65536 / TEXTURE_METADATA_ENTRIES_PER_ROW;

struct RawTexture {
uint64_t texture_id;

Vec2I size;

std::string name;
};

struct MergedPaletteInfo {
std::map<RenderTargetId, RenderTargetId> render_target_mapping;
std::map<uint16_t, uint16_t> paint_mapping;
Expand Down
Loading

0 comments on commit d612503

Please sign in to comment.