xref: /OK3568_Linux_fs/external/xserver/glamor/glamor_xv.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright © 2013 Red Hat
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * Authors:
24  *      Dave Airlie <airlied@redhat.com>
25  *
26  * some code is derived from the xf86-video-ati radeon driver, mainly
27  * the calculations.
28  */
29 
30 /** @file glamor_xv.c
31  *
32  * Xv acceleration implementation
33  */
34 
35 #ifdef HAVE_DIX_CONFIG_H
36 #include <dix-config.h>
37 #endif
38 
39 #include "glamor_priv.h"
40 #include "glamor_transform.h"
41 #include "glamor_transfer.h"
42 
43 #include <stdio.h>
44 #include <unistd.h>
45 #include <sys/socket.h>
46 #include <sys/stat.h>
47 #include <sys/un.h>
48 #include <libdrm/drm_fourcc.h>
49 
50 #include <X11/extensions/Xv.h>
51 #include "../hw/xfree86/common/fourcc.h"
52 /* Reference color space transform data */
53 typedef struct tagREF_TRANSFORM {
54     float RefLuma;
55     float RefRCb;
56     float RefRCr;
57     float RefGCb;
58     float RefGCr;
59     float RefBCb;
60     float RefBCr;
61 } REF_TRANSFORM;
62 
63 #define RTFSaturation(a)   (1.0 + ((a)*1.0)/1000.0)
64 #define RTFBrightness(a)   (((a)*1.0)/2000.0)
65 #define RTFIntensity(a)   (((a)*1.0)/2000.0)
66 #define RTFContrast(a)   (1.0 + ((a)*1.0)/1000.0)
67 #define RTFHue(a)   (((a)*3.1416)/1000.0)
68 
69 #ifndef DRM_FORMAT_NV12_10
70 #define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '2')
71 #endif
72 
73 #ifndef DRM_FORMAT_NV15
74 #define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5')
75 #endif
76 
77 #ifndef DRM_FORMAT_YUV420_8BIT
78 #define DRM_FORMAT_YUV420_8BIT fourcc_code('Y', 'U', '0', '8')
79 #endif
80 
81 #ifndef DRM_FORMAT_YUV420_10BIT
82 #define DRM_FORMAT_YUV420_10BIT fourcc_code('Y', 'U', '1', '0')
83 #endif
84 
85 #ifndef DRM_FORMAT_MOD_VENDOR_ARM
86 #define DRM_FORMAT_MOD_VENDOR_ARM 0x08
87 #endif
88 
89 #ifndef DRM_FORMAT_MOD_ARM_AFBC
90 #define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode)
91 #endif
92 
93 #ifndef AFBC_FORMAT_MOD_BLOCK_SIZE_16x16
94 #define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 (1ULL)
95 #endif
96 
97 #ifndef AFBC_FORMAT_MOD_SPARSE
98 #define AFBC_FORMAT_MOD_SPARSE (((__u64)1) << 6)
99 #endif
100 
101 #define DRM_AFBC_MODIFIER \
102   (DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_SPARSE) | \
103    DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16))
104 
105 #define XV_MAX_DMA_FD 3
106 
107 static const glamor_facet glamor_facet_xv_planar_2 = {
108     .name = "xv_planar_2",
109 
110     .version = 120,
111 
112     .source_name = "v_texcoord0",
113     .vs_vars = ("attribute vec2 position;\n"
114                 "attribute vec2 v_texcoord0;\n"
115                 "varying vec2 tcs;\n"),
116     .vs_exec = (GLAMOR_POS(gl_Position, position)
117                 "        tcs = v_texcoord0;\n"),
118 
119     .fs_vars = ("uniform sampler2D y_sampler;\n"
120                 "uniform sampler2D u_sampler;\n"
121                 "uniform vec4 offsetyco;\n"
122                 "uniform vec4 ucogamma;\n"
123                 "uniform vec4 vco;\n"
124                 "varying vec2 tcs;\n"),
125     .fs_exec = (
126                 "        float sample;\n"
127                 "        vec2 sample_uv;\n"
128                 "        vec4 temp1;\n"
129                 "        sample = texture2D(y_sampler, tcs).w;\n"
130                 "        temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n"
131                 "        sample_uv = texture2D(u_sampler, tcs).xy;\n"
132                 "        temp1.xyz = ucogamma.xyz * vec3(sample_uv.x) + temp1.xyz;\n"
133                 "        temp1.xyz = clamp(vco.xyz * vec3(sample_uv.y) + temp1.xyz, 0.0, 1.0);\n"
134                 "        temp1.w = 1.0;\n"
135                 "        gl_FragColor = temp1;\n"
136                 ),
137 };
138 
139 static const glamor_facet glamor_facet_xv_planar_3 = {
140     .name = "xv_planar_3",
141 
142     .version = 120,
143 
144     .source_name = "v_texcoord0",
145     .vs_vars = ("attribute vec2 position;\n"
146                 "attribute vec2 v_texcoord0;\n"
147                 "varying vec2 tcs;\n"),
148     .vs_exec = (GLAMOR_POS(gl_Position, position)
149                 "        tcs = v_texcoord0;\n"),
150 
151     .fs_vars = ("uniform sampler2D y_sampler;\n"
152                 "uniform sampler2D u_sampler;\n"
153                 "uniform sampler2D v_sampler;\n"
154                 "uniform vec4 offsetyco;\n"
155                 "uniform vec4 ucogamma;\n"
156                 "uniform vec4 vco;\n"
157                 "varying vec2 tcs;\n"),
158     .fs_exec = (
159                 "        float sample;\n"
160                 "        vec4 temp1;\n"
161                 "        sample = texture2D(y_sampler, tcs).w;\n"
162                 "        temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n"
163                 "        sample = texture2D(u_sampler, tcs).w;\n"
164                 "        temp1.xyz = ucogamma.xyz * vec3(sample) + temp1.xyz;\n"
165                 "        sample = texture2D(v_sampler, tcs).w;\n"
166                 "        temp1.xyz = clamp(vco.xyz * vec3(sample) + temp1.xyz, 0.0, 1.0);\n"
167                 "        temp1.w = 1.0;\n"
168                 "        gl_FragColor = temp1;\n"
169                 ),
170 };
171 
172 static const glamor_facet glamor_facet_xv_egl_external = {
173     .name = "xv_egl_external",
174 
175     .source_name = "v_texcoord0",
176     .vs_vars = ("attribute vec2 position;\n"
177                 "attribute vec2 v_texcoord0;\n"
178                 "varying vec2 tcs;\n"),
179     .vs_exec = (GLAMOR_POS(gl_Position, position)
180                 "        tcs = v_texcoord0;\n"),
181 
182     .fs_extensions = ("#extension GL_OES_EGL_image_external : require\n"),
183     .fs_vars = ("uniform samplerExternalOES sampler;\n"
184                 "varying vec2 tcs;\n"),
185     .fs_exec = (
186                 "        gl_FragColor = texture2D(sampler, tcs);\n"
187                 ),
188 };
189 
190 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
191 
192 XvAttributeRec glamor_xv_attributes[] = {
193     {XvSettable | XvGettable, -1000, 1000, (char *)"XV_BRIGHTNESS"},
194     {XvSettable | XvGettable, -1000, 1000, (char *)"XV_CONTRAST"},
195     {XvSettable | XvGettable, -1000, 1000, (char *)"XV_SATURATION"},
196     {XvSettable | XvGettable, -1000, 1000, (char *)"XV_HUE"},
197     {XvSettable | XvGettable, 0, 1, (char *)"XV_COLORSPACE"},
198     {XvSettable | XvGettable, 0, 0xFFFFFFFF, (char *)"XV_DMA_CLIENT_ID"},
199     {XvSettable | XvGettable, 0, 0xFFFFFFFF, (char *)"XV_DMA_HOR_STRIDE"},
200     {XvSettable | XvGettable, 0, 0xFFFFFFFF, (char *)"XV_DMA_VER_STRIDE"},
201     {XvSettable | XvGettable, 0, 0xFFFFFFFF, (char *)"XV_DMA_DRM_FOURCC"},
202     {XvSettable | XvGettable, 0, 1, (char *)"XV_DMA_DRM_AFBC"},
203     {0, 0, 0, NULL}
204 };
205 int glamor_xv_num_attributes = ARRAY_SIZE(glamor_xv_attributes) - 1;
206 
207 Atom glamorBrightness, glamorContrast, glamorSaturation, glamorHue,
208     glamorColorspace, glamorGamma, glamorDmaClient, glamorDmaHorStride,
209     glamorDmaVerStride, glamorDmaDrmFourcc, glamorDmaDrmAFBC;
210 
211 XvImageRec glamor_xv_images[] = {
212     XVIMAGE_YV12,
213     XVIMAGE_I420,
214     XVIMAGE_NV12
215 };
216 int glamor_xv_num_images = ARRAY_SIZE(glamor_xv_images);
217 
218 static void
glamor_init_xv_shader(ScreenPtr screen,int id)219 glamor_init_xv_shader(ScreenPtr screen, int id)
220 {
221     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
222     GLint sampler_loc;
223     const glamor_facet *glamor_facet_xv_planar = NULL;
224 
225     switch (id) {
226     case FOURCC_YV12:
227     case FOURCC_I420:
228         glamor_facet_xv_planar = &glamor_facet_xv_planar_3;
229         break;
230     case FOURCC_NV12:
231         glamor_facet_xv_planar = &glamor_facet_xv_planar_2;
232         break;
233     default:
234         break;
235     }
236 
237     glamor_build_program(screen,
238                          &glamor_priv->xv_prog,
239                          glamor_facet_xv_planar, NULL, NULL, NULL);
240 
241     glUseProgram(glamor_priv->xv_prog.prog);
242     sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "y_sampler");
243     glUniform1i(sampler_loc, 0);
244     sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "u_sampler");
245     glUniform1i(sampler_loc, 1);
246 
247     switch (id) {
248     case FOURCC_YV12:
249     case FOURCC_I420:
250         sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "v_sampler");
251         glUniform1i(sampler_loc, 2);
252         break;
253     case FOURCC_NV12:
254         break;
255     default:
256         break;
257     }
258 
259 }
260 
261 static void
glamor_init_xv_shader_egl_external(ScreenPtr screen)262 glamor_init_xv_shader_egl_external(ScreenPtr screen)
263 {
264     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
265     GLint sampler_loc;
266 
267     glamor_build_program(screen,
268                          &glamor_priv->xv_prog_ext,
269                          &glamor_facet_xv_egl_external, NULL, NULL, NULL);
270     glUseProgram(glamor_priv->xv_prog_ext.prog);
271 
272     sampler_loc =
273         glGetUniformLocation(glamor_priv->xv_prog_ext.prog, "sampler");
274     glUniform1i(sampler_loc, 0);
275 }
276 
277 #define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
278 
279 static void
glamor_xv_set_dma_client(glamor_port_private * port_priv,uint32_t dma_client)280 glamor_xv_set_dma_client(glamor_port_private *port_priv,
281                          uint32_t dma_client)
282 {
283     struct sockaddr_un addr;
284 
285     // re-open socket to flush pending messages
286     if (port_priv->dma_client)
287         close(port_priv->dma_socket_fd);
288 
289     port_priv->dma_client = dma_client;
290 
291     if (!dma_client)
292         goto clear;
293 
294     port_priv->dma_socket_fd = socket(PF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
295     if (port_priv->dma_socket_fd < 0)
296         goto clear;
297 
298     addr.sun_family = AF_LOCAL;
299     snprintf(addr.sun_path, sizeof(addr.sun_path),
300              "/tmp/.xv_dma_client.%d", port_priv->dma_client);
301     addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
302 
303     unlink(addr.sun_path);
304     if (bind(port_priv->dma_socket_fd,
305              (struct sockaddr *)&addr, sizeof(addr)) < 0)
306         goto clear;
307 
308     chmod(addr.sun_path, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
309 
310     return;
311 clear:
312     if (port_priv->dma_socket_fd > 0) {
313         close(port_priv->dma_socket_fd);
314         port_priv->dma_socket_fd = 0;
315     }
316     port_priv->dma_client = 0;
317     port_priv->dma_hor_stride = 0;
318     port_priv->dma_ver_stride = 0;
319     port_priv->dma_drm_fourcc = 0;
320     port_priv->dma_drm_afbc = 0;
321 }
322 
323 void
glamor_xv_stop_video(glamor_port_private * port_priv)324 glamor_xv_stop_video(glamor_port_private *port_priv)
325 {
326     glamor_xv_set_dma_client(port_priv, 0);
327 }
328 
329 static void
glamor_xv_free_port_data(glamor_port_private * port_priv)330 glamor_xv_free_port_data(glamor_port_private *port_priv)
331 {
332     int i;
333 
334     for (i = 0; i < 3; i++) {
335         if (port_priv->src_pix[i]) {
336             glamor_destroy_pixmap(port_priv->src_pix[i]);
337             port_priv->src_pix[i] = NULL;
338         }
339     }
340     RegionUninit(&port_priv->clip);
341     RegionNull(&port_priv->clip);
342 }
343 
344 int
glamor_xv_set_port_attribute(glamor_port_private * port_priv,Atom attribute,INT32 value)345 glamor_xv_set_port_attribute(glamor_port_private *port_priv,
346                              Atom attribute, INT32 value)
347 {
348     if (attribute == glamorBrightness)
349         port_priv->brightness = ClipValue(value, -1000, 1000);
350     else if (attribute == glamorHue)
351         port_priv->hue = ClipValue(value, -1000, 1000);
352     else if (attribute == glamorContrast)
353         port_priv->contrast = ClipValue(value, -1000, 1000);
354     else if (attribute == glamorSaturation)
355         port_priv->saturation = ClipValue(value, -1000, 1000);
356     else if (attribute == glamorGamma)
357         port_priv->gamma = ClipValue(value, 100, 10000);
358     else if (attribute == glamorColorspace)
359         port_priv->transform_index = ClipValue(value, 0, 1);
360     else if (attribute == glamorDmaClient)
361         glamor_xv_set_dma_client(port_priv, ClipValue(value, 0, 0xFFFFFFFF));
362     else if (attribute == glamorDmaHorStride)
363         port_priv->dma_hor_stride = ClipValue(value, 0, 0xFFFFFFFF);
364     else if (attribute == glamorDmaVerStride)
365         port_priv->dma_ver_stride = ClipValue(value, 0, 0xFFFFFFFF);
366     else if (attribute == glamorDmaDrmFourcc)
367         port_priv->dma_drm_fourcc = ClipValue(value, 0, 0xFFFFFFFF);
368     else if (attribute == glamorDmaDrmAFBC)
369         port_priv->dma_drm_afbc = ClipValue(value, 0, 0xFFFFFFFF);
370     else
371         return BadMatch;
372     return Success;
373 }
374 
375 int
glamor_xv_get_port_attribute(glamor_port_private * port_priv,Atom attribute,INT32 * value)376 glamor_xv_get_port_attribute(glamor_port_private *port_priv,
377                              Atom attribute, INT32 *value)
378 {
379     if (attribute == glamorBrightness)
380         *value = port_priv->brightness;
381     else if (attribute == glamorHue)
382         *value = port_priv->hue;
383     else if (attribute == glamorContrast)
384         *value = port_priv->contrast;
385     else if (attribute == glamorSaturation)
386         *value = port_priv->saturation;
387     else if (attribute == glamorGamma)
388         *value = port_priv->gamma;
389     else if (attribute == glamorColorspace)
390         *value = port_priv->transform_index;
391     else if (attribute == glamorDmaClient)
392         *value = port_priv->dma_client;
393     else if (attribute == glamorDmaHorStride)
394         *value = port_priv->dma_hor_stride;
395     else if (attribute == glamorDmaVerStride)
396         *value = port_priv->dma_ver_stride;
397     else if (attribute == glamorDmaDrmFourcc)
398         *value = port_priv->dma_drm_fourcc;
399     else if (attribute == glamorDmaDrmAFBC)
400         *value = port_priv->dma_drm_afbc;
401     else
402         return BadMatch;
403 
404     return Success;
405 }
406 
407 int
glamor_xv_query_image_attributes(int id,unsigned short * w,unsigned short * h,int * pitches,int * offsets)408 glamor_xv_query_image_attributes(int id,
409                                  unsigned short *w, unsigned short *h,
410                                  int *pitches, int *offsets)
411 {
412     int size = 0, tmp;
413 
414     if (offsets)
415         offsets[0] = 0;
416     switch (id) {
417     case FOURCC_YV12:
418     case FOURCC_I420:
419         *w = ALIGN(*w, 2);
420         *h = ALIGN(*h, 2);
421         size = ALIGN(*w, 4);
422         if (pitches)
423             pitches[0] = size;
424         size *= *h;
425         if (offsets)
426             offsets[1] = size;
427         tmp = ALIGN(*w >> 1, 4);
428         if (pitches)
429             pitches[1] = pitches[2] = tmp;
430         tmp *= (*h >> 1);
431         size += tmp;
432         if (offsets)
433             offsets[2] = size;
434         size += tmp;
435         break;
436     case FOURCC_NV12:
437         *w = ALIGN(*w, 2);
438         *h = ALIGN(*h, 2);
439         size = ALIGN(*w, 4);
440         if (pitches)
441             pitches[0] = size;
442         size *= *h;
443         if (offsets)
444             offsets[1] = size;
445         tmp = ALIGN(*w, 4);
446         if (pitches)
447             pitches[1] = tmp;
448         tmp *= (*h >> 1);
449         size += tmp;
450         break;
451     }
452     return size;
453 }
454 
455 /* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces
456    note the difference to the parameters used in overlay are due
457    to 10bit vs. float calcs */
458 static REF_TRANSFORM trans[2] = {
459     {1.1643, 0.0, 1.5960, -0.3918, -0.8129, 2.0172, 0.0},       /* BT.601 */
460     {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0}        /* BT.709 */
461 };
462 
463 void
glamor_xv_render(glamor_port_private * port_priv,int id)464 glamor_xv_render(glamor_port_private *port_priv, int id)
465 {
466     ScreenPtr screen = port_priv->pPixmap->drawable.pScreen;
467     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
468     PixmapPtr pixmap = port_priv->pPixmap;
469     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
470     glamor_pixmap_private *src_pixmap_priv[3];
471     BoxPtr box = REGION_RECTS(&port_priv->clip);
472     int nBox = REGION_NUM_RECTS(&port_priv->clip);
473     GLfloat src_xscale[3], src_yscale[3];
474     int i;
475     const float Loff = -0.0627;
476     const float Coff = -0.502;
477     float uvcosf, uvsinf;
478     float yco;
479     float uco[3], vco[3], off[3];
480     float bright, cont, gamma;
481     int ref = port_priv->transform_index;
482     GLint uloc;
483     GLfloat *v;
484     char *vbo_offset;
485     int dst_box_index;
486 
487     DamageRegionAppend(port_priv->pDraw, &port_priv->clip);
488 
489     if (!glamor_priv->xv_prog.prog)
490         glamor_init_xv_shader(screen, id);
491 
492     cont = RTFContrast(port_priv->contrast);
493     bright = RTFBrightness(port_priv->brightness);
494     gamma = (float) port_priv->gamma / 1000.0;
495     uvcosf = RTFSaturation(port_priv->saturation) * cos(RTFHue(port_priv->hue));
496     uvsinf = RTFSaturation(port_priv->saturation) * sin(RTFHue(port_priv->hue));
497 /* overlay video also does pre-gamma contrast/sat adjust, should we? */
498 
499     yco = trans[ref].RefLuma * cont;
500     uco[0] = -trans[ref].RefRCr * uvsinf;
501     uco[1] = trans[ref].RefGCb * uvcosf - trans[ref].RefGCr * uvsinf;
502     uco[2] = trans[ref].RefBCb * uvcosf;
503     vco[0] = trans[ref].RefRCr * uvcosf;
504     vco[1] = trans[ref].RefGCb * uvsinf + trans[ref].RefGCr * uvcosf;
505     vco[2] = trans[ref].RefBCb * uvsinf;
506     off[0] = Loff * yco + Coff * (uco[0] + vco[0]) + bright;
507     off[1] = Loff * yco + Coff * (uco[1] + vco[1]) + bright;
508     off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright;
509     gamma = 1.0;
510 
511     glamor_set_alu(screen, GXcopy);
512 
513     for (i = 0; i < 3; i++) {
514         if (port_priv->src_pix[i]) {
515             src_pixmap_priv[i] =
516                 glamor_get_pixmap_private(port_priv->src_pix[i]);
517             pixmap_priv_get_scale(src_pixmap_priv[i], &src_xscale[i],
518                                   &src_yscale[i]);
519         } else {
520            src_pixmap_priv[i] = NULL;
521         }
522     }
523     glamor_make_current(glamor_priv);
524     glUseProgram(glamor_priv->xv_prog.prog);
525 
526     uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "offsetyco");
527     glUniform4f(uloc, off[0], off[1], off[2], yco);
528     uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "ucogamma");
529     glUniform4f(uloc, uco[0], uco[1], uco[2], gamma);
530     uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "vco");
531     glUniform4f(uloc, vco[0], vco[1], vco[2], 0);
532 
533     glActiveTexture(GL_TEXTURE0);
534     glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[0]->fbo->tex);
535     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
536     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
537     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
538     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
539 
540     glActiveTexture(GL_TEXTURE1);
541     glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[1]->fbo->tex);
542     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
543     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
544     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
545     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
546 
547     switch (id) {
548     case FOURCC_YV12:
549     case FOURCC_I420:
550         glActiveTexture(GL_TEXTURE2);
551         glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->fbo->tex);
552         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
553         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
554         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
555         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
556         break;
557     case FOURCC_NV12:
558         break;
559     default:
560         break;
561     }
562 
563     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
564     glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
565 
566     glEnable(GL_SCISSOR_TEST);
567 
568     v = glamor_get_vbo_space(screen, 3 * 4 * sizeof(GLfloat), &vbo_offset);
569 
570     /* Set up a single primitive covering the area being drawn.  We'll
571      * clip it to port_priv->clip using GL scissors instead of just
572      * emitting a GL_QUAD per box, because this way we hopefully avoid
573      * diagonal tearing between the two triangles used to rasterize a
574      * GL_QUAD.
575      */
576     i = 0;
577     v[i++] = port_priv->drw_x;
578     v[i++] = port_priv->drw_y;
579 
580     v[i++] = port_priv->drw_x + port_priv->dst_w * 2;
581     v[i++] = port_priv->drw_y;
582 
583     v[i++] = port_priv->drw_x;
584     v[i++] = port_priv->drw_y + port_priv->dst_h * 2;
585 
586     v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x);
587     v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y);
588 
589     v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x +
590                               port_priv->src_w * 2);
591     v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y);
592 
593     v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x);
594     v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y +
595                               port_priv->src_h * 2);
596 
597     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2,
598                           GL_FLOAT, GL_FALSE,
599                           2 * sizeof(float), vbo_offset);
600 
601     glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
602                           GL_FLOAT, GL_FALSE,
603                           2 * sizeof(float), vbo_offset + 6 * sizeof(GLfloat));
604 
605     glamor_put_vbo_space(screen);
606 
607     /* Now draw our big triangle, clipped to each of the clip boxes. */
608     glamor_pixmap_loop(pixmap_priv, dst_box_index) {
609         int dst_off_x, dst_off_y;
610 
611         glamor_set_destination_drawable(port_priv->pDraw,
612                                         dst_box_index,
613                                         FALSE, FALSE,
614                                         glamor_priv->xv_prog.matrix_uniform,
615                                         &dst_off_x, &dst_off_y);
616 
617         for (i = 0; i < nBox; i++) {
618             int dstx, dsty, dstw, dsth;
619 
620             dstx = box[i].x1 + dst_off_x;
621             dsty = box[i].y1 + dst_off_y;
622             dstw = box[i].x2 - box[i].x1;
623             dsth = box[i].y2 - box[i].y1;
624 
625             glScissor(dstx, dsty, dstw, dsth);
626             glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
627         }
628     }
629     glDisable(GL_SCISSOR_TEST);
630 
631     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
632     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
633 
634     DamageRegionProcessPending(port_priv->pDraw);
635 
636     glamor_xv_free_port_data(port_priv);
637 
638     glamor_pixmap_invalid(pixmap);
639 }
640 
641 static int
glamor_xv_render_dma(glamor_port_private * port_priv,int dma_fd)642 glamor_xv_render_dma(glamor_port_private *port_priv, int dma_fd)
643 {
644     ScreenPtr screen = port_priv->pPixmap->drawable.pScreen;
645     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
646     PixmapPtr pixmap = port_priv->pPixmap;
647     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
648     BoxPtr box = REGION_RECTS(&port_priv->clip);
649     int nBox = REGION_NUM_RECTS(&port_priv->clip);
650     GLfloat src_xscale, src_yscale;
651     int i;
652     GLfloat *v;
653     char *vbo_offset;
654     int dst_box_index;
655 
656     int hor_stride =
657         port_priv->dma_hor_stride ? port_priv->dma_hor_stride : port_priv->w;
658     int ver_stride =
659         port_priv->dma_ver_stride ? port_priv->dma_ver_stride : port_priv->h;
660     int width = hor_stride;
661     uint32_t fourcc =
662         port_priv->dma_drm_fourcc ? port_priv->dma_drm_fourcc : DRM_FORMAT_NV12;
663     int afbc = port_priv->dma_drm_afbc;
664 
665     PFNEGLCREATEIMAGEKHRPROC create_image;
666     PFNEGLDESTROYIMAGEKHRPROC destroy_image;
667     PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
668     EGLImageKHR image;
669     GLuint texture;
670 
671     /* Mali is using NV15 for NV12_10 */
672     switch (fourcc) {
673     case DRM_FORMAT_NV12_10:
674     case DRM_FORMAT_NV15:
675         fourcc = DRM_FORMAT_NV15;
676 
677         /* HACK: guess a width from 10B stride */
678         width = hor_stride / 10 * 8;
679 
680         if (afbc) {
681             fourcc = DRM_FORMAT_YUV420_10BIT;
682             hor_stride *= 1.5;
683         }
684         break;
685     case DRM_FORMAT_NV12:
686         if (afbc) {
687             fourcc = DRM_FORMAT_YUV420_8BIT;
688             hor_stride *= 1.5;
689         }
690         break;
691     case DRM_FORMAT_NV16:
692         if (afbc) {
693             fourcc = DRM_FORMAT_YUYV;
694             hor_stride *= 2;
695         }
696         break;
697     default:
698         ErrorF("glamor xv only support DMA for NV12|NV12_10|NV16\n");
699         return BadMatch;
700     }
701 
702     const EGLint attrs[] = {
703         EGL_WIDTH, width,
704         EGL_HEIGHT, ver_stride,
705         EGL_LINUX_DRM_FOURCC_EXT, fourcc,
706         EGL_DMA_BUF_PLANE0_FD_EXT, dma_fd,
707         EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
708         EGL_DMA_BUF_PLANE0_PITCH_EXT, hor_stride,
709         EGL_DMA_BUF_PLANE1_FD_EXT, dma_fd,
710         EGL_DMA_BUF_PLANE1_OFFSET_EXT, hor_stride * ver_stride,
711         EGL_DMA_BUF_PLANE1_PITCH_EXT, hor_stride,
712         EGL_YUV_COLOR_SPACE_HINT_EXT, EGL_ITU_REC601_EXT,
713         EGL_SAMPLE_RANGE_HINT_EXT, EGL_YUV_NARROW_RANGE_EXT,
714         EGL_NONE
715     };
716 
717     const EGLint attrs_afbc[] = {
718         EGL_WIDTH, width,
719         EGL_HEIGHT, ver_stride,
720         EGL_LINUX_DRM_FOURCC_EXT, fourcc,
721         EGL_DMA_BUF_PLANE0_FD_EXT, dma_fd,
722         EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
723         EGL_DMA_BUF_PLANE0_PITCH_EXT, hor_stride,
724         EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, DRM_AFBC_MODIFIER & 0xFFFFFFFF,
725         EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, DRM_AFBC_MODIFIER >> 32,
726         EGL_NONE
727     };
728 
729     create_image =
730         (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
731     destroy_image =
732         (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
733     image_target_texture_2d =
734         (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
735         eglGetProcAddress("glEGLImageTargetTexture2DOES");
736     if (!create_image || !destroy_image || !image_target_texture_2d) {
737         ErrorF("glamor xv without EGL_EXT_image_dma_buf_import\n");
738         return BadMatch;
739     }
740 
741     glamor_make_current(glamor_priv);
742 
743     image = create_image(glamor_priv->ctx.display, EGL_NO_CONTEXT,
744                          EGL_LINUX_DMA_BUF_EXT, NULL,
745                          afbc ? attrs_afbc : attrs);
746     if (image == EGL_NO_IMAGE) {
747         ErrorF("glamor xv failed to create egl image\n");
748         return BadMatch;
749     }
750 
751     DamageRegionAppend(port_priv->pDraw, &port_priv->clip);
752 
753     if (!glamor_priv->xv_prog_ext.prog)
754         glamor_init_xv_shader_egl_external(screen);
755 
756     /* TODO: support contrast/brightness/gamma/saturation/hue */
757     glamor_set_alu(screen, GXcopy);
758 
759     src_xscale = 1.0 / width;
760     src_yscale = 1.0 / ver_stride;
761 
762     glUseProgram(glamor_priv->xv_prog_ext.prog);
763 
764     glGenTextures(1, &texture);
765 
766     glActiveTexture(GL_TEXTURE0);
767     glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
768     image_target_texture_2d(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
769 
770     glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
771     glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
772     glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
773                     GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
774     glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
775                     GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
776 
777     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
778     glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
779 
780     glEnable(GL_SCISSOR_TEST);
781 
782     v = glamor_get_vbo_space(screen, 3 * 4 * sizeof(GLfloat), &vbo_offset);
783 
784     /* Set up a single primitive covering the area being drawn.  We'll
785      * clip it to port_priv->clip using GL scissors instead of just
786      * emitting a GL_QUAD per box, because this way we hopefully avoid
787      * diagonal tearing between the two triangles used to rasterize a
788      * GL_QUAD.
789      */
790     i = 0;
791     v[i++] = port_priv->drw_x;
792     v[i++] = port_priv->drw_y;
793 
794     v[i++] = port_priv->drw_x + port_priv->dst_w * 2;
795     v[i++] = port_priv->drw_y;
796 
797     v[i++] = port_priv->drw_x;
798     v[i++] = port_priv->drw_y + port_priv->dst_h * 2;
799 
800     v[i++] = t_from_x_coord_x(src_xscale, port_priv->src_x);
801     v[i++] = t_from_x_coord_y(src_yscale, port_priv->src_y);
802 
803     v[i++] = t_from_x_coord_x(src_xscale, port_priv->src_x +
804                               port_priv->src_w * 2);
805     v[i++] = t_from_x_coord_y(src_yscale, port_priv->src_y);
806 
807     v[i++] = t_from_x_coord_x(src_xscale, port_priv->src_x);
808     v[i++] = t_from_x_coord_y(src_yscale, port_priv->src_y +
809                               port_priv->src_h * 2);
810 
811     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2,
812                           GL_FLOAT, GL_FALSE,
813                           2 * sizeof(float), vbo_offset);
814 
815     glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
816                           GL_FLOAT, GL_FALSE,
817                           2 * sizeof(float), vbo_offset + 6 * sizeof(GLfloat));
818 
819     glamor_put_vbo_space(screen);
820 
821     /* Now draw our big triangle, clipped to each of the clip boxes. */
822     glamor_pixmap_loop(pixmap_priv, dst_box_index) {
823         int dst_off_x, dst_off_y;
824 
825         glamor_set_destination_drawable(port_priv->pDraw,
826                                         dst_box_index,
827                                         FALSE, FALSE,
828                                         glamor_priv->xv_prog_ext.matrix_uniform,
829                                         &dst_off_x, &dst_off_y);
830 
831         for (i = 0; i < nBox; i++) {
832             int dstx, dsty, dstw, dsth;
833 
834             dstx = box[i].x1 + dst_off_x;
835             dsty = box[i].y1 + dst_off_y;
836             dstw = box[i].x2 - box[i].x1;
837             dsth = box[i].y2 - box[i].y1;
838 
839             glScissor(dstx, dsty, dstw, dsth);
840             glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
841         }
842     }
843     glDisable(GL_SCISSOR_TEST);
844 
845     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
846     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
847 
848     DamageRegionProcessPending(port_priv->pDraw);
849 
850     glamor_xv_free_port_data(port_priv);
851 
852     glDeleteTextures(1, &texture);
853     destroy_image(glamor_priv->ctx.display, image);
854 
855     glamor_pixmap_invalid(pixmap);
856 
857     return Success;
858 }
859 
860 static int
glamor_xv_put_dma_image(glamor_port_private * port_priv,DrawablePtr pDrawable,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,short width,short height,Bool sync,RegionPtr clipBoxes)861 glamor_xv_put_dma_image(glamor_port_private *port_priv,
862                         DrawablePtr pDrawable,
863                         short src_x, short src_y,
864                         short drw_x, short drw_y,
865                         short src_w, short src_h,
866                         short drw_w, short drw_h,
867                         int id,
868                         short width,
869                         short height,
870                         Bool sync,
871                         RegionPtr clipBoxes)
872 {
873     ScreenPtr pScreen = pDrawable->pScreen;
874     struct iovec iov;
875     struct msghdr msg;
876     struct cmsghdr *header;
877     char buf[CMSG_SPACE (sizeof (int))];
878     int dma_fds[XV_MAX_DMA_FD], num_dma_fd;
879     int ret = BadMatch;
880 
881     if (!port_priv->dma_client || port_priv->dma_socket_fd <= 0)
882         return BadMatch;
883 
884     /* Only support NV12 for now */
885     if (id != FOURCC_NV12)
886         return BadValue;
887 
888     iov.iov_base = buf;
889     iov.iov_len = 1;
890 
891     msg.msg_iov = &iov;
892     msg.msg_iovlen = 1;
893     msg.msg_name = NULL;
894     msg.msg_namelen = 0;
895 
896     num_dma_fd = 0;
897     while (1) {
898         msg.msg_control = buf;
899         msg.msg_controllen = sizeof(buf);
900 
901         if (recvmsg(port_priv->dma_socket_fd, &msg, 0) < 0)
902             break;
903 
904         /* End with a empty msg */
905         header = CMSG_FIRSTHDR(&msg);
906         if (!header)
907             break;
908 
909         for (; header != NULL; header = CMSG_NXTHDR(&msg, header)) {
910             if (header->cmsg_level != SOL_SOCKET
911                 || header->cmsg_type != SCM_RIGHTS
912                 || header->cmsg_len != CMSG_LEN(sizeof(int)))
913                 break;
914 
915             dma_fds[num_dma_fd++] = *((int *)CMSG_DATA(header));
916         }
917     }
918 
919     /* Expected 1 buffer for NV12 */
920     if (num_dma_fd != 1)
921         goto out;
922 
923     if (pDrawable->type == DRAWABLE_WINDOW)
924         port_priv->pPixmap = pScreen->GetWindowPixmap((WindowPtr) pDrawable);
925     else
926         port_priv->pPixmap = (PixmapPtr) pDrawable;
927 
928     RegionCopy(&port_priv->clip, clipBoxes);
929 
930     port_priv->src_x = src_x;
931     port_priv->src_y = src_y;
932     port_priv->src_w = src_w;
933     port_priv->src_h = src_h;
934     port_priv->dst_w = drw_w;
935     port_priv->dst_h = drw_h;
936     port_priv->drw_x = drw_x;
937     port_priv->drw_y = drw_y;
938     port_priv->w = width;
939     port_priv->h = height;
940     port_priv->pDraw = pDrawable;
941 
942     ret = glamor_xv_render_dma(port_priv, dma_fds[0]);
943     if (ret == Success && sync)
944         glamor_finish(pScreen);
945 
946 out:
947     while (num_dma_fd--)
948         close(dma_fds[num_dma_fd]);
949 
950     if (ret != Success) {
951         ErrorF("glamor xv failed to render dma image\n");
952         glamor_xv_set_dma_client(port_priv, 0);
953     }
954 
955     return ret;
956 }
957 
958 int
glamor_xv_put_image(glamor_port_private * port_priv,DrawablePtr pDrawable,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)959 glamor_xv_put_image(glamor_port_private *port_priv,
960                     DrawablePtr pDrawable,
961                     short src_x, short src_y,
962                     short drw_x, short drw_y,
963                     short src_w, short src_h,
964                     short drw_w, short drw_h,
965                     int id,
966                     unsigned char *buf,
967                     short width,
968                     short height,
969                     Bool sync,
970                     RegionPtr clipBoxes)
971 {
972     ScreenPtr pScreen = pDrawable->pScreen;
973     glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen);
974     int srcPitch, srcPitch2;
975     int top, nlines;
976     int s2offset, s3offset, tmp;
977     BoxRec full_box, half_box;
978 
979     if (glamor_xv_put_dma_image(port_priv, pDrawable,
980                                 src_x, src_y, drw_x, drw_y,
981                                 src_w, src_h, drw_w, drw_h,
982                                 id, width, height, sync, clipBoxes) == Success)
983         return Success;
984 
985     s2offset = s3offset = srcPitch2 = 0;
986 
987     if (!port_priv->src_pix[0] ||
988         (width != port_priv->src_pix_w || height != port_priv->src_pix_h) ||
989         (port_priv->src_pix[2] && id == FOURCC_NV12) ||
990         (!port_priv->src_pix[2] && id != FOURCC_NV12)) {
991         int i;
992 
993         if (glamor_priv->xv_prog.prog) {
994             glDeleteProgram(glamor_priv->xv_prog.prog);
995             glamor_priv->xv_prog.prog = 0;
996         }
997 
998         for (i = 0; i < 3; i++)
999             if (port_priv->src_pix[i])
1000                 glamor_destroy_pixmap(port_priv->src_pix[i]);
1001 
1002         port_priv->src_pix[0] =
1003             glamor_create_pixmap(pScreen, width, height, 8,
1004                                  GLAMOR_CREATE_FBO_NO_FBO);
1005 
1006         switch (id) {
1007         case FOURCC_YV12:
1008         case FOURCC_I420:
1009             port_priv->src_pix[1] =
1010                 glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8,
1011                                      GLAMOR_CREATE_FBO_NO_FBO);
1012             port_priv->src_pix[2] =
1013                 glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8,
1014                                      GLAMOR_CREATE_FBO_NO_FBO);
1015             if (!port_priv->src_pix[2])
1016                 return BadAlloc;
1017             break;
1018         case FOURCC_NV12:
1019             port_priv->src_pix[1] =
1020                 glamor_create_pixmap(pScreen, width >> 1, height >> 1, 16,
1021                                      GLAMOR_CREATE_FBO_NO_FBO |
1022                                      GLAMOR_CREATE_FORMAT_CBCR);
1023             port_priv->src_pix[2] = NULL;
1024             break;
1025         default:
1026             return BadMatch;
1027         }
1028 
1029         port_priv->src_pix_w = width;
1030         port_priv->src_pix_h = height;
1031 
1032         if (!port_priv->src_pix[0] || !port_priv->src_pix[1])
1033             return BadAlloc;
1034     }
1035 
1036     top = (src_y) & ~1;
1037     nlines = (src_y + src_h) - top;
1038 
1039     switch (id) {
1040     case FOURCC_YV12:
1041     case FOURCC_I420:
1042         srcPitch = ALIGN(width, 4);
1043         srcPitch2 = ALIGN(width >> 1, 4);
1044         s2offset = srcPitch * height;
1045         s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1));
1046         s2offset += ((top >> 1) * srcPitch2);
1047         s3offset += ((top >> 1) * srcPitch2);
1048         if (id == FOURCC_YV12) {
1049             tmp = s2offset;
1050             s2offset = s3offset;
1051             s3offset = tmp;
1052         }
1053 
1054         full_box.x1 = 0;
1055         full_box.y1 = 0;
1056         full_box.x2 = width;
1057         full_box.y2 = nlines;
1058 
1059         half_box.x1 = 0;
1060         half_box.y1 = 0;
1061         half_box.x2 = width >> 1;
1062         half_box.y2 = (nlines + 1) >> 1;
1063 
1064         glamor_upload_boxes(port_priv->src_pix[0], &full_box, 1,
1065                             0, 0, 0, 0,
1066                             buf + (top * srcPitch), srcPitch);
1067 
1068         glamor_upload_boxes(port_priv->src_pix[1], &half_box, 1,
1069                             0, 0, 0, 0,
1070                             buf + s2offset, srcPitch2);
1071 
1072         glamor_upload_boxes(port_priv->src_pix[2], &half_box, 1,
1073                             0, 0, 0, 0,
1074                             buf + s3offset, srcPitch2);
1075         break;
1076     case FOURCC_NV12:
1077         srcPitch = ALIGN(width, 4);
1078         s2offset = srcPitch * height;
1079         s2offset += ((top >> 1) * srcPitch);
1080 
1081         full_box.x1 = 0;
1082         full_box.y1 = 0;
1083         full_box.x2 = width;
1084         full_box.y2 = nlines;
1085 
1086         half_box.x1 = 0;
1087         half_box.y1 = 0;
1088         half_box.x2 = width;
1089         half_box.y2 = (nlines + 1) >> 1;
1090 
1091         glamor_upload_boxes(port_priv->src_pix[0], &full_box, 1,
1092                             0, 0, 0, 0,
1093                             buf + (top * srcPitch), srcPitch);
1094 
1095         glamor_upload_boxes(port_priv->src_pix[1], &half_box, 1,
1096                             0, 0, 0, 0,
1097                             buf + s2offset, srcPitch);
1098         break;
1099     default:
1100         return BadMatch;
1101     }
1102 
1103     if (pDrawable->type == DRAWABLE_WINDOW)
1104         port_priv->pPixmap = pScreen->GetWindowPixmap((WindowPtr) pDrawable);
1105     else
1106         port_priv->pPixmap = (PixmapPtr) pDrawable;
1107 
1108     RegionCopy(&port_priv->clip, clipBoxes);
1109 
1110     port_priv->src_x = src_x;
1111     port_priv->src_y = src_y - top;
1112     port_priv->src_w = src_w;
1113     port_priv->src_h = src_h;
1114     port_priv->dst_w = drw_w;
1115     port_priv->dst_h = drw_h;
1116     port_priv->drw_x = drw_x;
1117     port_priv->drw_y = drw_y;
1118     port_priv->w = width;
1119     port_priv->h = height;
1120     port_priv->pDraw = pDrawable;
1121     glamor_xv_render(port_priv, id);
1122     return Success;
1123 }
1124 
1125 void
glamor_xv_init_port(glamor_port_private * port_priv)1126 glamor_xv_init_port(glamor_port_private *port_priv)
1127 {
1128     port_priv->brightness = 0;
1129     port_priv->contrast = 0;
1130     port_priv->saturation = 0;
1131     port_priv->hue = 0;
1132     port_priv->gamma = 1000;
1133     port_priv->transform_index = 0;
1134     port_priv->dma_client = 0;
1135     port_priv->dma_socket_fd = 0;
1136     port_priv->dma_hor_stride = 0;
1137     port_priv->dma_ver_stride = 0;
1138     port_priv->dma_drm_fourcc = 0;
1139     port_priv->dma_drm_afbc = 0;
1140 
1141     REGION_NULL(pScreen, &port_priv->clip);
1142 }
1143 
1144 void
glamor_xv_core_init(ScreenPtr screen)1145 glamor_xv_core_init(ScreenPtr screen)
1146 {
1147     glamorBrightness = MAKE_ATOM("XV_BRIGHTNESS");
1148     glamorContrast = MAKE_ATOM("XV_CONTRAST");
1149     glamorSaturation = MAKE_ATOM("XV_SATURATION");
1150     glamorHue = MAKE_ATOM("XV_HUE");
1151     glamorGamma = MAKE_ATOM("XV_GAMMA");
1152     glamorColorspace = MAKE_ATOM("XV_COLORSPACE");
1153     glamorDmaClient = MAKE_ATOM("XV_DMA_CLIENT_ID");
1154     glamorDmaHorStride = MAKE_ATOM("XV_DMA_HOR_STRIDE");
1155     glamorDmaVerStride = MAKE_ATOM("XV_DMA_VER_STRIDE");
1156     glamorDmaDrmFourcc = MAKE_ATOM("XV_DMA_DRM_FOURCC");
1157     glamorDmaDrmAFBC = MAKE_ATOM("XV_DMA_DRM_AFBC");
1158 }
1159