1 /*
2 * Copyright (c) 1998-2003 by The XFree86 Project, Inc.
3 * Copyright © 2013 Red Hat
4 * Copyright © 2014 Intel Corporation
5 * Copyright © 2016 Red Hat
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * IN THE SOFTWARE.
25 *
26 * Authors:
27 * Olivier Fourdan <ofourdan@redhat.com>
28 *
29 * Derived from the glamor_xf86_xv, ephyr_glamor_xv and xf86xv
30 * implementations
31 */
32
33 #include "xwayland.h"
34 #include "glamor_priv.h"
35
36 #include <X11/extensions/Xv.h>
37
38 #define NUM_FORMATS 3
39 #define NUM_PORTS 16
40 #define ADAPTOR_NAME "glamor textured video"
41 #define ENCODER_NAME "XV_IMAGE"
42
43 static DevPrivateKeyRec xwlXvScreenPrivateKeyRec;
44 #define xwlXvScreenPrivateKey (&xwlXvScreenPrivateKeyRec)
45
46 typedef struct {
47 XvAdaptorPtr glxv_adaptor; /* We have only one adaptor, glamor Xv */
48 glamor_port_private *port_privates;
49
50 CloseScreenProcPtr CloseScreen;
51 } xwlXvScreenRec, *xwlXvScreenPtr;
52
53 typedef struct {
54 char depth;
55 short class;
56 } xwlVideoFormatRec, *xwlVideoFormatPtr;
57
58 static xwlVideoFormatRec Formats[NUM_FORMATS] = {
59 {15, TrueColor},
60 {16, TrueColor},
61 {24, TrueColor}
62 };
63
64 static int
xwl_glamor_xv_stop_video(XvPortPtr pPort,DrawablePtr pDraw)65 xwl_glamor_xv_stop_video(XvPortPtr pPort,
66 DrawablePtr pDraw)
67 {
68 glamor_port_private *gpp = (glamor_port_private *) (pPort->devPriv.ptr);
69
70 if (pDraw->type != DRAWABLE_WINDOW)
71 return BadAlloc;
72
73 glamor_xv_stop_video(gpp);
74
75 return Success;
76 }
77
78 static int
xwl_glamor_xv_set_port_attribute(XvPortPtr pPort,Atom attribute,INT32 value)79 xwl_glamor_xv_set_port_attribute(XvPortPtr pPort,
80 Atom attribute,
81 INT32 value)
82 {
83 glamor_port_private *gpp = (glamor_port_private *) (pPort->devPriv.ptr);
84
85 return glamor_xv_set_port_attribute(gpp, attribute, value);
86 }
87
88 static int
xwl_glamor_xv_get_port_attribute(XvPortPtr pPort,Atom attribute,INT32 * pValue)89 xwl_glamor_xv_get_port_attribute(XvPortPtr pPort,
90 Atom attribute,
91 INT32 *pValue)
92 {
93 glamor_port_private *gpp = (glamor_port_private *) (pPort->devPriv.ptr);
94
95 return glamor_xv_get_port_attribute(gpp, attribute, pValue);
96 }
97
98 static int
xwl_glamor_xv_query_best_size(XvPortPtr pPort,CARD8 motion,CARD16 vid_w,CARD16 vid_h,CARD16 drw_w,CARD16 drw_h,unsigned int * p_w,unsigned int * p_h)99 xwl_glamor_xv_query_best_size(XvPortPtr pPort,
100 CARD8 motion,
101 CARD16 vid_w,
102 CARD16 vid_h,
103 CARD16 drw_w,
104 CARD16 drw_h,
105 unsigned int *p_w,
106 unsigned int *p_h)
107 {
108 *p_w = drw_w;
109 *p_h = drw_h;
110
111 return Success;
112 }
113
114 static int
xwl_glamor_xv_query_image_attributes(XvPortPtr pPort,XvImagePtr format,CARD16 * width,CARD16 * height,int * pitches,int * offsets)115 xwl_glamor_xv_query_image_attributes(XvPortPtr pPort,
116 XvImagePtr format,
117 CARD16 *width,
118 CARD16 *height,
119 int *pitches,
120 int *offsets)
121 {
122 return glamor_xv_query_image_attributes(format->id,
123 width,
124 height,
125 pitches,
126 offsets);
127 }
128
129 static int
xwl_glamor_xv_put_image(DrawablePtr pDrawable,XvPortPtr pPort,GCPtr pGC,INT16 src_x,INT16 src_y,CARD16 src_w,CARD16 src_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h,XvImagePtr format,unsigned char * data,Bool sync,CARD16 width,CARD16 height)130 xwl_glamor_xv_put_image(DrawablePtr pDrawable,
131 XvPortPtr pPort,
132 GCPtr pGC,
133 INT16 src_x,
134 INT16 src_y,
135 CARD16 src_w,
136 CARD16 src_h,
137 INT16 drw_x,
138 INT16 drw_y,
139 CARD16 drw_w,
140 CARD16 drw_h,
141 XvImagePtr format,
142 unsigned char *data,
143 Bool sync,
144 CARD16 width,
145 CARD16 height)
146 {
147 glamor_port_private *gpp = (glamor_port_private *) (pPort->devPriv.ptr);
148
149 RegionRec WinRegion;
150 RegionRec ClipRegion;
151 BoxRec WinBox;
152 int ret = Success;
153
154 if (pDrawable->type != DRAWABLE_WINDOW)
155 return BadWindow;
156
157 WinBox.x1 = pDrawable->x + drw_x;
158 WinBox.y1 = pDrawable->y + drw_y;
159 WinBox.x2 = WinBox.x1 + drw_w;
160 WinBox.y2 = WinBox.y1 + drw_h;
161
162 RegionInit(&WinRegion, &WinBox, 1);
163 RegionInit(&ClipRegion, NullBox, 1);
164 RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
165
166 if (RegionNotEmpty(&ClipRegion))
167 ret = glamor_xv_put_image(gpp,
168 pDrawable,
169 src_x,
170 src_y,
171 pDrawable->x + drw_x,
172 pDrawable->y + drw_y,
173 src_w,
174 src_h,
175 drw_w,
176 drw_h,
177 format->id,
178 data,
179 width,
180 height,
181 sync,
182 &ClipRegion);
183
184 RegionUninit(&WinRegion);
185 RegionUninit(&ClipRegion);
186
187 return ret;
188
189 }
190
191 static Bool
xwl_glamor_xv_add_formats(XvAdaptorPtr pa)192 xwl_glamor_xv_add_formats(XvAdaptorPtr pa)
193 {
194 ScreenPtr pScreen;
195 XvFormatPtr pFormat, pf;
196 VisualPtr pVisual;
197 int numFormat;
198 int totFormat;
199 int numVisuals;
200 int i;
201
202 totFormat = NUM_FORMATS;
203 pFormat = xnfcalloc(totFormat, sizeof(XvFormatRec));
204 pScreen = pa->pScreen;
205 for (pf = pFormat, i = 0, numFormat = 0; i < NUM_FORMATS; i++) {
206 numVisuals = pScreen->numVisuals;
207 pVisual = pScreen->visuals;
208
209 while (numVisuals--) {
210 if ((pVisual->class == Formats[i].class) &&
211 (pVisual->nplanes == Formats[i].depth)) {
212 if (numFormat >= totFormat) {
213 void *moreSpace;
214
215 totFormat *= 2;
216 moreSpace = xnfreallocarray(pFormat, totFormat,
217 sizeof(XvFormatRec));
218 pFormat = moreSpace;
219 pf = pFormat + numFormat;
220 }
221
222 pf->visual = pVisual->vid;
223 pf->depth = Formats[i].depth;
224
225 pf++;
226 numFormat++;
227 }
228 pVisual++;
229 }
230 }
231 pa->nFormats = numFormat;
232 pa->pFormats = pFormat;
233
234 return numFormat != 0;
235 }
236
237 static Bool
xwl_glamor_xv_add_ports(XvAdaptorPtr pa)238 xwl_glamor_xv_add_ports(XvAdaptorPtr pa)
239 {
240 XvPortPtr pPorts, pp;
241 xwlXvScreenPtr xwlXvScreen;
242 unsigned long PortResource = 0;
243 int nPorts;
244 int i;
245
246 pPorts = xnfcalloc(NUM_PORTS, sizeof(XvPortRec));
247 xwlXvScreen = dixLookupPrivate(&(pa->pScreen)->devPrivates,
248 xwlXvScreenPrivateKey);
249 xwlXvScreen->port_privates = xnfcalloc(NUM_PORTS,
250 sizeof(glamor_port_private));
251
252 PortResource = XvGetRTPort();
253 for (pp = pPorts, i = 0, nPorts = 0; i < NUM_PORTS; i++) {
254 if (!(pp->id = FakeClientID(0)))
255 continue;
256
257 pp->pAdaptor = pa;
258
259 glamor_xv_init_port(&xwlXvScreen->port_privates[i]);
260 pp->devPriv.ptr = &xwlXvScreen->port_privates[i];
261
262 if (AddResource(pp->id, PortResource, pp)) {
263 pp++;
264 nPorts++;
265 }
266 }
267
268 pa->base_id = pPorts->id;
269 pa->nPorts = nPorts;
270 pa->pPorts = pPorts;
271
272 return nPorts != 0;
273 }
274
275 static void
xwl_glamor_xv_add_attributes(XvAdaptorPtr pa)276 xwl_glamor_xv_add_attributes(XvAdaptorPtr pa)
277 {
278 int i;
279
280 pa->pAttributes = xnfcalloc(glamor_xv_num_attributes, sizeof(XvAttributeRec));
281 memcpy(pa->pAttributes, glamor_xv_attributes,
282 glamor_xv_num_attributes * sizeof(XvAttributeRec));
283
284 for (i = 0; i < glamor_xv_num_attributes; i++)
285 pa->pAttributes[i].name = strdup(glamor_xv_attributes[i].name);
286
287 pa->nAttributes = glamor_xv_num_attributes;
288 }
289
290 static void
xwl_glamor_xv_add_images(XvAdaptorPtr pa)291 xwl_glamor_xv_add_images(XvAdaptorPtr pa)
292 {
293 pa->pImages = xnfcalloc(glamor_xv_num_images, sizeof(XvImageRec));
294 memcpy(pa->pImages, glamor_xv_images, glamor_xv_num_images * sizeof(XvImageRec));
295
296 pa->nImages = glamor_xv_num_images;
297 }
298
299 static void
xwl_glamor_xv_add_encodings(XvAdaptorPtr pa)300 xwl_glamor_xv_add_encodings(XvAdaptorPtr pa)
301 {
302 XvEncodingPtr pe;
303 GLint texsize;
304
305 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texsize);
306
307 pe = xnfcalloc(1, sizeof(XvEncodingRec));
308 pe->id = 0;
309 pe->pScreen = pa->pScreen;
310 pe->name = strdup(ENCODER_NAME);
311 pe->width = texsize;
312 pe->height = texsize;
313 pe->rate.numerator = 1;
314 pe->rate.denominator = 1;
315
316 pa->pEncodings = pe;
317 pa->nEncodings = 1;
318 }
319
320 static Bool
xwl_glamor_xv_add_adaptors(ScreenPtr pScreen)321 xwl_glamor_xv_add_adaptors(ScreenPtr pScreen)
322 {
323 DevPrivateKey XvScreenKey;
324 XvScreenPtr XvScreen;
325 xwlXvScreenPtr xwlXvScreen;
326 XvAdaptorPtr pa;
327
328 if (XvScreenInit(pScreen) != Success)
329 return FALSE;
330
331 XvScreenKey = XvGetScreenKey();
332 XvScreen = dixLookupPrivate(&(pScreen)->devPrivates, XvScreenKey);
333
334 XvScreen->nAdaptors = 0;
335 XvScreen->pAdaptors = NULL;
336
337 pa = xnfcalloc(1, sizeof(XvAdaptorRec));
338 pa->pScreen = pScreen;
339 pa->type = (unsigned char) (XvInputMask | XvImageMask);
340 pa->ddStopVideo = xwl_glamor_xv_stop_video;
341 pa->ddPutImage = xwl_glamor_xv_put_image;
342 pa->ddSetPortAttribute = xwl_glamor_xv_set_port_attribute;
343 pa->ddGetPortAttribute = xwl_glamor_xv_get_port_attribute;
344 pa->ddQueryBestSize = xwl_glamor_xv_query_best_size;
345 pa->ddQueryImageAttributes = xwl_glamor_xv_query_image_attributes;
346 pa->name = strdup(ADAPTOR_NAME);
347
348 xwl_glamor_xv_add_encodings(pa);
349 xwl_glamor_xv_add_images(pa);
350 xwl_glamor_xv_add_attributes(pa);
351 if (!xwl_glamor_xv_add_formats(pa))
352 goto failed;
353 if (!xwl_glamor_xv_add_ports(pa))
354 goto failed;
355
356 /* We're good now with out Xv adaptor */
357 XvScreen->nAdaptors = 1;
358 XvScreen->pAdaptors = pa;
359
360 xwlXvScreen = dixLookupPrivate(&(pa->pScreen)->devPrivates,
361 xwlXvScreenPrivateKey);
362 xwlXvScreen->glxv_adaptor = pa;
363
364 return TRUE;
365
366 failed:
367 XvFreeAdaptor(pa);
368 free(pa);
369
370 return FALSE;
371 }
372
373 static Bool
xwl_glamor_xv_close_screen(ScreenPtr pScreen)374 xwl_glamor_xv_close_screen(ScreenPtr pScreen)
375 {
376 xwlXvScreenPtr xwlXvScreen;
377
378 xwlXvScreen = dixLookupPrivate(&(pScreen)->devPrivates,
379 xwlXvScreenPrivateKey);
380
381 if (xwlXvScreen->glxv_adaptor) {
382 XvFreeAdaptor(xwlXvScreen->glxv_adaptor);
383 free(xwlXvScreen->glxv_adaptor);
384 }
385 free(xwlXvScreen->port_privates);
386
387 pScreen->CloseScreen = xwlXvScreen->CloseScreen;
388
389 return pScreen->CloseScreen(pScreen);
390 }
391
392 Bool
xwl_glamor_xv_init(ScreenPtr pScreen)393 xwl_glamor_xv_init(ScreenPtr pScreen)
394 {
395 xwlXvScreenPtr xwlXvScreen;
396
397 if (!dixRegisterPrivateKey(xwlXvScreenPrivateKey, PRIVATE_SCREEN,
398 sizeof(xwlXvScreenRec)))
399 return FALSE;
400
401 xwlXvScreen = dixLookupPrivate(&(pScreen)->devPrivates,
402 xwlXvScreenPrivateKey);
403
404 xwlXvScreen->port_privates = NULL;
405 xwlXvScreen->glxv_adaptor = NULL;
406 xwlXvScreen->CloseScreen = pScreen->CloseScreen;
407 pScreen->CloseScreen = xwl_glamor_xv_close_screen;
408
409 glamor_xv_core_init(pScreen);
410
411 return xwl_glamor_xv_add_adaptors(pScreen);
412 }
413