2 * Copyright © 2013 Red Hat
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:
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
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
24 * Dave Airlie <airlied@redhat.com>
26 * some code is derived from the xf86-video-ati radeon driver, mainly
32 * Xv acceleration implementation
35 #include <dix-config.h>
37 #include "glamor_priv.h"
38 #include "glamor_transform.h"
39 #include "glamor_transfer.h"
41 #include <X11/extensions/Xv.h>
43 /* Reference color space transform data */
44 typedef struct tagREF_TRANSFORM
{
54 #define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
55 #define RTFBrightness(a) (((a)*1.0)/2000.0)
56 #define RTFIntensity(a) (((a)*1.0)/2000.0)
57 #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
58 #define RTFHue(a) (((a)*3.1416)/1000.0)
60 static const glamor_facet glamor_facet_xv_planar_2
= {
61 .name
= "xv_planar_2",
63 .source_name
= "v_texcoord0",
64 .vs_vars
= ("in vec2 position;\n"
65 "in vec2 v_texcoord0;\n"
67 .vs_exec
= (GLAMOR_POS(gl_Position
, position
)
68 " tcs = v_texcoord0;\n"),
70 .fs_vars
= ("uniform sampler2D y_sampler;\n"
71 "uniform sampler2D u_sampler;\n"
72 "uniform vec4 offsetyco;\n"
73 "uniform vec4 ucogamma;\n"
80 " sample = texture(y_sampler, tcs).w;\n"
81 " temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n"
82 " sample_uv = texture(u_sampler, tcs).xy;\n"
83 " temp1.xyz = ucogamma.xyz * vec3(sample_uv.x) + temp1.xyz;\n"
84 " temp1.xyz = clamp(vco.xyz * vec3(sample_uv.y) + temp1.xyz, 0.0, 1.0);\n"
86 " frag_color = temp1;\n"
90 static const glamor_facet glamor_facet_xv_planar_3
= {
91 .name
= "xv_planar_3",
93 .source_name
= "v_texcoord0",
94 .vs_vars
= ("in vec2 position;\n"
95 "in vec2 v_texcoord0;\n"
97 .vs_exec
= (GLAMOR_POS(gl_Position
, position
)
98 " tcs = v_texcoord0;\n"),
100 .fs_vars
= ("uniform sampler2D y_sampler;\n"
101 "uniform sampler2D u_sampler;\n"
102 "uniform sampler2D v_sampler;\n"
103 "uniform vec4 offsetyco;\n"
104 "uniform vec4 ucogamma;\n"
105 "uniform vec4 vco;\n"
110 " sample = texture(y_sampler, tcs).w;\n"
111 " temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n"
112 " sample = texture(u_sampler, tcs).w;\n"
113 " temp1.xyz = ucogamma.xyz * vec3(sample) + temp1.xyz;\n"
114 " sample = texture(v_sampler, tcs).w;\n"
115 " temp1.xyz = clamp(vco.xyz * vec3(sample) + temp1.xyz, 0.0, 1.0);\n"
117 " frag_color = temp1;\n"
121 static const glamor_facet glamor_facet_xv_uyvy
= {
124 .source_name
= "v_texcoord0",
125 .vs_vars
= ("in vec2 position;\n"
126 "in vec2 v_texcoord0;\n"
128 .vs_exec
= (GLAMOR_POS(gl_Position
, position
)
129 " tcs = v_texcoord0;\n"),
131 .fs_vars
= ("#ifdef GL_ES\n"
132 "precision highp float;\n"
134 "uniform sampler2D sampler;\n"
135 "uniform vec2 texelSize;\n"
136 "uniform vec4 offsetyco;\n"
137 "uniform vec4 ucogamma;\n"
138 "uniform vec4 vco;\n"
143 " vec2 xy = texture(sampler, tcs.st).xy;\n"
144 " vec2 prev_xy = texture(sampler, vec2(tcs.s - texelSize.x, tcs.t)).xy;\n"
145 " vec2 next_xy = texture(sampler, vec2(tcs.s + texelSize.x, tcs.t)).xy;\n"
147 " vec3 sample_yuv;\n"
148 " int odd = int(mod(tcs.x / texelSize.x, 2.0));\n"
149 " int even = 1 - odd;\n"
150 " sample_yuv.yxz = float(even)*vec3(xy, next_xy.x) + float(odd)*vec3(prev_xy.x, xy.yx);\n"
152 " temp1.xyz = offsetyco.www * vec3(sample_yuv.x) + offsetyco.xyz;\n"
153 " temp1.xyz = ucogamma.xyz * vec3(sample_yuv.y) + temp1.xyz;\n"
154 " temp1.xyz = clamp(vco.xyz * vec3(sample_yuv.z) + temp1.xyz, 0.0, 1.0);\n"
156 " frag_color = temp1;\n"
160 static const glamor_facet glamor_facet_xv_rgb_raw
= {
163 .source_name
= "v_texcoord0",
164 .vs_vars
= ("in vec2 position;\n"
165 "in vec2 v_texcoord0;\n"
167 .vs_exec
= (GLAMOR_POS(gl_Position
, position
)
168 " tcs = v_texcoord0;\n"),
170 .fs_vars
= ("uniform sampler2D sampler;\n"
173 " frag_color = texture2D(sampler, tcs);\n"
177 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
179 XvAttributeRec glamor_xv_attributes
[] = {
180 {XvSettable
| XvGettable
, -1000, 1000, (char *)"XV_BRIGHTNESS"},
181 {XvSettable
| XvGettable
, -1000, 1000, (char *)"XV_CONTRAST"},
182 {XvSettable
| XvGettable
, -1000, 1000, (char *)"XV_SATURATION"},
183 {XvSettable
| XvGettable
, -1000, 1000, (char *)"XV_HUE"},
184 {XvSettable
| XvGettable
, 0, 1, (char *)"XV_COLORSPACE"},
187 int glamor_xv_num_attributes
= ARRAY_SIZE(glamor_xv_attributes
) - 1;
189 Atom glamorBrightness
, glamorContrast
, glamorSaturation
, glamorHue
,
190 glamorColorspace
, glamorGamma
;
192 XvImageRec glamor_xv_images
[] = {
200 int glamor_xv_num_images
= ARRAY_SIZE(glamor_xv_images
);
203 glamor_init_xv_shader(ScreenPtr screen
, glamor_port_private
*port_priv
, int id
)
206 const glamor_facet
*glamor_facet_xv_planar
= NULL
;
211 glamor_facet_xv_planar
= &glamor_facet_xv_planar_3
;
214 glamor_facet_xv_planar
= &glamor_facet_xv_planar_2
;
217 glamor_facet_xv_planar
= &glamor_facet_xv_uyvy
;
221 glamor_facet_xv_planar
= &glamor_facet_xv_rgb_raw
;
227 glamor_build_program(screen
,
229 glamor_facet_xv_planar
, NULL
, NULL
, NULL
);
231 glUseProgram(port_priv
->xv_prog
.prog
);
236 sampler_loc
= glGetUniformLocation(port_priv
->xv_prog
.prog
, "y_sampler");
237 glUniform1i(sampler_loc
, 0);
238 sampler_loc
= glGetUniformLocation(port_priv
->xv_prog
.prog
, "u_sampler");
239 glUniform1i(sampler_loc
, 1);
240 sampler_loc
= glGetUniformLocation(port_priv
->xv_prog
.prog
, "v_sampler");
241 glUniform1i(sampler_loc
, 2);
244 sampler_loc
= glGetUniformLocation(port_priv
->xv_prog
.prog
, "y_sampler");
245 glUniform1i(sampler_loc
, 0);
246 sampler_loc
= glGetUniformLocation(port_priv
->xv_prog
.prog
, "u_sampler");
247 glUniform1i(sampler_loc
, 1);
252 sampler_loc
= glGetUniformLocation(port_priv
->xv_prog
.prog
, "sampler");
253 glUniform1i(sampler_loc
, 0);
261 #define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
264 glamor_xv_stop_video(glamor_port_private
*port_priv
)
269 glamor_xv_free_port_data(glamor_port_private
*port_priv
)
273 for (i
= 0; i
< 3; i
++) {
274 if (port_priv
->src_pix
[i
]) {
275 glamor_destroy_pixmap(port_priv
->src_pix
[i
]);
276 port_priv
->src_pix
[i
] = NULL
;
279 RegionUninit(&port_priv
->clip
);
280 RegionNull(&port_priv
->clip
);
284 glamor_xv_set_port_attribute(glamor_port_private
*port_priv
,
285 Atom attribute
, INT32 value
)
287 if (attribute
== glamorBrightness
)
288 port_priv
->brightness
= ClipValue(value
, -1000, 1000);
289 else if (attribute
== glamorHue
)
290 port_priv
->hue
= ClipValue(value
, -1000, 1000);
291 else if (attribute
== glamorContrast
)
292 port_priv
->contrast
= ClipValue(value
, -1000, 1000);
293 else if (attribute
== glamorSaturation
)
294 port_priv
->saturation
= ClipValue(value
, -1000, 1000);
295 else if (attribute
== glamorGamma
)
296 port_priv
->gamma
= ClipValue(value
, 100, 10000);
297 else if (attribute
== glamorColorspace
)
298 port_priv
->transform_index
= ClipValue(value
, 0, 1);
305 glamor_xv_get_port_attribute(glamor_port_private
*port_priv
,
306 Atom attribute
, INT32
*value
)
308 if (attribute
== glamorBrightness
)
309 *value
= port_priv
->brightness
;
310 else if (attribute
== glamorHue
)
311 *value
= port_priv
->hue
;
312 else if (attribute
== glamorContrast
)
313 *value
= port_priv
->contrast
;
314 else if (attribute
== glamorSaturation
)
315 *value
= port_priv
->saturation
;
316 else if (attribute
== glamorGamma
)
317 *value
= port_priv
->gamma
;
318 else if (attribute
== glamorColorspace
)
319 *value
= port_priv
->transform_index
;
327 glamor_xv_query_image_attributes(int id
,
328 unsigned short *w
, unsigned short *h
,
329 int *pitches
, int *offsets
)
346 tmp
= ALIGN(*w
>> 1, 4);
348 pitches
[1] = pitches
[2] = tmp
;
379 /* UYVU is single-plane really, all tranformation is processed inside a shader */
380 size
= ALIGN(*w
, 2) * 2;
399 /* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces
400 note the difference to the parameters used in overlay are due
401 to 10bit vs. float calcs */
402 static REF_TRANSFORM trans
[2] = {
403 {1.1643, 0.0, 1.5960, -0.3918, -0.8129, 2.0172, 0.0}, /* BT.601 */
404 {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0} /* BT.709 */
408 glamor_xv_render(glamor_port_private
*port_priv
, int id
)
410 ScreenPtr screen
= port_priv
->pPixmap
->drawable
.pScreen
;
411 glamor_screen_private
*glamor_priv
= glamor_get_screen_private(screen
);
412 PixmapPtr pixmap
= port_priv
->pPixmap
;
413 glamor_pixmap_private
*pixmap_priv
= glamor_get_pixmap_private(pixmap
);
414 glamor_pixmap_private
*src_pixmap_priv
[3];
415 BoxPtr box
= REGION_RECTS(&port_priv
->clip
);
416 int nBox
= REGION_NUM_RECTS(&port_priv
->clip
);
417 GLfloat src_xscale
[3], src_yscale
[3];
419 const float Loff
= -0.0627;
420 const float Coff
= -0.502;
421 float uvcosf
, uvsinf
;
423 float uco
[3], vco
[3], off
[3];
424 float bright
, cont
, gamma
;
425 int ref
= port_priv
->transform_index
;
431 if (!port_priv
->xv_prog
.prog
)
432 glamor_init_xv_shader(screen
, port_priv
, id
);
434 cont
= RTFContrast(port_priv
->contrast
);
435 bright
= RTFBrightness(port_priv
->brightness
);
436 gamma
= (float) port_priv
->gamma
/ 1000.0;
437 uvcosf
= RTFSaturation(port_priv
->saturation
) * cos(RTFHue(port_priv
->hue
));
438 uvsinf
= RTFSaturation(port_priv
->saturation
) * sin(RTFHue(port_priv
->hue
));
439 /* overlay video also does pre-gamma contrast/sat adjust, should we? */
441 yco
= trans
[ref
].RefLuma
* cont
;
442 uco
[0] = -trans
[ref
].RefRCr
* uvsinf
;
443 uco
[1] = trans
[ref
].RefGCb
* uvcosf
- trans
[ref
].RefGCr
* uvsinf
;
444 uco
[2] = trans
[ref
].RefBCb
* uvcosf
;
445 vco
[0] = trans
[ref
].RefRCr
* uvcosf
;
446 vco
[1] = trans
[ref
].RefGCb
* uvsinf
+ trans
[ref
].RefGCr
* uvcosf
;
447 vco
[2] = trans
[ref
].RefBCb
* uvsinf
;
448 off
[0] = Loff
* yco
+ Coff
* (uco
[0] + vco
[0]) + bright
;
449 off
[1] = Loff
* yco
+ Coff
* (uco
[1] + vco
[1]) + bright
;
450 off
[2] = Loff
* yco
+ Coff
* (uco
[2] + vco
[2]) + bright
;
453 glamor_set_alu(&pixmap
->drawable
, GXcopy
);
455 for (i
= 0; i
< 3; i
++) {
456 if (port_priv
->src_pix
[i
]) {
458 glamor_get_pixmap_private(port_priv
->src_pix
[i
]);
459 pixmap_priv_get_scale(src_pixmap_priv
[i
], &src_xscale
[i
],
462 src_pixmap_priv
[i
] = NULL
;
465 glamor_make_current(glamor_priv
);
466 glUseProgram(port_priv
->xv_prog
.prog
);
468 uloc
= glGetUniformLocation(port_priv
->xv_prog
.prog
, "offsetyco");
469 glUniform4f(uloc
, off
[0], off
[1], off
[2], yco
);
470 uloc
= glGetUniformLocation(port_priv
->xv_prog
.prog
, "ucogamma");
471 glUniform4f(uloc
, uco
[0], uco
[1], uco
[2], gamma
);
472 uloc
= glGetUniformLocation(port_priv
->xv_prog
.prog
, "vco");
473 glUniform4f(uloc
, vco
[0], vco
[1], vco
[2], 0);
478 glActiveTexture(GL_TEXTURE0
);
479 glBindTexture(GL_TEXTURE_2D
, src_pixmap_priv
[0]->fbo
->tex
);
480 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
481 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
482 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
483 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
485 glActiveTexture(GL_TEXTURE1
);
486 glBindTexture(GL_TEXTURE_2D
, src_pixmap_priv
[1]->fbo
->tex
);
487 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
488 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
489 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
490 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
492 glActiveTexture(GL_TEXTURE2
);
493 glBindTexture(GL_TEXTURE_2D
, src_pixmap_priv
[2]->fbo
->tex
);
494 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
495 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
496 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
497 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
500 glActiveTexture(GL_TEXTURE0
);
501 glBindTexture(GL_TEXTURE_2D
, src_pixmap_priv
[0]->fbo
->tex
);
502 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
503 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
504 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
505 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
507 glActiveTexture(GL_TEXTURE1
);
508 glBindTexture(GL_TEXTURE_2D
, src_pixmap_priv
[1]->fbo
->tex
);
509 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
510 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
511 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
512 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
515 uloc
= glGetUniformLocation(port_priv
->xv_prog
.prog
, "texelSize");
516 glUniform2f(uloc
, 1.0 / port_priv
->w
, 1.0 / port_priv
->h
);
518 glActiveTexture(GL_TEXTURE0
);
519 glBindTexture(GL_TEXTURE_2D
, src_pixmap_priv
[0]->fbo
->tex
);
520 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
521 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
522 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
523 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
527 glActiveTexture(GL_TEXTURE0
);
528 glBindTexture(GL_TEXTURE_2D
, src_pixmap_priv
[0]->fbo
->tex
);
529 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
530 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
531 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
532 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
538 glEnableVertexAttribArray(GLAMOR_VERTEX_POS
);
539 glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE
);
541 glEnable(GL_SCISSOR_TEST
);
543 v
= glamor_get_vbo_space(screen
, 3 * 4 * sizeof(GLfloat
), &vbo_offset
);
545 /* Set up a single primitive covering the area being drawn. We'll
546 * clip it to port_priv->clip using GL scissors instead of just
547 * emitting a GL_QUAD per box, because this way we hopefully avoid
548 * diagonal tearing between the two triangles used to rasterize a
552 v
[i
++] = port_priv
->drw_x
;
553 v
[i
++] = port_priv
->drw_y
;
555 v
[i
++] = port_priv
->drw_x
+ port_priv
->dst_w
* 2;
556 v
[i
++] = port_priv
->drw_y
;
558 v
[i
++] = port_priv
->drw_x
;
559 v
[i
++] = port_priv
->drw_y
+ port_priv
->dst_h
* 2;
561 v
[i
++] = t_from_x_coord_x(src_xscale
[0], port_priv
->src_x
);
562 v
[i
++] = t_from_x_coord_y(src_yscale
[0], port_priv
->src_y
);
564 v
[i
++] = t_from_x_coord_x(src_xscale
[0], port_priv
->src_x
+
565 port_priv
->src_w
* 2);
566 v
[i
++] = t_from_x_coord_y(src_yscale
[0], port_priv
->src_y
);
568 v
[i
++] = t_from_x_coord_x(src_xscale
[0], port_priv
->src_x
);
569 v
[i
++] = t_from_x_coord_y(src_yscale
[0], port_priv
->src_y
+
570 port_priv
->src_h
* 2);
572 glVertexAttribPointer(GLAMOR_VERTEX_POS
, 2,
574 2 * sizeof(float), vbo_offset
);
576 glVertexAttribPointer(GLAMOR_VERTEX_SOURCE
, 2,
578 2 * sizeof(float), vbo_offset
+ 6 * sizeof(GLfloat
));
580 glamor_put_vbo_space(screen
);
582 /* Now draw our big triangle, clipped to each of the clip boxes. */
583 glamor_pixmap_loop(pixmap_priv
, dst_box_index
) {
584 int dst_off_x
, dst_off_y
;
586 glamor_set_destination_drawable(port_priv
->pDraw
,
589 port_priv
->xv_prog
.matrix_uniform
,
590 &dst_off_x
, &dst_off_y
);
592 for (i
= 0; i
< nBox
; i
++) {
593 int dstx
, dsty
, dstw
, dsth
;
595 dstx
= box
[i
].x1
+ dst_off_x
;
596 dsty
= box
[i
].y1
+ dst_off_y
;
597 dstw
= box
[i
].x2
- box
[i
].x1
;
598 dsth
= box
[i
].y2
- box
[i
].y1
;
600 glScissor(dstx
, dsty
, dstw
, dsth
);
601 glDrawArrays(GL_TRIANGLE_FAN
, 0, 3);
604 glDisable(GL_SCISSOR_TEST
);
606 glDisableVertexAttribArray(GLAMOR_VERTEX_POS
);
607 glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE
);
609 DamageDamageRegion(port_priv
->pDraw
, &port_priv
->clip
);
613 glamor_xv_can_reuse_port(glamor_port_private
*port_priv
, int id
, short w
, short h
)
617 if (port_priv
->prev_fmt
!= id
)
620 if (w
!= port_priv
->src_pix_w
|| h
!= port_priv
->src_pix_h
)
623 if (!port_priv
->src_pix
[0])
626 port_priv
->prev_fmt
= id
;
632 glamor_xv_put_image(glamor_port_private
*port_priv
,
633 DrawablePtr pDrawable
,
634 short src_x
, short src_y
,
635 short drw_x
, short drw_y
,
636 short src_w
, short src_h
,
637 short drw_w
, short drw_h
,
645 ScreenPtr pScreen
= pDrawable
->pScreen
;
646 int srcPitch
, srcPitch2
;
648 int s2offset
, s3offset
, tmp
;
649 BoxRec full_box
, half_box
;
651 s2offset
= s3offset
= srcPitch2
= 0;
653 if (!glamor_xv_can_reuse_port(port_priv
, id
, width
, height
)) {
656 glamor_xv_free_port_data(port_priv
);
658 if (port_priv
->xv_prog
.prog
) {
659 glDeleteProgram(port_priv
->xv_prog
.prog
);
660 port_priv
->xv_prog
.prog
= 0;
663 for (i
= 0; i
< 3; i
++)
664 if (port_priv
->src_pix
[i
])
665 glamor_destroy_pixmap(port_priv
->src_pix
[i
]);
670 port_priv
->src_pix
[0] =
671 glamor_create_pixmap(pScreen
, width
, height
, 8,
672 GLAMOR_CREATE_FBO_NO_FBO
);
674 port_priv
->src_pix
[1] =
675 glamor_create_pixmap(pScreen
, width
>> 1, height
>> 1, 8,
676 GLAMOR_CREATE_FBO_NO_FBO
);
677 port_priv
->src_pix
[2] =
678 glamor_create_pixmap(pScreen
, width
>> 1, height
>> 1, 8,
679 GLAMOR_CREATE_FBO_NO_FBO
);
680 if (!port_priv
->src_pix
[1] || !port_priv
->src_pix
[2])
684 port_priv
->src_pix
[0] =
685 glamor_create_pixmap(pScreen
, width
, height
, 8,
686 GLAMOR_CREATE_FBO_NO_FBO
);
687 port_priv
->src_pix
[1] =
688 glamor_create_pixmap(pScreen
, width
>> 1, height
>> 1, 16,
689 GLAMOR_CREATE_FBO_NO_FBO
|
690 GLAMOR_CREATE_FORMAT_CBCR
);
691 port_priv
->src_pix
[2] = NULL
;
693 if (!port_priv
->src_pix
[1])
697 port_priv
->src_pix
[0] =
698 glamor_create_pixmap(pScreen
, width
, height
, 32,
699 GLAMOR_CREATE_FBO_NO_FBO
);
700 port_priv
->src_pix
[1] = NULL
;
701 port_priv
->src_pix
[2] = NULL
;
704 port_priv
->src_pix
[0] =
705 glamor_create_pixmap(pScreen
, width
, height
, 16,
706 GLAMOR_CREATE_FBO_NO_FBO
);
707 port_priv
->src_pix
[1] = NULL
;
708 port_priv
->src_pix
[2] = NULL
;
711 port_priv
->src_pix
[0] =
712 glamor_create_pixmap(pScreen
, width
, height
, 32,
713 GLAMOR_CREATE_FBO_NO_FBO
|
714 GLAMOR_CREATE_FORMAT_CBCR
);
715 port_priv
->src_pix
[1] = NULL
;
716 port_priv
->src_pix
[2] = NULL
;
722 port_priv
->src_pix_w
= width
;
723 port_priv
->src_pix_h
= height
;
725 if (!port_priv
->src_pix
[0])
730 nlines
= (src_y
+ src_h
) - top
;
735 srcPitch
= ALIGN(width
, 4);
736 srcPitch2
= ALIGN(width
>> 1, 4);
737 s2offset
= srcPitch
* height
;
738 s3offset
= s2offset
+ (srcPitch2
* ((height
+ 1) >> 1));
739 s2offset
+= ((top
>> 1) * srcPitch2
);
740 s3offset
+= ((top
>> 1) * srcPitch2
);
741 if (id
== FOURCC_YV12
) {
750 full_box
.y2
= nlines
;
754 half_box
.x2
= width
>> 1;
755 half_box
.y2
= (nlines
+ 1) >> 1;
757 glamor_upload_boxes(&port_priv
->src_pix
[0]->drawable
, &full_box
, 1,
759 buf
+ (top
* srcPitch
), srcPitch
);
761 glamor_upload_boxes(&port_priv
->src_pix
[1]->drawable
, &half_box
, 1,
763 buf
+ s2offset
, srcPitch2
);
765 glamor_upload_boxes(&port_priv
->src_pix
[2]->drawable
, &half_box
, 1,
767 buf
+ s3offset
, srcPitch2
);
770 srcPitch
= ALIGN(width
, 4);
771 s2offset
= srcPitch
* height
;
772 s2offset
+= ((top
>> 1) * srcPitch
);
777 full_box
.y2
= nlines
;
782 half_box
.y2
= (nlines
+ 1) >> 1;
784 glamor_upload_boxes(&port_priv
->src_pix
[0]->drawable
, &full_box
, 1,
786 buf
+ (top
* srcPitch
), srcPitch
);
788 glamor_upload_boxes(&port_priv
->src_pix
[1]->drawable
, &half_box
, 1,
790 buf
+ s2offset
, srcPitch
);
793 srcPitch
= ALIGN(width
, 2) * 2;
797 full_box
.y2
= height
;
798 glamor_upload_boxes(&port_priv
->src_pix
[0]->drawable
, &full_box
, 1,
803 srcPitch
= width
* 2;
807 full_box
.y2
= height
;
808 glamor_upload_boxes(&port_priv
->src_pix
[0]->drawable
, &full_box
, 1,
813 srcPitch
= width
* 4;
817 full_box
.y2
= height
;
818 glamor_upload_boxes(&port_priv
->src_pix
[0]->drawable
, &full_box
, 1,
826 if (pDrawable
->type
== DRAWABLE_WINDOW
)
827 port_priv
->pPixmap
= pScreen
->GetWindowPixmap((WindowPtr
) pDrawable
);
829 port_priv
->pPixmap
= (PixmapPtr
) pDrawable
;
831 RegionCopy(&port_priv
->clip
, clipBoxes
);
833 port_priv
->src_x
= src_x
;
834 port_priv
->src_y
= src_y
- top
;
835 port_priv
->src_w
= src_w
;
836 port_priv
->src_h
= src_h
;
837 port_priv
->dst_w
= drw_w
;
838 port_priv
->dst_h
= drw_h
;
839 port_priv
->drw_x
= drw_x
;
840 port_priv
->drw_y
= drw_y
;
841 port_priv
->w
= width
;
842 port_priv
->h
= height
;
843 port_priv
->pDraw
= pDrawable
;
844 glamor_xv_render(port_priv
, id
);
849 glamor_xv_init_port(glamor_port_private
*port_priv
)
851 port_priv
->brightness
= 0;
852 port_priv
->contrast
= 0;
853 port_priv
->saturation
= 0;
855 port_priv
->gamma
= 1000;
856 port_priv
->transform_index
= 0;
858 REGION_NULL(pScreen
, &port_priv
->clip
);
862 glamor_xv_core_init(ScreenPtr screen
)
864 glamorBrightness
= MAKE_ATOM("XV_BRIGHTNESS");
865 glamorContrast
= MAKE_ATOM("XV_CONTRAST");
866 glamorSaturation
= MAKE_ATOM("XV_SATURATION");
867 glamorHue
= MAKE_ATOM("XV_HUE");
868 glamorGamma
= MAKE_ATOM("XV_GAMMA");
869 glamorColorspace
= MAKE_ATOM("XV_COLORSPACE");