1/*
2 * Copyright © 2013-2014 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission.  The copyright holders make no representations
11 * about the suitability of this software for any purpose.  It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "xorg-server.h"
28#include "xf86.h"
29#include "fb.h"
30
31#include "intel.h"
32#if USE_UXA
33#include "intel_uxa.h"
34#endif
35#include "dri3.h"
36
37static int
38intel_dri3_open(ScreenPtr screen,
39                RRProviderPtr provider,
40                int *out)
41{
42	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
43	intel_screen_private *intel = intel_get_screen_private(scrn);
44	int fd;
45
46	fd = intel_get_client_fd(intel->dev);
47	if (fd < 0)
48		return -fd;
49
50	*out = fd;
51	return Success;
52}
53
54static PixmapPtr intel_dri3_pixmap_from_fd(ScreenPtr screen,
55					   int fd,
56					   CARD16 width,
57					   CARD16 height,
58					   CARD16 stride,
59					   CARD8 depth,
60					   CARD8 bpp)
61{
62	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
63	intel_screen_private *intel = intel_get_screen_private(scrn);
64	struct intel_uxa_pixmap *priv;
65	PixmapPtr pixmap;
66	dri_bo *bo;
67
68	if (depth < 8)
69		return NULL;
70
71	switch (bpp) {
72	case 8:
73	case 16:
74	case 32:
75		break;
76	default:
77		return NULL;
78	}
79
80	pixmap = fbCreatePixmap(screen, 0, 0, depth, 0);
81	if (!pixmap)
82		return NULL;
83
84	if (!screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL))
85		goto free_pixmap;
86
87	bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr,
88						fd, (uint32_t)height * stride);
89	if (bo == NULL)
90		goto free_pixmap;
91
92	intel_uxa_set_pixmap_bo(pixmap, bo);
93	dri_bo_unreference(bo);
94
95	priv = intel_uxa_get_pixmap_private(pixmap);
96	if (priv == NULL)
97		goto free_pixmap;
98
99	priv->pinned |= PIN_DRI3;
100
101	return pixmap;
102
103free_pixmap:
104	fbDestroyPixmap(pixmap);
105	return NULL;
106}
107
108static int intel_dri3_fd_from_pixmap(ScreenPtr screen,
109				     PixmapPtr pixmap,
110				     CARD16 *stride,
111				     CARD32 *size)
112{
113	struct intel_uxa_pixmap *priv;
114	int fd;
115
116	priv = intel_uxa_get_pixmap_private(pixmap);
117	if (!priv)
118		return -1;
119
120	if (intel_pixmap_pitch(pixmap) > UINT16_MAX)
121		return -1;
122
123	if (drm_intel_bo_gem_export_to_prime(priv->bo, &fd) < 0)
124		return -1;
125
126	priv->pinned |= PIN_DRI3;
127
128	*stride = intel_pixmap_pitch(pixmap);
129	*size = priv->bo->size;
130	return fd;
131}
132
133static dri3_screen_info_rec intel_dri3_screen_info = {
134        .version = DRI3_SCREEN_INFO_VERSION,
135
136        .open = intel_dri3_open,
137        .pixmap_from_fd = intel_dri3_pixmap_from_fd,
138        .fd_from_pixmap = intel_dri3_fd_from_pixmap
139};
140
141Bool
142intel_dri3_screen_init(ScreenPtr screen)
143{
144        return dri3_screen_init(screen, &intel_dri3_screen_info);
145}
146