1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2019, Fuzhou Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify
5*4882a593Smuzhiyun * it under the terms of the GNU General Public License as published by
6*4882a593Smuzhiyun * the Free Software Foundation; either version 2 of the License, or
7*4882a593Smuzhiyun * (at your option) any later version.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful,
10*4882a593Smuzhiyun * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*4882a593Smuzhiyun * GNU General Public License for more details.
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
16*4882a593Smuzhiyun #include "dix-config.h"
17*4882a593Smuzhiyun #endif
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include "driver.h"
20*4882a593Smuzhiyun #include "dumb_bo.h"
21*4882a593Smuzhiyun /*
22*4882a593Smuzhiyun #include "xf86.h"
23*4882a593Smuzhiyun */
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include <stdio.h>
26*4882a593Smuzhiyun #include <unistd.h>
27*4882a593Smuzhiyun #include <sys/socket.h>
28*4882a593Smuzhiyun #include <sys/stat.h>
29*4882a593Smuzhiyun #include <sys/un.h>
30*4882a593Smuzhiyun #include <libdrm/drm_fourcc.h>
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #include <X11/extensions/Xv.h>
33*4882a593Smuzhiyun #include "fourcc.h"
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #ifndef DRM_FORMAT_NV12_10
36*4882a593Smuzhiyun #define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '2')
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #define XVIMAGE_XRGB8888 \
40*4882a593Smuzhiyun { \
41*4882a593Smuzhiyun DRM_FORMAT_XRGB8888, \
42*4882a593Smuzhiyun XvRGB, \
43*4882a593Smuzhiyun LSBFirst, \
44*4882a593Smuzhiyun {'R','G','B','X', \
45*4882a593Smuzhiyun 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
46*4882a593Smuzhiyun 32, \
47*4882a593Smuzhiyun XvPacked, \
48*4882a593Smuzhiyun 1, \
49*4882a593Smuzhiyun 24, 0xff0000, 0x00ff00, 0x0000ff, \
50*4882a593Smuzhiyun 0, 0, 0, \
51*4882a593Smuzhiyun 0, 0, 0, \
52*4882a593Smuzhiyun 0, 0, 0, \
53*4882a593Smuzhiyun {'B','G','R', \
54*4882a593Smuzhiyun 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
55*4882a593Smuzhiyun XvTopToBottom \
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun #define NUM_FORMATS 4
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun static XF86VideoFormatRec Formats[NUM_FORMATS] = {
61*4882a593Smuzhiyun {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, {30, TrueColor}
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun XvAttributeRec ms_exa_xv_attributes[] = {
67*4882a593Smuzhiyun {XvSettable | XvGettable, 0, 0xFFFFFFFF, (char *)"XV_DMA_CLIENT_ID"},
68*4882a593Smuzhiyun {XvSettable | XvGettable, 0, 0xFFFFFFFF, (char *)"XV_DMA_HOR_STRIDE"},
69*4882a593Smuzhiyun {XvSettable | XvGettable, 0, 0xFFFFFFFF, (char *)"XV_DMA_VER_STRIDE"},
70*4882a593Smuzhiyun {XvSettable | XvGettable, 0, 0xFFFFFFFF, (char *)"XV_DMA_DRM_FOURCC"},
71*4882a593Smuzhiyun {0, 0, 0, NULL}
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun int ms_exa_xv_num_attributes = ARRAY_SIZE(ms_exa_xv_attributes) - 1;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun Atom msDmaClient, msDmaHorStride, msDmaVerStride, msDmaDrmFourcc;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun XvImageRec ms_exa_xv_images[] = {
78*4882a593Smuzhiyun XVIMAGE_NV12,
79*4882a593Smuzhiyun XVIMAGE_XRGB8888
80*4882a593Smuzhiyun };
81*4882a593Smuzhiyun int ms_exa_xv_num_images = ARRAY_SIZE(ms_exa_xv_images);
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun #define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1))
84*4882a593Smuzhiyun #define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun #define XV_MAX_DMA_FD 3
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun typedef struct {
89*4882a593Smuzhiyun uint32_t dma_client;
90*4882a593Smuzhiyun uint32_t dma_hor_stride;
91*4882a593Smuzhiyun uint32_t dma_ver_stride;
92*4882a593Smuzhiyun uint32_t dma_drm_fourcc;
93*4882a593Smuzhiyun int dma_socket_fd;
94*4882a593Smuzhiyun } ms_exa_port_private;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun static void
ms_exa_xv_set_dma_client(ms_exa_port_private * port_priv,uint32_t dma_client)97*4882a593Smuzhiyun ms_exa_xv_set_dma_client(ms_exa_port_private *port_priv, uint32_t dma_client)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun struct sockaddr_un addr;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun // re-open socket to flush pending messages
102*4882a593Smuzhiyun if (port_priv->dma_client)
103*4882a593Smuzhiyun close(port_priv->dma_socket_fd);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun port_priv->dma_client = dma_client;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun if (!dma_client)
108*4882a593Smuzhiyun goto clear;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun port_priv->dma_socket_fd = socket(PF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
111*4882a593Smuzhiyun if (port_priv->dma_socket_fd < 0)
112*4882a593Smuzhiyun goto clear;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun addr.sun_family = AF_LOCAL;
115*4882a593Smuzhiyun snprintf(addr.sun_path, sizeof(addr.sun_path),
116*4882a593Smuzhiyun "/tmp/.xv_dma_client.%d", port_priv->dma_client);
117*4882a593Smuzhiyun addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun unlink(addr.sun_path);
120*4882a593Smuzhiyun if (bind(port_priv->dma_socket_fd,
121*4882a593Smuzhiyun (struct sockaddr *)&addr, sizeof(addr)) < 0)
122*4882a593Smuzhiyun goto clear;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun chmod(addr.sun_path, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun return;
127*4882a593Smuzhiyun clear:
128*4882a593Smuzhiyun if (port_priv->dma_socket_fd > 0) {
129*4882a593Smuzhiyun close(port_priv->dma_socket_fd);
130*4882a593Smuzhiyun port_priv->dma_socket_fd = 0;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun port_priv->dma_client = 0;
133*4882a593Smuzhiyun port_priv->dma_hor_stride = 0;
134*4882a593Smuzhiyun port_priv->dma_ver_stride = 0;
135*4882a593Smuzhiyun port_priv->dma_drm_fourcc = 0;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun static void
ms_exa_xv_stop_video(ScrnInfoPtr pScrn,void * data,Bool cleanup)139*4882a593Smuzhiyun ms_exa_xv_stop_video(ScrnInfoPtr pScrn, void *data, Bool cleanup)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun ms_exa_port_private *port_priv = data;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun if (!cleanup)
144*4882a593Smuzhiyun return;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun ms_exa_xv_set_dma_client(port_priv, 0);
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun static int
ms_exa_xv_set_port_attribute(ScrnInfoPtr pScrn,Atom attribute,INT32 value,void * data)150*4882a593Smuzhiyun ms_exa_xv_set_port_attribute(ScrnInfoPtr pScrn,
151*4882a593Smuzhiyun Atom attribute, INT32 value, void *data)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun ms_exa_port_private *port_priv = data;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun if (attribute == msDmaClient)
156*4882a593Smuzhiyun ms_exa_xv_set_dma_client(port_priv, ClipValue(value, 0, 0xFFFFFFFF));
157*4882a593Smuzhiyun else if (attribute == msDmaHorStride)
158*4882a593Smuzhiyun port_priv->dma_hor_stride = ClipValue(value, 0, 0xFFFFFFFF);
159*4882a593Smuzhiyun else if (attribute == msDmaVerStride)
160*4882a593Smuzhiyun port_priv->dma_ver_stride = ClipValue(value, 0, 0xFFFFFFFF);
161*4882a593Smuzhiyun else if (attribute == msDmaDrmFourcc)
162*4882a593Smuzhiyun port_priv->dma_drm_fourcc = ClipValue(value, 0, 0xFFFFFFFF);
163*4882a593Smuzhiyun else
164*4882a593Smuzhiyun return BadMatch;
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun return Success;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun static int
ms_exa_xv_get_port_attribute(ScrnInfoPtr pScrn,Atom attribute,INT32 * value,void * data)170*4882a593Smuzhiyun ms_exa_xv_get_port_attribute(ScrnInfoPtr pScrn,
171*4882a593Smuzhiyun Atom attribute, INT32 *value, void *data)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun ms_exa_port_private *port_priv = data;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun if (attribute == msDmaClient)
176*4882a593Smuzhiyun *value = port_priv->dma_client;
177*4882a593Smuzhiyun else if (attribute == msDmaHorStride)
178*4882a593Smuzhiyun *value = port_priv->dma_hor_stride;
179*4882a593Smuzhiyun else if (attribute == msDmaVerStride)
180*4882a593Smuzhiyun *value = port_priv->dma_ver_stride;
181*4882a593Smuzhiyun else if (attribute == msDmaDrmFourcc)
182*4882a593Smuzhiyun *value = port_priv->dma_drm_fourcc;
183*4882a593Smuzhiyun else
184*4882a593Smuzhiyun return BadMatch;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun return Success;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun static void
ms_exa_xv_query_best_size(ScrnInfoPtr pScrn,Bool motion,short vid_w,short vid_h,short drw_w,short drw_h,unsigned int * p_w,unsigned int * p_h,void * data)190*4882a593Smuzhiyun ms_exa_xv_query_best_size(ScrnInfoPtr pScrn,
191*4882a593Smuzhiyun Bool motion,
192*4882a593Smuzhiyun short vid_w, short vid_h,
193*4882a593Smuzhiyun short drw_w, short drw_h,
194*4882a593Smuzhiyun unsigned int *p_w, unsigned int *p_h, void *data)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun *p_w = drw_w;
197*4882a593Smuzhiyun *p_h = drw_h;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun static int
ms_exa_xv_query_image_attributes(ScrnInfoPtr pScrn,int id,unsigned short * w,unsigned short * h,int * pitches,int * offsets)201*4882a593Smuzhiyun ms_exa_xv_query_image_attributes(ScrnInfoPtr pScrn,
202*4882a593Smuzhiyun int id,
203*4882a593Smuzhiyun unsigned short *w, unsigned short *h,
204*4882a593Smuzhiyun int *pitches, int *offsets)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun int size = 0, tmp;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun if (offsets)
209*4882a593Smuzhiyun offsets[0] = 0;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun if (id != FOURCC_NV12 && id != DRM_FORMAT_XRGB8888)
212*4882a593Smuzhiyun return 0;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun *w = ALIGN(*w, 2);
215*4882a593Smuzhiyun *h = ALIGN(*h, 2);
216*4882a593Smuzhiyun size = ALIGN(*w, 4);
217*4882a593Smuzhiyun if (pitches)
218*4882a593Smuzhiyun pitches[0] = size;
219*4882a593Smuzhiyun size *= *h;
220*4882a593Smuzhiyun if (offsets)
221*4882a593Smuzhiyun offsets[1] = size;
222*4882a593Smuzhiyun tmp = ALIGN(*w, 4);
223*4882a593Smuzhiyun if (id == DRM_FORMAT_XRGB8888)
224*4882a593Smuzhiyun tmp *= 4;
225*4882a593Smuzhiyun if (pitches)
226*4882a593Smuzhiyun pitches[1] = tmp;
227*4882a593Smuzhiyun tmp *= (*h >> 1);
228*4882a593Smuzhiyun size += tmp;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun return size;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun static PixmapPtr
ms_exa_xv_create_dma_pixmap(ScrnInfoPtr scrn,ms_exa_port_private * port_priv,int id)234*4882a593Smuzhiyun ms_exa_xv_create_dma_pixmap(ScrnInfoPtr scrn,
235*4882a593Smuzhiyun ms_exa_port_private *port_priv, int id)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun modesettingPtr ms = modesettingPTR(scrn);
238*4882a593Smuzhiyun ScreenPtr screen = scrn->pScreen;
239*4882a593Smuzhiyun PixmapPtr pixmap = NULL;
240*4882a593Smuzhiyun struct dumb_bo *bo = NULL;
241*4882a593Smuzhiyun struct iovec iov;
242*4882a593Smuzhiyun struct msghdr msg;
243*4882a593Smuzhiyun struct cmsghdr *header;
244*4882a593Smuzhiyun char buf[CMSG_SPACE (sizeof (int))];
245*4882a593Smuzhiyun int dma_fds[XV_MAX_DMA_FD], num_dma_fd = 0;
246*4882a593Smuzhiyun int width, height, pitch, bpp, depth;
247*4882a593Smuzhiyun uint32_t drm_fourcc;
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun if (!port_priv->dma_client || port_priv->dma_socket_fd <= 0)
250*4882a593Smuzhiyun return NULL;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun if (!port_priv->dma_hor_stride || !port_priv->dma_ver_stride)
253*4882a593Smuzhiyun goto err;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun iov.iov_base = buf;
256*4882a593Smuzhiyun iov.iov_len = 1;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun msg.msg_iov = &iov;
259*4882a593Smuzhiyun msg.msg_iovlen = 1;
260*4882a593Smuzhiyun msg.msg_name = NULL;
261*4882a593Smuzhiyun msg.msg_namelen = 0;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun num_dma_fd = 0;
264*4882a593Smuzhiyun while (1) {
265*4882a593Smuzhiyun msg.msg_control = buf;
266*4882a593Smuzhiyun msg.msg_controllen = sizeof(buf);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun if (recvmsg(port_priv->dma_socket_fd, &msg, 0) < 0)
269*4882a593Smuzhiyun break;
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun /* End with a empty msg */
272*4882a593Smuzhiyun header = CMSG_FIRSTHDR(&msg);
273*4882a593Smuzhiyun if (!header)
274*4882a593Smuzhiyun break;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun for (; header != NULL; header = CMSG_NXTHDR(&msg, header)) {
277*4882a593Smuzhiyun if (header->cmsg_level != SOL_SOCKET
278*4882a593Smuzhiyun || header->cmsg_type != SCM_RIGHTS
279*4882a593Smuzhiyun || header->cmsg_len != CMSG_LEN(sizeof(int)))
280*4882a593Smuzhiyun break;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun dma_fds[num_dma_fd++] = *((int *)CMSG_DATA(header));
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun /* Only expect 1 buffer */
287*4882a593Smuzhiyun if (num_dma_fd != 1)
288*4882a593Smuzhiyun goto err;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun width = port_priv->dma_hor_stride;
291*4882a593Smuzhiyun height = port_priv->dma_ver_stride;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun drm_fourcc = port_priv->dma_drm_fourcc ? port_priv->dma_drm_fourcc : id;
294*4882a593Smuzhiyun if (drm_fourcc == DRM_FORMAT_XRGB8888) {
295*4882a593Smuzhiyun pitch = width * 4;
296*4882a593Smuzhiyun depth = bpp = 32;
297*4882a593Smuzhiyun } else {
298*4882a593Smuzhiyun pitch = width * 3 / 2;
299*4882a593Smuzhiyun depth = bpp = 12;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun /* HACK: Special depth for NV12_10 and NV16*/
302*4882a593Smuzhiyun if (drm_fourcc == DRM_FORMAT_NV12_10) {
303*4882a593Smuzhiyun depth = 10;
304*4882a593Smuzhiyun } else if (drm_fourcc == DRM_FORMAT_NV16) {
305*4882a593Smuzhiyun depth = 16;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun pixmap = drmmode_create_pixmap_header(screen, width, height,
310*4882a593Smuzhiyun depth, bpp, pitch, NULL);
311*4882a593Smuzhiyun if (!pixmap)
312*4882a593Smuzhiyun goto err;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun bo = dumb_get_bo_from_fd(ms->drmmode.fd, dma_fds[0],
315*4882a593Smuzhiyun pitch, pitch * height);
316*4882a593Smuzhiyun if (!bo)
317*4882a593Smuzhiyun goto err_free_pixmap;
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun if (!ms_exa_set_pixmap_bo(scrn, pixmap, bo, TRUE))
320*4882a593Smuzhiyun goto err_free_bo;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun goto out;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun err_free_bo:
325*4882a593Smuzhiyun dumb_bo_destroy(ms->drmmode.fd, bo);
326*4882a593Smuzhiyun err_free_pixmap:
327*4882a593Smuzhiyun screen->DestroyPixmap(pixmap);
328*4882a593Smuzhiyun pixmap = NULL;
329*4882a593Smuzhiyun err:
330*4882a593Smuzhiyun ErrorF("ms xv failed to import dma pixmap\n");
331*4882a593Smuzhiyun ms_exa_xv_set_dma_client(port_priv, 0);
332*4882a593Smuzhiyun out:
333*4882a593Smuzhiyun while (num_dma_fd--)
334*4882a593Smuzhiyun close(dma_fds[num_dma_fd]);
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun return pixmap;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun static PixmapPtr
ms_exa_xv_create_pixmap(ScrnInfoPtr scrn,ms_exa_port_private * port_priv,int id,unsigned char * buf,short width,short height)340*4882a593Smuzhiyun ms_exa_xv_create_pixmap(ScrnInfoPtr scrn, ms_exa_port_private *port_priv,
341*4882a593Smuzhiyun int id,
342*4882a593Smuzhiyun unsigned char *buf,
343*4882a593Smuzhiyun short width,
344*4882a593Smuzhiyun short height)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun ScreenPtr screen = scrn->pScreen;
347*4882a593Smuzhiyun PixmapPtr pixmap;
348*4882a593Smuzhiyun int pitch, bpp;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun if (id == FOURCC_NV12) {
351*4882a593Smuzhiyun pitch = ALIGN(width, 4) * 3 / 2;
352*4882a593Smuzhiyun bpp = 12;
353*4882a593Smuzhiyun } else {
354*4882a593Smuzhiyun pitch = ALIGN(width, 4) * 4;
355*4882a593Smuzhiyun bpp = 32;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun pixmap = drmmode_create_pixmap_header(screen, width, height,
359*4882a593Smuzhiyun bpp, bpp, pitch, buf);
360*4882a593Smuzhiyun if (!pixmap)
361*4882a593Smuzhiyun return NULL;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun pixmap->devKind = pitch;
364*4882a593Smuzhiyun pixmap->devPrivate.ptr = buf;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun return pixmap;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun static int
ms_exa_xv_put_image(ScrnInfoPtr pScrn,short src_x,short src_y,short drw_x,short drw_y,short src_w,short src_h,short drw_w,short drw_h,int id,unsigned char * buf,short width,short height,Bool sync,RegionPtr clipBoxes,void * data,DrawablePtr pDrawable)370*4882a593Smuzhiyun ms_exa_xv_put_image(ScrnInfoPtr pScrn,
371*4882a593Smuzhiyun short src_x, short src_y,
372*4882a593Smuzhiyun short drw_x, short drw_y,
373*4882a593Smuzhiyun short src_w, short src_h,
374*4882a593Smuzhiyun short drw_w, short drw_h,
375*4882a593Smuzhiyun int id,
376*4882a593Smuzhiyun unsigned char *buf,
377*4882a593Smuzhiyun short width,
378*4882a593Smuzhiyun short height,
379*4882a593Smuzhiyun Bool sync,
380*4882a593Smuzhiyun RegionPtr clipBoxes, void *data, DrawablePtr pDrawable)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun ms_exa_port_private *port_priv = data;
383*4882a593Smuzhiyun ScreenPtr screen = pScrn->pScreen;
384*4882a593Smuzhiyun PixmapPtr src_pixmap, dst_pixmap;
385*4882a593Smuzhiyun pixman_f_transform_t transform;
386*4882a593Smuzhiyun double sx, sy, tx, ty;
387*4882a593Smuzhiyun int ret = Success;
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun if (id != FOURCC_NV12 && id != DRM_FORMAT_XRGB8888)
390*4882a593Smuzhiyun return BadMatch;
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun src_pixmap = ms_exa_xv_create_dma_pixmap(pScrn, port_priv, id);
393*4882a593Smuzhiyun if (!src_pixmap) {
394*4882a593Smuzhiyun src_pixmap = ms_exa_xv_create_pixmap(pScrn, port_priv, id,
395*4882a593Smuzhiyun buf, width, height);
396*4882a593Smuzhiyun if (!src_pixmap)
397*4882a593Smuzhiyun return BadMatch;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun if (pDrawable->type == DRAWABLE_WINDOW)
401*4882a593Smuzhiyun dst_pixmap = screen->GetWindowPixmap((WindowPtr) pDrawable);
402*4882a593Smuzhiyun else
403*4882a593Smuzhiyun dst_pixmap = (PixmapPtr) pDrawable;
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun DamageRegionAppend(pDrawable, clipBoxes);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun sx = (double)src_w / drw_w;
408*4882a593Smuzhiyun sy = (double)src_h / drw_h;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun tx = drw_x - src_x;
411*4882a593Smuzhiyun ty = drw_y - src_y;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun #ifdef COMPOSITE
414*4882a593Smuzhiyun RegionTranslate(clipBoxes, -dst_pixmap->screen_x, -dst_pixmap->screen_y);
415*4882a593Smuzhiyun tx -= dst_pixmap->screen_x;
416*4882a593Smuzhiyun ty -= dst_pixmap->screen_y;
417*4882a593Smuzhiyun #endif
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun pixman_f_transform_init_scale(&transform, sx, sy);
420*4882a593Smuzhiyun pixman_f_transform_translate(NULL, &transform, tx, ty);
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun if (!ms_exa_copy_area(src_pixmap, dst_pixmap, &transform, clipBoxes))
423*4882a593Smuzhiyun ret = BadMatch;
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun DamageRegionProcessPending(pDrawable);
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun screen->DestroyPixmap(src_pixmap);
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun return ret;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun static XF86VideoEncodingRec DummyEncoding[1] = {
433*4882a593Smuzhiyun { 0, "XV_IMAGE", 8192, 8192, {1, 1} }
434*4882a593Smuzhiyun };
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun XF86VideoAdaptorPtr
ms_exa_xv_init(ScreenPtr screen,int num_texture_ports)437*4882a593Smuzhiyun ms_exa_xv_init(ScreenPtr screen, int num_texture_ports)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun ms_exa_port_private *port_priv;
440*4882a593Smuzhiyun XF86VideoAdaptorPtr adapt;
441*4882a593Smuzhiyun int i;
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun msDmaClient = MAKE_ATOM("XV_DMA_CLIENT_ID");
444*4882a593Smuzhiyun msDmaHorStride = MAKE_ATOM("XV_DMA_HOR_STRIDE");
445*4882a593Smuzhiyun msDmaVerStride = MAKE_ATOM("XV_DMA_VER_STRIDE");
446*4882a593Smuzhiyun msDmaDrmFourcc = MAKE_ATOM("XV_DMA_DRM_FOURCC");
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports *
449*4882a593Smuzhiyun (sizeof(ms_exa_port_private) + sizeof(DevUnion)));
450*4882a593Smuzhiyun if (adapt == NULL)
451*4882a593Smuzhiyun return NULL;
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun adapt->type = XvWindowMask | XvInputMask | XvImageMask;
454*4882a593Smuzhiyun adapt->flags = 0;
455*4882a593Smuzhiyun adapt->name = "Modesetting Textured Video";
456*4882a593Smuzhiyun adapt->nEncodings = 1;
457*4882a593Smuzhiyun adapt->pEncodings = DummyEncoding;
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun adapt->nFormats = NUM_FORMATS;
460*4882a593Smuzhiyun adapt->pFormats = Formats;
461*4882a593Smuzhiyun adapt->nPorts = num_texture_ports;
462*4882a593Smuzhiyun adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun adapt->pAttributes = ms_exa_xv_attributes;
465*4882a593Smuzhiyun adapt->nAttributes = ms_exa_xv_num_attributes;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun port_priv =
468*4882a593Smuzhiyun (ms_exa_port_private *) (&adapt->pPortPrivates[num_texture_ports]);
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun adapt->pImages = ms_exa_xv_images;
471*4882a593Smuzhiyun adapt->nImages = ms_exa_xv_num_images;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun adapt->PutVideo = NULL;
474*4882a593Smuzhiyun adapt->PutStill = NULL;
475*4882a593Smuzhiyun adapt->GetVideo = NULL;
476*4882a593Smuzhiyun adapt->GetStill = NULL;
477*4882a593Smuzhiyun adapt->StopVideo = ms_exa_xv_stop_video;
478*4882a593Smuzhiyun adapt->SetPortAttribute = ms_exa_xv_set_port_attribute;
479*4882a593Smuzhiyun adapt->GetPortAttribute = ms_exa_xv_get_port_attribute;
480*4882a593Smuzhiyun adapt->QueryBestSize = ms_exa_xv_query_best_size;
481*4882a593Smuzhiyun adapt->PutImage = ms_exa_xv_put_image;
482*4882a593Smuzhiyun adapt->ReputImage = NULL;
483*4882a593Smuzhiyun adapt->QueryImageAttributes = ms_exa_xv_query_image_attributes;
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun for (i = 0; i < num_texture_ports; i++) {
486*4882a593Smuzhiyun ms_exa_port_private *priv = &port_priv[i];
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun priv->dma_client = 0;
489*4882a593Smuzhiyun priv->dma_socket_fd = 0;
490*4882a593Smuzhiyun priv->dma_hor_stride = 0;
491*4882a593Smuzhiyun priv->dma_ver_stride = 0;
492*4882a593Smuzhiyun priv->dma_drm_fourcc = 0;
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun adapt->pPortPrivates[i].ptr = (void *) (priv);
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun return adapt;
497*4882a593Smuzhiyun }
498