xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/va/image.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /**************************************************************************
2*61046927SAndroid Build Coastguard Worker  *
3*61046927SAndroid Build Coastguard Worker  * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian.
4*61046927SAndroid Build Coastguard Worker  * Copyright 2014 Advanced Micro Devices, Inc.
5*61046927SAndroid Build Coastguard Worker  * All Rights Reserved.
6*61046927SAndroid Build Coastguard Worker  *
7*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
8*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the
9*61046927SAndroid Build Coastguard Worker  * "Software"), to deal in the Software without restriction, including
10*61046927SAndroid Build Coastguard Worker  * without limitation the rights to use, copy, modify, merge, publish,
11*61046927SAndroid Build Coastguard Worker  * distribute, sub license, and/or sell copies of the Software, and to
12*61046927SAndroid Build Coastguard Worker  * permit persons to whom the Software is furnished to do so, subject to
13*61046927SAndroid Build Coastguard Worker  * the following conditions:
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the
16*61046927SAndroid Build Coastguard Worker  * next paragraph) shall be included in all copies or substantial portions
17*61046927SAndroid Build Coastguard Worker  * of the Software.
18*61046927SAndroid Build Coastguard Worker  *
19*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21*61046927SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22*61046927SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
23*61046927SAndroid Build Coastguard Worker  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24*61046927SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25*61046927SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26*61046927SAndroid Build Coastguard Worker  *
27*61046927SAndroid Build Coastguard Worker  **************************************************************************/
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker #include "pipe/p_screen.h"
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker #include "util/u_memory.h"
32*61046927SAndroid Build Coastguard Worker #include "util/u_handle_table.h"
33*61046927SAndroid Build Coastguard Worker #include "util/u_surface.h"
34*61046927SAndroid Build Coastguard Worker #include "util/u_video.h"
35*61046927SAndroid Build Coastguard Worker #include "util/u_process.h"
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker #include "vl/vl_winsys.h"
38*61046927SAndroid Build Coastguard Worker #include "vl/vl_video_buffer.h"
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker #include "va_private.h"
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker static const VAImageFormat formats[] =
43*61046927SAndroid Build Coastguard Worker {
44*61046927SAndroid Build Coastguard Worker    {VA_FOURCC('N','V','1','2')},
45*61046927SAndroid Build Coastguard Worker    {VA_FOURCC('P','0','1','0')},
46*61046927SAndroid Build Coastguard Worker    {VA_FOURCC('P','0','1','6')},
47*61046927SAndroid Build Coastguard Worker    {VA_FOURCC('I','4','2','0')},
48*61046927SAndroid Build Coastguard Worker    {VA_FOURCC('Y','V','1','2')},
49*61046927SAndroid Build Coastguard Worker    {VA_FOURCC('Y','U','Y','V')},
50*61046927SAndroid Build Coastguard Worker    {VA_FOURCC('Y','U','Y','2')},
51*61046927SAndroid Build Coastguard Worker    {VA_FOURCC('U','Y','V','Y')},
52*61046927SAndroid Build Coastguard Worker    {VA_FOURCC('Y','8','0','0')},
53*61046927SAndroid Build Coastguard Worker    {VA_FOURCC('4','4','4','P')},
54*61046927SAndroid Build Coastguard Worker    {VA_FOURCC('4','2','2','V')},
55*61046927SAndroid Build Coastguard Worker    {VA_FOURCC('R','G','B','P')},
56*61046927SAndroid Build Coastguard Worker    {.fourcc = VA_FOURCC('B','G','R','A'), .byte_order = VA_LSB_FIRST, 32, 32,
57*61046927SAndroid Build Coastguard Worker     0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000},
58*61046927SAndroid Build Coastguard Worker    {.fourcc = VA_FOURCC('R','G','B','A'), .byte_order = VA_LSB_FIRST, 32, 32,
59*61046927SAndroid Build Coastguard Worker     0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000},
60*61046927SAndroid Build Coastguard Worker    {.fourcc = VA_FOURCC('A','R','G','B'), .byte_order = VA_LSB_FIRST, 32, 32,
61*61046927SAndroid Build Coastguard Worker     0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000},
62*61046927SAndroid Build Coastguard Worker    {.fourcc = VA_FOURCC('B','G','R','X'), .byte_order = VA_LSB_FIRST, 32, 24,
63*61046927SAndroid Build Coastguard Worker     0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000},
64*61046927SAndroid Build Coastguard Worker    {.fourcc = VA_FOURCC('R','G','B','X'), .byte_order = VA_LSB_FIRST, 32, 24,
65*61046927SAndroid Build Coastguard Worker     0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000},
66*61046927SAndroid Build Coastguard Worker    {.fourcc = VA_FOURCC('A','R','3','0'), .byte_order = VA_LSB_FIRST, 32, 30,
67*61046927SAndroid Build Coastguard Worker     0x3ff00000, 0x000ffc00, 0x000003ff, 0x30000000},
68*61046927SAndroid Build Coastguard Worker    {.fourcc = VA_FOURCC('A','B','3','0'), .byte_order = VA_LSB_FIRST, 32, 30,
69*61046927SAndroid Build Coastguard Worker     0x000003ff, 0x000ffc00, 0x3ff00000, 0x30000000},
70*61046927SAndroid Build Coastguard Worker    {.fourcc = VA_FOURCC('X','R','3','0'), .byte_order = VA_LSB_FIRST, 32, 30,
71*61046927SAndroid Build Coastguard Worker     0x3ff00000, 0x000ffc00, 0x000003ff, 0x00000000},
72*61046927SAndroid Build Coastguard Worker    {.fourcc = VA_FOURCC('X','B','3','0'), .byte_order = VA_LSB_FIRST, 32, 30,
73*61046927SAndroid Build Coastguard Worker     0x000003ff, 0x000ffc00, 0x3ff00000, 0x00000000},
74*61046927SAndroid Build Coastguard Worker };
75*61046927SAndroid Build Coastguard Worker 
76*61046927SAndroid Build Coastguard Worker static void
vlVaVideoSurfaceSize(vlVaSurface * p_surf,int component,unsigned * width,unsigned * height)77*61046927SAndroid Build Coastguard Worker vlVaVideoSurfaceSize(vlVaSurface *p_surf, int component,
78*61046927SAndroid Build Coastguard Worker                      unsigned *width, unsigned *height)
79*61046927SAndroid Build Coastguard Worker {
80*61046927SAndroid Build Coastguard Worker    *width = p_surf->templat.width;
81*61046927SAndroid Build Coastguard Worker    *height = p_surf->templat.height;
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker    vl_video_buffer_adjust_size(width, height, component,
84*61046927SAndroid Build Coastguard Worker                                pipe_format_to_chroma_format(p_surf->templat.buffer_format),
85*61046927SAndroid Build Coastguard Worker                                p_surf->templat.interlaced);
86*61046927SAndroid Build Coastguard Worker }
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker VAStatus
vlVaQueryImageFormats(VADriverContextP ctx,VAImageFormat * format_list,int * num_formats)89*61046927SAndroid Build Coastguard Worker vlVaQueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, int *num_formats)
90*61046927SAndroid Build Coastguard Worker {
91*61046927SAndroid Build Coastguard Worker    struct pipe_screen *pscreen;
92*61046927SAndroid Build Coastguard Worker    enum pipe_format format;
93*61046927SAndroid Build Coastguard Worker    int i;
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker    STATIC_ASSERT(ARRAY_SIZE(formats) == VL_VA_MAX_IMAGE_FORMATS);
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker    if (!ctx)
98*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_CONTEXT;
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker    if (!(format_list && num_formats))
101*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_PARAMETER;
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker    *num_formats = 0;
104*61046927SAndroid Build Coastguard Worker    pscreen = VL_VA_PSCREEN(ctx);
105*61046927SAndroid Build Coastguard Worker    for (i = 0; i < ARRAY_SIZE(formats); ++i) {
106*61046927SAndroid Build Coastguard Worker       format = VaFourccToPipeFormat(formats[i].fourcc);
107*61046927SAndroid Build Coastguard Worker       if (pscreen->is_video_format_supported(pscreen, format,
108*61046927SAndroid Build Coastguard Worker           PIPE_VIDEO_PROFILE_UNKNOWN,
109*61046927SAndroid Build Coastguard Worker           PIPE_VIDEO_ENTRYPOINT_BITSTREAM))
110*61046927SAndroid Build Coastguard Worker          format_list[(*num_formats)++] = formats[i];
111*61046927SAndroid Build Coastguard Worker    }
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker    return VA_STATUS_SUCCESS;
114*61046927SAndroid Build Coastguard Worker }
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker VAStatus
vlVaCreateImage(VADriverContextP ctx,VAImageFormat * format,int width,int height,VAImage * image)117*61046927SAndroid Build Coastguard Worker vlVaCreateImage(VADriverContextP ctx, VAImageFormat *format, int width, int height, VAImage *image)
118*61046927SAndroid Build Coastguard Worker {
119*61046927SAndroid Build Coastguard Worker    VAStatus status;
120*61046927SAndroid Build Coastguard Worker    vlVaDriver *drv;
121*61046927SAndroid Build Coastguard Worker    VAImage *img;
122*61046927SAndroid Build Coastguard Worker    int w, h;
123*61046927SAndroid Build Coastguard Worker 
124*61046927SAndroid Build Coastguard Worker    if (!ctx)
125*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_CONTEXT;
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker    if (!(format && image && width && height))
128*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_PARAMETER;
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker    drv = VL_VA_DRIVER(ctx);
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker    img = CALLOC(1, sizeof(VAImage));
133*61046927SAndroid Build Coastguard Worker    if (!img)
134*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_ALLOCATION_FAILED;
135*61046927SAndroid Build Coastguard Worker    mtx_lock(&drv->mutex);
136*61046927SAndroid Build Coastguard Worker    img->image_id = handle_table_add(drv->htab, img);
137*61046927SAndroid Build Coastguard Worker    mtx_unlock(&drv->mutex);
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker    img->format = *format;
140*61046927SAndroid Build Coastguard Worker    img->width = width;
141*61046927SAndroid Build Coastguard Worker    img->height = height;
142*61046927SAndroid Build Coastguard Worker    w = align(width, 2);
143*61046927SAndroid Build Coastguard Worker    h = align(height, 2);
144*61046927SAndroid Build Coastguard Worker 
145*61046927SAndroid Build Coastguard Worker    switch (format->fourcc) {
146*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('N','V','1','2'):
147*61046927SAndroid Build Coastguard Worker       img->num_planes = 2;
148*61046927SAndroid Build Coastguard Worker       img->pitches[0] = w;
149*61046927SAndroid Build Coastguard Worker       img->offsets[0] = 0;
150*61046927SAndroid Build Coastguard Worker       img->pitches[1] = w;
151*61046927SAndroid Build Coastguard Worker       img->offsets[1] = w * h;
152*61046927SAndroid Build Coastguard Worker       img->data_size  = w * h * 3 / 2;
153*61046927SAndroid Build Coastguard Worker       break;
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('P','0','1','0'):
156*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('P','0','1','6'):
157*61046927SAndroid Build Coastguard Worker       img->num_planes = 2;
158*61046927SAndroid Build Coastguard Worker       img->pitches[0] = w * 2;
159*61046927SAndroid Build Coastguard Worker       img->offsets[0] = 0;
160*61046927SAndroid Build Coastguard Worker       img->pitches[1] = w * 2;
161*61046927SAndroid Build Coastguard Worker       img->offsets[1] = w * h * 2;
162*61046927SAndroid Build Coastguard Worker       img->data_size  = w * h * 3;
163*61046927SAndroid Build Coastguard Worker       break;
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('I','4','2','0'):
166*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('Y','V','1','2'):
167*61046927SAndroid Build Coastguard Worker       img->num_planes = 3;
168*61046927SAndroid Build Coastguard Worker       img->pitches[0] = w;
169*61046927SAndroid Build Coastguard Worker       img->offsets[0] = 0;
170*61046927SAndroid Build Coastguard Worker       img->pitches[1] = w / 2;
171*61046927SAndroid Build Coastguard Worker       img->offsets[1] = w * h;
172*61046927SAndroid Build Coastguard Worker       img->pitches[2] = w / 2;
173*61046927SAndroid Build Coastguard Worker       img->offsets[2] = w * h * 5 / 4;
174*61046927SAndroid Build Coastguard Worker       img->data_size  = w * h * 3 / 2;
175*61046927SAndroid Build Coastguard Worker       break;
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('U','Y','V','Y'):
178*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('Y','U','Y','V'):
179*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('Y','U','Y','2'):
180*61046927SAndroid Build Coastguard Worker       img->num_planes = 1;
181*61046927SAndroid Build Coastguard Worker       img->pitches[0] = w * 2;
182*61046927SAndroid Build Coastguard Worker       img->offsets[0] = 0;
183*61046927SAndroid Build Coastguard Worker       img->data_size  = w * h * 2;
184*61046927SAndroid Build Coastguard Worker       break;
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('B','G','R','A'):
187*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('R','G','B','A'):
188*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('A','R','G','B'):
189*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('B','G','R','X'):
190*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('R','G','B','X'):
191*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('A','R','3','0'):
192*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('A','B','3','0'):
193*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('X','R','3','0'):
194*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('X','B','3','0'):
195*61046927SAndroid Build Coastguard Worker       img->num_planes = 1;
196*61046927SAndroid Build Coastguard Worker       img->pitches[0] = w * 4;
197*61046927SAndroid Build Coastguard Worker       img->offsets[0] = 0;
198*61046927SAndroid Build Coastguard Worker       img->data_size  = w * h * 4;
199*61046927SAndroid Build Coastguard Worker       break;
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('Y','8','0','0'):
202*61046927SAndroid Build Coastguard Worker       img->num_planes = 1;
203*61046927SAndroid Build Coastguard Worker       img->pitches[0] = w;
204*61046927SAndroid Build Coastguard Worker       img->offsets[0] = 0;
205*61046927SAndroid Build Coastguard Worker       img->data_size  = w * h;
206*61046927SAndroid Build Coastguard Worker       break;
207*61046927SAndroid Build Coastguard Worker 
208*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('4','4','4', 'P'):
209*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('R','G','B', 'P'):
210*61046927SAndroid Build Coastguard Worker       img->num_planes = 3;
211*61046927SAndroid Build Coastguard Worker       img->offsets[0] = 0;
212*61046927SAndroid Build Coastguard Worker       img->offsets[1] = w * h;
213*61046927SAndroid Build Coastguard Worker       img->offsets[2] = w * h * 2;
214*61046927SAndroid Build Coastguard Worker       img->pitches[0] = w;
215*61046927SAndroid Build Coastguard Worker       img->pitches[1] = w;
216*61046927SAndroid Build Coastguard Worker       img->pitches[2] = w;
217*61046927SAndroid Build Coastguard Worker       img->data_size  = w * h * 3;
218*61046927SAndroid Build Coastguard Worker       break;
219*61046927SAndroid Build Coastguard Worker 
220*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('4','2','2', 'V'):
221*61046927SAndroid Build Coastguard Worker       img->num_planes = 3;
222*61046927SAndroid Build Coastguard Worker       img->offsets[0] = 0;
223*61046927SAndroid Build Coastguard Worker       img->offsets[1] = w * h;
224*61046927SAndroid Build Coastguard Worker       img->offsets[2] = w * h * 3 / 2;
225*61046927SAndroid Build Coastguard Worker       img->pitches[0] = w;
226*61046927SAndroid Build Coastguard Worker       img->pitches[1] = w;
227*61046927SAndroid Build Coastguard Worker       img->pitches[2] = w;
228*61046927SAndroid Build Coastguard Worker       img->data_size  = w * h * 2;
229*61046927SAndroid Build Coastguard Worker       break;
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker    default:
232*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
233*61046927SAndroid Build Coastguard Worker    }
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker    status =  vlVaCreateBuffer(ctx, 0, VAImageBufferType,
236*61046927SAndroid Build Coastguard Worker                            align(img->data_size, 16),
237*61046927SAndroid Build Coastguard Worker                            1, NULL, &img->buf);
238*61046927SAndroid Build Coastguard Worker    if (status != VA_STATUS_SUCCESS)
239*61046927SAndroid Build Coastguard Worker       return status;
240*61046927SAndroid Build Coastguard Worker    *image = *img;
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker    return status;
243*61046927SAndroid Build Coastguard Worker }
244*61046927SAndroid Build Coastguard Worker 
245*61046927SAndroid Build Coastguard Worker VAStatus
vlVaDeriveImage(VADriverContextP ctx,VASurfaceID surface,VAImage * image)246*61046927SAndroid Build Coastguard Worker vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
247*61046927SAndroid Build Coastguard Worker {
248*61046927SAndroid Build Coastguard Worker    vlVaDriver *drv;
249*61046927SAndroid Build Coastguard Worker    vlVaSurface *surf;
250*61046927SAndroid Build Coastguard Worker    vlVaBuffer *img_buf;
251*61046927SAndroid Build Coastguard Worker    VAImage *img = NULL;
252*61046927SAndroid Build Coastguard Worker    VAStatus status;
253*61046927SAndroid Build Coastguard Worker    struct pipe_screen *screen;
254*61046927SAndroid Build Coastguard Worker    struct pipe_resource *buf_resources[VL_NUM_COMPONENTS];
255*61046927SAndroid Build Coastguard Worker    struct pipe_video_buffer *new_buffer = NULL;
256*61046927SAndroid Build Coastguard Worker    int w;
257*61046927SAndroid Build Coastguard Worker    int h;
258*61046927SAndroid Build Coastguard Worker    int i;
259*61046927SAndroid Build Coastguard Worker    unsigned stride = 0;
260*61046927SAndroid Build Coastguard Worker    unsigned offset = 0;
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker    /* This function is used by some programs to test for hardware decoding, but on
263*61046927SAndroid Build Coastguard Worker     * AMD devices, the buffers default to interlaced, which causes this function to fail.
264*61046927SAndroid Build Coastguard Worker     * Some programs expect this function to fail, while others, assume this means
265*61046927SAndroid Build Coastguard Worker     * hardware acceleration is not available and give up without trying the fall-back
266*61046927SAndroid Build Coastguard Worker     * vaCreateImage + vaPutImage
267*61046927SAndroid Build Coastguard Worker     */
268*61046927SAndroid Build Coastguard Worker    const char *proc = util_get_process_name();
269*61046927SAndroid Build Coastguard Worker    const char *derive_interlaced_allowlist[] = {
270*61046927SAndroid Build Coastguard Worker          "vlc",
271*61046927SAndroid Build Coastguard Worker          "h264encode",
272*61046927SAndroid Build Coastguard Worker          "hevcencode"
273*61046927SAndroid Build Coastguard Worker    };
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker    if (!ctx)
276*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_CONTEXT;
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker    drv = VL_VA_DRIVER(ctx);
279*61046927SAndroid Build Coastguard Worker 
280*61046927SAndroid Build Coastguard Worker    if (!drv)
281*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_CONTEXT;
282*61046927SAndroid Build Coastguard Worker 
283*61046927SAndroid Build Coastguard Worker    screen = VL_VA_PSCREEN(ctx);
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker    if (!screen)
286*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_CONTEXT;
287*61046927SAndroid Build Coastguard Worker 
288*61046927SAndroid Build Coastguard Worker    mtx_lock(&drv->mutex);
289*61046927SAndroid Build Coastguard Worker    surf = handle_table_get(drv->htab, surface);
290*61046927SAndroid Build Coastguard Worker    vlVaGetSurfaceBuffer(drv, surf);
291*61046927SAndroid Build Coastguard Worker    if (!surf || !surf->buffer) {
292*61046927SAndroid Build Coastguard Worker       status = VA_STATUS_ERROR_INVALID_SURFACE;
293*61046927SAndroid Build Coastguard Worker       goto exit_on_error;
294*61046927SAndroid Build Coastguard Worker    }
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker    if (surf->buffer->interlaced) {
297*61046927SAndroid Build Coastguard Worker       for (i = 0; i < ARRAY_SIZE(derive_interlaced_allowlist); i++)
298*61046927SAndroid Build Coastguard Worker          if ((strcmp(derive_interlaced_allowlist[i], proc) == 0))
299*61046927SAndroid Build Coastguard Worker             break;
300*61046927SAndroid Build Coastguard Worker 
301*61046927SAndroid Build Coastguard Worker       if (i >= ARRAY_SIZE(derive_interlaced_allowlist) ||
302*61046927SAndroid Build Coastguard Worker           !screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
303*61046927SAndroid Build Coastguard Worker                                    PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
304*61046927SAndroid Build Coastguard Worker                                    PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE)) {
305*61046927SAndroid Build Coastguard Worker          status = VA_STATUS_ERROR_OPERATION_FAILED;
306*61046927SAndroid Build Coastguard Worker          goto exit_on_error;
307*61046927SAndroid Build Coastguard Worker       }
308*61046927SAndroid Build Coastguard Worker    } else if (util_format_get_num_planes(surf->buffer->buffer_format) >= 2 &&
309*61046927SAndroid Build Coastguard Worker               (!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
310*61046927SAndroid Build Coastguard Worker                                        PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
311*61046927SAndroid Build Coastguard Worker                                        PIPE_VIDEO_CAP_SUPPORTS_CONTIGUOUS_PLANES_MAP) ||
312*61046927SAndroid Build Coastguard Worker                !surf->buffer->contiguous_planes)) {
313*61046927SAndroid Build Coastguard Worker       status = VA_STATUS_ERROR_OPERATION_FAILED;
314*61046927SAndroid Build Coastguard Worker       goto exit_on_error;
315*61046927SAndroid Build Coastguard Worker    }
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker    memset(buf_resources, 0, sizeof(buf_resources));
318*61046927SAndroid Build Coastguard Worker    surf->buffer->get_resources(surf->buffer, buf_resources);
319*61046927SAndroid Build Coastguard Worker 
320*61046927SAndroid Build Coastguard Worker    if (!buf_resources[0]) {
321*61046927SAndroid Build Coastguard Worker       status = VA_STATUS_ERROR_ALLOCATION_FAILED;
322*61046927SAndroid Build Coastguard Worker       goto exit_on_error;
323*61046927SAndroid Build Coastguard Worker    }
324*61046927SAndroid Build Coastguard Worker 
325*61046927SAndroid Build Coastguard Worker    img = CALLOC(1, sizeof(VAImage));
326*61046927SAndroid Build Coastguard Worker    if (!img) {
327*61046927SAndroid Build Coastguard Worker       status = VA_STATUS_ERROR_ALLOCATION_FAILED;
328*61046927SAndroid Build Coastguard Worker       goto exit_on_error;
329*61046927SAndroid Build Coastguard Worker    }
330*61046927SAndroid Build Coastguard Worker 
331*61046927SAndroid Build Coastguard Worker    img->format.fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format);
332*61046927SAndroid Build Coastguard Worker    img->buf = VA_INVALID_ID;
333*61046927SAndroid Build Coastguard Worker    /* Use the visible dimensions. */
334*61046927SAndroid Build Coastguard Worker    img->width = surf->templat.width;
335*61046927SAndroid Build Coastguard Worker    img->height = surf->templat.height;
336*61046927SAndroid Build Coastguard Worker    img->num_palette_entries = 0;
337*61046927SAndroid Build Coastguard Worker    img->entry_bytes = 0;
338*61046927SAndroid Build Coastguard Worker    /* Image data size is computed using internal dimensions. */
339*61046927SAndroid Build Coastguard Worker    w = align(surf->buffer->width, 2);
340*61046927SAndroid Build Coastguard Worker    h = align(surf->buffer->height, 2);
341*61046927SAndroid Build Coastguard Worker 
342*61046927SAndroid Build Coastguard Worker    for (i = 0; i < ARRAY_SIZE(formats); ++i) {
343*61046927SAndroid Build Coastguard Worker       if (img->format.fourcc == formats[i].fourcc) {
344*61046927SAndroid Build Coastguard Worker          img->format = formats[i];
345*61046927SAndroid Build Coastguard Worker          break;
346*61046927SAndroid Build Coastguard Worker       }
347*61046927SAndroid Build Coastguard Worker    }
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker    if (screen->resource_get_info) {
350*61046927SAndroid Build Coastguard Worker       screen->resource_get_info(screen, buf_resources[0], &stride,
351*61046927SAndroid Build Coastguard Worker                                 &offset);
352*61046927SAndroid Build Coastguard Worker       if (!stride)
353*61046927SAndroid Build Coastguard Worker          offset = 0;
354*61046927SAndroid Build Coastguard Worker    }
355*61046927SAndroid Build Coastguard Worker 
356*61046927SAndroid Build Coastguard Worker    img->num_planes = 1;
357*61046927SAndroid Build Coastguard Worker    img->offsets[0] = offset;
358*61046927SAndroid Build Coastguard Worker 
359*61046927SAndroid Build Coastguard Worker    switch (img->format.fourcc) {
360*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('U','Y','V','Y'):
361*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('Y','U','Y','V'):
362*61046927SAndroid Build Coastguard Worker       img->pitches[0] = stride > 0 ? stride : w * 2;
363*61046927SAndroid Build Coastguard Worker       assert(img->pitches[0] >= (w * 2));
364*61046927SAndroid Build Coastguard Worker       img->data_size  = img->pitches[0] * h;
365*61046927SAndroid Build Coastguard Worker       break;
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('B','G','R','A'):
368*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('R','G','B','A'):
369*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('B','G','R','X'):
370*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('R','G','B','X'):
371*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('A','R','3','0'):
372*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('A','B','3','0'):
373*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('X','R','3','0'):
374*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('X','B','3','0'):
375*61046927SAndroid Build Coastguard Worker       img->pitches[0] = stride > 0 ? stride : w * 4;
376*61046927SAndroid Build Coastguard Worker       assert(img->pitches[0] >= (w * 4));
377*61046927SAndroid Build Coastguard Worker       img->data_size  = img->pitches[0] * h;
378*61046927SAndroid Build Coastguard Worker       break;
379*61046927SAndroid Build Coastguard Worker 
380*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('N','V','1','2'):
381*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('P','0','1','0'):
382*61046927SAndroid Build Coastguard Worker    case VA_FOURCC('P','0','1','6'):
383*61046927SAndroid Build Coastguard Worker    {
384*61046927SAndroid Build Coastguard Worker       /* In some gallium platforms, the stride and offset are different*/
385*61046927SAndroid Build Coastguard Worker       /* for the Y and UV planes, query them independently.*/
386*61046927SAndroid Build Coastguard Worker       if (screen->resource_get_info) {
387*61046927SAndroid Build Coastguard Worker          /* resource_get_info is called above for buf_resources[0] and */
388*61046927SAndroid Build Coastguard Worker          /* saved results in stride, offset, reuse those values to avoid a new call to: */
389*61046927SAndroid Build Coastguard Worker          /* screen->resource_get_info(screen, buf_resources[0], &img->pitches[0],*/
390*61046927SAndroid Build Coastguard Worker          /*                         &img->offsets[0]);*/
391*61046927SAndroid Build Coastguard Worker          img->pitches[0] = stride;
392*61046927SAndroid Build Coastguard Worker          img->offsets[0] = offset;
393*61046927SAndroid Build Coastguard Worker 
394*61046927SAndroid Build Coastguard Worker          screen->resource_get_info(screen, buf_resources[1], &img->pitches[1],
395*61046927SAndroid Build Coastguard Worker                                  &img->offsets[1]);
396*61046927SAndroid Build Coastguard Worker          if (!img->pitches[1])
397*61046927SAndroid Build Coastguard Worker                img->offsets[1] = 0;
398*61046927SAndroid Build Coastguard Worker       }
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker       if (surf->buffer->interlaced) {
401*61046927SAndroid Build Coastguard Worker          struct u_rect src_rect, dst_rect;
402*61046927SAndroid Build Coastguard Worker          struct pipe_video_buffer new_template;
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker          new_template = surf->templat;
405*61046927SAndroid Build Coastguard Worker          new_template.interlaced = false;
406*61046927SAndroid Build Coastguard Worker          new_buffer = drv->pipe->create_video_buffer(drv->pipe, &new_template);
407*61046927SAndroid Build Coastguard Worker 
408*61046927SAndroid Build Coastguard Worker          /* not all devices support non-interlaced buffers */
409*61046927SAndroid Build Coastguard Worker          if (!new_buffer) {
410*61046927SAndroid Build Coastguard Worker             status = VA_STATUS_ERROR_OPERATION_FAILED;
411*61046927SAndroid Build Coastguard Worker             goto exit_on_error;
412*61046927SAndroid Build Coastguard Worker          }
413*61046927SAndroid Build Coastguard Worker 
414*61046927SAndroid Build Coastguard Worker          /* convert the interlaced to the progressive */
415*61046927SAndroid Build Coastguard Worker          src_rect.x0 = dst_rect.x0 = 0;
416*61046927SAndroid Build Coastguard Worker          src_rect.x1 = dst_rect.x1 = surf->templat.width;
417*61046927SAndroid Build Coastguard Worker          src_rect.y0 = dst_rect.y0 = 0;
418*61046927SAndroid Build Coastguard Worker          src_rect.y1 = dst_rect.y1 = surf->templat.height;
419*61046927SAndroid Build Coastguard Worker 
420*61046927SAndroid Build Coastguard Worker          vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
421*61046927SAndroid Build Coastguard Worker                            surf->buffer, new_buffer,
422*61046927SAndroid Build Coastguard Worker                            &src_rect, &dst_rect,
423*61046927SAndroid Build Coastguard Worker                            VL_COMPOSITOR_WEAVE);
424*61046927SAndroid Build Coastguard Worker 
425*61046927SAndroid Build Coastguard Worker          /* recalculate the values now that we have a new surface */
426*61046927SAndroid Build Coastguard Worker          memset(buf_resources, 0, sizeof(buf_resources));
427*61046927SAndroid Build Coastguard Worker          new_buffer->get_resources(new_buffer, buf_resources);
428*61046927SAndroid Build Coastguard Worker          if (screen->resource_get_info) {
429*61046927SAndroid Build Coastguard Worker             screen->resource_get_info(screen, buf_resources[0], &img->pitches[0],
430*61046927SAndroid Build Coastguard Worker                                     &img->offsets[0]);
431*61046927SAndroid Build Coastguard Worker             if (!img->pitches[0])
432*61046927SAndroid Build Coastguard Worker                img->offsets[0] = 0;
433*61046927SAndroid Build Coastguard Worker 
434*61046927SAndroid Build Coastguard Worker             screen->resource_get_info(screen, buf_resources[1], &img->pitches[1],
435*61046927SAndroid Build Coastguard Worker                                     &img->offsets[1]);
436*61046927SAndroid Build Coastguard Worker             if (!img->pitches[1])
437*61046927SAndroid Build Coastguard Worker                img->offsets[1] = 0;
438*61046927SAndroid Build Coastguard Worker          }
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker          w = align(new_buffer->width, 2);
441*61046927SAndroid Build Coastguard Worker          h = align(new_buffer->height, 2);
442*61046927SAndroid Build Coastguard Worker       }
443*61046927SAndroid Build Coastguard Worker 
444*61046927SAndroid Build Coastguard Worker       img->num_planes = 2;
445*61046927SAndroid Build Coastguard Worker       if(screen->resource_get_info) {
446*61046927SAndroid Build Coastguard Worker          /* Note this block might use h and w from the recalculated size if it entered
447*61046927SAndroid Build Coastguard Worker             the interlaced branch above.*/
448*61046927SAndroid Build Coastguard Worker          img->data_size  = (img->pitches[0] * h) + (img->pitches[1] * h / 2);
449*61046927SAndroid Build Coastguard Worker       } else {
450*61046927SAndroid Build Coastguard Worker          /* Use stride = w as default if screen->resource_get_info was not available */
451*61046927SAndroid Build Coastguard Worker          img->pitches[0] = w;
452*61046927SAndroid Build Coastguard Worker          img->pitches[1] = w;
453*61046927SAndroid Build Coastguard Worker          img->offsets[1] = w * h;
454*61046927SAndroid Build Coastguard Worker          img->data_size  = w * h * 3 / 2;
455*61046927SAndroid Build Coastguard Worker       }
456*61046927SAndroid Build Coastguard Worker    } break;
457*61046927SAndroid Build Coastguard Worker    default:
458*61046927SAndroid Build Coastguard Worker       /* VaDeriveImage only supports contiguous planes. But there is now a
459*61046927SAndroid Build Coastguard Worker          more generic api vlVaExportSurfaceHandle. */
460*61046927SAndroid Build Coastguard Worker       status = VA_STATUS_ERROR_OPERATION_FAILED;
461*61046927SAndroid Build Coastguard Worker       goto exit_on_error;
462*61046927SAndroid Build Coastguard Worker    }
463*61046927SAndroid Build Coastguard Worker 
464*61046927SAndroid Build Coastguard Worker    img_buf = CALLOC(1, sizeof(vlVaBuffer));
465*61046927SAndroid Build Coastguard Worker    if (!img_buf) {
466*61046927SAndroid Build Coastguard Worker       status = VA_STATUS_ERROR_ALLOCATION_FAILED;
467*61046927SAndroid Build Coastguard Worker       goto exit_on_error;
468*61046927SAndroid Build Coastguard Worker    }
469*61046927SAndroid Build Coastguard Worker 
470*61046927SAndroid Build Coastguard Worker    img->image_id = handle_table_add(drv->htab, img);
471*61046927SAndroid Build Coastguard Worker 
472*61046927SAndroid Build Coastguard Worker    img_buf->type = VAImageBufferType;
473*61046927SAndroid Build Coastguard Worker    img_buf->size = img->data_size;
474*61046927SAndroid Build Coastguard Worker    img_buf->num_elements = 1;
475*61046927SAndroid Build Coastguard Worker 
476*61046927SAndroid Build Coastguard Worker    pipe_resource_reference(&img_buf->derived_surface.resource, buf_resources[0]);
477*61046927SAndroid Build Coastguard Worker    img_buf->derived_image_buffer = new_buffer;
478*61046927SAndroid Build Coastguard Worker 
479*61046927SAndroid Build Coastguard Worker    if (surf->ctx)
480*61046927SAndroid Build Coastguard Worker       img_buf->derived_surface.entrypoint = surf->ctx->templat.entrypoint;
481*61046927SAndroid Build Coastguard Worker 
482*61046927SAndroid Build Coastguard Worker    img->buf = handle_table_add(VL_VA_DRIVER(ctx)->htab, img_buf);
483*61046927SAndroid Build Coastguard Worker    mtx_unlock(&drv->mutex);
484*61046927SAndroid Build Coastguard Worker 
485*61046927SAndroid Build Coastguard Worker    *image = *img;
486*61046927SAndroid Build Coastguard Worker 
487*61046927SAndroid Build Coastguard Worker    return VA_STATUS_SUCCESS;
488*61046927SAndroid Build Coastguard Worker 
489*61046927SAndroid Build Coastguard Worker exit_on_error:
490*61046927SAndroid Build Coastguard Worker    FREE(img);
491*61046927SAndroid Build Coastguard Worker    mtx_unlock(&drv->mutex);
492*61046927SAndroid Build Coastguard Worker    return status;
493*61046927SAndroid Build Coastguard Worker }
494*61046927SAndroid Build Coastguard Worker 
495*61046927SAndroid Build Coastguard Worker VAStatus
vlVaDestroyImage(VADriverContextP ctx,VAImageID image)496*61046927SAndroid Build Coastguard Worker vlVaDestroyImage(VADriverContextP ctx, VAImageID image)
497*61046927SAndroid Build Coastguard Worker {
498*61046927SAndroid Build Coastguard Worker    vlVaDriver *drv;
499*61046927SAndroid Build Coastguard Worker    VAImage  *vaimage;
500*61046927SAndroid Build Coastguard Worker    VAStatus status;
501*61046927SAndroid Build Coastguard Worker 
502*61046927SAndroid Build Coastguard Worker    if (!ctx)
503*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_CONTEXT;
504*61046927SAndroid Build Coastguard Worker 
505*61046927SAndroid Build Coastguard Worker    drv = VL_VA_DRIVER(ctx);
506*61046927SAndroid Build Coastguard Worker    mtx_lock(&drv->mutex);
507*61046927SAndroid Build Coastguard Worker    vaimage = handle_table_get(drv->htab, image);
508*61046927SAndroid Build Coastguard Worker    if (!vaimage) {
509*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
510*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_IMAGE;
511*61046927SAndroid Build Coastguard Worker    }
512*61046927SAndroid Build Coastguard Worker 
513*61046927SAndroid Build Coastguard Worker    handle_table_remove(VL_VA_DRIVER(ctx)->htab, image);
514*61046927SAndroid Build Coastguard Worker    mtx_unlock(&drv->mutex);
515*61046927SAndroid Build Coastguard Worker    status = vlVaDestroyBuffer(ctx, vaimage->buf);
516*61046927SAndroid Build Coastguard Worker    FREE(vaimage);
517*61046927SAndroid Build Coastguard Worker    return status;
518*61046927SAndroid Build Coastguard Worker }
519*61046927SAndroid Build Coastguard Worker 
520*61046927SAndroid Build Coastguard Worker VAStatus
vlVaSetImagePalette(VADriverContextP ctx,VAImageID image,unsigned char * palette)521*61046927SAndroid Build Coastguard Worker vlVaSetImagePalette(VADriverContextP ctx, VAImageID image, unsigned char *palette)
522*61046927SAndroid Build Coastguard Worker {
523*61046927SAndroid Build Coastguard Worker    if (!ctx)
524*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_CONTEXT;
525*61046927SAndroid Build Coastguard Worker 
526*61046927SAndroid Build Coastguard Worker    return VA_STATUS_ERROR_UNIMPLEMENTED;
527*61046927SAndroid Build Coastguard Worker }
528*61046927SAndroid Build Coastguard Worker 
529*61046927SAndroid Build Coastguard Worker VAStatus
vlVaGetImage(VADriverContextP ctx,VASurfaceID surface,int x,int y,unsigned int width,unsigned int height,VAImageID image)530*61046927SAndroid Build Coastguard Worker vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y,
531*61046927SAndroid Build Coastguard Worker              unsigned int width, unsigned int height, VAImageID image)
532*61046927SAndroid Build Coastguard Worker {
533*61046927SAndroid Build Coastguard Worker    vlVaDriver *drv;
534*61046927SAndroid Build Coastguard Worker    vlVaSurface *surf;
535*61046927SAndroid Build Coastguard Worker    vlVaBuffer *img_buf;
536*61046927SAndroid Build Coastguard Worker    VAImage *vaimage;
537*61046927SAndroid Build Coastguard Worker    struct pipe_resource *view_resources[VL_NUM_COMPONENTS];
538*61046927SAndroid Build Coastguard Worker    enum pipe_format format;
539*61046927SAndroid Build Coastguard Worker    bool convert = false;
540*61046927SAndroid Build Coastguard Worker    uint8_t *data[3];
541*61046927SAndroid Build Coastguard Worker    unsigned pitches[3], i, j;
542*61046927SAndroid Build Coastguard Worker 
543*61046927SAndroid Build Coastguard Worker    if (!ctx)
544*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_CONTEXT;
545*61046927SAndroid Build Coastguard Worker 
546*61046927SAndroid Build Coastguard Worker    drv = VL_VA_DRIVER(ctx);
547*61046927SAndroid Build Coastguard Worker 
548*61046927SAndroid Build Coastguard Worker    mtx_lock(&drv->mutex);
549*61046927SAndroid Build Coastguard Worker    surf = handle_table_get(drv->htab, surface);
550*61046927SAndroid Build Coastguard Worker    vlVaGetSurfaceBuffer(drv, surf);
551*61046927SAndroid Build Coastguard Worker    if (!surf || !surf->buffer) {
552*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
553*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_SURFACE;
554*61046927SAndroid Build Coastguard Worker    }
555*61046927SAndroid Build Coastguard Worker 
556*61046927SAndroid Build Coastguard Worker    vaimage = handle_table_get(drv->htab, image);
557*61046927SAndroid Build Coastguard Worker    if (!vaimage) {
558*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
559*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_IMAGE;
560*61046927SAndroid Build Coastguard Worker    }
561*61046927SAndroid Build Coastguard Worker 
562*61046927SAndroid Build Coastguard Worker    if (x < 0 || y < 0) {
563*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
564*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_PARAMETER;
565*61046927SAndroid Build Coastguard Worker    }
566*61046927SAndroid Build Coastguard Worker 
567*61046927SAndroid Build Coastguard Worker    if (x + width > surf->templat.width ||
568*61046927SAndroid Build Coastguard Worker        y + height > surf->templat.height) {
569*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
570*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_PARAMETER;
571*61046927SAndroid Build Coastguard Worker    }
572*61046927SAndroid Build Coastguard Worker 
573*61046927SAndroid Build Coastguard Worker    if (width > vaimage->width ||
574*61046927SAndroid Build Coastguard Worker        height > vaimage->height) {
575*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
576*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_PARAMETER;
577*61046927SAndroid Build Coastguard Worker    }
578*61046927SAndroid Build Coastguard Worker 
579*61046927SAndroid Build Coastguard Worker    img_buf = handle_table_get(drv->htab, vaimage->buf);
580*61046927SAndroid Build Coastguard Worker    if (!img_buf) {
581*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
582*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_BUFFER;
583*61046927SAndroid Build Coastguard Worker    }
584*61046927SAndroid Build Coastguard Worker 
585*61046927SAndroid Build Coastguard Worker    format = VaFourccToPipeFormat(vaimage->format.fourcc);
586*61046927SAndroid Build Coastguard Worker    if (format == PIPE_FORMAT_NONE) {
587*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
588*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_OPERATION_FAILED;
589*61046927SAndroid Build Coastguard Worker    }
590*61046927SAndroid Build Coastguard Worker 
591*61046927SAndroid Build Coastguard Worker 
592*61046927SAndroid Build Coastguard Worker    if (format != surf->buffer->buffer_format) {
593*61046927SAndroid Build Coastguard Worker       /* support NV12 to YV12 and IYUV conversion now only */
594*61046927SAndroid Build Coastguard Worker       if ((format == PIPE_FORMAT_YV12 &&
595*61046927SAndroid Build Coastguard Worker          surf->buffer->buffer_format == PIPE_FORMAT_NV12) ||
596*61046927SAndroid Build Coastguard Worker          (format == PIPE_FORMAT_IYUV &&
597*61046927SAndroid Build Coastguard Worker          surf->buffer->buffer_format == PIPE_FORMAT_NV12))
598*61046927SAndroid Build Coastguard Worker          convert = true;
599*61046927SAndroid Build Coastguard Worker       else if (format == PIPE_FORMAT_NV12 &&
600*61046927SAndroid Build Coastguard Worker          (surf->buffer->buffer_format == PIPE_FORMAT_P010 ||
601*61046927SAndroid Build Coastguard Worker           surf->buffer->buffer_format == PIPE_FORMAT_P016)) {
602*61046927SAndroid Build Coastguard Worker          mtx_unlock(&drv->mutex);
603*61046927SAndroid Build Coastguard Worker          return VA_STATUS_ERROR_OPERATION_FAILED;
604*61046927SAndroid Build Coastguard Worker       }
605*61046927SAndroid Build Coastguard Worker       else {
606*61046927SAndroid Build Coastguard Worker          mtx_unlock(&drv->mutex);
607*61046927SAndroid Build Coastguard Worker          return VA_STATUS_ERROR_OPERATION_FAILED;
608*61046927SAndroid Build Coastguard Worker       }
609*61046927SAndroid Build Coastguard Worker    }
610*61046927SAndroid Build Coastguard Worker 
611*61046927SAndroid Build Coastguard Worker    memset(view_resources, 0, sizeof(view_resources));
612*61046927SAndroid Build Coastguard Worker    surf->buffer->get_resources(surf->buffer, view_resources);
613*61046927SAndroid Build Coastguard Worker 
614*61046927SAndroid Build Coastguard Worker    for (i = 0; i < MIN2(vaimage->num_planes, 3); i++) {
615*61046927SAndroid Build Coastguard Worker       data[i] = ((uint8_t*)img_buf->data) + vaimage->offsets[i];
616*61046927SAndroid Build Coastguard Worker       pitches[i] = vaimage->pitches[i];
617*61046927SAndroid Build Coastguard Worker    }
618*61046927SAndroid Build Coastguard Worker    if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) {
619*61046927SAndroid Build Coastguard Worker       void *tmp_d;
620*61046927SAndroid Build Coastguard Worker       unsigned tmp_p;
621*61046927SAndroid Build Coastguard Worker       tmp_d  = data[1];
622*61046927SAndroid Build Coastguard Worker       data[1] = data[2];
623*61046927SAndroid Build Coastguard Worker       data[2] = tmp_d;
624*61046927SAndroid Build Coastguard Worker       tmp_p = pitches[1];
625*61046927SAndroid Build Coastguard Worker       pitches[1] = pitches[2];
626*61046927SAndroid Build Coastguard Worker       pitches[2] = tmp_p;
627*61046927SAndroid Build Coastguard Worker    }
628*61046927SAndroid Build Coastguard Worker 
629*61046927SAndroid Build Coastguard Worker    for (i = 0; i < vaimage->num_planes; i++) {
630*61046927SAndroid Build Coastguard Worker       unsigned box_w = align(width, 2);
631*61046927SAndroid Build Coastguard Worker       unsigned box_h = align(height, 2);
632*61046927SAndroid Build Coastguard Worker       unsigned box_x = x & ~1;
633*61046927SAndroid Build Coastguard Worker       unsigned box_y = y & ~1;
634*61046927SAndroid Build Coastguard Worker       if (!view_resources[i]) continue;
635*61046927SAndroid Build Coastguard Worker       vl_video_buffer_adjust_size(&box_w, &box_h, i,
636*61046927SAndroid Build Coastguard Worker                                   pipe_format_to_chroma_format(surf->templat.buffer_format),
637*61046927SAndroid Build Coastguard Worker                                   surf->templat.interlaced);
638*61046927SAndroid Build Coastguard Worker       vl_video_buffer_adjust_size(&box_x, &box_y, i,
639*61046927SAndroid Build Coastguard Worker                                   pipe_format_to_chroma_format(surf->templat.buffer_format),
640*61046927SAndroid Build Coastguard Worker                                   surf->templat.interlaced);
641*61046927SAndroid Build Coastguard Worker       for (j = 0; j < view_resources[i]->array_size; ++j) {
642*61046927SAndroid Build Coastguard Worker          struct pipe_box box;
643*61046927SAndroid Build Coastguard Worker          u_box_3d(box_x, box_y, j, box_w, box_h, 1, &box);
644*61046927SAndroid Build Coastguard Worker          struct pipe_transfer *transfer;
645*61046927SAndroid Build Coastguard Worker          uint8_t *map;
646*61046927SAndroid Build Coastguard Worker          map = drv->pipe->texture_map(drv->pipe, view_resources[i], 0,
647*61046927SAndroid Build Coastguard Worker                   PIPE_MAP_READ, &box, &transfer);
648*61046927SAndroid Build Coastguard Worker          if (!map) {
649*61046927SAndroid Build Coastguard Worker             mtx_unlock(&drv->mutex);
650*61046927SAndroid Build Coastguard Worker             return VA_STATUS_ERROR_OPERATION_FAILED;
651*61046927SAndroid Build Coastguard Worker          }
652*61046927SAndroid Build Coastguard Worker 
653*61046927SAndroid Build Coastguard Worker          if (i == 1 && convert) {
654*61046927SAndroid Build Coastguard Worker             u_copy_nv12_to_yv12((void *const *)data, pitches, i, j,
655*61046927SAndroid Build Coastguard Worker                transfer->stride, view_resources[i]->array_size,
656*61046927SAndroid Build Coastguard Worker                map, box.width, box.height);
657*61046927SAndroid Build Coastguard Worker          } else {
658*61046927SAndroid Build Coastguard Worker             util_copy_rect((uint8_t*)(data[i] + pitches[i] * j),
659*61046927SAndroid Build Coastguard Worker                view_resources[i]->format,
660*61046927SAndroid Build Coastguard Worker                pitches[i] * view_resources[i]->array_size, 0, 0,
661*61046927SAndroid Build Coastguard Worker                box.width, box.height, map, transfer->stride, 0, 0);
662*61046927SAndroid Build Coastguard Worker          }
663*61046927SAndroid Build Coastguard Worker          pipe_texture_unmap(drv->pipe, transfer);
664*61046927SAndroid Build Coastguard Worker       }
665*61046927SAndroid Build Coastguard Worker    }
666*61046927SAndroid Build Coastguard Worker    mtx_unlock(&drv->mutex);
667*61046927SAndroid Build Coastguard Worker 
668*61046927SAndroid Build Coastguard Worker    return VA_STATUS_SUCCESS;
669*61046927SAndroid Build Coastguard Worker }
670*61046927SAndroid Build Coastguard Worker 
671*61046927SAndroid Build Coastguard Worker VAStatus
vlVaPutImage(VADriverContextP ctx,VASurfaceID surface,VAImageID image,int src_x,int src_y,unsigned int src_width,unsigned int src_height,int dest_x,int dest_y,unsigned int dest_width,unsigned int dest_height)672*61046927SAndroid Build Coastguard Worker vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image,
673*61046927SAndroid Build Coastguard Worker              int src_x, int src_y, unsigned int src_width, unsigned int src_height,
674*61046927SAndroid Build Coastguard Worker              int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height)
675*61046927SAndroid Build Coastguard Worker {
676*61046927SAndroid Build Coastguard Worker    vlVaDriver *drv;
677*61046927SAndroid Build Coastguard Worker    vlVaSurface *surf;
678*61046927SAndroid Build Coastguard Worker    vlVaBuffer *img_buf;
679*61046927SAndroid Build Coastguard Worker    VAImage *vaimage;
680*61046927SAndroid Build Coastguard Worker    struct pipe_resource *view_resources[VL_NUM_COMPONENTS];
681*61046927SAndroid Build Coastguard Worker    enum pipe_format format;
682*61046927SAndroid Build Coastguard Worker    uint8_t *data[3];
683*61046927SAndroid Build Coastguard Worker    unsigned pitches[3], i, j;
684*61046927SAndroid Build Coastguard Worker 
685*61046927SAndroid Build Coastguard Worker    if (!ctx)
686*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_CONTEXT;
687*61046927SAndroid Build Coastguard Worker 
688*61046927SAndroid Build Coastguard Worker    drv = VL_VA_DRIVER(ctx);
689*61046927SAndroid Build Coastguard Worker    mtx_lock(&drv->mutex);
690*61046927SAndroid Build Coastguard Worker 
691*61046927SAndroid Build Coastguard Worker    surf = handle_table_get(drv->htab, surface);
692*61046927SAndroid Build Coastguard Worker    vlVaGetSurfaceBuffer(drv, surf);
693*61046927SAndroid Build Coastguard Worker    if (!surf || !surf->buffer) {
694*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
695*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_SURFACE;
696*61046927SAndroid Build Coastguard Worker    }
697*61046927SAndroid Build Coastguard Worker 
698*61046927SAndroid Build Coastguard Worker    vaimage = handle_table_get(drv->htab, image);
699*61046927SAndroid Build Coastguard Worker    if (!vaimage) {
700*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
701*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_IMAGE;
702*61046927SAndroid Build Coastguard Worker    }
703*61046927SAndroid Build Coastguard Worker 
704*61046927SAndroid Build Coastguard Worker    img_buf = handle_table_get(drv->htab, vaimage->buf);
705*61046927SAndroid Build Coastguard Worker    if (!img_buf) {
706*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
707*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_INVALID_BUFFER;
708*61046927SAndroid Build Coastguard Worker    }
709*61046927SAndroid Build Coastguard Worker 
710*61046927SAndroid Build Coastguard Worker    if (img_buf->derived_surface.resource) {
711*61046927SAndroid Build Coastguard Worker       /* Attempting to transfer derived image to surface */
712*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
713*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_UNIMPLEMENTED;
714*61046927SAndroid Build Coastguard Worker    }
715*61046927SAndroid Build Coastguard Worker 
716*61046927SAndroid Build Coastguard Worker    format = VaFourccToPipeFormat(vaimage->format.fourcc);
717*61046927SAndroid Build Coastguard Worker 
718*61046927SAndroid Build Coastguard Worker    if (format == PIPE_FORMAT_NONE) {
719*61046927SAndroid Build Coastguard Worker       mtx_unlock(&drv->mutex);
720*61046927SAndroid Build Coastguard Worker       return VA_STATUS_ERROR_OPERATION_FAILED;
721*61046927SAndroid Build Coastguard Worker    }
722*61046927SAndroid Build Coastguard Worker 
723*61046927SAndroid Build Coastguard Worker    if ((format != surf->buffer->buffer_format) &&
724*61046927SAndroid Build Coastguard Worker          ((format != PIPE_FORMAT_YV12) || (surf->buffer->buffer_format != PIPE_FORMAT_NV12)) &&
725*61046927SAndroid Build Coastguard Worker          ((format != PIPE_FORMAT_IYUV) || (surf->buffer->buffer_format != PIPE_FORMAT_NV12))) {
726*61046927SAndroid Build Coastguard Worker       struct pipe_video_buffer *tmp_buf;
727*61046927SAndroid Build Coastguard Worker 
728*61046927SAndroid Build Coastguard Worker       surf->templat.buffer_format = format;
729*61046927SAndroid Build Coastguard Worker       if (format == PIPE_FORMAT_YUYV || format == PIPE_FORMAT_UYVY ||
730*61046927SAndroid Build Coastguard Worker           format == PIPE_FORMAT_B8G8R8A8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM ||
731*61046927SAndroid Build Coastguard Worker           format == PIPE_FORMAT_R8G8B8A8_UNORM || format == PIPE_FORMAT_R8G8B8X8_UNORM ||
732*61046927SAndroid Build Coastguard Worker           format == PIPE_FORMAT_B10G10R10A2_UNORM || format == PIPE_FORMAT_B10G10R10X2_UNORM ||
733*61046927SAndroid Build Coastguard Worker           format == PIPE_FORMAT_R10G10B10A2_UNORM || format == PIPE_FORMAT_R10G10B10X2_UNORM)
734*61046927SAndroid Build Coastguard Worker          surf->templat.interlaced = false;
735*61046927SAndroid Build Coastguard Worker       tmp_buf = drv->pipe->create_video_buffer(drv->pipe, &surf->templat);
736*61046927SAndroid Build Coastguard Worker 
737*61046927SAndroid Build Coastguard Worker       if (!tmp_buf) {
738*61046927SAndroid Build Coastguard Worker          mtx_unlock(&drv->mutex);
739*61046927SAndroid Build Coastguard Worker          return VA_STATUS_ERROR_ALLOCATION_FAILED;
740*61046927SAndroid Build Coastguard Worker       }
741*61046927SAndroid Build Coastguard Worker 
742*61046927SAndroid Build Coastguard Worker       surf->buffer->destroy(surf->buffer);
743*61046927SAndroid Build Coastguard Worker       surf->buffer = tmp_buf;
744*61046927SAndroid Build Coastguard Worker    }
745*61046927SAndroid Build Coastguard Worker 
746*61046927SAndroid Build Coastguard Worker    memset(view_resources, 0, sizeof(view_resources));
747*61046927SAndroid Build Coastguard Worker    surf->buffer->get_resources(surf->buffer, view_resources);
748*61046927SAndroid Build Coastguard Worker 
749*61046927SAndroid Build Coastguard Worker    for (i = 0; i < MIN2(vaimage->num_planes, 3); i++) {
750*61046927SAndroid Build Coastguard Worker       data[i] = ((uint8_t*)img_buf->data) + vaimage->offsets[i];
751*61046927SAndroid Build Coastguard Worker       pitches[i] = vaimage->pitches[i];
752*61046927SAndroid Build Coastguard Worker    }
753*61046927SAndroid Build Coastguard Worker    if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) {
754*61046927SAndroid Build Coastguard Worker       void *tmp_d;
755*61046927SAndroid Build Coastguard Worker       unsigned tmp_p;
756*61046927SAndroid Build Coastguard Worker       tmp_d  = data[1];
757*61046927SAndroid Build Coastguard Worker       data[1] = data[2];
758*61046927SAndroid Build Coastguard Worker       data[2] = tmp_d;
759*61046927SAndroid Build Coastguard Worker       tmp_p = pitches[1];
760*61046927SAndroid Build Coastguard Worker       pitches[1] = pitches[2];
761*61046927SAndroid Build Coastguard Worker       pitches[2] = tmp_p;
762*61046927SAndroid Build Coastguard Worker    }
763*61046927SAndroid Build Coastguard Worker 
764*61046927SAndroid Build Coastguard Worker    for (i = 0; i < vaimage->num_planes; ++i) {
765*61046927SAndroid Build Coastguard Worker       unsigned width, height;
766*61046927SAndroid Build Coastguard Worker       struct pipe_resource *tex;
767*61046927SAndroid Build Coastguard Worker 
768*61046927SAndroid Build Coastguard Worker       if (!view_resources[i]) continue;
769*61046927SAndroid Build Coastguard Worker       tex = view_resources[i];
770*61046927SAndroid Build Coastguard Worker 
771*61046927SAndroid Build Coastguard Worker       vlVaVideoSurfaceSize(surf, i, &width, &height);
772*61046927SAndroid Build Coastguard Worker       for (j = 0; j < tex->array_size; ++j) {
773*61046927SAndroid Build Coastguard Worker          struct pipe_box dst_box;
774*61046927SAndroid Build Coastguard Worker          u_box_3d(0, 0, j, width, height, 1, &dst_box);
775*61046927SAndroid Build Coastguard Worker 
776*61046927SAndroid Build Coastguard Worker          if (((format == PIPE_FORMAT_YV12) || (format == PIPE_FORMAT_IYUV))
777*61046927SAndroid Build Coastguard Worker              && (surf->buffer->buffer_format == PIPE_FORMAT_NV12)
778*61046927SAndroid Build Coastguard Worker              && i == 1) {
779*61046927SAndroid Build Coastguard Worker             struct pipe_transfer *transfer = NULL;
780*61046927SAndroid Build Coastguard Worker             uint8_t *map = NULL;
781*61046927SAndroid Build Coastguard Worker 
782*61046927SAndroid Build Coastguard Worker             map = drv->pipe->texture_map(drv->pipe,
783*61046927SAndroid Build Coastguard Worker                                           tex,
784*61046927SAndroid Build Coastguard Worker                                           0,
785*61046927SAndroid Build Coastguard Worker                                           PIPE_MAP_WRITE |
786*61046927SAndroid Build Coastguard Worker                                           PIPE_MAP_DISCARD_RANGE,
787*61046927SAndroid Build Coastguard Worker                                           &dst_box, &transfer);
788*61046927SAndroid Build Coastguard Worker             if (map == NULL) {
789*61046927SAndroid Build Coastguard Worker                mtx_unlock(&drv->mutex);
790*61046927SAndroid Build Coastguard Worker                return VA_STATUS_ERROR_OPERATION_FAILED;
791*61046927SAndroid Build Coastguard Worker             }
792*61046927SAndroid Build Coastguard Worker 
793*61046927SAndroid Build Coastguard Worker             u_copy_nv12_from_yv12((const void * const*) data, pitches, i, j,
794*61046927SAndroid Build Coastguard Worker                                   transfer->stride, tex->array_size,
795*61046927SAndroid Build Coastguard Worker                                   map, dst_box.width, dst_box.height);
796*61046927SAndroid Build Coastguard Worker             pipe_texture_unmap(drv->pipe, transfer);
797*61046927SAndroid Build Coastguard Worker          } else {
798*61046927SAndroid Build Coastguard Worker             drv->pipe->texture_subdata(drv->pipe, tex, 0,
799*61046927SAndroid Build Coastguard Worker                                        PIPE_MAP_WRITE, &dst_box,
800*61046927SAndroid Build Coastguard Worker                                        data[i] + pitches[i] * j,
801*61046927SAndroid Build Coastguard Worker                                        pitches[i] * view_resources[i]->array_size, 0);
802*61046927SAndroid Build Coastguard Worker          }
803*61046927SAndroid Build Coastguard Worker       }
804*61046927SAndroid Build Coastguard Worker    }
805*61046927SAndroid Build Coastguard Worker    drv->pipe->flush(drv->pipe, NULL, 0);
806*61046927SAndroid Build Coastguard Worker    mtx_unlock(&drv->mutex);
807*61046927SAndroid Build Coastguard Worker 
808*61046927SAndroid Build Coastguard Worker    return VA_STATUS_SUCCESS;
809*61046927SAndroid Build Coastguard Worker }
810