MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ plan_fit()

FitPlan MayaFlux::Portal::Graphics::SamplerForge::plan_fit ( uint32_t  src_width,
uint32_t  src_height,
uint32_t  dst_width,
uint32_t  dst_height,
FitMode  mode = FitMode::STRETCH,
FilterMode  filter = FilterMode::LINEAR 
)
static

Work out how a source extent maps onto a destination extent.

Pure arithmetic, no device needed. Zero in any extent yields an empty plan. Tiling produces one blit per tile, so a source much smaller than the destination produces many.

Parameters
src_widthSource width in pixels.
src_heightSource height in pixels.
dst_widthDestination width in pixels.
dst_heightDestination height in pixels.
modeHow the source is fitted.
filterFilter for the blits and the sampler.
Returns
Rectangles for an image write and the matching sampler.

Definition at line 270 of file SamplerForge.cpp.

277{
278 FitPlan plan;
279 plan.sampler.mag_filter = filter;
280 plan.sampler.min_filter = filter;
281
282 if (src_width == 0 || src_height == 0 || dst_width == 0 || dst_height == 0) {
283 return plan;
284 }
285
286 const auto addressing = [&plan](AddressMode address, BorderColor border = BorderColor::DEFAULT) {
287 plan.sampler.address_mode_u = address;
288 plan.sampler.address_mode_v = address;
289 plan.sampler.address_mode_w = address;
290 plan.sampler.border_color = border;
291 };
292
293 const auto place = [&plan, filter](
294 vk::Rect2D src, vk::Rect2D dst, bool flip_x = false, bool flip_y = false) {
295 plan.blits.push_back(LayerBlit {
296 .src = src, .dst = dst, .filter = filter, .flip_x = flip_x, .flip_y = flip_y });
297 };
298
299 const auto region = [](int32_t x, int32_t y, uint32_t width, uint32_t height) {
300 return vk::Rect2D { vk::Offset2D { x, y }, vk::Extent2D { width, height } };
301 };
302
303 const auto centered = [](uint32_t outer, uint32_t inner) {
304 return static_cast<int32_t>((outer - inner) / 2);
305 };
306
307 const auto extent = [](double value, uint32_t limit) {
308 return std::clamp(static_cast<uint32_t>(std::lround(value)), 1U, limit);
309 };
310
311 const auto sw = static_cast<double>(src_width);
312 const auto sh = static_cast<double>(src_height);
313 const auto dw = static_cast<double>(dst_width);
314 const auto dh = static_cast<double>(dst_height);
315
316 switch (mode) {
317 case FitMode::STRETCH:
318 addressing(AddressMode::CLAMP_TO_EDGE);
319 place(region(0, 0, src_width, src_height), region(0, 0, dst_width, dst_height));
320 break;
321
322 case FitMode::CONTAIN: {
323 const double scale = std::min(dw / sw, dh / sh);
324 const uint32_t w = extent(sw * scale, dst_width);
325 const uint32_t h = extent(sh * scale, dst_height);
327 place(region(0, 0, src_width, src_height),
328 region(centered(dst_width, w), centered(dst_height, h), w, h));
329 break;
330 }
331
332 case FitMode::COVER: {
333 const double scale = std::max(dw / sw, dh / sh);
334 const uint32_t w = extent(dw / scale, src_width);
335 const uint32_t h = extent(dh / scale, src_height);
336 addressing(AddressMode::CLAMP_TO_EDGE);
337 place(region(centered(src_width, w), centered(src_height, h), w, h),
338 region(0, 0, dst_width, dst_height));
339 break;
340 }
341
342 case FitMode::CENTER: {
343 const uint32_t w = std::min(src_width, dst_width);
344 const uint32_t h = std::min(src_height, dst_height);
346 place(region(centered(src_width, w), centered(src_height, h), w, h),
347 region(centered(dst_width, w), centered(dst_height, h), w, h));
348 break;
349 }
350
351 case FitMode::TILE:
353 const bool mirrored = mode == FitMode::TILE_MIRRORED;
354 addressing(mirrored ? AddressMode::MIRRORED_REPEAT : AddressMode::REPEAT);
355
356 uint32_t row = 0;
357 for (uint32_t y = 0; y < dst_height; y += src_height, ++row) {
358 const uint32_t h = std::min(src_height, dst_height - y);
359 const bool flip_y = mirrored && (row % 2 == 1);
360
361 uint32_t column = 0;
362 for (uint32_t x = 0; x < dst_width; x += src_width, ++column) {
363 const uint32_t w = std::min(src_width, dst_width - x);
364 const bool flip_x = mirrored && (column % 2 == 1);
365
366 place(region(flip_x ? static_cast<int32_t>(src_width - w) : 0,
367 flip_y ? static_cast<int32_t>(src_height - h) : 0, w, h),
368 region(static_cast<int32_t>(x), static_cast<int32_t>(y), w, h),
369 flip_x, flip_y);
370 }
371 }
372 break;
373 }
374 }
375
376 return plan;
377}
uint32_t h
Definition InkPress.cpp:29
uint32_t * dst
const uint32_t * src
uint32_t mode
glm::vec3 value
uint32_t width
uint32_t height
AABB2D place(AABB2D anchor, Side side, float w, float h, float gap=0.F, Align align=Align::Center) noexcept
Compute a region of size (w, h) positioned relative to anchor.
Definition Bounds.hpp:579
Tendency< D, float > scale(const Tendency< D, float > &t, float factor)
Uniform scaling of a scalar-output tendency.
Definition Tendency.hpp:98
AddressMode
Texture addressing mode (wrapping)
@ CLAMP_TO_BORDER
Clamp to border color.
BorderColor
Color read outside the texture when an address mode is CLAMP_TO_BORDER.
@ TRANSPARENT_BLACK
Zero in every channel.
@ DEFAULT
The sampler's historical border, opaque black.
@ TILE_MIRRORED
Source repeated, every other tile mirrored.
@ STRETCH
Whole source onto whole destination, aspect ignored.
@ CONTAIN
Whole source, aspect kept, centered, the rest left uncovered.
@ COVER
Aspect kept, destination filled, source cropped.
@ CENTER
No scaling, centered, clipped to the destination.
@ TILE
Source repeated at its own size.

