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