pH/sommelier/sommelier-transform.h

183 lines
8.3 KiB
C

// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef VM_TOOLS_SOMMELIER_SOMMELIER_TRANSFORM_H_
#define VM_TOOLS_SOMMELIER_SOMMELIER_TRANSFORM_H_
#include "sommelier.h" // NOLINT(build/include_directory)
#include "sommelier-ctx.h" // NOLINT(build/include_directory)
// Direct Scaling Mode Explained:
//
// It will be helpful to define the 3 coordinate spaces that we need to
// manage:
//
// 1. Physical Coordinate Space: This refers to the actual physical dimensions
// of the devices display. Typical sizes would be 3840x2160, 1920x1080, etc.
//
// 2. Virtual Coordinate Space: This refers to the coordinate space that is
// formed by multiplying the scale factor with the physical dimensions.
// (Example: scale = 1.0, physical = 3840x2160, virtual = 3840x2160)
// (Example: scale = 0.5, physical = 3840x2160, virtual = 1920x1080)
// The scale factor will come from the "--scale" command line parameter or
// from the associated environment variable.
//
// 3. Host Logical Space: The dimensions of this space are defined
// entirely by the host. The exact dimensions are retrieved through
// the xdg_output interface. It is assumed that there is a direct, linear
// relationship between the logical space and the physical space on the
// host. As an example:
// a) A 1600x900 logical space
// b) A 3840x2160 physical space
//
// If we place a 1600x900 dimensioned object at the origin of the logical
// space, it should appear as a 3840x2160 object within the physical space
// (also at the origin).
//
// The product of the desired scale factor and the physical dimensions may
// result in non-integer values. In these cases, the result
// is rounded down towards zero (truncate). This slight modification
// will require recomputation of the scale factors to maintain consistency
// between the two coordinate spaces. For this reason, the (single) scale
// factor provided as input from the user is used to generate the virtual
// coordinates. Then once those have been computed (and rounded), the scale
// factors for each axis will then be recalculated using the virtual and
// logical dimensions. Each axis is given its own scale factor because
// it is possible for only one axis to require rounding.
//
// The logical coordinates come to us from the host. This is the
// coordinate space that the host is operating in. This can change
// based on the users scale settings.
//
// The physical coordinate space is no longer necessary once the virtual
// coordinate space has been formed, so no scaling factors are needed to
// convert to that space.
//
// Xwayland operates within the virtual coordinate space and the
// host is operating within its logical space. Sommelier only needs to
// facilitate translations between these two coordinate spaces.
//
// The virtual to logical scale factors are derived from the ratios between
// the virtual coordinate spaces dimensions and the logical coordinate spaces
// dimensions.
//
// In this mode, a buffer that is full screen sized within Xwayland (virtual)
// will also be full screen sized in the logical coordinate space. The same
// pattern holds with a quarter resolution sized image. With a scale factor
// of 1.0, it is expected that there will be no scaling done to present the
// image onto the screen.
// Coordinate transform functions
//
// In general, the transformation functions fall under one of these
// two classes:
//
// 1. Transformations which follow the basic rules:
// A straight multiply for host->guest and straight divide for the opposite
// 2. Transformations which perform their transformations in a slightly
// different manner.
//
// The functions immediately following this block fall under the latter
// They are separate functions so these cases can be easily identified
// throughout the rest of the code.
//
// The functions that fall under the latter case work in the
// guest->host direction and do not have variants which work in the
// opposite direction.
// This particular function will return true if setting a destination
// viewport size is necessary. It can be false if the host/guest spaces
// matches.
// This is a potential optimization as it removes one step
// from the guest->host surface_attach cycle.
bool sl_transform_viewport_scale(struct sl_context* ctx,
struct sl_host_surface* surface,
double contents_scale,
int32_t* width,
int32_t* height);
void sl_transform_damage_coord(struct sl_context* ctx,
const struct sl_host_surface* surface,
double buffer_scalex,
double buffer_scaley,
int64_t* x1,
int64_t* y1,
int64_t* x2,
int64_t* y2);
// Basic Transformations
// The following transformations fall under the basic type
// 1D transformation functions have an axis specifier
// to indicate along which axis the transformation is to
// take place.
//
// The axis specifier will follow the wl_pointer::axis definitions
// 0 = vertical axis (Y)
// 1 = horizontal axis (X)
void sl_transform_host_to_guest(struct sl_context* ctx,
struct sl_host_surface* surface,
int32_t* x,
int32_t* y);
void sl_transform_host_to_guest_fixed(struct sl_context* ctx,
struct sl_host_surface* surface,
wl_fixed_t* x,
wl_fixed_t* y);
void sl_transform_host_to_guest_fixed(struct sl_context* ctx,
struct sl_host_surface* surface,
wl_fixed_t* coord,
uint32_t axis);
// Opposite Direction
void sl_transform_guest_to_host(struct sl_context* ctx,
struct sl_host_surface* surface,
int32_t* x,
int32_t* y);
void sl_transform_guest_to_host_fixed(struct sl_context* ctx,
struct sl_host_surface* surface,
wl_fixed_t* x,
wl_fixed_t* y);
void sl_transform_guest_to_host_fixed(struct sl_context* ctx,
struct sl_host_surface* surface,
wl_fixed_t* coord,
uint32_t axis);
// Given the desired window size in virtual pixels, this function
// will see if it can be cleanly converted to logical coordinates and back.
//
// If the desired dimensions can be met with the default scaling factors,
// no intervention will take place.
//
// If the desired dimensions CANNOT be met with the default scaling factors,
// a set of scaling factors will be chosen to match the nearest logical
// coordinates to the desired virtual pixel dimensions. These scaling factors
// will then be used for all transformations being performed on this surface.
//
// This function is a no-op when not in direct scale mode.
void sl_transform_try_window_scale(struct sl_context* ctx,
struct sl_host_surface* surface,
int32_t width_in_pixels,
int32_t height_in_pixels);
// Removes any custom scaling factors that have been set on the surface
// by try_window_scale
void sl_transform_reset_surface_scale(struct sl_context* ctx,
struct sl_host_surface* surface);
// This function performs the physical to virtual transformation
// based on the scale factor provided by the command line/env.
// This function is called in response to the physical dimensions being sent
// by the host. The virtual dimensions are calculated by this function and
// then relayed to the guest.
void sl_transform_output_dimensions(struct sl_context* ctx,
int32_t* width,
int32_t* height);
#endif // VM_TOOLS_SOMMELIER_SOMMELIER_TRANSFORM_H_