References MayaFlux::Portal::Graphics::SamplerConfig::address_mode_u, MayaFlux::Portal::Graphics::SamplerConfig::address_mode_v, MayaFlux::Portal::Graphics::SamplerConfig::address_mode_w, MayaFlux::Portal::Graphics::FitPlan::blits, MayaFlux::Portal::Graphics::SamplerConfig::border_color, MayaFlux::Portal::Graphics::CENTER, MayaFlux::Portal::Graphics::CLAMP_TO_BORDER, MayaFlux::Portal::Graphics::CLAMP_TO_EDGE, MayaFlux::Portal::Graphics::CONTAIN, MayaFlux::Portal::Graphics::COVER, MayaFlux::Portal::Graphics::DEFAULT, dst, h, height, MayaFlux::Portal::Graphics::SamplerConfig::mag_filter, MayaFlux::Portal::Graphics::SamplerConfig::min_filter, MayaFlux::Portal::Graphics::MIRRORED_REPEAT, mode, MayaFlux::Portal::Graphics::REPEAT, MayaFlux::Portal::Graphics::FitPlan::sampler, src, MayaFlux::Portal::Graphics::LayerBlit::src, MayaFlux::Portal::Graphics::STRETCH, MayaFlux::Portal::Graphics::TILE, MayaFlux::Portal::Graphics::TILE_MIRRORED, MayaFlux::Portal::Graphics::TRANSPARENT_BLACK, value, and width.

Referenced by MayaFlux::Buffers::TextureArrayBuffer::submit_layer().

+ Here is the caller graph for this function: