xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/vdpau/surface.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /**************************************************************************
2*61046927SAndroid Build Coastguard Worker  *
3*61046927SAndroid Build Coastguard Worker  * Copyright 2010 Thomas Balling Sørensen.
4*61046927SAndroid Build Coastguard Worker  * Copyright 2011 Christian König.
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 VMWARE AND/OR ITS SUPPLIERS 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 <assert.h>
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker #include "pipe/p_state.h"
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #include "util/u_memory.h"
34*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
35*61046927SAndroid Build Coastguard Worker #include "util/u_rect.h"
36*61046927SAndroid Build Coastguard Worker #include "util/u_surface.h"
37*61046927SAndroid Build Coastguard Worker #include "util/u_video.h"
38*61046927SAndroid Build Coastguard Worker #include "vl/vl_defines.h"
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker #include "frontend/drm_driver.h"
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker #include "vdpau_private.h"
43*61046927SAndroid Build Coastguard Worker 
44*61046927SAndroid Build Coastguard Worker enum getbits_conversion {
45*61046927SAndroid Build Coastguard Worker    CONVERSION_NONE,
46*61046927SAndroid Build Coastguard Worker    CONVERSION_NV12_TO_YV12,
47*61046927SAndroid Build Coastguard Worker    CONVERSION_YV12_TO_NV12,
48*61046927SAndroid Build Coastguard Worker    CONVERSION_SWAP_YUYV_UYVY,
49*61046927SAndroid Build Coastguard Worker };
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker /**
52*61046927SAndroid Build Coastguard Worker  * Create a VdpVideoSurface.
53*61046927SAndroid Build Coastguard Worker  */
54*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoSurfaceCreate(VdpDevice device,VdpChromaType chroma_type,uint32_t width,uint32_t height,VdpVideoSurface * surface)55*61046927SAndroid Build Coastguard Worker vlVdpVideoSurfaceCreate(VdpDevice device, VdpChromaType chroma_type,
56*61046927SAndroid Build Coastguard Worker                         uint32_t width, uint32_t height,
57*61046927SAndroid Build Coastguard Worker                         VdpVideoSurface *surface)
58*61046927SAndroid Build Coastguard Worker {
59*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe;
60*61046927SAndroid Build Coastguard Worker    vlVdpSurface *p_surf;
61*61046927SAndroid Build Coastguard Worker    VdpStatus ret;
62*61046927SAndroid Build Coastguard Worker 
63*61046927SAndroid Build Coastguard Worker    if (!(width && height)) {
64*61046927SAndroid Build Coastguard Worker       ret = VDP_STATUS_INVALID_SIZE;
65*61046927SAndroid Build Coastguard Worker       goto inv_size;
66*61046927SAndroid Build Coastguard Worker    }
67*61046927SAndroid Build Coastguard Worker 
68*61046927SAndroid Build Coastguard Worker    p_surf = CALLOC(1, sizeof(vlVdpSurface));
69*61046927SAndroid Build Coastguard Worker    if (!p_surf) {
70*61046927SAndroid Build Coastguard Worker       ret = VDP_STATUS_RESOURCES;
71*61046927SAndroid Build Coastguard Worker       goto no_res;
72*61046927SAndroid Build Coastguard Worker    }
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker    vlVdpDevice *dev = vlGetDataHTAB(device);
75*61046927SAndroid Build Coastguard Worker    if (!dev) {
76*61046927SAndroid Build Coastguard Worker       ret = VDP_STATUS_INVALID_HANDLE;
77*61046927SAndroid Build Coastguard Worker       goto inv_device;
78*61046927SAndroid Build Coastguard Worker    }
79*61046927SAndroid Build Coastguard Worker 
80*61046927SAndroid Build Coastguard Worker    DeviceReference(&p_surf->device, dev);
81*61046927SAndroid Build Coastguard Worker    pipe = dev->context;
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker    mtx_lock(&dev->mutex);
84*61046927SAndroid Build Coastguard Worker    memset(&p_surf->templat, 0, sizeof(p_surf->templat));
85*61046927SAndroid Build Coastguard Worker    p_surf->templat.buffer_format = ChromaToPipeFormat(chroma_type);
86*61046927SAndroid Build Coastguard Worker    p_surf->templat.width = width;
87*61046927SAndroid Build Coastguard Worker    p_surf->templat.height = height;
88*61046927SAndroid Build Coastguard Worker    p_surf->templat.interlaced = pipe->screen->get_video_param
89*61046927SAndroid Build Coastguard Worker    (
90*61046927SAndroid Build Coastguard Worker       pipe->screen,
91*61046927SAndroid Build Coastguard Worker       PIPE_VIDEO_PROFILE_UNKNOWN,
92*61046927SAndroid Build Coastguard Worker       PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
93*61046927SAndroid Build Coastguard Worker       PIPE_VIDEO_CAP_PREFERS_INTERLACED
94*61046927SAndroid Build Coastguard Worker    );
95*61046927SAndroid Build Coastguard Worker    if (p_surf->templat.buffer_format != PIPE_FORMAT_NONE)
96*61046927SAndroid Build Coastguard Worker       p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat);
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker    /* do not mandate early allocation of a video buffer */
99*61046927SAndroid Build Coastguard Worker    vlVdpVideoSurfaceClear(p_surf);
100*61046927SAndroid Build Coastguard Worker    mtx_unlock(&dev->mutex);
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker    *surface = vlAddDataHTAB(p_surf);
103*61046927SAndroid Build Coastguard Worker    if (*surface == 0) {
104*61046927SAndroid Build Coastguard Worker       ret = VDP_STATUS_ERROR;
105*61046927SAndroid Build Coastguard Worker       goto no_handle;
106*61046927SAndroid Build Coastguard Worker    }
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker no_handle:
111*61046927SAndroid Build Coastguard Worker    p_surf->video_buffer->destroy(p_surf->video_buffer);
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker inv_device:
114*61046927SAndroid Build Coastguard Worker    DeviceReference(&p_surf->device, NULL);
115*61046927SAndroid Build Coastguard Worker    FREE(p_surf);
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker no_res:
118*61046927SAndroid Build Coastguard Worker inv_size:
119*61046927SAndroid Build Coastguard Worker    return ret;
120*61046927SAndroid Build Coastguard Worker }
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker /**
123*61046927SAndroid Build Coastguard Worker  * Destroy a VdpVideoSurface.
124*61046927SAndroid Build Coastguard Worker  */
125*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoSurfaceDestroy(VdpVideoSurface surface)126*61046927SAndroid Build Coastguard Worker vlVdpVideoSurfaceDestroy(VdpVideoSurface surface)
127*61046927SAndroid Build Coastguard Worker {
128*61046927SAndroid Build Coastguard Worker    vlVdpSurface *p_surf;
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker    p_surf = (vlVdpSurface *)vlGetDataHTAB((vlHandle)surface);
131*61046927SAndroid Build Coastguard Worker    if (!p_surf)
132*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker    mtx_lock(&p_surf->device->mutex);
135*61046927SAndroid Build Coastguard Worker    if (p_surf->video_buffer)
136*61046927SAndroid Build Coastguard Worker       p_surf->video_buffer->destroy(p_surf->video_buffer);
137*61046927SAndroid Build Coastguard Worker    mtx_unlock(&p_surf->device->mutex);
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker    vlRemoveDataHTAB(surface);
140*61046927SAndroid Build Coastguard Worker    DeviceReference(&p_surf->device, NULL);
141*61046927SAndroid Build Coastguard Worker    FREE(p_surf);
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
144*61046927SAndroid Build Coastguard Worker }
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker /**
147*61046927SAndroid Build Coastguard Worker  * Retrieve the parameters used to create a VdpVideoSurface.
148*61046927SAndroid Build Coastguard Worker  */
149*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoSurfaceGetParameters(VdpVideoSurface surface,VdpChromaType * chroma_type,uint32_t * width,uint32_t * height)150*61046927SAndroid Build Coastguard Worker vlVdpVideoSurfaceGetParameters(VdpVideoSurface surface,
151*61046927SAndroid Build Coastguard Worker                                VdpChromaType *chroma_type,
152*61046927SAndroid Build Coastguard Worker                                uint32_t *width, uint32_t *height)
153*61046927SAndroid Build Coastguard Worker {
154*61046927SAndroid Build Coastguard Worker    if (!(width && height && chroma_type))
155*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_POINTER;
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    vlVdpSurface *p_surf = vlGetDataHTAB(surface);
158*61046927SAndroid Build Coastguard Worker    if (!p_surf)
159*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
160*61046927SAndroid Build Coastguard Worker 
161*61046927SAndroid Build Coastguard Worker    if (p_surf->video_buffer) {
162*61046927SAndroid Build Coastguard Worker       *width = p_surf->video_buffer->width;
163*61046927SAndroid Build Coastguard Worker       *height = p_surf->video_buffer->height;
164*61046927SAndroid Build Coastguard Worker       *chroma_type = PipeToChroma(pipe_format_to_chroma_format(p_surf->video_buffer->buffer_format));
165*61046927SAndroid Build Coastguard Worker    } else {
166*61046927SAndroid Build Coastguard Worker       *width = p_surf->templat.width;
167*61046927SAndroid Build Coastguard Worker       *height = p_surf->templat.height;
168*61046927SAndroid Build Coastguard Worker       *chroma_type = PipeToChroma(pipe_format_to_chroma_format(p_surf->templat.buffer_format));
169*61046927SAndroid Build Coastguard Worker    }
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
172*61046927SAndroid Build Coastguard Worker }
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker static void
vlVdpVideoSurfaceSize(vlVdpSurface * p_surf,int component,unsigned * width,unsigned * height)175*61046927SAndroid Build Coastguard Worker vlVdpVideoSurfaceSize(vlVdpSurface *p_surf, int component,
176*61046927SAndroid Build Coastguard Worker                       unsigned *width, unsigned *height)
177*61046927SAndroid Build Coastguard Worker {
178*61046927SAndroid Build Coastguard Worker    *width = p_surf->templat.width;
179*61046927SAndroid Build Coastguard Worker    *height = p_surf->templat.height;
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker    vl_video_buffer_adjust_size(width, height, component,
182*61046927SAndroid Build Coastguard Worker                                pipe_format_to_chroma_format(p_surf->templat.buffer_format),
183*61046927SAndroid Build Coastguard Worker                                p_surf->templat.interlaced);
184*61046927SAndroid Build Coastguard Worker }
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker /**
187*61046927SAndroid Build Coastguard Worker  * Copy image data from a VdpVideoSurface to application memory in a specified
188*61046927SAndroid Build Coastguard Worker  * YCbCr format.
189*61046927SAndroid Build Coastguard Worker  */
190*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoSurfaceGetBitsYCbCr(VdpVideoSurface surface,VdpYCbCrFormat destination_ycbcr_format,void * const * destination_data,uint32_t const * destination_pitches)191*61046927SAndroid Build Coastguard Worker vlVdpVideoSurfaceGetBitsYCbCr(VdpVideoSurface surface,
192*61046927SAndroid Build Coastguard Worker                               VdpYCbCrFormat destination_ycbcr_format,
193*61046927SAndroid Build Coastguard Worker                               void *const *destination_data,
194*61046927SAndroid Build Coastguard Worker                               uint32_t const *destination_pitches)
195*61046927SAndroid Build Coastguard Worker {
196*61046927SAndroid Build Coastguard Worker    vlVdpSurface *vlsurface;
197*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe;
198*61046927SAndroid Build Coastguard Worker    enum pipe_format format, buffer_format;
199*61046927SAndroid Build Coastguard Worker    struct pipe_sampler_view **sampler_views;
200*61046927SAndroid Build Coastguard Worker    enum getbits_conversion conversion = CONVERSION_NONE;
201*61046927SAndroid Build Coastguard Worker    unsigned i, j;
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker    vlsurface = vlGetDataHTAB(surface);
204*61046927SAndroid Build Coastguard Worker    if (!vlsurface)
205*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
206*61046927SAndroid Build Coastguard Worker 
207*61046927SAndroid Build Coastguard Worker    pipe = vlsurface->device->context;
208*61046927SAndroid Build Coastguard Worker    if (!pipe)
209*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker    if (!destination_data || !destination_pitches)
212*61046927SAndroid Build Coastguard Worker        return VDP_STATUS_INVALID_POINTER;
213*61046927SAndroid Build Coastguard Worker 
214*61046927SAndroid Build Coastguard Worker    format = FormatYCBCRToPipe(destination_ycbcr_format);
215*61046927SAndroid Build Coastguard Worker    if (format == PIPE_FORMAT_NONE)
216*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_Y_CB_CR_FORMAT;
217*61046927SAndroid Build Coastguard Worker 
218*61046927SAndroid Build Coastguard Worker    if (vlsurface->video_buffer == NULL)
219*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_VALUE;
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker    buffer_format = vlsurface->video_buffer->buffer_format;
222*61046927SAndroid Build Coastguard Worker    if (format != buffer_format) {
223*61046927SAndroid Build Coastguard Worker       if (format == PIPE_FORMAT_YV12 && buffer_format == PIPE_FORMAT_NV12)
224*61046927SAndroid Build Coastguard Worker          conversion = CONVERSION_NV12_TO_YV12;
225*61046927SAndroid Build Coastguard Worker       else if (format == PIPE_FORMAT_NV12 && buffer_format == PIPE_FORMAT_YV12)
226*61046927SAndroid Build Coastguard Worker          conversion = CONVERSION_YV12_TO_NV12;
227*61046927SAndroid Build Coastguard Worker       else if ((format == PIPE_FORMAT_YUYV && buffer_format == PIPE_FORMAT_UYVY) ||
228*61046927SAndroid Build Coastguard Worker                (format == PIPE_FORMAT_UYVY && buffer_format == PIPE_FORMAT_YUYV))
229*61046927SAndroid Build Coastguard Worker          conversion = CONVERSION_SWAP_YUYV_UYVY;
230*61046927SAndroid Build Coastguard Worker       else
231*61046927SAndroid Build Coastguard Worker          return VDP_STATUS_NO_IMPLEMENTATION;
232*61046927SAndroid Build Coastguard Worker    }
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker    mtx_lock(&vlsurface->device->mutex);
235*61046927SAndroid Build Coastguard Worker    sampler_views = vlsurface->video_buffer->get_sampler_view_planes(vlsurface->video_buffer);
236*61046927SAndroid Build Coastguard Worker    if (!sampler_views) {
237*61046927SAndroid Build Coastguard Worker       mtx_unlock(&vlsurface->device->mutex);
238*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_RESOURCES;
239*61046927SAndroid Build Coastguard Worker    }
240*61046927SAndroid Build Coastguard Worker 
241*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 3; ++i) {
242*61046927SAndroid Build Coastguard Worker       unsigned width, height;
243*61046927SAndroid Build Coastguard Worker       struct pipe_sampler_view *sv = sampler_views[i];
244*61046927SAndroid Build Coastguard Worker       if (!sv) continue;
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker       vlVdpVideoSurfaceSize(vlsurface, i, &width, &height);
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker       for (j = 0; j < sv->texture->array_size; ++j) {
249*61046927SAndroid Build Coastguard Worker          struct pipe_box box;
250*61046927SAndroid Build Coastguard Worker          u_box_3d(0, 0, j, width, height, 1, &box);
251*61046927SAndroid Build Coastguard Worker          struct pipe_transfer *transfer;
252*61046927SAndroid Build Coastguard Worker          uint8_t *map;
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker          map = pipe->texture_map(pipe, sv->texture, 0,
255*61046927SAndroid Build Coastguard Worker                                        PIPE_MAP_READ, &box, &transfer);
256*61046927SAndroid Build Coastguard Worker          if (!map) {
257*61046927SAndroid Build Coastguard Worker             mtx_unlock(&vlsurface->device->mutex);
258*61046927SAndroid Build Coastguard Worker             return VDP_STATUS_RESOURCES;
259*61046927SAndroid Build Coastguard Worker          }
260*61046927SAndroid Build Coastguard Worker 
261*61046927SAndroid Build Coastguard Worker          if (conversion == CONVERSION_NV12_TO_YV12 && i == 1) {
262*61046927SAndroid Build Coastguard Worker             u_copy_nv12_to_yv12(destination_data, destination_pitches,
263*61046927SAndroid Build Coastguard Worker                                 i, j, transfer->stride, sv->texture->array_size,
264*61046927SAndroid Build Coastguard Worker                                 map, box.width, box.height);
265*61046927SAndroid Build Coastguard Worker          } else if (conversion == CONVERSION_YV12_TO_NV12 && i > 0) {
266*61046927SAndroid Build Coastguard Worker             u_copy_yv12_to_nv12(destination_data, destination_pitches,
267*61046927SAndroid Build Coastguard Worker                                 i, j, transfer->stride, sv->texture->array_size,
268*61046927SAndroid Build Coastguard Worker                                 map, box.width, box.height);
269*61046927SAndroid Build Coastguard Worker          } else if (conversion == CONVERSION_SWAP_YUYV_UYVY) {
270*61046927SAndroid Build Coastguard Worker             u_copy_swap422_packed(destination_data, destination_pitches,
271*61046927SAndroid Build Coastguard Worker                                    i, j, transfer->stride, sv->texture->array_size,
272*61046927SAndroid Build Coastguard Worker                                    map, box.width, box.height);
273*61046927SAndroid Build Coastguard Worker          } else {
274*61046927SAndroid Build Coastguard Worker             util_copy_rect(destination_data[i] + destination_pitches[i] * j, sv->texture->format,
275*61046927SAndroid Build Coastguard Worker                            destination_pitches[i] * sv->texture->array_size, 0, 0,
276*61046927SAndroid Build Coastguard Worker                            box.width, box.height, map, transfer->stride, 0, 0);
277*61046927SAndroid Build Coastguard Worker          }
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker          pipe_texture_unmap(pipe, transfer);
280*61046927SAndroid Build Coastguard Worker       }
281*61046927SAndroid Build Coastguard Worker    }
282*61046927SAndroid Build Coastguard Worker    mtx_unlock(&vlsurface->device->mutex);
283*61046927SAndroid Build Coastguard Worker 
284*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
285*61046927SAndroid Build Coastguard Worker }
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker /**
288*61046927SAndroid Build Coastguard Worker  * Copy image data from application memory in a specific YCbCr format to
289*61046927SAndroid Build Coastguard Worker  * a VdpVideoSurface.
290*61046927SAndroid Build Coastguard Worker  */
291*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoSurfacePutBitsYCbCr(VdpVideoSurface surface,VdpYCbCrFormat source_ycbcr_format,void const * const * source_data,uint32_t const * source_pitches)292*61046927SAndroid Build Coastguard Worker vlVdpVideoSurfacePutBitsYCbCr(VdpVideoSurface surface,
293*61046927SAndroid Build Coastguard Worker                               VdpYCbCrFormat source_ycbcr_format,
294*61046927SAndroid Build Coastguard Worker                               void const *const *source_data,
295*61046927SAndroid Build Coastguard Worker                               uint32_t const *source_pitches)
296*61046927SAndroid Build Coastguard Worker {
297*61046927SAndroid Build Coastguard Worker    enum pipe_format pformat = FormatYCBCRToPipe(source_ycbcr_format);
298*61046927SAndroid Build Coastguard Worker    enum getbits_conversion conversion = CONVERSION_NONE;
299*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe;
300*61046927SAndroid Build Coastguard Worker    struct pipe_sampler_view **sampler_views;
301*61046927SAndroid Build Coastguard Worker    unsigned i, j;
302*61046927SAndroid Build Coastguard Worker    unsigned usage = PIPE_MAP_WRITE;
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker    vlVdpSurface *p_surf = vlGetDataHTAB(surface);
305*61046927SAndroid Build Coastguard Worker    if (!p_surf)
306*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker    pipe = p_surf->device->context;
309*61046927SAndroid Build Coastguard Worker    if (!pipe)
310*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
311*61046927SAndroid Build Coastguard Worker 
312*61046927SAndroid Build Coastguard Worker    if (!source_data || !source_pitches)
313*61046927SAndroid Build Coastguard Worker        return VDP_STATUS_INVALID_POINTER;
314*61046927SAndroid Build Coastguard Worker 
315*61046927SAndroid Build Coastguard Worker    mtx_lock(&p_surf->device->mutex);
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker    if (p_surf->video_buffer == NULL ||
318*61046927SAndroid Build Coastguard Worker        ((pformat != p_surf->video_buffer->buffer_format))) {
319*61046927SAndroid Build Coastguard Worker       enum pipe_format nformat = pformat;
320*61046927SAndroid Build Coastguard Worker       struct pipe_screen *screen = pipe->screen;
321*61046927SAndroid Build Coastguard Worker 
322*61046927SAndroid Build Coastguard Worker       /* Determine the most suitable format for the new surface */
323*61046927SAndroid Build Coastguard Worker       if (!screen->is_video_format_supported(screen, nformat,
324*61046927SAndroid Build Coastguard Worker                                              PIPE_VIDEO_PROFILE_UNKNOWN,
325*61046927SAndroid Build Coastguard Worker                                              PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) {
326*61046927SAndroid Build Coastguard Worker          nformat = screen->get_video_param(screen,
327*61046927SAndroid Build Coastguard Worker                                            PIPE_VIDEO_PROFILE_UNKNOWN,
328*61046927SAndroid Build Coastguard Worker                                            PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
329*61046927SAndroid Build Coastguard Worker                                            PIPE_VIDEO_CAP_PREFERED_FORMAT);
330*61046927SAndroid Build Coastguard Worker          if (nformat == PIPE_FORMAT_NONE) {
331*61046927SAndroid Build Coastguard Worker             mtx_unlock(&p_surf->device->mutex);
332*61046927SAndroid Build Coastguard Worker             return VDP_STATUS_NO_IMPLEMENTATION;
333*61046927SAndroid Build Coastguard Worker          }
334*61046927SAndroid Build Coastguard Worker       }
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker       if (p_surf->video_buffer == NULL  ||
337*61046927SAndroid Build Coastguard Worker           nformat != p_surf->video_buffer->buffer_format) {
338*61046927SAndroid Build Coastguard Worker          /* destroy the old one */
339*61046927SAndroid Build Coastguard Worker          if (p_surf->video_buffer)
340*61046927SAndroid Build Coastguard Worker             p_surf->video_buffer->destroy(p_surf->video_buffer);
341*61046927SAndroid Build Coastguard Worker 
342*61046927SAndroid Build Coastguard Worker          /* adjust the template parameters */
343*61046927SAndroid Build Coastguard Worker          p_surf->templat.buffer_format = nformat;
344*61046927SAndroid Build Coastguard Worker          if (nformat == PIPE_FORMAT_YUYV || nformat == PIPE_FORMAT_UYVY)
345*61046927SAndroid Build Coastguard Worker             p_surf->templat.interlaced = false;
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker          /* and try to create the video buffer with the new format */
348*61046927SAndroid Build Coastguard Worker          p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat);
349*61046927SAndroid Build Coastguard Worker 
350*61046927SAndroid Build Coastguard Worker          /* stil no luck? ok forget it we don't support it */
351*61046927SAndroid Build Coastguard Worker          if (!p_surf->video_buffer) {
352*61046927SAndroid Build Coastguard Worker             mtx_unlock(&p_surf->device->mutex);
353*61046927SAndroid Build Coastguard Worker             return VDP_STATUS_NO_IMPLEMENTATION;
354*61046927SAndroid Build Coastguard Worker          }
355*61046927SAndroid Build Coastguard Worker          vlVdpVideoSurfaceClear(p_surf);
356*61046927SAndroid Build Coastguard Worker       }
357*61046927SAndroid Build Coastguard Worker    }
358*61046927SAndroid Build Coastguard Worker 
359*61046927SAndroid Build Coastguard Worker    if (pformat != p_surf->video_buffer->buffer_format) {
360*61046927SAndroid Build Coastguard Worker       if (pformat == PIPE_FORMAT_YV12 &&
361*61046927SAndroid Build Coastguard Worker           p_surf->video_buffer->buffer_format == PIPE_FORMAT_NV12)
362*61046927SAndroid Build Coastguard Worker          conversion = CONVERSION_YV12_TO_NV12;
363*61046927SAndroid Build Coastguard Worker       else {
364*61046927SAndroid Build Coastguard Worker          mtx_unlock(&p_surf->device->mutex);
365*61046927SAndroid Build Coastguard Worker          return VDP_STATUS_NO_IMPLEMENTATION;
366*61046927SAndroid Build Coastguard Worker       }
367*61046927SAndroid Build Coastguard Worker    }
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker    sampler_views = p_surf->video_buffer->get_sampler_view_planes(p_surf->video_buffer);
370*61046927SAndroid Build Coastguard Worker    if (!sampler_views) {
371*61046927SAndroid Build Coastguard Worker       mtx_unlock(&p_surf->device->mutex);
372*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_RESOURCES;
373*61046927SAndroid Build Coastguard Worker    }
374*61046927SAndroid Build Coastguard Worker 
375*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 3; ++i) {
376*61046927SAndroid Build Coastguard Worker       unsigned width, height;
377*61046927SAndroid Build Coastguard Worker       struct pipe_sampler_view *sv = sampler_views[i];
378*61046927SAndroid Build Coastguard Worker       struct pipe_resource *tex;
379*61046927SAndroid Build Coastguard Worker       if (!sv || !source_pitches[i]) continue;
380*61046927SAndroid Build Coastguard Worker 
381*61046927SAndroid Build Coastguard Worker       tex = sv->texture;
382*61046927SAndroid Build Coastguard Worker       vlVdpVideoSurfaceSize(p_surf, i, &width, &height);
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker       for (j = 0; j < tex->array_size; ++j) {
385*61046927SAndroid Build Coastguard Worker          struct pipe_box dst_box;
386*61046927SAndroid Build Coastguard Worker          u_box_3d(0, 0, j, width, height, 1, &dst_box);
387*61046927SAndroid Build Coastguard Worker 
388*61046927SAndroid Build Coastguard Worker          if (conversion == CONVERSION_YV12_TO_NV12 && i == 1) {
389*61046927SAndroid Build Coastguard Worker             struct pipe_transfer *transfer;
390*61046927SAndroid Build Coastguard Worker             uint8_t *map;
391*61046927SAndroid Build Coastguard Worker 
392*61046927SAndroid Build Coastguard Worker             map = pipe->texture_map(pipe, tex, 0, usage,
393*61046927SAndroid Build Coastguard Worker                                      &dst_box, &transfer);
394*61046927SAndroid Build Coastguard Worker             if (!map) {
395*61046927SAndroid Build Coastguard Worker                mtx_unlock(&p_surf->device->mutex);
396*61046927SAndroid Build Coastguard Worker                return VDP_STATUS_RESOURCES;
397*61046927SAndroid Build Coastguard Worker             }
398*61046927SAndroid Build Coastguard Worker 
399*61046927SAndroid Build Coastguard Worker             u_copy_nv12_from_yv12(source_data, source_pitches,
400*61046927SAndroid Build Coastguard Worker                                   i, j, transfer->stride, tex->array_size,
401*61046927SAndroid Build Coastguard Worker                                   map, dst_box.width, dst_box.height);
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker             pipe_texture_unmap(pipe, transfer);
404*61046927SAndroid Build Coastguard Worker          } else {
405*61046927SAndroid Build Coastguard Worker             pipe->texture_subdata(pipe, tex, 0,
406*61046927SAndroid Build Coastguard Worker                                   PIPE_MAP_WRITE, &dst_box,
407*61046927SAndroid Build Coastguard Worker                                   source_data[i] + source_pitches[i] * j,
408*61046927SAndroid Build Coastguard Worker                                   source_pitches[i] * tex->array_size,
409*61046927SAndroid Build Coastguard Worker                                   0);
410*61046927SAndroid Build Coastguard Worker          }
411*61046927SAndroid Build Coastguard Worker          /*
412*61046927SAndroid Build Coastguard Worker           * This surface has already been synced
413*61046927SAndroid Build Coastguard Worker           * by the first map.
414*61046927SAndroid Build Coastguard Worker           */
415*61046927SAndroid Build Coastguard Worker          usage |= PIPE_MAP_UNSYNCHRONIZED;
416*61046927SAndroid Build Coastguard Worker       }
417*61046927SAndroid Build Coastguard Worker    }
418*61046927SAndroid Build Coastguard Worker    mtx_unlock(&p_surf->device->mutex);
419*61046927SAndroid Build Coastguard Worker 
420*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
421*61046927SAndroid Build Coastguard Worker }
422*61046927SAndroid Build Coastguard Worker 
423*61046927SAndroid Build Coastguard Worker /**
424*61046927SAndroid Build Coastguard Worker  * Helper function to initially clear the VideoSurface after (re-)creation
425*61046927SAndroid Build Coastguard Worker  */
426*61046927SAndroid Build Coastguard Worker void
vlVdpVideoSurfaceClear(vlVdpSurface * vlsurf)427*61046927SAndroid Build Coastguard Worker vlVdpVideoSurfaceClear(vlVdpSurface *vlsurf)
428*61046927SAndroid Build Coastguard Worker {
429*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe = vlsurf->device->context;
430*61046927SAndroid Build Coastguard Worker    struct pipe_surface **surfaces;
431*61046927SAndroid Build Coastguard Worker    unsigned i;
432*61046927SAndroid Build Coastguard Worker 
433*61046927SAndroid Build Coastguard Worker    if (!vlsurf->video_buffer)
434*61046927SAndroid Build Coastguard Worker       return;
435*61046927SAndroid Build Coastguard Worker 
436*61046927SAndroid Build Coastguard Worker    surfaces = vlsurf->video_buffer->get_surfaces(vlsurf->video_buffer);
437*61046927SAndroid Build Coastguard Worker    for (i = 0; i < VL_MAX_SURFACES; ++i) {
438*61046927SAndroid Build Coastguard Worker       union pipe_color_union c = {};
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker       if (!surfaces[i])
441*61046927SAndroid Build Coastguard Worker          continue;
442*61046927SAndroid Build Coastguard Worker 
443*61046927SAndroid Build Coastguard Worker       if (i > !!vlsurf->templat.interlaced)
444*61046927SAndroid Build Coastguard Worker          c.f[0] = c.f[1] = c.f[2] = c.f[3] = 0.5f;
445*61046927SAndroid Build Coastguard Worker 
446*61046927SAndroid Build Coastguard Worker       pipe->clear_render_target(pipe, surfaces[i], &c, 0, 0,
447*61046927SAndroid Build Coastguard Worker                                 surfaces[i]->width, surfaces[i]->height, false);
448*61046927SAndroid Build Coastguard Worker    }
449*61046927SAndroid Build Coastguard Worker    pipe->flush(pipe, NULL, 0);
450*61046927SAndroid Build Coastguard Worker }
451*61046927SAndroid Build Coastguard Worker 
452*61046927SAndroid Build Coastguard Worker /**
453*61046927SAndroid Build Coastguard Worker  * Interop for the GL gallium frontend
454*61046927SAndroid Build Coastguard Worker  */
vlVdpVideoSurfaceGallium(VdpVideoSurface surface)455*61046927SAndroid Build Coastguard Worker struct pipe_video_buffer *vlVdpVideoSurfaceGallium(VdpVideoSurface surface)
456*61046927SAndroid Build Coastguard Worker {
457*61046927SAndroid Build Coastguard Worker    vlVdpSurface *p_surf = vlGetDataHTAB(surface);
458*61046927SAndroid Build Coastguard Worker    if (!p_surf)
459*61046927SAndroid Build Coastguard Worker       return NULL;
460*61046927SAndroid Build Coastguard Worker 
461*61046927SAndroid Build Coastguard Worker    mtx_lock(&p_surf->device->mutex);
462*61046927SAndroid Build Coastguard Worker    if (p_surf->video_buffer == NULL) {
463*61046927SAndroid Build Coastguard Worker       struct pipe_context *pipe = p_surf->device->context;
464*61046927SAndroid Build Coastguard Worker 
465*61046927SAndroid Build Coastguard Worker       /* try to create a video buffer if we don't already have one */
466*61046927SAndroid Build Coastguard Worker       p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat);
467*61046927SAndroid Build Coastguard Worker    }
468*61046927SAndroid Build Coastguard Worker    mtx_unlock(&p_surf->device->mutex);
469*61046927SAndroid Build Coastguard Worker 
470*61046927SAndroid Build Coastguard Worker    return p_surf->video_buffer;
471*61046927SAndroid Build Coastguard Worker }
472*61046927SAndroid Build Coastguard Worker 
vlVdpVideoSurfaceDMABuf(VdpVideoSurface surface,VdpVideoSurfacePlane plane,struct VdpSurfaceDMABufDesc * result)473*61046927SAndroid Build Coastguard Worker VdpStatus vlVdpVideoSurfaceDMABuf(VdpVideoSurface surface,
474*61046927SAndroid Build Coastguard Worker                                   VdpVideoSurfacePlane plane,
475*61046927SAndroid Build Coastguard Worker                                   struct VdpSurfaceDMABufDesc *result)
476*61046927SAndroid Build Coastguard Worker {
477*61046927SAndroid Build Coastguard Worker    vlVdpSurface *p_surf = vlGetDataHTAB(surface);
478*61046927SAndroid Build Coastguard Worker 
479*61046927SAndroid Build Coastguard Worker    struct pipe_screen *pscreen;
480*61046927SAndroid Build Coastguard Worker    struct winsys_handle whandle;
481*61046927SAndroid Build Coastguard Worker 
482*61046927SAndroid Build Coastguard Worker    struct pipe_surface *surf;
483*61046927SAndroid Build Coastguard Worker 
484*61046927SAndroid Build Coastguard Worker    if (!p_surf)
485*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
486*61046927SAndroid Build Coastguard Worker 
487*61046927SAndroid Build Coastguard Worker    if (plane > 3)
488*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_VALUE;
489*61046927SAndroid Build Coastguard Worker 
490*61046927SAndroid Build Coastguard Worker    if (!result)
491*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_POINTER;
492*61046927SAndroid Build Coastguard Worker 
493*61046927SAndroid Build Coastguard Worker    memset(result, 0, sizeof(*result));
494*61046927SAndroid Build Coastguard Worker    result->handle = -1;
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker    mtx_lock(&p_surf->device->mutex);
497*61046927SAndroid Build Coastguard Worker    if (p_surf->video_buffer == NULL) {
498*61046927SAndroid Build Coastguard Worker       struct pipe_context *pipe = p_surf->device->context;
499*61046927SAndroid Build Coastguard Worker 
500*61046927SAndroid Build Coastguard Worker       /* try to create a video buffer if we don't already have one */
501*61046927SAndroid Build Coastguard Worker       p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat);
502*61046927SAndroid Build Coastguard Worker    }
503*61046927SAndroid Build Coastguard Worker 
504*61046927SAndroid Build Coastguard Worker    /* Check if surface match interop requirements */
505*61046927SAndroid Build Coastguard Worker    if (p_surf->video_buffer == NULL || !p_surf->video_buffer->interlaced ||
506*61046927SAndroid Build Coastguard Worker        p_surf->video_buffer->buffer_format != PIPE_FORMAT_NV12) {
507*61046927SAndroid Build Coastguard Worker       mtx_unlock(&p_surf->device->mutex);
508*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_NO_IMPLEMENTATION;
509*61046927SAndroid Build Coastguard Worker    }
510*61046927SAndroid Build Coastguard Worker 
511*61046927SAndroid Build Coastguard Worker    surf = p_surf->video_buffer->get_surfaces(p_surf->video_buffer)[plane];
512*61046927SAndroid Build Coastguard Worker    if (!surf) {
513*61046927SAndroid Build Coastguard Worker       mtx_unlock(&p_surf->device->mutex);
514*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_RESOURCES;
515*61046927SAndroid Build Coastguard Worker    }
516*61046927SAndroid Build Coastguard Worker 
517*61046927SAndroid Build Coastguard Worker    memset(&whandle, 0, sizeof(struct winsys_handle));
518*61046927SAndroid Build Coastguard Worker    whandle.type = WINSYS_HANDLE_TYPE_FD;
519*61046927SAndroid Build Coastguard Worker    whandle.layer = surf->u.tex.first_layer;
520*61046927SAndroid Build Coastguard Worker 
521*61046927SAndroid Build Coastguard Worker    pscreen = surf->texture->screen;
522*61046927SAndroid Build Coastguard Worker    if (!pscreen->resource_get_handle(pscreen, p_surf->device->context,
523*61046927SAndroid Build Coastguard Worker                                      surf->texture, &whandle,
524*61046927SAndroid Build Coastguard Worker                                      PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) {
525*61046927SAndroid Build Coastguard Worker       mtx_unlock(&p_surf->device->mutex);
526*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_NO_IMPLEMENTATION;
527*61046927SAndroid Build Coastguard Worker    }
528*61046927SAndroid Build Coastguard Worker 
529*61046927SAndroid Build Coastguard Worker    mtx_unlock(&p_surf->device->mutex);
530*61046927SAndroid Build Coastguard Worker 
531*61046927SAndroid Build Coastguard Worker    result->handle = whandle.handle;
532*61046927SAndroid Build Coastguard Worker    result->width = surf->width;
533*61046927SAndroid Build Coastguard Worker    result->height = surf->height;
534*61046927SAndroid Build Coastguard Worker    result->offset = whandle.offset;
535*61046927SAndroid Build Coastguard Worker    result->stride = whandle.stride;
536*61046927SAndroid Build Coastguard Worker 
537*61046927SAndroid Build Coastguard Worker    if (surf->format == PIPE_FORMAT_R8_UNORM)
538*61046927SAndroid Build Coastguard Worker       result->format = VDP_RGBA_FORMAT_R8;
539*61046927SAndroid Build Coastguard Worker    else
540*61046927SAndroid Build Coastguard Worker       result->format = VDP_RGBA_FORMAT_R8G8;
541*61046927SAndroid Build Coastguard Worker 
542*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
543*61046927SAndroid Build Coastguard Worker }
544