xref: /aosp_15_r20/external/virglrenderer/src/vrend_video.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
1*bbecb9d1SAndroid Build Coastguard Worker /**************************************************************************
2*bbecb9d1SAndroid Build Coastguard Worker  *
3*bbecb9d1SAndroid Build Coastguard Worker  * Copyright (C) 2022 Kylin Software Co., Ltd.
4*bbecb9d1SAndroid Build Coastguard Worker  *
5*bbecb9d1SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
6*bbecb9d1SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
7*bbecb9d1SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
8*bbecb9d1SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*bbecb9d1SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
10*bbecb9d1SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
11*bbecb9d1SAndroid Build Coastguard Worker  *
12*bbecb9d1SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included
13*bbecb9d1SAndroid Build Coastguard Worker  * in all copies or substantial portions of the Software.
14*bbecb9d1SAndroid Build Coastguard Worker  *
15*bbecb9d1SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16*bbecb9d1SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*bbecb9d1SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*bbecb9d1SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19*bbecb9d1SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20*bbecb9d1SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21*bbecb9d1SAndroid Build Coastguard Worker  * OTHER DEALINGS IN THE SOFTWARE.
22*bbecb9d1SAndroid Build Coastguard Worker  *
23*bbecb9d1SAndroid Build Coastguard Worker  **************************************************************************/
24*bbecb9d1SAndroid Build Coastguard Worker 
25*bbecb9d1SAndroid Build Coastguard Worker /**
26*bbecb9d1SAndroid Build Coastguard Worker  * @file
27*bbecb9d1SAndroid Build Coastguard Worker  * The video implementation of the vrend renderer.
28*bbecb9d1SAndroid Build Coastguard Worker  *
29*bbecb9d1SAndroid Build Coastguard Worker  * It is based on the general virgl video submodule and handles data transfer
30*bbecb9d1SAndroid Build Coastguard Worker  * and synchronization between host and guest.
31*bbecb9d1SAndroid Build Coastguard Worker  *
32*bbecb9d1SAndroid Build Coastguard Worker  * The relationship between vaSurface and video buffer objects:
33*bbecb9d1SAndroid Build Coastguard Worker  *
34*bbecb9d1SAndroid Build Coastguard Worker  *           GUEST (Mesa)           |       HOST (Virglrenderer)
35*bbecb9d1SAndroid Build Coastguard Worker  *                                  |
36*bbecb9d1SAndroid Build Coastguard Worker  *         +------------+           |          +------------+
37*bbecb9d1SAndroid Build Coastguard Worker  *         | vaSurface  |           |          | vaSurface  | <------+
38*bbecb9d1SAndroid Build Coastguard Worker  *         +------------+           |          +------------+        |
39*bbecb9d1SAndroid Build Coastguard Worker  *               |                  |                                |
40*bbecb9d1SAndroid Build Coastguard Worker  *  +---------------------------+   |   +-------------------------+  |
41*bbecb9d1SAndroid Build Coastguard Worker  *  |    virgl_video_buffer     |   |   |    vrend_video_buffer   |  |
42*bbecb9d1SAndroid Build Coastguard Worker  *  | +-----------------------+ |   |   |  +-------------------+  |  |
43*bbecb9d1SAndroid Build Coastguard Worker  *  | |    vl_video_buffer    | |   |   |  | vrend_resource(s) |  |  |
44*bbecb9d1SAndroid Build Coastguard Worker  *  | | +-------------------+ | |<--+-->|  +-------------------+  |  |
45*bbecb9d1SAndroid Build Coastguard Worker  *  | | | virgl_resource(s) | | |   |   |  +--------------------+ |  |
46*bbecb9d1SAndroid Build Coastguard Worker  *  | | +-------------------+ | |   |   |  | virgl_video_buffer |-+--+
47*bbecb9d1SAndroid Build Coastguard Worker  *  | +-----------------------+ |   |   |  +--------------------+ |
48*bbecb9d1SAndroid Build Coastguard Worker  *  +---------------------------+   |   +-------------------------+
49*bbecb9d1SAndroid Build Coastguard Worker  *
50*bbecb9d1SAndroid Build Coastguard Worker  * The relationship between vaContext and video codec objects:
51*bbecb9d1SAndroid Build Coastguard Worker  *
52*bbecb9d1SAndroid Build Coastguard Worker  *           GUEST (Mesa)         |         HOST (Virglrenderer)
53*bbecb9d1SAndroid Build Coastguard Worker  *                                |
54*bbecb9d1SAndroid Build Coastguard Worker  *         +------------+         |           +------------+
55*bbecb9d1SAndroid Build Coastguard Worker  *         | vaContext  |         |           | vaContext  | <-------+
56*bbecb9d1SAndroid Build Coastguard Worker  *         +------------+         |           +------------+         |
57*bbecb9d1SAndroid Build Coastguard Worker  *               |                |                                  |
58*bbecb9d1SAndroid Build Coastguard Worker  *  +------------------------+    |    +--------------------------+  |
59*bbecb9d1SAndroid Build Coastguard Worker  *  |    virgl_video_codec   | <--+--> |    vrend_video_codec     |  |
60*bbecb9d1SAndroid Build Coastguard Worker  *  +------------------------+    |    |  +--------------------+  |  |
61*bbecb9d1SAndroid Build Coastguard Worker  *                                |    |  | virgl_video_codec  | -+--+
62*bbecb9d1SAndroid Build Coastguard Worker  *                                |    |  +--------------------+  |
63*bbecb9d1SAndroid Build Coastguard Worker  *                                |    +--------------------------+
64*bbecb9d1SAndroid Build Coastguard Worker  *
65*bbecb9d1SAndroid Build Coastguard Worker  * @author Feng Jiang <[email protected]>
66*bbecb9d1SAndroid Build Coastguard Worker  */
67*bbecb9d1SAndroid Build Coastguard Worker 
68*bbecb9d1SAndroid Build Coastguard Worker 
69*bbecb9d1SAndroid Build Coastguard Worker #include <sys/param.h>
70*bbecb9d1SAndroid Build Coastguard Worker 
71*bbecb9d1SAndroid Build Coastguard Worker #include "virgl_video.h"
72*bbecb9d1SAndroid Build Coastguard Worker #include "virgl_video_hw.h"
73*bbecb9d1SAndroid Build Coastguard Worker 
74*bbecb9d1SAndroid Build Coastguard Worker #include "vrend_debug.h"
75*bbecb9d1SAndroid Build Coastguard Worker #include "vrend_winsys.h"
76*bbecb9d1SAndroid Build Coastguard Worker #include "vrend_renderer.h"
77*bbecb9d1SAndroid Build Coastguard Worker #include "vrend_video.h"
78*bbecb9d1SAndroid Build Coastguard Worker 
79*bbecb9d1SAndroid Build Coastguard Worker struct vrend_context;
80*bbecb9d1SAndroid Build Coastguard Worker 
81*bbecb9d1SAndroid Build Coastguard Worker struct vrend_video_context {
82*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_context *ctx;
83*bbecb9d1SAndroid Build Coastguard Worker     struct list_head codecs;
84*bbecb9d1SAndroid Build Coastguard Worker     struct list_head buffers;
85*bbecb9d1SAndroid Build Coastguard Worker };
86*bbecb9d1SAndroid Build Coastguard Worker 
87*bbecb9d1SAndroid Build Coastguard Worker struct vrend_video_codec {
88*bbecb9d1SAndroid Build Coastguard Worker     struct virgl_video_codec *codec;
89*bbecb9d1SAndroid Build Coastguard Worker     uint32_t handle;
90*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_resource *feed_res;    /* encoding feedback */
91*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_resource *dest_res;    /* encoding coded buffer */
92*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_context *ctx;
93*bbecb9d1SAndroid Build Coastguard Worker     struct list_head head;
94*bbecb9d1SAndroid Build Coastguard Worker };
95*bbecb9d1SAndroid Build Coastguard Worker 
96*bbecb9d1SAndroid Build Coastguard Worker struct vrend_video_plane {
97*bbecb9d1SAndroid Build Coastguard Worker     uint32_t res_handle;
98*bbecb9d1SAndroid Build Coastguard Worker     GLuint texture;         /* texture for temporary use */
99*bbecb9d1SAndroid Build Coastguard Worker     GLuint framebuffer;     /* framebuffer for temporary use */
100*bbecb9d1SAndroid Build Coastguard Worker     EGLImageKHR egl_image;  /* egl image for temporary use */
101*bbecb9d1SAndroid Build Coastguard Worker };
102*bbecb9d1SAndroid Build Coastguard Worker 
103*bbecb9d1SAndroid Build Coastguard Worker struct vrend_video_buffer {
104*bbecb9d1SAndroid Build Coastguard Worker     struct virgl_video_buffer *buffer;
105*bbecb9d1SAndroid Build Coastguard Worker 
106*bbecb9d1SAndroid Build Coastguard Worker     uint32_t handle;
107*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_context *ctx;
108*bbecb9d1SAndroid Build Coastguard Worker     struct list_head head;
109*bbecb9d1SAndroid Build Coastguard Worker 
110*bbecb9d1SAndroid Build Coastguard Worker     uint32_t num_planes;
111*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_plane planes[3];
112*bbecb9d1SAndroid Build Coastguard Worker };
113*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_codec(struct virgl_video_codec * codec)114*bbecb9d1SAndroid Build Coastguard Worker static struct vrend_video_codec *vrend_video_codec(
115*bbecb9d1SAndroid Build Coastguard Worker         struct virgl_video_codec *codec)
116*bbecb9d1SAndroid Build Coastguard Worker {
117*bbecb9d1SAndroid Build Coastguard Worker     return virgl_video_codec_opaque_data(codec);
118*bbecb9d1SAndroid Build Coastguard Worker }
119*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_buffer(struct virgl_video_buffer * buffer)120*bbecb9d1SAndroid Build Coastguard Worker static struct vrend_video_buffer *vrend_video_buffer(
121*bbecb9d1SAndroid Build Coastguard Worker         struct virgl_video_buffer *buffer)
122*bbecb9d1SAndroid Build Coastguard Worker {
123*bbecb9d1SAndroid Build Coastguard Worker     return virgl_video_buffer_opaque_data(buffer);
124*bbecb9d1SAndroid Build Coastguard Worker }
125*bbecb9d1SAndroid Build Coastguard Worker 
get_video_codec(struct vrend_video_context * ctx,uint32_t cdc_handle)126*bbecb9d1SAndroid Build Coastguard Worker static struct vrend_video_codec *get_video_codec(
127*bbecb9d1SAndroid Build Coastguard Worker                                         struct vrend_video_context *ctx,
128*bbecb9d1SAndroid Build Coastguard Worker                                         uint32_t cdc_handle)
129*bbecb9d1SAndroid Build Coastguard Worker {
130*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_codec *cdc;
131*bbecb9d1SAndroid Build Coastguard Worker 
132*bbecb9d1SAndroid Build Coastguard Worker     LIST_FOR_EACH_ENTRY(cdc, &ctx->codecs, head) {
133*bbecb9d1SAndroid Build Coastguard Worker         if (cdc->handle == cdc_handle)
134*bbecb9d1SAndroid Build Coastguard Worker             return cdc;
135*bbecb9d1SAndroid Build Coastguard Worker     }
136*bbecb9d1SAndroid Build Coastguard Worker 
137*bbecb9d1SAndroid Build Coastguard Worker     return NULL;
138*bbecb9d1SAndroid Build Coastguard Worker }
139*bbecb9d1SAndroid Build Coastguard Worker 
get_video_buffer(struct vrend_video_context * ctx,uint32_t buf_handle)140*bbecb9d1SAndroid Build Coastguard Worker static struct vrend_video_buffer *get_video_buffer(
141*bbecb9d1SAndroid Build Coastguard Worker                                         struct vrend_video_context *ctx,
142*bbecb9d1SAndroid Build Coastguard Worker                                         uint32_t buf_handle)
143*bbecb9d1SAndroid Build Coastguard Worker {
144*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_buffer *buf;
145*bbecb9d1SAndroid Build Coastguard Worker 
146*bbecb9d1SAndroid Build Coastguard Worker     LIST_FOR_EACH_ENTRY(buf, &ctx->buffers, head) {
147*bbecb9d1SAndroid Build Coastguard Worker         if (buf->handle == buf_handle)
148*bbecb9d1SAndroid Build Coastguard Worker             return buf;
149*bbecb9d1SAndroid Build Coastguard Worker     }
150*bbecb9d1SAndroid Build Coastguard Worker 
151*bbecb9d1SAndroid Build Coastguard Worker     return NULL;
152*bbecb9d1SAndroid Build Coastguard Worker }
153*bbecb9d1SAndroid Build Coastguard Worker 
154*bbecb9d1SAndroid Build Coastguard Worker 
sync_dmabuf_to_video_buffer(struct vrend_video_buffer * buf,const struct virgl_video_dma_buf * dmabuf)155*bbecb9d1SAndroid Build Coastguard Worker static int sync_dmabuf_to_video_buffer(struct vrend_video_buffer *buf,
156*bbecb9d1SAndroid Build Coastguard Worker                                        const struct virgl_video_dma_buf *dmabuf)
157*bbecb9d1SAndroid Build Coastguard Worker {
158*bbecb9d1SAndroid Build Coastguard Worker     if (!(dmabuf->flags & VIRGL_VIDEO_DMABUF_READ_ONLY)) {
159*bbecb9d1SAndroid Build Coastguard Worker         vrend_printf("%s: dmabuf is not readable\n", __func__);
160*bbecb9d1SAndroid Build Coastguard Worker         return -1;
161*bbecb9d1SAndroid Build Coastguard Worker     }
162*bbecb9d1SAndroid Build Coastguard Worker 
163*bbecb9d1SAndroid Build Coastguard Worker     for (unsigned i = 0; i < dmabuf->num_planes && i < buf->num_planes; i++) {
164*bbecb9d1SAndroid Build Coastguard Worker         struct vrend_video_plane *plane = &buf->planes[i];
165*bbecb9d1SAndroid Build Coastguard Worker         struct vrend_resource *res;
166*bbecb9d1SAndroid Build Coastguard Worker 
167*bbecb9d1SAndroid Build Coastguard Worker         res = vrend_renderer_ctx_res_lookup(buf->ctx->ctx, plane->res_handle);
168*bbecb9d1SAndroid Build Coastguard Worker         if (!res) {
169*bbecb9d1SAndroid Build Coastguard Worker             vrend_printf("%s: res %d not found\n", __func__, plane->res_handle);
170*bbecb9d1SAndroid Build Coastguard Worker             continue;
171*bbecb9d1SAndroid Build Coastguard Worker         }
172*bbecb9d1SAndroid Build Coastguard Worker 
173*bbecb9d1SAndroid Build Coastguard Worker         /* dmabuf -> eglimage */
174*bbecb9d1SAndroid Build Coastguard Worker         if (EGL_NO_IMAGE_KHR == plane->egl_image) {
175*bbecb9d1SAndroid Build Coastguard Worker             EGLint img_attrs[16] = {
176*bbecb9d1SAndroid Build Coastguard Worker                 EGL_LINUX_DRM_FOURCC_EXT,       dmabuf->planes[i].drm_format,
177*bbecb9d1SAndroid Build Coastguard Worker                 EGL_WIDTH,                      dmabuf->width / (i + 1),
178*bbecb9d1SAndroid Build Coastguard Worker                 EGL_HEIGHT,                     dmabuf->height / (i + 1),
179*bbecb9d1SAndroid Build Coastguard Worker                 EGL_DMA_BUF_PLANE0_FD_EXT,      dmabuf->planes[i].fd,
180*bbecb9d1SAndroid Build Coastguard Worker                 EGL_DMA_BUF_PLANE0_OFFSET_EXT,  dmabuf->planes[i].offset,
181*bbecb9d1SAndroid Build Coastguard Worker                 EGL_DMA_BUF_PLANE0_PITCH_EXT,   dmabuf->planes[i].pitch,
182*bbecb9d1SAndroid Build Coastguard Worker                 EGL_NONE
183*bbecb9d1SAndroid Build Coastguard Worker             };
184*bbecb9d1SAndroid Build Coastguard Worker 
185*bbecb9d1SAndroid Build Coastguard Worker             plane->egl_image = eglCreateImageKHR(eglGetCurrentDisplay(),
186*bbecb9d1SAndroid Build Coastguard Worker                     EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, img_attrs);
187*bbecb9d1SAndroid Build Coastguard Worker         }
188*bbecb9d1SAndroid Build Coastguard Worker 
189*bbecb9d1SAndroid Build Coastguard Worker         if (EGL_NO_IMAGE_KHR == plane->egl_image) {
190*bbecb9d1SAndroid Build Coastguard Worker             vrend_printf("%s: create egl image failed\n", __func__);
191*bbecb9d1SAndroid Build Coastguard Worker             continue;
192*bbecb9d1SAndroid Build Coastguard Worker         }
193*bbecb9d1SAndroid Build Coastguard Worker 
194*bbecb9d1SAndroid Build Coastguard Worker         /* eglimage -> texture */
195*bbecb9d1SAndroid Build Coastguard Worker         glBindTexture(GL_TEXTURE_2D, plane->texture);
196*bbecb9d1SAndroid Build Coastguard Worker         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
197*bbecb9d1SAndroid Build Coastguard Worker                                     (GLeglImageOES)(plane->egl_image));
198*bbecb9d1SAndroid Build Coastguard Worker 
199*bbecb9d1SAndroid Build Coastguard Worker         /* texture -> framebuffer */
200*bbecb9d1SAndroid Build Coastguard Worker         glBindFramebuffer(GL_READ_FRAMEBUFFER, plane->framebuffer);
201*bbecb9d1SAndroid Build Coastguard Worker         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
202*bbecb9d1SAndroid Build Coastguard Worker                                GL_TEXTURE_2D, plane->texture, 0);
203*bbecb9d1SAndroid Build Coastguard Worker 
204*bbecb9d1SAndroid Build Coastguard Worker         /* framebuffer -> vrend_video_buffer.planes[i] */
205*bbecb9d1SAndroid Build Coastguard Worker         glBindTexture(GL_TEXTURE_2D, res->id);
206*bbecb9d1SAndroid Build Coastguard Worker         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0,
207*bbecb9d1SAndroid Build Coastguard Worker                             res->base.width0, res->base.height0);
208*bbecb9d1SAndroid Build Coastguard Worker     }
209*bbecb9d1SAndroid Build Coastguard Worker 
210*bbecb9d1SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, 0);
211*bbecb9d1SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, 0);
212*bbecb9d1SAndroid Build Coastguard Worker 
213*bbecb9d1SAndroid Build Coastguard Worker     return 0;
214*bbecb9d1SAndroid Build Coastguard Worker }
215*bbecb9d1SAndroid Build Coastguard Worker 
sync_video_buffer_to_dmabuf(struct vrend_video_buffer * buf,const struct virgl_video_dma_buf * dmabuf)216*bbecb9d1SAndroid Build Coastguard Worker static int sync_video_buffer_to_dmabuf(struct vrend_video_buffer *buf,
217*bbecb9d1SAndroid Build Coastguard Worker                                        const struct virgl_video_dma_buf *dmabuf)
218*bbecb9d1SAndroid Build Coastguard Worker {
219*bbecb9d1SAndroid Build Coastguard Worker     if (!(dmabuf->flags & VIRGL_VIDEO_DMABUF_WRITE_ONLY)) {
220*bbecb9d1SAndroid Build Coastguard Worker         vrend_printf("%s: dmabuf is not writable\n", __func__);
221*bbecb9d1SAndroid Build Coastguard Worker         return -1;
222*bbecb9d1SAndroid Build Coastguard Worker     }
223*bbecb9d1SAndroid Build Coastguard Worker 
224*bbecb9d1SAndroid Build Coastguard Worker     for (unsigned i = 0; i < dmabuf->num_planes && i < buf->num_planes; i++) {
225*bbecb9d1SAndroid Build Coastguard Worker         struct vrend_video_plane *plane = &buf->planes[i];
226*bbecb9d1SAndroid Build Coastguard Worker         struct vrend_resource *res;
227*bbecb9d1SAndroid Build Coastguard Worker 
228*bbecb9d1SAndroid Build Coastguard Worker         res = vrend_renderer_ctx_res_lookup(buf->ctx->ctx, plane->res_handle);
229*bbecb9d1SAndroid Build Coastguard Worker         if (!res) {
230*bbecb9d1SAndroid Build Coastguard Worker             vrend_printf("%s: res %d not found\n", __func__, plane->res_handle);
231*bbecb9d1SAndroid Build Coastguard Worker             continue;
232*bbecb9d1SAndroid Build Coastguard Worker         }
233*bbecb9d1SAndroid Build Coastguard Worker 
234*bbecb9d1SAndroid Build Coastguard Worker         /* dmabuf -> eglimage */
235*bbecb9d1SAndroid Build Coastguard Worker         if (EGL_NO_IMAGE_KHR == plane->egl_image) {
236*bbecb9d1SAndroid Build Coastguard Worker             EGLint img_attrs[16] = {
237*bbecb9d1SAndroid Build Coastguard Worker                 EGL_LINUX_DRM_FOURCC_EXT,       dmabuf->planes[i].drm_format,
238*bbecb9d1SAndroid Build Coastguard Worker                 EGL_WIDTH,                      dmabuf->width / (i + 1),
239*bbecb9d1SAndroid Build Coastguard Worker                 EGL_HEIGHT,                     dmabuf->height / (i + 1),
240*bbecb9d1SAndroid Build Coastguard Worker                 EGL_DMA_BUF_PLANE0_FD_EXT,      dmabuf->planes[i].fd,
241*bbecb9d1SAndroid Build Coastguard Worker                 EGL_DMA_BUF_PLANE0_OFFSET_EXT,  dmabuf->planes[i].offset,
242*bbecb9d1SAndroid Build Coastguard Worker                 EGL_DMA_BUF_PLANE0_PITCH_EXT,   dmabuf->planes[i].pitch,
243*bbecb9d1SAndroid Build Coastguard Worker                 EGL_NONE
244*bbecb9d1SAndroid Build Coastguard Worker             };
245*bbecb9d1SAndroid Build Coastguard Worker 
246*bbecb9d1SAndroid Build Coastguard Worker             plane->egl_image = eglCreateImageKHR(eglGetCurrentDisplay(),
247*bbecb9d1SAndroid Build Coastguard Worker                     EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, img_attrs);
248*bbecb9d1SAndroid Build Coastguard Worker         }
249*bbecb9d1SAndroid Build Coastguard Worker 
250*bbecb9d1SAndroid Build Coastguard Worker         if (EGL_NO_IMAGE_KHR == plane->egl_image) {
251*bbecb9d1SAndroid Build Coastguard Worker             vrend_printf("%s: create egl image failed\n", __func__);
252*bbecb9d1SAndroid Build Coastguard Worker             continue;
253*bbecb9d1SAndroid Build Coastguard Worker         }
254*bbecb9d1SAndroid Build Coastguard Worker 
255*bbecb9d1SAndroid Build Coastguard Worker         /* eglimage -> texture */
256*bbecb9d1SAndroid Build Coastguard Worker         glBindTexture(GL_TEXTURE_2D, plane->texture);
257*bbecb9d1SAndroid Build Coastguard Worker         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
258*bbecb9d1SAndroid Build Coastguard Worker                                     (GLeglImageOES)(plane->egl_image));
259*bbecb9d1SAndroid Build Coastguard Worker 
260*bbecb9d1SAndroid Build Coastguard Worker         /* vrend_video_buffer.planes[i] -> framebuffer */
261*bbecb9d1SAndroid Build Coastguard Worker         glBindFramebuffer(GL_READ_FRAMEBUFFER, plane->framebuffer);
262*bbecb9d1SAndroid Build Coastguard Worker         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
263*bbecb9d1SAndroid Build Coastguard Worker                                GL_TEXTURE_2D, res->id, 0);
264*bbecb9d1SAndroid Build Coastguard Worker 
265*bbecb9d1SAndroid Build Coastguard Worker         /* framebuffer -> texture */
266*bbecb9d1SAndroid Build Coastguard Worker         glBindTexture(GL_TEXTURE_2D, plane->texture);
267*bbecb9d1SAndroid Build Coastguard Worker         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0,
268*bbecb9d1SAndroid Build Coastguard Worker                             res->base.width0, res->base.height0);
269*bbecb9d1SAndroid Build Coastguard Worker 
270*bbecb9d1SAndroid Build Coastguard Worker     }
271*bbecb9d1SAndroid Build Coastguard Worker 
272*bbecb9d1SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, 0);
273*bbecb9d1SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, 0);
274*bbecb9d1SAndroid Build Coastguard Worker 
275*bbecb9d1SAndroid Build Coastguard Worker     return 0;
276*bbecb9d1SAndroid Build Coastguard Worker }
277*bbecb9d1SAndroid Build Coastguard Worker 
278*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_decode_completed(struct virgl_video_codec * codec,const struct virgl_video_dma_buf * dmabuf)279*bbecb9d1SAndroid Build Coastguard Worker static void vrend_video_decode_completed(
280*bbecb9d1SAndroid Build Coastguard Worker                                 struct virgl_video_codec *codec,
281*bbecb9d1SAndroid Build Coastguard Worker                                 const struct virgl_video_dma_buf *dmabuf)
282*bbecb9d1SAndroid Build Coastguard Worker {
283*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_buffer *buf = vrend_video_buffer(dmabuf->buf);
284*bbecb9d1SAndroid Build Coastguard Worker 
285*bbecb9d1SAndroid Build Coastguard Worker     (void)codec;
286*bbecb9d1SAndroid Build Coastguard Worker 
287*bbecb9d1SAndroid Build Coastguard Worker     sync_dmabuf_to_video_buffer(buf, dmabuf);
288*bbecb9d1SAndroid Build Coastguard Worker }
289*bbecb9d1SAndroid Build Coastguard Worker 
290*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_enocde_upload_picture(struct virgl_video_codec * codec,const struct virgl_video_dma_buf * dmabuf)291*bbecb9d1SAndroid Build Coastguard Worker static void vrend_video_enocde_upload_picture(
292*bbecb9d1SAndroid Build Coastguard Worker                                 struct virgl_video_codec *codec,
293*bbecb9d1SAndroid Build Coastguard Worker                                 const struct virgl_video_dma_buf *dmabuf)
294*bbecb9d1SAndroid Build Coastguard Worker {
295*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_buffer *buf = vrend_video_buffer(dmabuf->buf);
296*bbecb9d1SAndroid Build Coastguard Worker 
297*bbecb9d1SAndroid Build Coastguard Worker     (void)codec;
298*bbecb9d1SAndroid Build Coastguard Worker 
299*bbecb9d1SAndroid Build Coastguard Worker     sync_video_buffer_to_dmabuf(buf, dmabuf);
300*bbecb9d1SAndroid Build Coastguard Worker }
301*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_encode_completed(struct virgl_video_codec * codec,const struct virgl_video_dma_buf * src_buf,const struct virgl_video_dma_buf * ref_buf,unsigned num_coded_bufs,const void * const * coded_bufs,const unsigned * coded_sizes)302*bbecb9d1SAndroid Build Coastguard Worker static void vrend_video_encode_completed(
303*bbecb9d1SAndroid Build Coastguard Worker                                 struct virgl_video_codec *codec,
304*bbecb9d1SAndroid Build Coastguard Worker                                 const struct virgl_video_dma_buf *src_buf,
305*bbecb9d1SAndroid Build Coastguard Worker                                 const struct virgl_video_dma_buf *ref_buf,
306*bbecb9d1SAndroid Build Coastguard Worker                                 unsigned num_coded_bufs,
307*bbecb9d1SAndroid Build Coastguard Worker                                 const void * const *coded_bufs,
308*bbecb9d1SAndroid Build Coastguard Worker                                 const unsigned *coded_sizes)
309*bbecb9d1SAndroid Build Coastguard Worker {
310*bbecb9d1SAndroid Build Coastguard Worker     void *buf;
311*bbecb9d1SAndroid Build Coastguard Worker     unsigned i, size, data_size;
312*bbecb9d1SAndroid Build Coastguard Worker     struct virgl_video_encode_feedback feedback;
313*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_codec *cdc = vrend_video_codec(codec);
314*bbecb9d1SAndroid Build Coastguard Worker 
315*bbecb9d1SAndroid Build Coastguard Worker     (void)src_buf;
316*bbecb9d1SAndroid Build Coastguard Worker     (void)ref_buf;
317*bbecb9d1SAndroid Build Coastguard Worker 
318*bbecb9d1SAndroid Build Coastguard Worker     if (!cdc->dest_res || !cdc->feed_res)
319*bbecb9d1SAndroid Build Coastguard Worker         return;
320*bbecb9d1SAndroid Build Coastguard Worker 
321*bbecb9d1SAndroid Build Coastguard Worker     memset(&feedback, 0, sizeof(feedback));
322*bbecb9d1SAndroid Build Coastguard Worker 
323*bbecb9d1SAndroid Build Coastguard Worker     /* sync coded data to guest */
324*bbecb9d1SAndroid Build Coastguard Worker     if (has_bit(cdc->dest_res->storage_bits, VREND_STORAGE_GL_BUFFER)) {
325*bbecb9d1SAndroid Build Coastguard Worker         glBindBufferARB(cdc->dest_res->target, cdc->dest_res->id);
326*bbecb9d1SAndroid Build Coastguard Worker         buf = glMapBufferRange(cdc->dest_res->target, 0,
327*bbecb9d1SAndroid Build Coastguard Worker                                cdc->dest_res->base.width0, GL_MAP_WRITE_BIT);
328*bbecb9d1SAndroid Build Coastguard Worker         for (i = 0, data_size = 0; i < num_coded_bufs &&
329*bbecb9d1SAndroid Build Coastguard Worker                     data_size < cdc->dest_res->base.width0; i++) {
330*bbecb9d1SAndroid Build Coastguard Worker             size = MIN(cdc->dest_res->base.width0 - data_size, coded_sizes[i]);
331*bbecb9d1SAndroid Build Coastguard Worker             memcpy((uint8_t *)buf + data_size, coded_bufs[i], size);
332*bbecb9d1SAndroid Build Coastguard Worker             vrend_write_to_iovec(cdc->dest_res->iov, cdc->dest_res->num_iovs,
333*bbecb9d1SAndroid Build Coastguard Worker                                  data_size, coded_bufs[i], size);
334*bbecb9d1SAndroid Build Coastguard Worker             data_size += size;
335*bbecb9d1SAndroid Build Coastguard Worker         }
336*bbecb9d1SAndroid Build Coastguard Worker         glUnmapBuffer(cdc->dest_res->target);
337*bbecb9d1SAndroid Build Coastguard Worker         glBindBufferARB(cdc->dest_res->target, 0);
338*bbecb9d1SAndroid Build Coastguard Worker         feedback.stat = VIRGL_VIDEO_ENCODE_STAT_SUCCESS;
339*bbecb9d1SAndroid Build Coastguard Worker         feedback.coded_size = data_size;
340*bbecb9d1SAndroid Build Coastguard Worker     } else {
341*bbecb9d1SAndroid Build Coastguard Worker         vrend_printf("unexcepted coded res type\n");
342*bbecb9d1SAndroid Build Coastguard Worker         feedback.stat = VIRGL_VIDEO_ENCODE_STAT_FAILURE;
343*bbecb9d1SAndroid Build Coastguard Worker         feedback.coded_size = 0;
344*bbecb9d1SAndroid Build Coastguard Worker     }
345*bbecb9d1SAndroid Build Coastguard Worker 
346*bbecb9d1SAndroid Build Coastguard Worker     /* send feedback */
347*bbecb9d1SAndroid Build Coastguard Worker     vrend_write_to_iovec(cdc->feed_res->iov, cdc->feed_res->num_iovs,
348*bbecb9d1SAndroid Build Coastguard Worker                          0, (char *)(&feedback),
349*bbecb9d1SAndroid Build Coastguard Worker                          MIN(cdc->feed_res->base.width0, sizeof(feedback)));
350*bbecb9d1SAndroid Build Coastguard Worker 
351*bbecb9d1SAndroid Build Coastguard Worker     cdc->dest_res = NULL;
352*bbecb9d1SAndroid Build Coastguard Worker     cdc->feed_res = NULL;
353*bbecb9d1SAndroid Build Coastguard Worker }
354*bbecb9d1SAndroid Build Coastguard Worker 
355*bbecb9d1SAndroid Build Coastguard Worker static struct virgl_video_callbacks video_callbacks = {
356*bbecb9d1SAndroid Build Coastguard Worker     .decode_completed           = vrend_video_decode_completed,
357*bbecb9d1SAndroid Build Coastguard Worker     .encode_upload_picture      = vrend_video_enocde_upload_picture,
358*bbecb9d1SAndroid Build Coastguard Worker     .encode_completed           = vrend_video_encode_completed,
359*bbecb9d1SAndroid Build Coastguard Worker };
360*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_init(int drm_fd)361*bbecb9d1SAndroid Build Coastguard Worker int vrend_video_init(int drm_fd)
362*bbecb9d1SAndroid Build Coastguard Worker {
363*bbecb9d1SAndroid Build Coastguard Worker     if (drm_fd < 0)
364*bbecb9d1SAndroid Build Coastguard Worker         return -1;
365*bbecb9d1SAndroid Build Coastguard Worker 
366*bbecb9d1SAndroid Build Coastguard Worker     return virgl_video_init(drm_fd, &video_callbacks, 0);
367*bbecb9d1SAndroid Build Coastguard Worker }
368*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_fini(void)369*bbecb9d1SAndroid Build Coastguard Worker void vrend_video_fini(void)
370*bbecb9d1SAndroid Build Coastguard Worker {
371*bbecb9d1SAndroid Build Coastguard Worker     virgl_video_destroy();
372*bbecb9d1SAndroid Build Coastguard Worker }
373*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_fill_caps(union virgl_caps * caps)374*bbecb9d1SAndroid Build Coastguard Worker int vrend_video_fill_caps(union virgl_caps *caps)
375*bbecb9d1SAndroid Build Coastguard Worker {
376*bbecb9d1SAndroid Build Coastguard Worker     return virgl_video_fill_caps(caps);
377*bbecb9d1SAndroid Build Coastguard Worker }
378*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_create_codec(struct vrend_video_context * ctx,uint32_t handle,uint32_t profile,uint32_t entrypoint,uint32_t chroma_format,uint32_t level,uint32_t width,uint32_t height,uint32_t max_ref,uint32_t flags)379*bbecb9d1SAndroid Build Coastguard Worker int vrend_video_create_codec(struct vrend_video_context *ctx,
380*bbecb9d1SAndroid Build Coastguard Worker                              uint32_t handle,
381*bbecb9d1SAndroid Build Coastguard Worker                              uint32_t profile,
382*bbecb9d1SAndroid Build Coastguard Worker                              uint32_t entrypoint,
383*bbecb9d1SAndroid Build Coastguard Worker                              uint32_t chroma_format,
384*bbecb9d1SAndroid Build Coastguard Worker                              uint32_t level,
385*bbecb9d1SAndroid Build Coastguard Worker                              uint32_t width,
386*bbecb9d1SAndroid Build Coastguard Worker                              uint32_t height,
387*bbecb9d1SAndroid Build Coastguard Worker                              uint32_t max_ref,
388*bbecb9d1SAndroid Build Coastguard Worker                              uint32_t flags)
389*bbecb9d1SAndroid Build Coastguard Worker {
390*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_codec *cdc = get_video_codec(ctx, handle);
391*bbecb9d1SAndroid Build Coastguard Worker     struct virgl_video_create_codec_args args;
392*bbecb9d1SAndroid Build Coastguard Worker 
393*bbecb9d1SAndroid Build Coastguard Worker     if (cdc)
394*bbecb9d1SAndroid Build Coastguard Worker         return 0;
395*bbecb9d1SAndroid Build Coastguard Worker 
396*bbecb9d1SAndroid Build Coastguard Worker     if (profile <= PIPE_VIDEO_PROFILE_UNKNOWN ||
397*bbecb9d1SAndroid Build Coastguard Worker         profile >= PIPE_VIDEO_PROFILE_MAX)
398*bbecb9d1SAndroid Build Coastguard Worker         return -1;
399*bbecb9d1SAndroid Build Coastguard Worker 
400*bbecb9d1SAndroid Build Coastguard Worker     if (entrypoint <= PIPE_VIDEO_ENTRYPOINT_UNKNOWN ||
401*bbecb9d1SAndroid Build Coastguard Worker         entrypoint > PIPE_VIDEO_ENTRYPOINT_ENCODE)
402*bbecb9d1SAndroid Build Coastguard Worker         return -1;
403*bbecb9d1SAndroid Build Coastguard Worker 
404*bbecb9d1SAndroid Build Coastguard Worker     if (chroma_format >= PIPE_VIDEO_CHROMA_FORMAT_NONE)
405*bbecb9d1SAndroid Build Coastguard Worker         return -1;
406*bbecb9d1SAndroid Build Coastguard Worker 
407*bbecb9d1SAndroid Build Coastguard Worker     if (!width || !height)
408*bbecb9d1SAndroid Build Coastguard Worker         return -1;
409*bbecb9d1SAndroid Build Coastguard Worker 
410*bbecb9d1SAndroid Build Coastguard Worker     cdc = (struct vrend_video_codec *)calloc(1, sizeof(*cdc));
411*bbecb9d1SAndroid Build Coastguard Worker     if (!cdc)
412*bbecb9d1SAndroid Build Coastguard Worker         return -1;
413*bbecb9d1SAndroid Build Coastguard Worker 
414*bbecb9d1SAndroid Build Coastguard Worker     args.profile = profile;
415*bbecb9d1SAndroid Build Coastguard Worker     args.entrypoint = entrypoint;
416*bbecb9d1SAndroid Build Coastguard Worker     args.chroma_format = chroma_format;
417*bbecb9d1SAndroid Build Coastguard Worker     args.level = level;
418*bbecb9d1SAndroid Build Coastguard Worker     args.width = width;
419*bbecb9d1SAndroid Build Coastguard Worker     args.height = height;
420*bbecb9d1SAndroid Build Coastguard Worker     args.max_references = max_ref;
421*bbecb9d1SAndroid Build Coastguard Worker     args.flags = flags;
422*bbecb9d1SAndroid Build Coastguard Worker     args.opaque = cdc;
423*bbecb9d1SAndroid Build Coastguard Worker     cdc->codec = virgl_video_create_codec(&args);
424*bbecb9d1SAndroid Build Coastguard Worker     if (!cdc->codec) {
425*bbecb9d1SAndroid Build Coastguard Worker         free(cdc);
426*bbecb9d1SAndroid Build Coastguard Worker         return -1;
427*bbecb9d1SAndroid Build Coastguard Worker     }
428*bbecb9d1SAndroid Build Coastguard Worker 
429*bbecb9d1SAndroid Build Coastguard Worker     cdc->handle = handle;
430*bbecb9d1SAndroid Build Coastguard Worker     cdc->ctx = ctx;
431*bbecb9d1SAndroid Build Coastguard Worker     list_add(&cdc->head, &ctx->codecs);
432*bbecb9d1SAndroid Build Coastguard Worker 
433*bbecb9d1SAndroid Build Coastguard Worker     return 0;
434*bbecb9d1SAndroid Build Coastguard Worker }
435*bbecb9d1SAndroid Build Coastguard Worker 
destroy_video_codec(struct vrend_video_codec * cdc)436*bbecb9d1SAndroid Build Coastguard Worker static void destroy_video_codec(struct vrend_video_codec *cdc)
437*bbecb9d1SAndroid Build Coastguard Worker {
438*bbecb9d1SAndroid Build Coastguard Worker     if (cdc) {
439*bbecb9d1SAndroid Build Coastguard Worker         list_del(&cdc->head);
440*bbecb9d1SAndroid Build Coastguard Worker         virgl_video_destroy_codec(cdc->codec);
441*bbecb9d1SAndroid Build Coastguard Worker         free(cdc);
442*bbecb9d1SAndroid Build Coastguard Worker     }
443*bbecb9d1SAndroid Build Coastguard Worker }
444*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_destroy_codec(struct vrend_video_context * ctx,uint32_t handle)445*bbecb9d1SAndroid Build Coastguard Worker void vrend_video_destroy_codec(struct vrend_video_context *ctx,
446*bbecb9d1SAndroid Build Coastguard Worker                                uint32_t handle)
447*bbecb9d1SAndroid Build Coastguard Worker {
448*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_codec *cdc = get_video_codec(ctx, handle);
449*bbecb9d1SAndroid Build Coastguard Worker 
450*bbecb9d1SAndroid Build Coastguard Worker     destroy_video_codec(cdc);
451*bbecb9d1SAndroid Build Coastguard Worker }
452*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_create_buffer(struct vrend_video_context * ctx,uint32_t handle,uint32_t format,uint32_t width,uint32_t height,uint32_t * res_handles,unsigned int num_res)453*bbecb9d1SAndroid Build Coastguard Worker int vrend_video_create_buffer(struct vrend_video_context *ctx,
454*bbecb9d1SAndroid Build Coastguard Worker                               uint32_t handle,
455*bbecb9d1SAndroid Build Coastguard Worker                               uint32_t format,
456*bbecb9d1SAndroid Build Coastguard Worker                               uint32_t width,
457*bbecb9d1SAndroid Build Coastguard Worker                               uint32_t height,
458*bbecb9d1SAndroid Build Coastguard Worker                               uint32_t *res_handles,
459*bbecb9d1SAndroid Build Coastguard Worker                               unsigned int num_res)
460*bbecb9d1SAndroid Build Coastguard Worker {
461*bbecb9d1SAndroid Build Coastguard Worker     unsigned i;
462*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_plane *plane;
463*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_buffer *buf = get_video_buffer(ctx, handle);
464*bbecb9d1SAndroid Build Coastguard Worker     struct virgl_video_create_buffer_args args;
465*bbecb9d1SAndroid Build Coastguard Worker 
466*bbecb9d1SAndroid Build Coastguard Worker     if (buf)
467*bbecb9d1SAndroid Build Coastguard Worker         return 0;
468*bbecb9d1SAndroid Build Coastguard Worker 
469*bbecb9d1SAndroid Build Coastguard Worker     if (format <= PIPE_FORMAT_NONE || format >= PIPE_FORMAT_COUNT)
470*bbecb9d1SAndroid Build Coastguard Worker         return -1;
471*bbecb9d1SAndroid Build Coastguard Worker 
472*bbecb9d1SAndroid Build Coastguard Worker     if (!width || !height || !res_handles || !num_res)
473*bbecb9d1SAndroid Build Coastguard Worker         return -1;
474*bbecb9d1SAndroid Build Coastguard Worker 
475*bbecb9d1SAndroid Build Coastguard Worker     buf = (struct vrend_video_buffer *)calloc(1, sizeof(*buf));
476*bbecb9d1SAndroid Build Coastguard Worker     if (!buf)
477*bbecb9d1SAndroid Build Coastguard Worker         return -1;
478*bbecb9d1SAndroid Build Coastguard Worker 
479*bbecb9d1SAndroid Build Coastguard Worker     args.format = format;
480*bbecb9d1SAndroid Build Coastguard Worker     args.width = width;
481*bbecb9d1SAndroid Build Coastguard Worker     args.height = height;
482*bbecb9d1SAndroid Build Coastguard Worker     args.interlaced = 0;
483*bbecb9d1SAndroid Build Coastguard Worker     args.opaque = buf;
484*bbecb9d1SAndroid Build Coastguard Worker     buf->buffer = virgl_video_create_buffer(&args);
485*bbecb9d1SAndroid Build Coastguard Worker     if (!buf->buffer) {
486*bbecb9d1SAndroid Build Coastguard Worker         free(buf);
487*bbecb9d1SAndroid Build Coastguard Worker         return -1;
488*bbecb9d1SAndroid Build Coastguard Worker     }
489*bbecb9d1SAndroid Build Coastguard Worker 
490*bbecb9d1SAndroid Build Coastguard Worker     for (i = 0; i < ARRAY_SIZE(buf->planes); i++)
491*bbecb9d1SAndroid Build Coastguard Worker         buf->planes[i].egl_image = EGL_NO_IMAGE_KHR;
492*bbecb9d1SAndroid Build Coastguard Worker 
493*bbecb9d1SAndroid Build Coastguard Worker     for (i = 0, buf->num_planes = 0;
494*bbecb9d1SAndroid Build Coastguard Worker          i < num_res && buf->num_planes < ARRAY_SIZE(buf->planes); i++) {
495*bbecb9d1SAndroid Build Coastguard Worker 
496*bbecb9d1SAndroid Build Coastguard Worker         if (!res_handles[i])
497*bbecb9d1SAndroid Build Coastguard Worker             continue;
498*bbecb9d1SAndroid Build Coastguard Worker 
499*bbecb9d1SAndroid Build Coastguard Worker         plane = &buf->planes[buf->num_planes++];
500*bbecb9d1SAndroid Build Coastguard Worker         plane->res_handle = res_handles[i];
501*bbecb9d1SAndroid Build Coastguard Worker         glGenFramebuffers(1, &plane->framebuffer);
502*bbecb9d1SAndroid Build Coastguard Worker         glGenTextures(1, &plane->texture);
503*bbecb9d1SAndroid Build Coastguard Worker         glBindTexture(GL_TEXTURE_2D, plane->texture);
504*bbecb9d1SAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
505*bbecb9d1SAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
506*bbecb9d1SAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
507*bbecb9d1SAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
508*bbecb9d1SAndroid Build Coastguard Worker         glBindTexture(GL_TEXTURE_2D, 0);
509*bbecb9d1SAndroid Build Coastguard Worker     }
510*bbecb9d1SAndroid Build Coastguard Worker 
511*bbecb9d1SAndroid Build Coastguard Worker     buf->handle = handle;
512*bbecb9d1SAndroid Build Coastguard Worker     buf->ctx = ctx;
513*bbecb9d1SAndroid Build Coastguard Worker     list_add(&buf->head, &ctx->buffers);
514*bbecb9d1SAndroid Build Coastguard Worker 
515*bbecb9d1SAndroid Build Coastguard Worker     return 0;
516*bbecb9d1SAndroid Build Coastguard Worker }
517*bbecb9d1SAndroid Build Coastguard Worker 
destroy_video_buffer(struct vrend_video_buffer * buf)518*bbecb9d1SAndroid Build Coastguard Worker static void destroy_video_buffer(struct vrend_video_buffer *buf)
519*bbecb9d1SAndroid Build Coastguard Worker {
520*bbecb9d1SAndroid Build Coastguard Worker     unsigned i;
521*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_plane *plane;
522*bbecb9d1SAndroid Build Coastguard Worker 
523*bbecb9d1SAndroid Build Coastguard Worker     if (!buf)
524*bbecb9d1SAndroid Build Coastguard Worker         return;
525*bbecb9d1SAndroid Build Coastguard Worker 
526*bbecb9d1SAndroid Build Coastguard Worker     list_del(&buf->head);
527*bbecb9d1SAndroid Build Coastguard Worker 
528*bbecb9d1SAndroid Build Coastguard Worker     for (i = 0; i < buf->num_planes; i++) {
529*bbecb9d1SAndroid Build Coastguard Worker         plane = &buf->planes[i];
530*bbecb9d1SAndroid Build Coastguard Worker 
531*bbecb9d1SAndroid Build Coastguard Worker         glDeleteTextures(1, &plane->texture);
532*bbecb9d1SAndroid Build Coastguard Worker         glDeleteFramebuffers(1, &plane->framebuffer);
533*bbecb9d1SAndroid Build Coastguard Worker         if (plane->egl_image == EGL_NO_IMAGE_KHR)
534*bbecb9d1SAndroid Build Coastguard Worker             eglDestroyImageKHR(eglGetCurrentDisplay(), plane->egl_image);
535*bbecb9d1SAndroid Build Coastguard Worker     }
536*bbecb9d1SAndroid Build Coastguard Worker 
537*bbecb9d1SAndroid Build Coastguard Worker     virgl_video_destroy_buffer(buf->buffer);
538*bbecb9d1SAndroid Build Coastguard Worker 
539*bbecb9d1SAndroid Build Coastguard Worker     free(buf);
540*bbecb9d1SAndroid Build Coastguard Worker }
541*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_destroy_buffer(struct vrend_video_context * ctx,uint32_t handle)542*bbecb9d1SAndroid Build Coastguard Worker void vrend_video_destroy_buffer(struct vrend_video_context *ctx,
543*bbecb9d1SAndroid Build Coastguard Worker                                 uint32_t handle)
544*bbecb9d1SAndroid Build Coastguard Worker {
545*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_buffer *buf = get_video_buffer(ctx, handle);
546*bbecb9d1SAndroid Build Coastguard Worker 
547*bbecb9d1SAndroid Build Coastguard Worker     destroy_video_buffer(buf);
548*bbecb9d1SAndroid Build Coastguard Worker }
549*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_create_context(struct vrend_context * ctx)550*bbecb9d1SAndroid Build Coastguard Worker struct vrend_video_context *vrend_video_create_context(struct vrend_context *ctx)
551*bbecb9d1SAndroid Build Coastguard Worker {
552*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_context *vctx;
553*bbecb9d1SAndroid Build Coastguard Worker 
554*bbecb9d1SAndroid Build Coastguard Worker     vctx = (struct vrend_video_context *)calloc(1, sizeof(*vctx));
555*bbecb9d1SAndroid Build Coastguard Worker     if (vctx) {
556*bbecb9d1SAndroid Build Coastguard Worker         vctx->ctx = ctx;
557*bbecb9d1SAndroid Build Coastguard Worker         list_inithead(&vctx->codecs);
558*bbecb9d1SAndroid Build Coastguard Worker         list_inithead(&vctx->buffers);
559*bbecb9d1SAndroid Build Coastguard Worker     }
560*bbecb9d1SAndroid Build Coastguard Worker 
561*bbecb9d1SAndroid Build Coastguard Worker     return vctx;
562*bbecb9d1SAndroid Build Coastguard Worker }
563*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_destroy_context(struct vrend_video_context * ctx)564*bbecb9d1SAndroid Build Coastguard Worker void vrend_video_destroy_context(struct vrend_video_context *ctx)
565*bbecb9d1SAndroid Build Coastguard Worker {
566*bbecb9d1SAndroid Build Coastguard Worker    struct vrend_video_codec *vcdc, *vcdc_tmp;
567*bbecb9d1SAndroid Build Coastguard Worker    struct vrend_video_buffer *vbuf, *vbuf_tmp;
568*bbecb9d1SAndroid Build Coastguard Worker 
569*bbecb9d1SAndroid Build Coastguard Worker    LIST_FOR_EACH_ENTRY_SAFE(vcdc, vcdc_tmp, &ctx->codecs, head)
570*bbecb9d1SAndroid Build Coastguard Worker       destroy_video_codec(vcdc);
571*bbecb9d1SAndroid Build Coastguard Worker 
572*bbecb9d1SAndroid Build Coastguard Worker    LIST_FOR_EACH_ENTRY_SAFE(vbuf, vbuf_tmp, &ctx->buffers, head)
573*bbecb9d1SAndroid Build Coastguard Worker       destroy_video_buffer(vbuf);
574*bbecb9d1SAndroid Build Coastguard Worker 
575*bbecb9d1SAndroid Build Coastguard Worker    free(ctx);
576*bbecb9d1SAndroid Build Coastguard Worker }
577*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_begin_frame(struct vrend_video_context * ctx,uint32_t cdc_handle,uint32_t tgt_handle)578*bbecb9d1SAndroid Build Coastguard Worker int vrend_video_begin_frame(struct vrend_video_context *ctx,
579*bbecb9d1SAndroid Build Coastguard Worker                             uint32_t cdc_handle,
580*bbecb9d1SAndroid Build Coastguard Worker                             uint32_t tgt_handle)
581*bbecb9d1SAndroid Build Coastguard Worker {
582*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_codec *cdc = get_video_codec(ctx, cdc_handle);
583*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_buffer *tgt = get_video_buffer(ctx, tgt_handle);
584*bbecb9d1SAndroid Build Coastguard Worker 
585*bbecb9d1SAndroid Build Coastguard Worker     if (!cdc || !tgt)
586*bbecb9d1SAndroid Build Coastguard Worker         return -1;
587*bbecb9d1SAndroid Build Coastguard Worker 
588*bbecb9d1SAndroid Build Coastguard Worker     return virgl_video_begin_frame(cdc->codec, tgt->buffer);
589*bbecb9d1SAndroid Build Coastguard Worker }
590*bbecb9d1SAndroid Build Coastguard Worker 
modify_h264_picture_desc(struct vrend_video_codec * cdc,struct vrend_video_buffer * tgt,struct virgl_h264_picture_desc * desc)591*bbecb9d1SAndroid Build Coastguard Worker static void modify_h264_picture_desc(struct vrend_video_codec *cdc,
592*bbecb9d1SAndroid Build Coastguard Worker                                      struct vrend_video_buffer *tgt,
593*bbecb9d1SAndroid Build Coastguard Worker                                      struct virgl_h264_picture_desc *desc)
594*bbecb9d1SAndroid Build Coastguard Worker {
595*bbecb9d1SAndroid Build Coastguard Worker     unsigned i;
596*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_buffer *vbuf;
597*bbecb9d1SAndroid Build Coastguard Worker 
598*bbecb9d1SAndroid Build Coastguard Worker     (void)tgt;
599*bbecb9d1SAndroid Build Coastguard Worker 
600*bbecb9d1SAndroid Build Coastguard Worker     for (i = 0; i < ARRAY_SIZE(desc->buffer_id); i++) {
601*bbecb9d1SAndroid Build Coastguard Worker         vbuf = get_video_buffer(cdc->ctx, desc->buffer_id[i]);
602*bbecb9d1SAndroid Build Coastguard Worker         desc->buffer_id[i] = virgl_video_buffer_id(vbuf ? vbuf->buffer : NULL);
603*bbecb9d1SAndroid Build Coastguard Worker     }
604*bbecb9d1SAndroid Build Coastguard Worker }
605*bbecb9d1SAndroid Build Coastguard Worker 
modify_h265_picture_desc(struct vrend_video_codec * cdc,struct vrend_video_buffer * tgt,struct virgl_h265_picture_desc * desc)606*bbecb9d1SAndroid Build Coastguard Worker static void modify_h265_picture_desc(struct vrend_video_codec *cdc,
607*bbecb9d1SAndroid Build Coastguard Worker                                      struct vrend_video_buffer *tgt,
608*bbecb9d1SAndroid Build Coastguard Worker                                      struct virgl_h265_picture_desc *desc)
609*bbecb9d1SAndroid Build Coastguard Worker {
610*bbecb9d1SAndroid Build Coastguard Worker     unsigned i;
611*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_buffer *vbuf;
612*bbecb9d1SAndroid Build Coastguard Worker 
613*bbecb9d1SAndroid Build Coastguard Worker     (void)tgt;
614*bbecb9d1SAndroid Build Coastguard Worker 
615*bbecb9d1SAndroid Build Coastguard Worker     for (i = 0; i < ARRAY_SIZE(desc->ref); i++) {
616*bbecb9d1SAndroid Build Coastguard Worker         vbuf = get_video_buffer(cdc->ctx, desc->ref[i]);
617*bbecb9d1SAndroid Build Coastguard Worker         desc->ref[i] = virgl_video_buffer_id(vbuf ? vbuf->buffer : NULL);
618*bbecb9d1SAndroid Build Coastguard Worker     }
619*bbecb9d1SAndroid Build Coastguard Worker }
620*bbecb9d1SAndroid Build Coastguard Worker 
modify_picture_desc(struct vrend_video_codec * cdc,struct vrend_video_buffer * tgt,union virgl_picture_desc * desc)621*bbecb9d1SAndroid Build Coastguard Worker static void modify_picture_desc(struct vrend_video_codec *cdc,
622*bbecb9d1SAndroid Build Coastguard Worker                                 struct vrend_video_buffer *tgt,
623*bbecb9d1SAndroid Build Coastguard Worker                                 union virgl_picture_desc *desc)
624*bbecb9d1SAndroid Build Coastguard Worker {
625*bbecb9d1SAndroid Build Coastguard Worker     switch(virgl_video_codec_profile(cdc->codec)) {
626*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
627*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE:
628*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
629*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED:
630*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
631*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10:
632*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH422:
633*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH444:
634*bbecb9d1SAndroid Build Coastguard Worker         modify_h264_picture_desc(cdc, tgt, &desc->h264);
635*bbecb9d1SAndroid Build Coastguard Worker         break;
636*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_HEVC_MAIN:
637*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_HEVC_MAIN_10:
638*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_HEVC_MAIN_STILL:
639*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_HEVC_MAIN_12:
640*bbecb9d1SAndroid Build Coastguard Worker     case PIPE_VIDEO_PROFILE_HEVC_MAIN_444:
641*bbecb9d1SAndroid Build Coastguard Worker         modify_h265_picture_desc(cdc, tgt, &desc->h265);
642*bbecb9d1SAndroid Build Coastguard Worker         break;
643*bbecb9d1SAndroid Build Coastguard Worker     default:
644*bbecb9d1SAndroid Build Coastguard Worker         break;
645*bbecb9d1SAndroid Build Coastguard Worker     }
646*bbecb9d1SAndroid Build Coastguard Worker }
647*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_decode_bitstream(struct vrend_video_context * ctx,uint32_t cdc_handle,uint32_t tgt_handle,uint32_t desc_handle,unsigned num_buffers,const uint32_t * buffer_handles,const uint32_t * buffer_sizes)648*bbecb9d1SAndroid Build Coastguard Worker int vrend_video_decode_bitstream(struct vrend_video_context *ctx,
649*bbecb9d1SAndroid Build Coastguard Worker                                  uint32_t cdc_handle,
650*bbecb9d1SAndroid Build Coastguard Worker                                  uint32_t tgt_handle,
651*bbecb9d1SAndroid Build Coastguard Worker                                  uint32_t desc_handle,
652*bbecb9d1SAndroid Build Coastguard Worker                                  unsigned num_buffers,
653*bbecb9d1SAndroid Build Coastguard Worker                                  const uint32_t *buffer_handles,
654*bbecb9d1SAndroid Build Coastguard Worker                                  const uint32_t *buffer_sizes)
655*bbecb9d1SAndroid Build Coastguard Worker {
656*bbecb9d1SAndroid Build Coastguard Worker     int err = -1;
657*bbecb9d1SAndroid Build Coastguard Worker     unsigned i, num_bs, *bs_sizes = NULL;
658*bbecb9d1SAndroid Build Coastguard Worker     void **bs_buffers = NULL;
659*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_resource *res;
660*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_codec  *cdc = get_video_codec(ctx, cdc_handle);
661*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_buffer *tgt = get_video_buffer(ctx, tgt_handle);
662*bbecb9d1SAndroid Build Coastguard Worker     union virgl_picture_desc desc;
663*bbecb9d1SAndroid Build Coastguard Worker 
664*bbecb9d1SAndroid Build Coastguard Worker     if (!cdc || !tgt)
665*bbecb9d1SAndroid Build Coastguard Worker         return -1;
666*bbecb9d1SAndroid Build Coastguard Worker 
667*bbecb9d1SAndroid Build Coastguard Worker     bs_buffers = calloc(num_buffers, sizeof(void *));
668*bbecb9d1SAndroid Build Coastguard Worker     if (!bs_buffers) {
669*bbecb9d1SAndroid Build Coastguard Worker         vrend_printf("%s: alloc bs_buffers failed\n", __func__);
670*bbecb9d1SAndroid Build Coastguard Worker         return -1;
671*bbecb9d1SAndroid Build Coastguard Worker     }
672*bbecb9d1SAndroid Build Coastguard Worker 
673*bbecb9d1SAndroid Build Coastguard Worker     bs_sizes = calloc(num_buffers, sizeof(unsigned));
674*bbecb9d1SAndroid Build Coastguard Worker     if (!bs_sizes) {
675*bbecb9d1SAndroid Build Coastguard Worker         vrend_printf("%s: alloc bs_sizes failed\n", __func__);
676*bbecb9d1SAndroid Build Coastguard Worker         goto err;
677*bbecb9d1SAndroid Build Coastguard Worker     }
678*bbecb9d1SAndroid Build Coastguard Worker 
679*bbecb9d1SAndroid Build Coastguard Worker     for (i = 0, num_bs = 0; i < num_buffers; i++) {
680*bbecb9d1SAndroid Build Coastguard Worker         res = vrend_renderer_ctx_res_lookup(ctx->ctx, buffer_handles[i]);
681*bbecb9d1SAndroid Build Coastguard Worker         if (!res || !res->ptr) {
682*bbecb9d1SAndroid Build Coastguard Worker             vrend_printf("%s: bs res %d invalid or not found",
683*bbecb9d1SAndroid Build Coastguard Worker                          __func__, buffer_handles[i]);
684*bbecb9d1SAndroid Build Coastguard Worker             continue;
685*bbecb9d1SAndroid Build Coastguard Worker         }
686*bbecb9d1SAndroid Build Coastguard Worker 
687*bbecb9d1SAndroid Build Coastguard Worker         vrend_read_from_iovec(res->iov, res->num_iovs, 0,
688*bbecb9d1SAndroid Build Coastguard Worker                               res->ptr, buffer_sizes[i]);
689*bbecb9d1SAndroid Build Coastguard Worker         bs_buffers[num_bs] = res->ptr;
690*bbecb9d1SAndroid Build Coastguard Worker         bs_sizes[num_bs] = buffer_sizes[i];
691*bbecb9d1SAndroid Build Coastguard Worker         num_bs++;
692*bbecb9d1SAndroid Build Coastguard Worker     }
693*bbecb9d1SAndroid Build Coastguard Worker 
694*bbecb9d1SAndroid Build Coastguard Worker     res = vrend_renderer_ctx_res_lookup(ctx->ctx, desc_handle);
695*bbecb9d1SAndroid Build Coastguard Worker     if (!res) {
696*bbecb9d1SAndroid Build Coastguard Worker         vrend_printf("%s: desc res %d not found\n", __func__, desc_handle);
697*bbecb9d1SAndroid Build Coastguard Worker         goto err;
698*bbecb9d1SAndroid Build Coastguard Worker     }
699*bbecb9d1SAndroid Build Coastguard Worker     memset(&desc, 0, sizeof(desc));
700*bbecb9d1SAndroid Build Coastguard Worker     vrend_read_from_iovec(res->iov, res->num_iovs, 0, (char *)(&desc),
701*bbecb9d1SAndroid Build Coastguard Worker                           MIN(res->base.width0, sizeof(desc)));
702*bbecb9d1SAndroid Build Coastguard Worker     modify_picture_desc(cdc, tgt, &desc);
703*bbecb9d1SAndroid Build Coastguard Worker 
704*bbecb9d1SAndroid Build Coastguard Worker     err = virgl_video_decode_bitstream(cdc->codec, tgt->buffer, &desc,
705*bbecb9d1SAndroid Build Coastguard Worker                            num_bs, (const void * const *)bs_buffers, bs_sizes);
706*bbecb9d1SAndroid Build Coastguard Worker 
707*bbecb9d1SAndroid Build Coastguard Worker err:
708*bbecb9d1SAndroid Build Coastguard Worker     free(bs_buffers);
709*bbecb9d1SAndroid Build Coastguard Worker     free(bs_sizes);
710*bbecb9d1SAndroid Build Coastguard Worker 
711*bbecb9d1SAndroid Build Coastguard Worker     return err;
712*bbecb9d1SAndroid Build Coastguard Worker }
713*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_encode_bitstream(struct vrend_video_context * ctx,uint32_t cdc_handle,uint32_t src_handle,uint32_t dest_handle,uint32_t desc_handle,uint32_t feed_handle)714*bbecb9d1SAndroid Build Coastguard Worker int vrend_video_encode_bitstream(struct vrend_video_context *ctx,
715*bbecb9d1SAndroid Build Coastguard Worker                                  uint32_t cdc_handle,
716*bbecb9d1SAndroid Build Coastguard Worker                                  uint32_t src_handle,
717*bbecb9d1SAndroid Build Coastguard Worker                                  uint32_t dest_handle,
718*bbecb9d1SAndroid Build Coastguard Worker                                  uint32_t desc_handle,
719*bbecb9d1SAndroid Build Coastguard Worker                                  uint32_t feed_handle)
720*bbecb9d1SAndroid Build Coastguard Worker {
721*bbecb9d1SAndroid Build Coastguard Worker     union virgl_picture_desc desc;
722*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_resource *dest_res, *desc_res, *feed_res;
723*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_codec  *cdc = get_video_codec(ctx, cdc_handle);
724*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_buffer *src = get_video_buffer(ctx, src_handle);
725*bbecb9d1SAndroid Build Coastguard Worker 
726*bbecb9d1SAndroid Build Coastguard Worker     if (!cdc || !src)
727*bbecb9d1SAndroid Build Coastguard Worker         return -1;
728*bbecb9d1SAndroid Build Coastguard Worker 
729*bbecb9d1SAndroid Build Coastguard Worker     /* Feedback resource */
730*bbecb9d1SAndroid Build Coastguard Worker     feed_res = vrend_renderer_ctx_res_lookup(ctx->ctx, feed_handle);
731*bbecb9d1SAndroid Build Coastguard Worker     if (!feed_res) {
732*bbecb9d1SAndroid Build Coastguard Worker         vrend_printf("%s: feedback res %d not found\n", __func__, feed_handle);
733*bbecb9d1SAndroid Build Coastguard Worker         return -1;
734*bbecb9d1SAndroid Build Coastguard Worker     }
735*bbecb9d1SAndroid Build Coastguard Worker 
736*bbecb9d1SAndroid Build Coastguard Worker     /* Picture descriptor resource */
737*bbecb9d1SAndroid Build Coastguard Worker     desc_res = vrend_renderer_ctx_res_lookup(ctx->ctx, desc_handle);
738*bbecb9d1SAndroid Build Coastguard Worker     if (!desc_res) {
739*bbecb9d1SAndroid Build Coastguard Worker         vrend_printf("%s: desc res %d not found\n", __func__, desc_handle);
740*bbecb9d1SAndroid Build Coastguard Worker         return -1;
741*bbecb9d1SAndroid Build Coastguard Worker     }
742*bbecb9d1SAndroid Build Coastguard Worker     memset(&desc, 0, sizeof(desc));
743*bbecb9d1SAndroid Build Coastguard Worker     vrend_read_from_iovec(desc_res->iov, desc_res->num_iovs, 0, (char *)(&desc),
744*bbecb9d1SAndroid Build Coastguard Worker                           MIN(desc_res->base.width0, sizeof(desc)));
745*bbecb9d1SAndroid Build Coastguard Worker 
746*bbecb9d1SAndroid Build Coastguard Worker     /* Destination buffer resource. */
747*bbecb9d1SAndroid Build Coastguard Worker     dest_res = vrend_renderer_ctx_res_lookup(ctx->ctx, dest_handle);
748*bbecb9d1SAndroid Build Coastguard Worker     if (!dest_res) {
749*bbecb9d1SAndroid Build Coastguard Worker         vrend_printf("%s: dest res %d not found\n", __func__, dest_handle);
750*bbecb9d1SAndroid Build Coastguard Worker         return -1;
751*bbecb9d1SAndroid Build Coastguard Worker     }
752*bbecb9d1SAndroid Build Coastguard Worker 
753*bbecb9d1SAndroid Build Coastguard Worker     cdc->feed_res = feed_res;
754*bbecb9d1SAndroid Build Coastguard Worker     cdc->dest_res = dest_res;
755*bbecb9d1SAndroid Build Coastguard Worker 
756*bbecb9d1SAndroid Build Coastguard Worker     return virgl_video_encode_bitstream(cdc->codec, src->buffer, &desc);
757*bbecb9d1SAndroid Build Coastguard Worker }
758*bbecb9d1SAndroid Build Coastguard Worker 
vrend_video_end_frame(struct vrend_video_context * ctx,uint32_t cdc_handle,uint32_t tgt_handle)759*bbecb9d1SAndroid Build Coastguard Worker int vrend_video_end_frame(struct vrend_video_context *ctx,
760*bbecb9d1SAndroid Build Coastguard Worker                           uint32_t cdc_handle,
761*bbecb9d1SAndroid Build Coastguard Worker                           uint32_t tgt_handle)
762*bbecb9d1SAndroid Build Coastguard Worker {
763*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_codec *cdc = get_video_codec(ctx, cdc_handle);
764*bbecb9d1SAndroid Build Coastguard Worker     struct vrend_video_buffer *tgt = get_video_buffer(ctx, tgt_handle);
765*bbecb9d1SAndroid Build Coastguard Worker 
766*bbecb9d1SAndroid Build Coastguard Worker     if (!cdc || !tgt)
767*bbecb9d1SAndroid Build Coastguard Worker         return -1;
768*bbecb9d1SAndroid Build Coastguard Worker 
769*bbecb9d1SAndroid Build Coastguard Worker     return virgl_video_end_frame(cdc->codec, tgt->buffer);
770*bbecb9d1SAndroid Build Coastguard Worker }
771*bbecb9d1SAndroid Build Coastguard Worker 
772