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