summaryrefslogtreecommitdiff
path: root/hw/xwayland/xwayland-output.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xwayland/xwayland-output.c')
-rw-r--r--hw/xwayland/xwayland-output.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
new file mode 100644
index 000000000..778914c61
--- /dev/null
+++ b/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;
+}