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