diff options
Diffstat (limited to 'xorg-server/hw/xwayland/xwayland-output.c')
-rw-r--r-- | xorg-server/hw/xwayland/xwayland-output.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/xorg-server/hw/xwayland/xwayland-output.c b/xorg-server/hw/xwayland/xwayland-output.c new file mode 100644 index 000000000..778914c61 --- /dev/null +++ b/xorg-server/hw/xwayland/xwayland-output.c @@ -0,0 +1,226 @@ +/* + * Copyright © 2011-2014 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of the + * copyright holders not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "xwayland.h" +#include <randrstr.h> + +static Rotation +wl_transform_to_xrandr(enum wl_output_transform transform) +{ + switch (transform) { + default: + case WL_OUTPUT_TRANSFORM_NORMAL: + return RR_Rotate_0; + case WL_OUTPUT_TRANSFORM_90: + return RR_Rotate_90; + case WL_OUTPUT_TRANSFORM_180: + return RR_Rotate_180; + case WL_OUTPUT_TRANSFORM_270: + return RR_Rotate_270; + case WL_OUTPUT_TRANSFORM_FLIPPED: + return RR_Reflect_X | RR_Rotate_0; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + return RR_Reflect_X | RR_Rotate_90; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + return RR_Reflect_X | RR_Rotate_180; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + return RR_Reflect_X | RR_Rotate_270; + } +} + +static int +wl_subpixel_to_xrandr(int subpixel) +{ + switch (subpixel) { + default: + case WL_OUTPUT_SUBPIXEL_UNKNOWN: + return SubPixelUnknown; + case WL_OUTPUT_SUBPIXEL_NONE: + return SubPixelNone; + case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB: + return SubPixelHorizontalRGB; + case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR: + return SubPixelHorizontalBGR; + case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB: + return SubPixelVerticalRGB; + case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR: + return SubPixelVerticalBGR; + } +} + +static void +output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, + int physical_width, int physical_height, int subpixel, + const char *make, const char *model, int transform) +{ + struct xwl_output *xwl_output = data; + + RROutputSetPhysicalSize(xwl_output->randr_output, + physical_width, physical_height); + RROutputSetSubpixelOrder(xwl_output->randr_output, + wl_subpixel_to_xrandr(subpixel)); + xwl_output->x = x; + xwl_output->y = y; + + xwl_output->rotation = wl_transform_to_xrandr(transform); +} + +static void +output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, + int width, int height, int refresh) +{ + struct xwl_output *xwl_output = data; + RRModePtr randr_mode; + + if (!(flags & WL_OUTPUT_MODE_CURRENT)) + return; + + xwl_output->width = width; + xwl_output->height = height; + + randr_mode = xwayland_cvt(width, height, refresh / 1000.0, 0, 0); + + RROutputSetModes(xwl_output->randr_output, &randr_mode, 1, 1); + + RRCrtcNotify(xwl_output->randr_crtc, randr_mode, + xwl_output->x, xwl_output->y, + xwl_output->rotation, NULL, 1, &xwl_output->randr_output); +} + +static void +output_handle_done(void *data, struct wl_output *wl_output) +{ + struct xwl_output *xwl_output = data; + struct xwl_screen *xwl_screen = xwl_output->xwl_screen; + int width, height; + + xorg_list_append(&xwl_output->link, &xwl_screen->output_list); + + width = 0; + height = 0; + xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) { + if (width < xwl_output->x + xwl_output->width) + width = xwl_output->x + xwl_output->width; + if (height < xwl_output->y + xwl_output->height) + height = xwl_output->y + xwl_output->height; + } + + xwl_screen->width = width; + xwl_screen->height = height; + RRScreenSizeNotify(xwl_screen->screen); + + xwl_screen->expecting_event--; +} + +static void +output_handle_scale(void *data, struct wl_output *wl_output, int32_t factor) +{ +} + +static const struct wl_output_listener output_listener = { + output_handle_geometry, + output_handle_mode, + output_handle_done, + output_handle_scale +}; + +struct xwl_output * +xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id) +{ + struct xwl_output *xwl_output; + static int serial; + char name[256]; + + xwl_output = calloc(sizeof *xwl_output, 1); + if (xwl_output == NULL) { + ErrorF("create_output ENOMEM"); + return NULL; + } + + xwl_output->output = wl_registry_bind(xwl_screen->registry, id, + &wl_output_interface, 2); + wl_output_add_listener(xwl_output->output, &output_listener, xwl_output); + + if (snprintf(name, sizeof name, "XWAYLAND%d", serial++) < 0) { + ErrorF("create_output ENOMEM"); + free(xwl_output); + return NULL; + } + + xwl_output->xwl_screen = xwl_screen; + xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output); + xwl_output->randr_output = RROutputCreate(xwl_screen->screen, name, + strlen(name), xwl_output); + RRCrtcGammaSetSize(xwl_output->randr_crtc, 256); + RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1); + RROutputSetConnection(xwl_output->randr_output, RR_Connected); + + return xwl_output; +} + +void +xwl_output_destroy(struct xwl_output *xwl_output) +{ + wl_output_destroy(xwl_output->output); + RRCrtcDestroy(xwl_output->randr_crtc); + RROutputDestroy(xwl_output->randr_output); + free(xwl_output); +} + +static Bool +xwl_randr_get_info(ScreenPtr pScreen, Rotation * rotations) +{ + *rotations = 0; + + return TRUE; +} + +static Bool +xwl_randr_set_config(ScreenPtr pScreen, + Rotation rotation, int rate, RRScreenSizePtr pSize) +{ + return FALSE; +} + +Bool +xwl_screen_init_output(struct xwl_screen *xwl_screen) +{ + rrScrPrivPtr rp; + + if (!RRScreenInit(xwl_screen->screen)) + return FALSE; + + RRScreenSetSizeRange(xwl_screen->screen, 320, 200, 8192, 8192); + + rp = rrGetScrPriv(xwl_screen->screen); + rp->rrGetInfo = xwl_randr_get_info; + rp->rrSetConfig = xwl_randr_set_config; + + return TRUE; +} |