1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright © 2013-2014 Intel Corporation
3428d7b3dSmrg *
4428d7b3dSmrg * Permission to use, copy, modify, distribute, and sell this software and its
5428d7b3dSmrg * documentation for any purpose is hereby granted without fee, provided that
6428d7b3dSmrg * the above copyright notice appear in all copies and that both that copyright
7428d7b3dSmrg * notice and this permission notice appear in supporting documentation, and
8428d7b3dSmrg * that the name of the copyright holders not be used in advertising or
9428d7b3dSmrg * publicity pertaining to distribution of the software without specific,
10428d7b3dSmrg * written prior permission.  The copyright holders make no representations
11428d7b3dSmrg * about the suitability of this software for any purpose.  It is provided "as
12428d7b3dSmrg * is" without express or implied warranty.
13428d7b3dSmrg *
14428d7b3dSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15428d7b3dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16428d7b3dSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17428d7b3dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18428d7b3dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19428d7b3dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20428d7b3dSmrg * OF THIS SOFTWARE.
21428d7b3dSmrg */
22428d7b3dSmrg
23428d7b3dSmrg#ifdef HAVE_CONFIG_H
24428d7b3dSmrg#include "config.h"
25428d7b3dSmrg#endif
26428d7b3dSmrg
27428d7b3dSmrg#include "xorg-server.h"
28428d7b3dSmrg#include "xf86.h"
29428d7b3dSmrg#include "fb.h"
30428d7b3dSmrg
31428d7b3dSmrg#include "intel.h"
32428d7b3dSmrg#if USE_UXA
33428d7b3dSmrg#include "intel_uxa.h"
34428d7b3dSmrg#endif
35428d7b3dSmrg#include "dri3.h"
36428d7b3dSmrg
37428d7b3dSmrgstatic int
38428d7b3dSmrgintel_dri3_open(ScreenPtr screen,
39428d7b3dSmrg                RRProviderPtr provider,
40428d7b3dSmrg                int *out)
41428d7b3dSmrg{
42428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
43428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
44428d7b3dSmrg	int fd;
45428d7b3dSmrg
46428d7b3dSmrg	fd = intel_get_client_fd(intel->dev);
47428d7b3dSmrg	if (fd < 0)
48428d7b3dSmrg		return -fd;
49428d7b3dSmrg
50428d7b3dSmrg	*out = fd;
51428d7b3dSmrg	return Success;
52428d7b3dSmrg}
53428d7b3dSmrg
54428d7b3dSmrgstatic PixmapPtr intel_dri3_pixmap_from_fd(ScreenPtr screen,
55428d7b3dSmrg					   int fd,
56428d7b3dSmrg					   CARD16 width,
57428d7b3dSmrg					   CARD16 height,
58428d7b3dSmrg					   CARD16 stride,
59428d7b3dSmrg					   CARD8 depth,
60428d7b3dSmrg					   CARD8 bpp)
61428d7b3dSmrg{
62428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
63428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
64428d7b3dSmrg	struct intel_uxa_pixmap *priv;
65428d7b3dSmrg	PixmapPtr pixmap;
66428d7b3dSmrg	dri_bo *bo;
67428d7b3dSmrg
68428d7b3dSmrg	if (depth < 8)
69428d7b3dSmrg		return NULL;
70428d7b3dSmrg
71428d7b3dSmrg	switch (bpp) {
72428d7b3dSmrg	case 8:
73428d7b3dSmrg	case 16:
74428d7b3dSmrg	case 32:
75428d7b3dSmrg		break;
76428d7b3dSmrg	default:
77428d7b3dSmrg		return NULL;
78428d7b3dSmrg	}
79428d7b3dSmrg
80428d7b3dSmrg	pixmap = fbCreatePixmap(screen, 0, 0, depth, 0);
81428d7b3dSmrg	if (!pixmap)
82428d7b3dSmrg		return NULL;
83428d7b3dSmrg
84428d7b3dSmrg	if (!screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL))
85428d7b3dSmrg		goto free_pixmap;
86428d7b3dSmrg
87428d7b3dSmrg	bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr,
88428d7b3dSmrg						fd, (uint32_t)height * stride);
89428d7b3dSmrg	if (bo == NULL)
90428d7b3dSmrg		goto free_pixmap;
91428d7b3dSmrg
92428d7b3dSmrg	intel_uxa_set_pixmap_bo(pixmap, bo);
93428d7b3dSmrg	dri_bo_unreference(bo);
94428d7b3dSmrg
95428d7b3dSmrg	priv = intel_uxa_get_pixmap_private(pixmap);
96428d7b3dSmrg	if (priv == NULL)
97428d7b3dSmrg		goto free_pixmap;
98428d7b3dSmrg
99428d7b3dSmrg	priv->pinned |= PIN_DRI3;
100428d7b3dSmrg
101428d7b3dSmrg	return pixmap;
102428d7b3dSmrg
103428d7b3dSmrgfree_pixmap:
104428d7b3dSmrg	fbDestroyPixmap(pixmap);
105428d7b3dSmrg	return NULL;
106428d7b3dSmrg}
107428d7b3dSmrg
108428d7b3dSmrgstatic int intel_dri3_fd_from_pixmap(ScreenPtr screen,
109428d7b3dSmrg				     PixmapPtr pixmap,
110428d7b3dSmrg				     CARD16 *stride,
111428d7b3dSmrg				     CARD32 *size)
112428d7b3dSmrg{
113428d7b3dSmrg	struct intel_uxa_pixmap *priv;
114428d7b3dSmrg	int fd;
115428d7b3dSmrg
116428d7b3dSmrg	priv = intel_uxa_get_pixmap_private(pixmap);
117428d7b3dSmrg	if (!priv)
118428d7b3dSmrg		return -1;
119428d7b3dSmrg
120428d7b3dSmrg	if (intel_pixmap_pitch(pixmap) > UINT16_MAX)
121428d7b3dSmrg		return -1;
122428d7b3dSmrg
123428d7b3dSmrg	if (drm_intel_bo_gem_export_to_prime(priv->bo, &fd) < 0)
124428d7b3dSmrg		return -1;
125428d7b3dSmrg
126428d7b3dSmrg	priv->pinned |= PIN_DRI3;
127428d7b3dSmrg
128428d7b3dSmrg	*stride = intel_pixmap_pitch(pixmap);
129428d7b3dSmrg	*size = priv->bo->size;
130428d7b3dSmrg	return fd;
131428d7b3dSmrg}
132428d7b3dSmrg
133428d7b3dSmrgstatic dri3_screen_info_rec intel_dri3_screen_info = {
134428d7b3dSmrg        .version = DRI3_SCREEN_INFO_VERSION,
135428d7b3dSmrg
136428d7b3dSmrg        .open = intel_dri3_open,
137428d7b3dSmrg        .pixmap_from_fd = intel_dri3_pixmap_from_fd,
138428d7b3dSmrg        .fd_from_pixmap = intel_dri3_fd_from_pixmap
139428d7b3dSmrg};
140428d7b3dSmrg
141428d7b3dSmrgBool
142428d7b3dSmrgintel_dri3_screen_init(ScreenPtr screen)
143428d7b3dSmrg{
144428d7b3dSmrg        return dri3_screen_init(screen, &intel_dri3_screen_info);
145428d7b3dSmrg}
146