183 lines
8.3 KiB
C
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_
|