1 /*
2  * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Shengquan Yuan  <shengquan.yuan@intel.com>
26  *    Zhaohan Ren  <zhaohan.ren@intel.com>
27  *    Jason Hu <jason.hu@intel.com>
28  *
29  */
30 
31 #ifndef ANDROID
32 #include <X11/Xutil.h>
33 #include <X11/extensions/Xrandr.h>
34 #include <va/va_dricommon.h>
35 #include "x11/psb_x11.h"
36 #include "x11/psb_xrandr.h"
37 #endif
38 #include <va/va_backend.h>
39 #include <dlfcn.h>
40 #include <stdlib.h>
41 #include "psb_output.h"
42 #include "psb_surface.h"
43 #include "psb_buffer.h"
44 #include "psb_surface_ext.h"
45 #include "pnw_rotate.h"
46 #include <stdio.h>
47 #include <string.h>
48 #include <stdarg.h>
49 #include <wsbm/wsbm_manager.h>
50 #include "psb_drv_debug.h"
51 #include <string.h>
52 #include <unistd.h>
53 #include <sys/ioctl.h>
54 #include <math.h>
55 
56 #define INIT_DRIVER_DATA        psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
57 
58 #define SURFACE(id)     ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
59 #define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
60 #define IMAGE(id)  ((object_image_p) object_heap_lookup( &driver_data->image_heap, id ))
61 #define SUBPIC(id)  ((object_subpic_p) object_heap_lookup( &driver_data->subpic_heap, id ))
62 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
63 
64 
65 /* surfaces link list associated with a subpicture */
66 typedef struct _subpic_surface {
67     VASurfaceID surface_id;
68     struct _subpic_surface *next;
69 } subpic_surface_s, *subpic_surface_p;
70 
71 
72 static VAImageFormat psb__SubpicFormat[] = {
73     psb__ImageRGBA,
74     //psb__ImageAYUV,
75     //psb__ImageAI44
76 };
77 
78 static VAImageFormat psb__CreateImageFormat[] = {
79     psb__ImageNV12,
80     psb__ImageRGBA,
81     //psb__ImageAYUV,
82     //psb__ImageAI44,
83     psb__ImageYV16,
84     psb__ImageYV32
85 };
86 
87 unsigned char *psb_x11_output_init(VADriverContextP ctx);
88 VAStatus psb_x11_output_deinit(VADriverContextP ctx);
89 unsigned char *psb_android_output_init(VADriverContextP ctx);
90 VAStatus psb_android_output_deinit(VADriverContextP ctx);
91 
92 int psb_coverlay_init(VADriverContextP ctx);
93 int psb_coverlay_deinit(VADriverContextP ctx);
94 
psb_initOutput(VADriverContextP ctx)95 VAStatus psb_initOutput(VADriverContextP ctx)
96 {
97     INIT_DRIVER_DATA;
98     unsigned char *ws_priv = NULL;
99     char env_value[1024];
100 
101     pthread_mutex_init(&driver_data->output_mutex, NULL);
102 
103     if (psb_parse_config("PSB_VIDEO_PUTSURFACE_DUMMY", &env_value[0]) == 0) {
104         drv_debug_msg(VIDEO_DEBUG_GENERAL, "vaPutSurface: dummy mode, return directly\n");
105         driver_data->dummy_putsurface = 0;
106 
107         return VA_STATUS_SUCCESS;
108     }
109 
110     if (psb_parse_config("PSB_VIDEO_FPS", &env_value[0]) == 0) {
111         driver_data->fixed_fps = atoi(env_value);
112         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Throttling at FPS=%d\n", driver_data->fixed_fps);
113     } else
114         driver_data->fixed_fps = 0;
115 
116     driver_data->outputmethod_checkinterval = 1;
117     if (psb_parse_config("PSB_VIDEO_INTERVAL", &env_value[0]) == 0) {
118         driver_data->outputmethod_checkinterval = atoi(env_value);
119         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Check output method at %d frames interval\n",
120                                  driver_data->outputmethod_checkinterval);
121     }
122 
123     driver_data->cur_displaying_surface = VA_INVALID_SURFACE;
124     driver_data->last_displaying_surface = VA_INVALID_SURFACE;
125 
126     psb_InitOutLoop(ctx);
127 
128 #ifdef ANDROID
129     ws_priv = psb_android_output_init(ctx);
130     driver_data->is_android = 1;
131 #else
132     ws_priv = psb_x11_output_init(ctx);
133     driver_data->is_android = 0;
134 #endif
135     driver_data->ws_priv = ws_priv;
136 
137 
138 #if 0
139     //use client textureblit
140     if (driver_data->ctexture == 1) {
141         int ret = psb_ctexture_init(ctx);
142         if (ret != 0)
143             driver_data->ctexture = 0;
144     }
145 #endif
146 
147     /*
148     //use texture streaming
149     if (driver_data->ctexstreaming == 1)
150     psb_ctexstreaing_init(ctx);
151     */
152 
153     return VA_STATUS_SUCCESS;
154 }
155 
psb_deinitOutput(VADriverContextP ctx)156 VAStatus psb_deinitOutput(
157     VADriverContextP ctx
158 )
159 {
160     INIT_DRIVER_DATA;
161 
162 #if 0
163     //use client textureblit
164     if (driver_data->ctexture == 1)
165         psb_ctexture_deinit(ctx);
166 #endif
167 
168     if (driver_data->coverlay_init) {
169         psb_coverlay_deinit(ctx);
170         driver_data->coverlay_init = 0;
171     }
172 
173 #ifndef ANDROID
174     psb_x11_output_deinit(ctx);
175 #else
176     psb_android_output_deinit(ctx);
177 #endif
178     /* free here, but allocate in window system specific */
179     free(driver_data->ws_priv);
180     /*
181     //use texture streaming
182     if (driver_data->ctexstreaming == 1)
183         psb_ctexstreaing_deinit(ctx);
184     */
185     /* clean the displaying surface information in kernel */
186 #ifndef _FOR_FPGA_
187     psb_surface_set_displaying(driver_data, 0, 0, NULL);
188 #endif
189     pthread_mutex_destroy(&driver_data->output_mutex);
190 
191     return VA_STATUS_SUCCESS;
192 }
193 
194 #ifndef VA_STATUS_ERROR_INVALID_IMAGE_FORMAT
195 #define VA_STATUS_ERROR_INVALID_IMAGE_FORMAT VA_STATUS_ERROR_UNKNOWN
196 #endif
197 
psb__VAImageCheckFourCC(VAImageFormat * src_format,VAImageFormat * dst_format,int dst_num)198 static VAImageFormat *psb__VAImageCheckFourCC(
199     VAImageFormat       *src_format,
200     VAImageFormat       *dst_format,
201     int                 dst_num
202 )
203 {
204     int i;
205     if (NULL == src_format || dst_format == NULL) {
206         return NULL;
207     }
208 
209     /* check VAImage at first */
210     for (i = 0; i < dst_num; i++) {
211         if (dst_format[i].fourcc == src_format->fourcc)
212             return &dst_format[i];
213     }
214 
215     drv_debug_msg(VIDEO_DEBUG_ERROR, "Unsupport fourcc 0x%x\n", src_format->fourcc);
216     return NULL;
217 }
218 
psb__VAImageCheckRegion(object_surface_p surface,VAImage * image,int * src_x,int * src_y,int * dest_x,int * dest_y,int * width,int * height)219 static void psb__VAImageCheckRegion(
220     object_surface_p surface,
221     VAImage *image,
222     int *src_x,
223     int *src_y,
224     int *dest_x,
225     int *dest_y,
226     int *width,
227     int *height
228 )
229 {
230     /* check for image */
231     if (*src_x < 0) *src_x = 0;
232     if (*src_x > image->width) *src_x = image->width - 1;
233     if (*src_y < 0) *src_y = 0;
234     if (*src_y > image->height) *src_y = image->height - 1;
235 
236     if (((*width) + (*src_x)) > image->width) *width = image->width - *src_x;
237     if (((*height) + (*src_y)) > image->height) *height = image->height - *src_x;
238 
239     /* check for surface */
240     if (*dest_x < 0) *dest_x = 0;
241     if (*dest_x > surface->width) *dest_x = surface->width - 1;
242     if (*dest_y < 0) *dest_y = 0;
243     if (*dest_y > surface->height) *dest_y = surface->height - 1;
244 
245     if (((*width) + (*dest_x)) > surface->width) *width = surface->width - *dest_x;
246     if (((*height) + (*dest_y)) > surface->height) *height = surface->height - *dest_x;
247 }
248 
249 
psb_QueryImageFormats(VADriverContextP __maybe_unused ctx,VAImageFormat * format_list,int * num_formats)250 VAStatus psb_QueryImageFormats(
251     VADriverContextP __maybe_unused ctx,
252     VAImageFormat *format_list,        /* out */
253     int *num_formats           /* out */
254 )
255 {
256     VAStatus vaStatus = VA_STATUS_SUCCESS;
257 
258     CHECK_INVALID_PARAM(format_list == NULL);
259     CHECK_INVALID_PARAM(num_formats == NULL);
260 
261     memcpy(format_list, psb__CreateImageFormat, sizeof(psb__CreateImageFormat));
262     *num_formats = PSB_MAX_IMAGE_FORMATS;
263 
264     return VA_STATUS_SUCCESS;
265 }
266 
min_POT(int n)267 inline int min_POT(int n)
268 {
269     if ((n & (n - 1)) == 0) /* already POT */
270         return n;
271 
272     return n |= n >> 16, n |= n >> 8, n |= n >> 4, n |= n >> 2, n |= n >> 1, n + 1;
273     /* return ((((n |= n>>16) |= n>>8) |= n>>4) |= n>>2) |= n>>1, n + 1; */
274 }
275 
psb_CreateImage(VADriverContextP ctx,VAImageFormat * format,int width,int height,VAImage * image)276 VAStatus psb_CreateImage(
277     VADriverContextP ctx,
278     VAImageFormat *format,
279     int width,
280     int height,
281     VAImage *image     /* out */
282 )
283 {
284     INIT_DRIVER_DATA;
285     VAImageID imageID;
286     object_image_p obj_image;
287     VAStatus vaStatus = VA_STATUS_SUCCESS;
288     VAImageFormat *img_fmt;
289     int pitch_pot;
290 
291     (void)driver_data;
292 
293     img_fmt = psb__VAImageCheckFourCC(format, psb__CreateImageFormat,
294                                       sizeof(psb__CreateImageFormat) / sizeof(VAImageFormat));
295     if (img_fmt == NULL)
296         return VA_STATUS_ERROR_UNKNOWN;
297 
298     CHECK_INVALID_PARAM(image == NULL);
299 
300     imageID = object_heap_allocate(&driver_data->image_heap);
301     obj_image = IMAGE(imageID);
302     CHECK_ALLOCATION(obj_image);
303 
304     MEMSET_OBJECT(obj_image, struct object_image_s);
305 
306     obj_image->image.image_id = imageID;
307     obj_image->image.format = *img_fmt;
308     obj_image->subpic_ref = 0;
309 
310     pitch_pot = min_POT(width);
311 
312     switch (format->fourcc) {
313     case VA_FOURCC_NV12: {
314         obj_image->image.width = width;
315         obj_image->image.height = height;
316         obj_image->image.data_size = pitch_pot * height /*Y*/ + 2 * (pitch_pot / 2) * (height / 2);/*UV*/
317         obj_image->image.num_planes = 2;
318         obj_image->image.pitches[0] = pitch_pot;
319         obj_image->image.pitches[1] = pitch_pot;
320         obj_image->image.offsets[0] = 0;
321         obj_image->image.offsets[1] = pitch_pot * height;
322         obj_image->image.num_palette_entries = 0;
323         obj_image->image.entry_bytes = 0;
324         obj_image->image.component_order[0] = 'Y';
325         obj_image->image.component_order[1] = 'U';/* fixed me: packed UV packed here! */
326         obj_image->image.component_order[2] = 'V';
327         obj_image->image.component_order[3] = '\0';
328         break;
329     }
330     case VA_FOURCC_AYUV: {
331         obj_image->image.width = width;
332         obj_image->image.height = height;
333         obj_image->image.data_size = 4 * pitch_pot * height;
334         obj_image->image.num_planes = 1;
335         obj_image->image.pitches[0] = 4 * pitch_pot;
336         obj_image->image.num_palette_entries = 0;
337         obj_image->image.entry_bytes = 0;
338         obj_image->image.component_order[0] = 'V';
339         obj_image->image.component_order[1] = 'U';
340         obj_image->image.component_order[2] = 'Y';
341         obj_image->image.component_order[3] = 'A';
342         break;
343     }
344     case VA_FOURCC_RGBA: {
345         obj_image->image.width = width;
346         obj_image->image.height = height;
347         obj_image->image.data_size = 4 * pitch_pot * height;
348         obj_image->image.num_planes = 1;
349         obj_image->image.pitches[0] = 4 * pitch_pot;
350         obj_image->image.num_palette_entries = 0;
351         obj_image->image.entry_bytes = 0;
352         obj_image->image.component_order[0] = 'R';
353         obj_image->image.component_order[1] = 'G';
354         obj_image->image.component_order[2] = 'B';
355         obj_image->image.component_order[3] = 'A';
356         break;
357     }
358     case VA_FOURCC_AI44: {
359         obj_image->image.width = width;
360         obj_image->image.height = height;
361         obj_image->image.data_size = pitch_pot * height;/* one byte one element */
362         obj_image->image.num_planes = 1;
363         obj_image->image.pitches[0] = pitch_pot;
364         obj_image->image.num_palette_entries = 16;
365         obj_image->image.entry_bytes = 4; /* AYUV */
366         obj_image->image.component_order[0] = 'I';
367         obj_image->image.component_order[1] = 'A';
368         obj_image->image.component_order[2] = '\0';
369         obj_image->image.component_order[3] = '\0';
370         break;
371     }
372     case VA_FOURCC_IYUV: {
373         obj_image->image.width = width;
374         obj_image->image.height = height;
375         obj_image->image.data_size = pitch_pot * height /*Y*/ + 2 * (pitch_pot / 2) * (height / 2);/*UV*/
376         obj_image->image.num_planes = 3;
377         obj_image->image.pitches[0] = pitch_pot;
378         obj_image->image.pitches[1] = pitch_pot / 2;
379         obj_image->image.pitches[2] = pitch_pot / 2;
380         obj_image->image.offsets[0] = 0;
381         obj_image->image.offsets[1] = pitch_pot * height;
382         obj_image->image.offsets[2] = pitch_pot * height + (pitch_pot / 2) * (height / 2);
383         obj_image->image.num_palette_entries = 0;
384         obj_image->image.entry_bytes = 0;
385         obj_image->image.component_order[0] = 'Y';
386         obj_image->image.component_order[1] = 'U';
387         obj_image->image.component_order[2] = 'V';
388         obj_image->image.component_order[3] = '\0';
389         break;
390     }
391     case VA_FOURCC_YV32: {
392         obj_image->image.width = width;
393         obj_image->image.height = height;
394         obj_image->image.data_size = 4 * pitch_pot * height;
395         obj_image->image.num_planes = 4;
396         obj_image->image.pitches[0] = pitch_pot;
397         obj_image->image.pitches[1] = pitch_pot;
398         obj_image->image.pitches[2] = pitch_pot;
399         obj_image->image.extra_pitch = pitch_pot;
400         obj_image->image.offsets[0] = 0;
401         obj_image->image.offsets[1] = pitch_pot * height;
402         obj_image->image.offsets[2] = pitch_pot * height * 2;
403         obj_image->image.extra_offset = pitch_pot * height * 3;
404         obj_image->image.num_palette_entries = 0;
405         obj_image->image.entry_bytes = 0;
406         obj_image->image.component_order[0] = 'V';
407         obj_image->image.component_order[1] = 'U';
408         obj_image->image.component_order[2] = 'Y';
409         obj_image->image.component_order[3] = 'A';
410         break;
411     }
412     default: {
413         vaStatus = VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
414         break;
415     }
416     }
417 
418     if (VA_STATUS_SUCCESS == vaStatus) {
419         /* create the buffer */
420         vaStatus = psb__CreateBuffer(driver_data, NULL, VAImageBufferType,
421                                      obj_image->image.data_size, 1, NULL, &obj_image->image.buf);
422     }
423 
424     obj_image->derived_surface = 0;
425 
426     if (VA_STATUS_SUCCESS != vaStatus) {
427         object_heap_free(&driver_data->image_heap, (object_base_p) obj_image);
428     } else {
429         memcpy(image, &obj_image->image, sizeof(VAImage));
430     }
431 
432     return vaStatus;
433 }
434 
psb_CheckIEDStatus(VADriverContextP ctx)435 static int psb_CheckIEDStatus(VADriverContextP ctx)
436 {
437     INIT_DRIVER_DATA;
438     struct drm_lnc_video_getparam_arg arg;
439     unsigned long temp;
440     int ret = 0;
441 
442     /* not settled, we get it from current HW FRAMESKIP flag */
443     arg.key = IMG_VIDEO_IED_STATE;
444     arg.value = (uint64_t)((unsigned long) & temp);
445     ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
446                               &arg, sizeof(arg));
447     if (ret == 0) {
448         if (temp == 1) {
449             drv_debug_msg(VIDEO_DEBUG_ERROR, "IED is enabled, image is encrypted.\n");
450             return 1;
451         } else {
452             return 0;
453         }
454     } else {
455         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to call IMG_VIDEO_IED_STATE.\n");
456         return -1;
457     }
458 }
459 
psb_DeriveImage(VADriverContextP ctx,VASurfaceID surface,VAImage * image)460 VAStatus psb_DeriveImage(
461     VADriverContextP ctx,
462     VASurfaceID surface,
463     VAImage *image     /* out */
464 )
465 {
466     INIT_DRIVER_DATA;
467     VAStatus vaStatus = VA_STATUS_SUCCESS;
468     VABufferID bufferID;
469     object_buffer_p obj_buffer;
470     VAImageID imageID;
471     object_image_p obj_image;
472     object_surface_p obj_surface = SURFACE(surface);
473     unsigned int fourcc, fourcc_index = ~0, i;
474     uint32_t srf_buf_ofs = 0;
475 
476     CHECK_SURFACE(obj_surface);
477     CHECK_INVALID_PARAM(image == NULL);
478     /* Can't derive image from reconstrued frame which is in tiled format */
479     if (obj_surface->is_ref_surface == 1 || obj_surface->is_ref_surface == 2) {
480 	if (getenv("PSB_VIDEO_IGNORE_TILED_FORMAT")) {
481 	    drv_debug_msg(VIDEO_DEBUG_GENERAL, "Ignore tiled memory format" \
482 			"of rec-frames\n");
483 	} else {
484 	    drv_debug_msg(VIDEO_DEBUG_ERROR, "Can't derive reference surface" \
485 			"which is tiled format\n");
486 	    return VA_STATUS_ERROR_OPERATION_FAILED;
487 	}
488     }
489 
490     if (IS_MFLD(driver_data) && (psb_CheckIEDStatus(ctx) == 1)) {
491         vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
492         return vaStatus;
493     }
494 
495     fourcc = obj_surface->psb_surface->extra_info[4];
496     for (i = 0; i < PSB_MAX_IMAGE_FORMATS; i++) {
497         if (psb__CreateImageFormat[i].fourcc == fourcc) {
498             fourcc_index = i;
499             break;
500         }
501     }
502     if (i == PSB_MAX_IMAGE_FORMATS) {
503         drv_debug_msg(VIDEO_DEBUG_ERROR, "Can't support the Fourcc\n");
504         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
505         return vaStatus;
506     }
507 
508     /* create the image */
509     imageID = object_heap_allocate(&driver_data->image_heap);
510     obj_image = IMAGE(imageID);
511     CHECK_ALLOCATION(obj_image);
512 
513     MEMSET_OBJECT(obj_image, struct object_image_s);
514 
515     /* create a buffer to represent surface buffer */
516     bufferID = object_heap_allocate(&driver_data->buffer_heap);
517     obj_buffer = BUFFER(bufferID);
518     if (NULL == obj_buffer) {
519         object_heap_free(&driver_data->image_heap, (object_base_p) obj_image);
520         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
521         DEBUG_FAILURE;
522         return vaStatus;
523     }
524     MEMSET_OBJECT(obj_buffer, struct object_buffer_s);
525 
526     obj_buffer->type = VAImageBufferType;
527     obj_buffer->buffer_data = NULL;
528     obj_buffer->psb_buffer = &obj_surface->psb_surface->buf;
529     obj_buffer->size = obj_surface->psb_surface->size;
530     obj_buffer->max_num_elements = 0;
531     obj_buffer->alloc_size = obj_buffer->size;
532 
533     /* fill obj_image data structure */
534     obj_image->image.image_id = imageID;
535     obj_image->image.format = psb__CreateImageFormat[fourcc_index];
536     obj_image->subpic_ref = 0;
537 
538     obj_image->image.buf = bufferID;
539     obj_image->image.width = obj_surface->width;
540     obj_image->image.height = obj_surface->height;
541     obj_image->image.data_size = obj_surface->psb_surface->size;
542 
543     srf_buf_ofs = obj_surface->psb_surface->buf.buffer_ofs;
544 
545     switch (fourcc) {
546     case VA_FOURCC_NV12: {
547         obj_image->image.num_planes = 2;
548         obj_image->image.pitches[0] = obj_surface->psb_surface->stride;
549         obj_image->image.pitches[1] = obj_surface->psb_surface->stride;
550 
551         obj_image->image.offsets[0] = srf_buf_ofs;
552         obj_image->image.offsets[1] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride;
553         obj_image->image.num_palette_entries = 0;
554         obj_image->image.entry_bytes = 0;
555         obj_image->image.component_order[0] = 'Y';
556         obj_image->image.component_order[1] = 'U';/* fixed me: packed UV packed here! */
557         obj_image->image.component_order[2] = 'V';
558         obj_image->image.component_order[3] = '\0';
559         break;
560     }
561     case VA_FOURCC_YV16: {
562         obj_image->image.num_planes = 3;
563         obj_image->image.pitches[0] = obj_surface->psb_surface->stride;
564         obj_image->image.pitches[1] = obj_surface->psb_surface->stride / 2;
565         obj_image->image.pitches[2] = obj_surface->psb_surface->stride / 2;
566 
567         obj_image->image.offsets[0] = srf_buf_ofs;
568         obj_image->image.offsets[1] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride;
569         obj_image->image.offsets[2] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride * 3 / 2;
570         obj_image->image.num_palette_entries = 0;
571         obj_image->image.entry_bytes = 0;
572         obj_image->image.component_order[0] = 'Y';
573         obj_image->image.component_order[1] = 'V';/* fixed me: packed UV packed here! */
574         obj_image->image.component_order[2] = 'U';
575         obj_image->image.component_order[3] = '\0';
576         break;
577     }
578     case VA_FOURCC_YV32: {
579         obj_image->image.num_planes = 3;
580         obj_image->image.pitches[0] = obj_surface->psb_surface->stride;
581         obj_image->image.pitches[1] = obj_surface->psb_surface->stride;
582         obj_image->image.pitches[2] = obj_surface->psb_surface->stride;
583 
584         obj_image->image.offsets[0] = srf_buf_ofs;
585         obj_image->image.offsets[1] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride;
586         obj_image->image.offsets[2] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride * 2;
587         obj_image->image.num_palette_entries = 0;
588         obj_image->image.entry_bytes = 0;
589         obj_image->image.component_order[0] = 'Y';
590         obj_image->image.component_order[1] = 'U';/* fixed me: packed UV packed here! */
591         obj_image->image.component_order[2] = 'V';
592         obj_image->image.component_order[3] = '\0';
593         break;
594     }
595     default:
596         break;
597     }
598 
599     obj_image->derived_surface = surface; /* this image is derived from a surface */
600     obj_surface->derived_imgcnt++;
601 
602     memcpy(image, &obj_image->image, sizeof(VAImage));
603 
604     return vaStatus;
605 }
606 
psb__destroy_image(psb_driver_data_p driver_data,object_image_p obj_image)607 VAStatus psb__destroy_image(psb_driver_data_p driver_data, object_image_p obj_image)
608 {
609     VAStatus vaStatus = VA_STATUS_SUCCESS;
610 
611     if (obj_image->subpic_ref > 0) {
612         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
613         return vaStatus;
614     }
615 
616     object_surface_p obj_surface = SURFACE(obj_image->derived_surface);
617 
618     if (obj_surface == NULL) { /* destroy the buffer */
619         object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
620         CHECK_BUFFER(obj_buffer);
621         psb__suspend_buffer(driver_data, obj_buffer);
622     } else {
623         object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
624         object_heap_free(&driver_data->buffer_heap, &obj_buffer->base);
625         obj_surface->derived_imgcnt--;
626     }
627     object_heap_free(&driver_data->image_heap, (object_base_p) obj_image);
628 
629     return VA_STATUS_SUCCESS;
630 }
631 
psb_DestroyImage(VADriverContextP ctx,VAImageID image)632 VAStatus psb_DestroyImage(
633     VADriverContextP ctx,
634     VAImageID image
635 )
636 {
637     INIT_DRIVER_DATA
638     VAStatus vaStatus = VA_STATUS_SUCCESS;
639     object_image_p obj_image;
640 
641     obj_image = IMAGE(image);
642     CHECK_IMAGE(obj_image);
643     return psb__destroy_image(driver_data, obj_image);
644 }
645 
psb_SetImagePalette(VADriverContextP ctx,VAImageID image,unsigned char * palette)646 VAStatus psb_SetImagePalette(
647     VADriverContextP ctx,
648     VAImageID image,
649     /*
650      * pointer to an array holding the palette data.  The size of the array is
651      * num_palette_entries * entry_bytes in size.  The order of the components
652      * in the palette is described by the component_order in VAImage struct
653      */
654     unsigned char *palette
655 )
656 {
657     INIT_DRIVER_DATA;
658     VAStatus vaStatus = VA_STATUS_SUCCESS;
659 
660     object_image_p obj_image = IMAGE(image);
661     CHECK_IMAGE(obj_image);
662 
663     if (obj_image->image.format.fourcc != VA_FOURCC_AI44) {
664         /* only support AI44 palette */
665         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
666         return vaStatus;
667     }
668 
669     if (obj_image->image.num_palette_entries > 16) {
670         drv_debug_msg(VIDEO_DEBUG_ERROR, "image.num_palette_entries(%d) is too big\n", obj_image->image.num_palette_entries);
671         memcpy(obj_image->palette, palette, 16);
672     } else
673         memcpy(obj_image->palette, palette, obj_image->image.num_palette_entries * sizeof(unsigned int));
674 
675     return vaStatus;
676 }
677 
lnc_unpack_topaz_rec(int src_width,int src_height,unsigned char * p_srcY,unsigned char * p_srcUV,unsigned char * p_dstY,unsigned char * p_dstU,unsigned char * p_dstV,int dstY_stride,int dstU_stride,int dstV_stride,int surface_height)678 static VAStatus lnc_unpack_topaz_rec(int src_width, int src_height,
679                                      unsigned char *p_srcY, unsigned char *p_srcUV,
680                                      unsigned char *p_dstY, unsigned char *p_dstU, unsigned char *p_dstV,
681                                      int dstY_stride, int dstU_stride, int dstV_stride,
682                                      int surface_height)
683 {
684     unsigned char *tmp_dstY = NULL;
685     unsigned char *tmp_dstUV = NULL;
686 
687     int n, i, index;
688 
689     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Unpack reconstructed frame to image\n");
690 
691     /* do this one column at a time. */
692     tmp_dstY = (unsigned char *)calloc(1, 16 * src_height);
693     if (tmp_dstY == NULL)
694         return  VA_STATUS_ERROR_ALLOCATION_FAILED;
695 
696     tmp_dstUV = (unsigned char*)calloc(1, 16 * src_height / 2);
697     if (tmp_dstUV == NULL) {
698         free(tmp_dstY);
699         return VA_STATUS_ERROR_ALLOCATION_FAILED;
700     }
701 
702     /*  Copy Y data */
703     for (n = 0; n < src_width / 16; n++) {
704         memcpy((void*)tmp_dstY, p_srcY, 16 * src_height);
705         p_srcY += (16 * surface_height);
706         for (i = 0; i < src_height; i++) {
707             memcpy(p_dstY + dstY_stride * i + n * 16, tmp_dstY + 16 * i, 16);
708         }
709     }
710 
711     /* Copy U/V data */
712     for (n = 0; n < src_width / 16; n++) {
713         memcpy((void*)tmp_dstUV, p_srcUV, 16 * src_height / 2);
714         p_srcUV += (16 * surface_height / 2);
715         for (i = 0; i < src_height / 2; i++) {
716             for (index = 0; index < 8; index++) {
717                 p_dstU[i*dstU_stride + n*8 + index] = tmp_dstUV[index*2 + i*16];
718                 p_dstV[i*dstV_stride + n*8 + index] = tmp_dstUV[index*2 + i*16+1];
719             }
720         }
721     }
722     if (tmp_dstY)
723         free(tmp_dstY);
724     if (tmp_dstUV)
725         free(tmp_dstUV);
726 
727     return VA_STATUS_SUCCESS;
728 }
729 
730 /*
731 * Convert the memroy format from tiled to linear
732 */
tng_unpack_vsp_rec(int src_width,int src_height,unsigned char * p_srcY,unsigned char * p_srcUV,unsigned char * p_dstY,unsigned char * p_dstU,int dstY_stride,int dstU_stride,int __maybe_unused dstV_stride,int __maybe_unused surface_height)733 static VAStatus tng_unpack_vsp_rec(
734     int src_width, int src_height,
735     unsigned char *p_srcY, unsigned char *p_srcUV,
736     unsigned char *p_dstY, unsigned char *p_dstU,
737     int dstY_stride, int dstU_stride, int __maybe_unused dstV_stride,
738     int __maybe_unused surface_height)
739 {
740     unsigned char *tmp_dstY = p_dstY;
741     unsigned char *tmp_dstU = p_dstU;
742 
743     int n, t,x,y;
744 
745    //"	Y_address(x,y) =    Y_base + (((H            +64+63)/64) * (x/64) + (y/64))*4096 + (y%64)*64 + (x%64)
746    //"	U_address(x,y) = UV_base + ((((H+1)/2+32+63)/64) * (x/32) + (y/64))*4096 + (y%64)*64 + (x%32)*2
747    //"	V_address(x,y) = UV_base + ((((H+1)/2+32+63)/64) * (x/32) + (y/64))*4096 + (y%64)*64 + (x%32)*2 + 1
748 
749     /*  Copy Y data */
750     for (y = 32; y < src_height + 32; y++) {
751         for (x= 32;x < src_width + 32; x++) {
752             * tmp_dstY++ =  *(p_srcY + (((src_height+64+63)/64) * (x/64) + (y/64))*4096 + (y%64)*64 + (x%64));
753             }
754             tmp_dstY += dstY_stride - src_width;
755     }
756 
757     /*  Copy UV data */
758     for (y = 16; y < 16 + ((src_height+1)>>1) ; y++) {
759         for (x= 16;x < 16 + ( (src_width+1)>>1); x++) {
760             * tmp_dstU++ = * (p_srcUV + ((((src_height+1)/2+32+63)/64) * (x/32) + (y/64))*4096 + (y%64)*64 + (x%32)*2);
761             * tmp_dstU++ = * (p_srcUV + ((((src_height+1)/2+32+63)/64) * (x/32) + (y/64))*4096 + (y%64)*64 + (x%32)*2 +1);
762             }
763            tmp_dstU += dstU_stride - ((src_width));
764     }
765 
766     return VA_STATUS_SUCCESS;
767 }
768 /*
769 * Convert the memroy format from tiled to linear
770 */
tng_unpack_topaz_rec(int src_width,int src_height,unsigned char * p_srcY,unsigned char * p_srcUV,unsigned char * p_dstY,unsigned char * p_dstU,unsigned char * p_dstV,int dstY_stride,int __maybe_unused dstU_stride,int __maybe_unused dstV_stride,int __maybe_unused surface_height)771 static VAStatus tng_unpack_topaz_rec(
772     int src_width, int src_height,
773     unsigned char *p_srcY, unsigned char *p_srcUV,
774     unsigned char *p_dstY, unsigned char *p_dstU, unsigned char *p_dstV,
775     int dstY_stride, int __maybe_unused dstU_stride, int __maybe_unused dstV_stride,
776     int __maybe_unused surface_height)
777 {
778     unsigned char *tmp_dstY = p_dstY;
779     unsigned char *tmp_dstU = p_dstU;
780     unsigned char *tmp_dstV = p_dstV;
781     unsigned char *tmp_srcY = p_srcY;
782     unsigned char *tmp_srcX = p_srcUV;
783 
784     int i, j, n, t;
785     int mb_src_y_w = src_width >> 4;
786     int mb_src_y_h = src_height >> 5;
787     int mb_src_y_p = src_height - (mb_src_y_h << 5);
788 
789     /*  Copy Y data */
790     for (j = 0; j < mb_src_y_h; j++) {
791         tmp_dstY = p_dstY + j * dstY_stride * 32;
792         for (i = 0; i < mb_src_y_w; i++) {
793             for (n = 0; n < 32; n++) {
794                 memcpy(tmp_dstY + dstY_stride * n, tmp_srcY,16);
795                 tmp_srcY += 16;
796             }
797             tmp_dstY += 16;
798         }
799     }
800 
801     if(mb_src_y_p != 0) {
802         tmp_dstY = p_dstY + j * dstY_stride * 32;
803         for (i = 0; i < mb_src_y_w; i++) {
804             for (n = 0; n < mb_src_y_p; n++) {
805                 memcpy(tmp_dstY + dstY_stride * n, tmp_srcY,16);
806                 tmp_srcY += 16;
807             }
808             for (; n < 32; n++) {
809                 tmp_srcY += 16;
810             }
811             tmp_dstY += 16;
812         }
813     }
814 
815     for (j = 0; j < mb_src_y_h; j++) {
816         tmp_dstU = p_dstU + j * dstY_stride * 16;
817         for (i = 0; i < mb_src_y_w; i++) {
818             for (n = 0; n < 16; n++) {
819                 for (t = 0; t < 16; t++) {
820                     tmp_dstU[(n * dstY_stride) + t] = tmp_srcX[t];
821                 }
822                 tmp_srcX += 16;
823             }
824             tmp_dstU += 16;
825         }
826     }
827     mb_src_y_p >>= 1;
828     if(mb_src_y_p != 0) {
829         tmp_dstU = p_dstU + j * dstY_stride * 16;
830         for (i = 0; i < mb_src_y_w; i++) {
831             for (n = 0; n < mb_src_y_p; n++) {
832                 for (t = 0; t < 16; t++) {
833                    tmp_dstU[(n * dstY_stride) + t] = tmp_srcX[t];
834                 }
835                 tmp_srcX += 16;
836             }
837 
838             for (; n < 16; n++) {
839                 tmp_srcX += 16;
840             }
841 
842             tmp_dstU += 16;
843         }
844     }
845 
846     return VA_STATUS_SUCCESS;
847 }
848 
psb_GetImage(VADriverContextP ctx,VASurfaceID surface,int x,int y,unsigned int width,unsigned int height,VAImageID image_id)849 VAStatus psb_GetImage(
850     VADriverContextP ctx,
851     VASurfaceID surface,
852     int x,     /* coordinates of the upper left source pixel */
853     int y,
854     unsigned int width, /* width and height of the region */
855     unsigned int height,
856     VAImageID image_id
857 )
858 {
859     INIT_DRIVER_DATA;
860     VAStatus vaStatus = VA_STATUS_SUCCESS;
861     int ret, src_x = 0, src_y = 0, dest_x = 0, dest_y = 0;
862 
863     (void)driver_data;
864     (void)lnc_unpack_topaz_rec;
865 
866     object_image_p obj_image = IMAGE(image_id);
867     CHECK_IMAGE(obj_image);
868 
869     if (IS_MFLD(driver_data) && (psb_CheckIEDStatus(ctx) == 1)) {
870         vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
871         return vaStatus;
872     }
873 
874     if (obj_image->image.format.fourcc != VA_FOURCC_NV12) {
875         drv_debug_msg(VIDEO_DEBUG_ERROR, "target VAImage fourcc should be NV12 or IYUV\n");
876         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
877         return vaStatus;
878     }
879 
880     object_surface_p obj_surface = SURFACE(surface);
881     CHECK_SURFACE(obj_surface);
882 
883     psb__VAImageCheckRegion(obj_surface, &obj_image->image, &src_x, &src_y, &dest_x, &dest_y,
884                             (int *)&width, (int *)&height);
885 
886     psb_surface_p psb_surface = obj_surface->psb_surface;
887     unsigned char *surface_data;
888     ret = psb_buffer_map(&psb_surface->buf, &surface_data);
889     if (ret) {
890         return VA_STATUS_ERROR_UNKNOWN;
891     }
892 
893     object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
894     CHECK_BUFFER(obj_buffer);
895 
896     unsigned char *image_data;
897     ret = psb_buffer_map(obj_buffer->psb_buffer, &image_data);
898     if (ret) {
899         drv_debug_msg(VIDEO_DEBUG_ERROR, "Map buffer failed\n");
900 
901         psb_buffer_unmap(&psb_surface->buf);
902         return VA_STATUS_ERROR_UNKNOWN;
903     }
904 
905 
906     image_data += obj_surface->psb_surface->buf.buffer_ofs;
907 
908 
909     switch (obj_image->image.format.fourcc) {
910     case VA_FOURCC_NV12: {
911         unsigned char *src_y, *src_uv, *dst_y, *dst_uv;
912 	unsigned char *dst_u, *dst_v;
913         unsigned int i;
914 
915 	/*
916 	 * For reconstructed frame, tiled to linear conversion
917 	 * must be done.
918 	*/
919 	if (obj_surface->is_ref_surface == 1) {
920 	    src_y = surface_data + y * psb_surface->stride + x;
921 	    src_uv = surface_data + ((height + 0x1f) & (~0x1f)) * width;
922 
923 	    dst_y = image_data;
924 	    dst_u = image_data + obj_image->image.offsets[1],
925 	    dst_v = dst_u + (height * width) / 4;
926 
927 	    tng_unpack_topaz_rec(width, height, \
928 				 src_y, src_uv, \
929 			         dst_y, dst_u, dst_v, \
930 			         obj_image->image.pitches[0], \
931 			         obj_image->image.width / 2, \
932 			         obj_image->image.width / 2, \
933 			         obj_surface->height);
934 	} else if (obj_surface->is_ref_surface == 2) {
935 	    src_y = surface_data + y * psb_surface->stride + x;
936 	    src_uv = surface_data + ((height + 2*32 + 63)/64*64) * ((width  + 2*32 + 63)/64*64);
937 	    dst_y = image_data;
938 	    dst_u = image_data +  obj_image->image.offsets[1];
939 
940 	    tng_unpack_vsp_rec(width, height, \
941 				 src_y, src_uv, \
942 			         dst_y, dst_u, \
943 			         obj_image->image.pitches[0], \
944 			         obj_image->image.pitches[1], \
945 			         obj_image->image.pitches[1], \
946 			         obj_surface->height);
947 	} else{
948             /* copy Y plane */
949             dst_y = image_data;
950             src_y = surface_data + y * psb_surface->stride + x;
951             for (i = 0; i < height; i++)  {
952 		memcpy(dst_y, src_y, width);
953 		dst_y += obj_image->image.pitches[0];
954 		src_y += psb_surface->stride;
955             }
956 
957 	    /* copy UV plane */
958 	    dst_uv = image_data + obj_image->image.offsets[1];
959             src_uv = surface_data + psb_surface->stride * obj_surface->height + (y / 2) * psb_surface->stride + x;;
960             for (i = 0; i < obj_image->image.height / 2; i++) {
961 		memcpy(dst_uv, src_uv, width);
962 		dst_uv += obj_image->image.pitches[1];
963 		src_uv += psb_surface->stride;
964 	    }
965 	}
966         break;
967     }
968 #if 0
969     case VA_FOURCC_IYUV: {
970         unsigned char *source_y, *dst_y;
971         unsigned char *source_uv, *source_u, *source_v, *dst_u, *dst_v;
972         unsigned int i;
973 
974         if (psb_surface->extra_info[4] == VA_FOURCC_IREC) {
975             /* copy Y plane */
976             dst_y = image_data + obj_image->image.offsets[0] + src_y * obj_image->image.pitches[0] + src_x;
977             dst_u = image_data + obj_image->image.offsets[1] + src_y * obj_image->image.pitches[1] + src_x;
978             dst_v = image_data + obj_image->image.offsets[2] + src_y * obj_image->image.pitches[2] + src_x;
979 
980             source_y = surface_data + dest_y * psb_surface->stride + dest_x;
981             source_uv = surface_data + obj_surface->height * psb_surface->stride
982                         + dest_y * (psb_surface->stride / 2) + dest_x;
983 
984             vaStatus = lnc_unpack_topaz_rec(width, height, source_y, source_uv,
985                                             dst_y, dst_u, dst_v,
986                                             obj_image->image.pitches[0],
987                                             obj_image->image.pitches[1],
988                                             obj_image->image.pitches[2],
989                                             obj_surface->height);
990         }
991 
992         break;
993     }
994 #endif
995     default:
996         break;
997     }
998     psb_buffer_unmap(obj_buffer->psb_buffer);
999     psb_buffer_unmap(&psb_surface->buf);
1000 
1001     return vaStatus;
1002 }
1003 
psb_PutImage2(VADriverContextP ctx,VASurfaceID surface,VAImageID image_id,int src_x,int src_y,unsigned int width,unsigned int height,int dest_x,int dest_y)1004 static VAStatus psb_PutImage2(
1005     VADriverContextP ctx,
1006     VASurfaceID surface,
1007     VAImageID image_id,
1008     int src_x,
1009     int src_y,
1010     unsigned int width,
1011     unsigned int height,
1012     int dest_x,
1013     int dest_y
1014 )
1015 {
1016     INIT_DRIVER_DATA;
1017     VAStatus vaStatus = VA_STATUS_SUCCESS;
1018     int ret;
1019 
1020     object_image_p obj_image = IMAGE(image_id);
1021     CHECK_IMAGE(obj_image);
1022 
1023     object_surface_p obj_surface = SURFACE(surface);
1024     CHECK_SURFACE(obj_surface);
1025 
1026     if (obj_image->image.format.fourcc != VA_FOURCC_NV12) {
1027         drv_debug_msg(VIDEO_DEBUG_ERROR, "target VAImage fourcc should be NV12 or IYUV\n");
1028         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
1029         return vaStatus;
1030     }
1031 
1032     psb__VAImageCheckRegion(obj_surface, &obj_image->image, &src_x, &src_y, &dest_x, &dest_y,
1033                             (int *)&width, (int *)&height);
1034 
1035     psb_surface_p psb_surface = obj_surface->psb_surface;
1036     unsigned char *surface_data;
1037     ret = psb_buffer_map(&psb_surface->buf, &surface_data);
1038     if (ret) {
1039         return VA_STATUS_ERROR_UNKNOWN;
1040     }
1041 
1042     object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
1043     CHECK_BUFFER(obj_buffer);
1044 
1045     unsigned char *image_data;
1046     ret = psb_buffer_map(obj_buffer->psb_buffer, &image_data);
1047     if (ret) {
1048         psb_buffer_unmap(&psb_surface->buf);
1049         return VA_STATUS_ERROR_UNKNOWN;
1050     }
1051 
1052     image_data += obj_surface->psb_surface->buf.buffer_ofs;
1053 
1054     switch (obj_image->image.format.fourcc) {
1055     case VA_FOURCC_NV12: {
1056         unsigned char *source_y, *src_uv, *dst_y, *dst_uv;
1057         unsigned int i;
1058 
1059         /* copy Y plane */
1060         source_y = image_data + obj_image->image.offsets[0] + src_y * obj_image->image.pitches[0] + src_x;
1061         dst_y = surface_data + dest_y * psb_surface->stride + dest_x;
1062         for (i = 0; i < height; i++)  {
1063             memcpy(dst_y, source_y, width);
1064             source_y += obj_image->image.pitches[0];
1065             dst_y += psb_surface->stride;
1066         }
1067 
1068         /* copy UV plane */
1069         src_uv = image_data + obj_image->image.offsets[1] + (src_y / 2) * obj_image->image.pitches[1] + src_x;
1070         dst_uv = surface_data + psb_surface->stride * obj_surface->height + (dest_y / 2) * psb_surface->stride + dest_x;
1071         for (i = 0; i < obj_image->image.height / 2; i++) {
1072             memcpy(dst_uv, src_uv, width);
1073             src_uv += obj_image->image.pitches[1];
1074             dst_uv += psb_surface->stride;
1075         }
1076         break;
1077     }
1078 #if 0
1079     case VA_FOURCC_IYUV: {
1080         char *source_y, *dst_y;
1081         char *source_u, *source_v, *dst_u, *dst_v;
1082         unsigned int i;
1083 
1084         /* copy Y plane */
1085         source_y = image_data + obj_image->image.offsets[0] + src_y * obj_image->image.pitches[0] + src_x;
1086         source_u = image_data + obj_image->image.offsets[1] + src_y * obj_image->image.pitches[1] + src_x;
1087         source_v = image_data + obj_image->image.offsets[2] + src_y * obj_image->image.pitches[2] + src_x;
1088 
1089         dst_y = surface_data + dest_y * psb_surface->stride + dest_x;
1090         dst_u = surface_data + obj_surface->height * psb_surface->stride
1091                 + dest_y * (psb_surface->stride / 2) + dest_x;
1092         dst_v = surface_data + obj_surface->height * psb_surface->stride
1093                 + (obj_surface->height / 2) * (psb_surface->stride / 2)
1094                 + dest_y * (psb_surface->stride / 2) + dest_x;
1095 
1096         for (i = 0; i < height; i++)  {
1097             memcpy(dst_y, source_y, width);
1098             source_y += obj_image->image.pitches[0];
1099             dst_y += psb_surface->stride;
1100         }
1101 
1102         /* copy UV plane */
1103         for (i = 0; i < obj_image->image.height / 2; i++) {
1104             memcpy(dst_u, source_u, width);
1105             memcpy(dst_v, source_v, width);
1106 
1107             source_u += obj_image->image.pitches[1];
1108             source_v += obj_image->image.pitches[2];
1109 
1110             dst_u += psb_surface->stride / 2;
1111             dst_v += psb_surface->stride / 2;
1112         }
1113         break;
1114     }
1115 #endif
1116     default:
1117         break;
1118     }
1119 
1120     psb_buffer_unmap(obj_buffer->psb_buffer);
1121     psb_buffer_unmap(&psb_surface->buf);
1122 
1123     return VA_STATUS_SUCCESS;
1124 }
1125 
1126 
psb__VAImageCheckRegion2(object_surface_p surface,VAImage * image,int * src_x,int * src_y,unsigned int * src_width,unsigned int * src_height,int * dest_x,int * dest_y,int * dest_width,int * dest_height)1127 static void psb__VAImageCheckRegion2(
1128     object_surface_p surface,
1129     VAImage *image,
1130     int *src_x,
1131     int *src_y,
1132     unsigned int *src_width,
1133     unsigned int *src_height,
1134     int *dest_x,
1135     int *dest_y,
1136     int *dest_width,
1137     int *dest_height
1138 )
1139 {
1140     /* check for image */
1141     if (*src_x < 0) *src_x = 0;
1142     if (*src_x > image->width) *src_x = image->width - 1;
1143     if (*src_y < 0) *src_y = 0;
1144     if (*src_y > image->height) *src_y = image->height - 1;
1145 
1146     if (((*src_width) + (*src_x)) > image->width) *src_width = image->width - *src_x;
1147     if (((*src_height) + (*src_y)) > image->height) *src_height = image->height - *src_x;
1148 
1149     /* check for surface */
1150     if (*dest_x < 0) *dest_x = 0;
1151     if (*dest_x > surface->width) *dest_x = surface->width - 1;
1152     if (*dest_y < 0) *dest_y = 0;
1153     if (*dest_y > surface->height) *dest_y = surface->height - 1;
1154 
1155     if (((*dest_width) + (*dest_x)) > (int)surface->width) *dest_width = surface->width - *dest_x;
1156     if (((*dest_height) + (*dest_y)) > (int)surface->height) *dest_height = surface->height - *dest_x;
1157 }
1158 
psb_PutImage(VADriverContextP ctx,VASurfaceID surface,VAImageID image_id,int src_x,int src_y,unsigned int src_width,unsigned int src_height,int dest_x,int dest_y,unsigned int dest_width,unsigned int dest_height)1159 VAStatus psb_PutImage(
1160     VADriverContextP ctx,
1161     VASurfaceID surface,
1162     VAImageID image_id,
1163     int src_x,
1164     int src_y,
1165     unsigned int src_width,
1166     unsigned int src_height,
1167     int dest_x,
1168     int dest_y,
1169     unsigned int dest_width,
1170     unsigned int dest_height
1171 )
1172 {
1173     INIT_DRIVER_DATA;
1174     VAStatus vaStatus = VA_STATUS_SUCCESS;
1175     int ret;
1176     CHECK_INVALID_PARAM(((int)src_width == -1) ||
1177                         ((int)src_height == -1) ||
1178                         ((int)dest_width == ~0) ||
1179                         ((int)dest_height == ~0));
1180 
1181     if ((src_width == dest_width) && (src_height == dest_height)) {
1182         /* Shortcut if scaling is not required */
1183         return psb_PutImage2(ctx, surface, image_id, src_x, src_y, src_width, src_height, dest_x, dest_y);
1184     }
1185 
1186     object_image_p obj_image = IMAGE(image_id);
1187     CHECK_IMAGE(obj_image);
1188 
1189     if (obj_image->image.format.fourcc != VA_FOURCC_NV12) {
1190         /* only support NV12 getImage/putImage */
1191         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
1192         return vaStatus;
1193     }
1194 
1195     object_surface_p obj_surface = SURFACE(surface);
1196     CHECK_SURFACE(obj_surface);
1197 
1198     psb__VAImageCheckRegion2(obj_surface, &obj_image->image,
1199                              &src_x, &src_y, &src_width, &src_height,
1200                              &dest_x, &dest_y, (int *)&dest_width, (int *)&dest_height);
1201 
1202     psb_surface_p psb_surface = obj_surface->psb_surface;
1203     unsigned char *surface_data;
1204     ret = psb_buffer_map(&psb_surface->buf, &surface_data);
1205     if (ret) {
1206         return VA_STATUS_ERROR_UNKNOWN;
1207     }
1208 
1209     object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
1210     CHECK_BUFFER(obj_buffer);
1211 
1212     unsigned char *image_data;
1213     ret = psb_buffer_map(obj_buffer->psb_buffer, &image_data);
1214     if (ret) {
1215         psb_buffer_unmap(&psb_surface->buf);
1216         return VA_STATUS_ERROR_UNKNOWN;
1217     }
1218 
1219     /* just a prototype, the algorithm is ugly and not optimized */
1220     switch (obj_image->image.format.fourcc) {
1221     case VA_FOURCC_NV12: {
1222         unsigned char *source_y, *dst_y;
1223         unsigned short *source_uv, *dst_uv;
1224         unsigned int i, j;
1225         float xratio = (float) src_width / dest_width;
1226         float yratio = (float) src_height / dest_height;
1227 
1228         /* dst_y/dst_uv: Y/UV plane of destination */
1229         dst_y = (unsigned char *)(surface_data + dest_y * psb_surface->stride + dest_x);
1230         dst_uv = (unsigned short *)(surface_data + psb_surface->stride * obj_surface->height
1231                                     + (dest_y / 2) * psb_surface->stride + dest_x);
1232 
1233         for (j = 0; j < dest_height; j++)  {
1234             unsigned char *dst_y_tmp = dst_y;
1235             unsigned short *dst_uv_tmp = dst_uv;
1236 
1237             for (i = 0; i < dest_width; i++)  {
1238                 int x = (int)(i * xratio);
1239                 int y = (int)(j * yratio);
1240 
1241                 source_y = image_data + obj_image->image.offsets[0]
1242                            + (src_y + y) * obj_image->image.pitches[0]
1243                            + (src_x + x);
1244                 *dst_y_tmp = *source_y;
1245                 dst_y_tmp++;
1246 
1247                 if (((i & 1) == 0)) {
1248                     source_uv = (unsigned short *)(image_data + obj_image->image.offsets[1]
1249                                                    + ((src_y + y) / 2) * obj_image->image.pitches[1])
1250                                 + ((src_x + x) / 2);
1251                     *dst_uv_tmp = *source_uv;
1252                     dst_uv_tmp++;
1253                 }
1254             }
1255             dst_y += psb_surface->stride;
1256 
1257             if (j & 1)
1258                 dst_uv = (unsigned short *)((unsigned char *)dst_uv + psb_surface->stride);
1259         }
1260         break;
1261     }
1262     default:/* will not reach here */
1263         break;
1264     }
1265 
1266     psb_buffer_unmap(obj_buffer->psb_buffer);
1267     psb_buffer_unmap(&psb_surface->buf);
1268 
1269     return VA_STATUS_SUCCESS;
1270 }
1271 
1272 /*
1273  * Link supbicture into one surface, when update is zero, not need to
1274  * update the location information
1275  * The image informatio and its BO of subpicture will copied to surface
1276  * so need to update it when a vaSetSubpictureImage is called
1277  */
psb__LinkSubpictIntoSurface(psb_driver_data_p driver_data,object_surface_p obj_surface,object_subpic_p obj_subpic,short src_x,short src_y,unsigned short src_w,unsigned short src_h,short dest_x,short dest_y,unsigned short dest_w,unsigned short dest_h,int update)1278 static VAStatus psb__LinkSubpictIntoSurface(
1279     psb_driver_data_p driver_data,
1280     object_surface_p obj_surface,
1281     object_subpic_p obj_subpic,
1282     short src_x,
1283     short src_y,
1284     unsigned short src_w,
1285     unsigned short src_h,
1286     short dest_x,
1287     short dest_y,
1288     unsigned short dest_w,
1289     unsigned short dest_h,
1290     int update /* update subpicture location */
1291 )
1292 {
1293     PsbVASurfaceRec *surface_subpic;
1294     object_image_p obj_image = IMAGE(obj_subpic->image_id);
1295     if (NULL == obj_image) {
1296         return VA_STATUS_ERROR_INVALID_IMAGE;
1297     }
1298 
1299     VAImage *image = &obj_image->image;
1300     object_buffer_p obj_buffer = BUFFER(image->buf);
1301     if (NULL == obj_buffer) {
1302         return VA_STATUS_ERROR_INVALID_BUFFER;
1303     }
1304 
1305     int found = 0;
1306 
1307     if (obj_surface->subpictures != NULL) {
1308         surface_subpic = (PsbVASurfaceRec *)obj_surface->subpictures;
1309         do {
1310             if (surface_subpic->subpic_id == obj_subpic->subpic_id) {
1311                 found = 1;
1312                 break;
1313             } else
1314                 surface_subpic = surface_subpic->next;
1315         } while (surface_subpic);
1316     }
1317 
1318     if (found == 0) { /* new node */
1319         if (obj_surface->subpic_count >= PSB_SUBPIC_MAX_NUM) {
1320             drv_debug_msg(VIDEO_DEBUG_ERROR, "can't support so many sub-pictures for the surface\n");
1321             return VA_STATUS_ERROR_UNKNOWN;
1322         }
1323 
1324         surface_subpic = (PsbVASurfaceRec *)calloc(1, sizeof(*surface_subpic));
1325         if (NULL == surface_subpic)
1326             return VA_STATUS_ERROR_ALLOCATION_FAILED;
1327     }
1328 
1329     surface_subpic->subpic_id = obj_subpic->subpic_id;
1330     surface_subpic->fourcc = image->format.fourcc;
1331     surface_subpic->size = image->data_size;
1332     surface_subpic->bo = obj_buffer->psb_buffer->drm_buf;
1333     surface_subpic->bufid = wsbmKBufHandle(wsbmKBuf(obj_buffer->psb_buffer->drm_buf));
1334     surface_subpic->pl_flags = obj_buffer->psb_buffer->pl_flags;
1335     surface_subpic->subpic_flags = obj_subpic->flags;
1336 
1337     surface_subpic->width = image->width;
1338     surface_subpic->height = image->height;
1339     switch (surface_subpic->fourcc) {
1340     case VA_FOURCC_AYUV:
1341         surface_subpic->stride = image->pitches[0] / 4;
1342         break;
1343     case VA_FOURCC_RGBA:
1344         surface_subpic->stride = image->pitches[0] / 4;
1345         break;
1346     case VA_FOURCC_AI44:
1347         surface_subpic->stride = image->pitches[0];
1348         /* point to Image palette */
1349         surface_subpic->palette_ptr = (PsbAYUVSample8 *) & obj_image->palette[0];
1350         break;
1351     }
1352 
1353     if (update) {
1354         surface_subpic->subpic_srcx = src_x;
1355         surface_subpic->subpic_srcy = src_y;
1356         surface_subpic->subpic_dstx = dest_x;
1357         surface_subpic->subpic_dsty = dest_y;
1358         surface_subpic->subpic_srcw = src_w;
1359         surface_subpic->subpic_srch = src_h;
1360         surface_subpic->subpic_dstw = dest_w;
1361         surface_subpic->subpic_dsth = dest_h;
1362     }
1363 
1364     if (found == 0) { /* new node, link into the list */
1365         if (NULL == obj_surface->subpictures) {
1366             obj_surface->subpictures = (void *)surface_subpic;
1367         } else { /* insert as the head */
1368             surface_subpic->next = (PsbVASurfacePtr)obj_surface->subpictures;
1369             obj_surface->subpictures = (void *)surface_subpic;
1370         }
1371         obj_surface->subpic_count++;
1372     }
1373 
1374     return VA_STATUS_SUCCESS;
1375 }
1376 
1377 
psb__LinkSurfaceIntoSubpict(object_subpic_p obj_subpic,VASurfaceID surface_id)1378 static VAStatus psb__LinkSurfaceIntoSubpict(
1379     object_subpic_p obj_subpic,
1380     VASurfaceID surface_id
1381 )
1382 {
1383     subpic_surface_s *subpic_surface;
1384     int found = 0;
1385 
1386     if (obj_subpic->surfaces != NULL) {
1387         subpic_surface = (subpic_surface_s *)obj_subpic->surfaces;
1388         do  {
1389             if (subpic_surface->surface_id == surface_id) {
1390                 found = 1;
1391                 return VA_STATUS_SUCCESS; /* reture directly */
1392             } else
1393                 subpic_surface = subpic_surface->next;
1394         } while (subpic_surface);
1395     }
1396 
1397     /* not found */
1398     subpic_surface = (subpic_surface_s *)calloc(1, sizeof(*subpic_surface));
1399     if (NULL == subpic_surface)
1400         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1401 
1402     subpic_surface->surface_id = surface_id;
1403     subpic_surface->next = NULL;
1404 
1405     if (NULL == obj_subpic->surfaces) {
1406         obj_subpic->surfaces = (void *)subpic_surface;
1407     } else { /* insert as the head */
1408         subpic_surface->next = (subpic_surface_p)obj_subpic->surfaces;
1409         obj_subpic->surfaces = (void *)subpic_surface;
1410     }
1411 
1412     return VA_STATUS_SUCCESS;
1413 }
1414 
psb__DelinkSubpictFromSurface(object_surface_p obj_surface,VASubpictureID subpic_id)1415 static VAStatus psb__DelinkSubpictFromSurface(
1416     object_surface_p obj_surface,
1417     VASubpictureID subpic_id
1418 )
1419 {
1420     PsbVASurfaceRec *surface_subpic, *pre_surface_subpic = NULL;
1421     int found = 0;
1422 
1423     if (obj_surface->subpictures != NULL) {
1424         surface_subpic = (PsbVASurfaceRec *)obj_surface->subpictures;
1425         do  {
1426             if (surface_subpic->subpic_id == subpic_id) {
1427                 found = 1;
1428                 break;
1429             } else {
1430                 pre_surface_subpic = surface_subpic;
1431                 surface_subpic = surface_subpic->next;
1432             }
1433         } while (surface_subpic);
1434     }
1435 
1436     if (found == 1) {
1437         if (pre_surface_subpic == NULL) { /* remove the first node */
1438             obj_surface->subpictures = (void *)surface_subpic->next;
1439         } else {
1440             pre_surface_subpic->next = surface_subpic->next;
1441         }
1442         free(surface_subpic);
1443         obj_surface->subpic_count--;
1444     }
1445 
1446     return VA_STATUS_SUCCESS;
1447 }
1448 
1449 
psb__DelinkSurfaceFromSubpict(object_subpic_p obj_subpic,VASurfaceID surface_id)1450 static VAStatus psb__DelinkSurfaceFromSubpict(
1451     object_subpic_p obj_subpic,
1452     VASurfaceID surface_id
1453 )
1454 {
1455     subpic_surface_s *subpic_surface, *pre_subpic_surface = NULL;
1456     int found = 0;
1457 
1458     if (obj_subpic->surfaces != NULL) {
1459         subpic_surface = (subpic_surface_s *)obj_subpic->surfaces;
1460         do {
1461             if (subpic_surface->surface_id == surface_id) {
1462                 found = 1;
1463                 break;
1464             } else {
1465                 pre_subpic_surface = subpic_surface;
1466                 subpic_surface = subpic_surface->next;
1467             }
1468         } while (subpic_surface);
1469     }
1470 
1471     if (found == 1) {
1472         if (pre_subpic_surface == NULL) { /* remove the first node */
1473             obj_subpic->surfaces = (void *)subpic_surface->next;
1474         } else {
1475             pre_subpic_surface->next = subpic_surface->next;
1476         }
1477         free(subpic_surface);
1478     }
1479 
1480     return VA_STATUS_SUCCESS;
1481 }
1482 
1483 
psb_QuerySubpictureFormats(VADriverContextP __maybe_unused ctx,VAImageFormat * format_list,unsigned int * flags,unsigned int * num_formats)1484 VAStatus psb_QuerySubpictureFormats(
1485     VADriverContextP __maybe_unused ctx,
1486     VAImageFormat *format_list,        /* out */
1487     unsigned int *flags,       /* out */
1488     unsigned int *num_formats  /* out */
1489 )
1490 {
1491     VAStatus vaStatus = VA_STATUS_SUCCESS;
1492 
1493     CHECK_INVALID_PARAM(format_list == NULL);
1494     CHECK_INVALID_PARAM(flags == NULL);
1495     CHECK_INVALID_PARAM(num_formats == NULL);
1496 
1497     memcpy(format_list, psb__SubpicFormat, sizeof(psb__SubpicFormat));
1498     *num_formats = PSB_MAX_SUBPIC_FORMATS;
1499     *flags = PSB_SUPPORTED_SUBPIC_FLAGS;
1500 
1501     return VA_STATUS_SUCCESS;
1502 }
1503 
1504 
psb_CreateSubpicture(VADriverContextP ctx,VAImageID image,VASubpictureID * subpicture)1505 VAStatus psb_CreateSubpicture(
1506     VADriverContextP ctx,
1507     VAImageID image,
1508     VASubpictureID *subpicture   /* out */
1509 )
1510 {
1511     INIT_DRIVER_DATA;
1512     VASubpictureID subpicID;
1513     object_subpic_p obj_subpic;
1514     object_image_p obj_image;
1515     VAStatus vaStatus = VA_STATUS_SUCCESS;
1516     VAImageFormat *img_fmt;
1517 
1518     obj_image = IMAGE(image);
1519     CHECK_IMAGE(obj_image);
1520     CHECK_SUBPICTURE(subpicture);
1521 
1522     img_fmt = psb__VAImageCheckFourCC(&obj_image->image.format, psb__SubpicFormat,
1523                                       sizeof(psb__SubpicFormat) / sizeof(VAImageFormat));
1524     if (img_fmt == NULL)
1525         return VA_STATUS_ERROR_UNKNOWN;
1526 
1527     subpicID = object_heap_allocate(&driver_data->subpic_heap);
1528     obj_subpic = SUBPIC(subpicID);
1529     CHECK_ALLOCATION(obj_subpic);
1530 
1531     MEMSET_OBJECT(obj_subpic, struct object_subpic_s);
1532 
1533     obj_subpic->subpic_id = subpicID;
1534     obj_subpic->image_id = obj_image->image.image_id;
1535     obj_subpic->surfaces = NULL;
1536     obj_subpic->global_alpha = 255;
1537 
1538     obj_image->subpic_ref ++;
1539 
1540     *subpicture = subpicID;
1541 
1542     return VA_STATUS_SUCCESS;
1543 }
1544 
1545 
1546 
psb__destroy_subpicture(psb_driver_data_p driver_data,object_subpic_p obj_subpic)1547 VAStatus psb__destroy_subpicture(psb_driver_data_p driver_data, object_subpic_p obj_subpic)
1548 {
1549     subpic_surface_s *subpic_surface = (subpic_surface_s *)obj_subpic->surfaces;
1550     VASubpictureID subpicture = obj_subpic->subpic_id;
1551 
1552     if (subpic_surface) {
1553         do {
1554             subpic_surface_s *tmp = subpic_surface;
1555             object_surface_p obj_surface = SURFACE(subpic_surface->surface_id);
1556 
1557             if (obj_surface) { /* remove subpict from surface */
1558                 psb__DelinkSubpictFromSurface(obj_surface, subpicture);
1559             }
1560             subpic_surface = subpic_surface->next;
1561             free(tmp);
1562         } while (subpic_surface);
1563     }
1564 
1565     object_heap_free(&driver_data->subpic_heap, (object_base_p) obj_subpic);
1566     return VA_STATUS_SUCCESS;
1567 }
1568 
1569 
psb_DestroySubpicture(VADriverContextP ctx,VASubpictureID subpicture)1570 VAStatus psb_DestroySubpicture(
1571     VADriverContextP ctx,
1572     VASubpictureID subpicture
1573 )
1574 {
1575     INIT_DRIVER_DATA;
1576     object_subpic_p obj_subpic;
1577     VAStatus vaStatus = VA_STATUS_SUCCESS;
1578 
1579     obj_subpic = SUBPIC(subpicture);
1580     CHECK_SUBPICTURE(obj_subpic);
1581 
1582     return psb__destroy_subpicture(driver_data, obj_subpic);
1583 }
1584 
psb_SetSubpictureImage(VADriverContextP ctx,VASubpictureID subpicture,VAImageID image)1585 VAStatus psb_SetSubpictureImage(
1586     VADriverContextP ctx,
1587     VASubpictureID subpicture,
1588     VAImageID image
1589 )
1590 {
1591     INIT_DRIVER_DATA;
1592     object_subpic_p obj_subpic;
1593     object_image_p obj_image;
1594     VAStatus vaStatus = VA_STATUS_SUCCESS;
1595     subpic_surface_s *subpic_surface;
1596     VAImageFormat *img_fmt;
1597 
1598     obj_image = IMAGE(image);
1599     CHECK_IMAGE(obj_image);
1600 
1601     img_fmt = psb__VAImageCheckFourCC(&obj_image->image.format,
1602                                       psb__SubpicFormat,
1603                                       sizeof(psb__SubpicFormat) / sizeof(VAImageFormat));
1604     CHECK_IMAGE(img_fmt);
1605 
1606     obj_subpic = SUBPIC(subpicture);
1607     CHECK_SUBPICTURE(obj_subpic);
1608 
1609     object_image_p old_obj_image = IMAGE(obj_subpic->image_id);
1610     if (old_obj_image) {
1611         old_obj_image->subpic_ref--;/* decrease reference count */
1612     }
1613 
1614     /* reset the image */
1615     obj_subpic->image_id = obj_image->image.image_id;
1616     obj_image->subpic_ref ++;
1617 
1618     /* relink again */
1619     if (obj_subpic->surfaces != NULL) {
1620         /* the subpicture already linked into surfaces
1621          * so not check the return value of psb__LinkSubpictIntoSurface
1622          */
1623         subpic_surface = (subpic_surface_s *)obj_subpic->surfaces;
1624         do {
1625             object_surface_p obj_surface = SURFACE(subpic_surface->surface_id);
1626             CHECK_SURFACE(obj_surface);
1627 
1628             psb__LinkSubpictIntoSurface(driver_data, obj_surface, obj_subpic,
1629                                         0, 0, 0, 0, 0, 0, 0, 0,
1630                                         0 /* not update location */
1631                                        );
1632             subpic_surface = subpic_surface->next;
1633         } while (subpic_surface);
1634     }
1635 
1636 
1637     return VA_STATUS_SUCCESS;
1638 }
1639 
1640 
psb_SetSubpictureChromakey(VADriverContextP ctx,VASubpictureID subpicture,unsigned int chromakey_min,unsigned int chromakey_max,unsigned int chromakey_mask)1641 VAStatus psb_SetSubpictureChromakey(
1642     VADriverContextP ctx,
1643     VASubpictureID subpicture,
1644     unsigned int chromakey_min,
1645     unsigned int chromakey_max,
1646     unsigned int chromakey_mask
1647 )
1648 {
1649     INIT_DRIVER_DATA;
1650     (void)driver_data;
1651     /* TODO */
1652     if ((chromakey_mask < chromakey_min) || (chromakey_mask > chromakey_max)) {
1653         drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid chromakey value %d, chromakey value should between min and max\n", chromakey_mask);
1654         return VA_STATUS_ERROR_INVALID_PARAMETER;
1655     }
1656     object_subpic_p obj_subpic = SUBPIC(subpicture);
1657     if (NULL == obj_subpic) {
1658         drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid subpicture value %d\n", subpicture);
1659         return VA_STATUS_ERROR_INVALID_SUBPICTURE;
1660     }
1661 
1662     return VA_STATUS_SUCCESS;
1663 }
1664 
psb_SetSubpictureGlobalAlpha(VADriverContextP ctx,VASubpictureID subpicture,float global_alpha)1665 VAStatus psb_SetSubpictureGlobalAlpha(
1666     VADriverContextP ctx,
1667     VASubpictureID subpicture,
1668     float global_alpha
1669 )
1670 {
1671     INIT_DRIVER_DATA;
1672 
1673     if (global_alpha < 0 || global_alpha > 1) {
1674         drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid global alpha value %07f, global alpha value should between 0 and 1\n", global_alpha);
1675         return VA_STATUS_ERROR_INVALID_PARAMETER;
1676     }
1677 
1678     object_subpic_p obj_subpic = SUBPIC(subpicture);
1679     if (NULL == obj_subpic) {
1680         drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid subpicture value %d\n", subpicture);
1681         return VA_STATUS_ERROR_INVALID_SUBPICTURE;
1682     }
1683 
1684     obj_subpic->global_alpha = global_alpha * 255;
1685 
1686     return VA_STATUS_SUCCESS;
1687 }
1688 
1689 
psb__AssociateSubpicture(VADriverContextP ctx,VASubpictureID subpicture,VASurfaceID * target_surfaces,int num_surfaces,short src_x,short src_y,unsigned short src_w,unsigned short src_h,short dest_x,short dest_y,unsigned short dest_w,unsigned short dest_h,unsigned int flags)1690 VAStatus psb__AssociateSubpicture(
1691     VADriverContextP ctx,
1692     VASubpictureID subpicture,
1693     VASurfaceID *target_surfaces,
1694     int num_surfaces,
1695     short src_x, /* upper left offset in subpicture */
1696     short src_y,
1697     unsigned short src_w,
1698     unsigned short src_h,
1699     short dest_x, /* upper left offset in surface */
1700     short dest_y,
1701     unsigned short dest_w,
1702     unsigned short dest_h,
1703     /*
1704      * whether to enable chroma-keying or global-alpha
1705      * see VA_SUBPICTURE_XXX values
1706      */
1707     unsigned int flags
1708 )
1709 {
1710     INIT_DRIVER_DATA;
1711 
1712     object_subpic_p obj_subpic;
1713     VAStatus vaStatus = VA_STATUS_SUCCESS;
1714     int i;
1715 
1716     CHECK_INVALID_PARAM(num_surfaces <= 0);
1717 
1718     obj_subpic = SUBPIC(subpicture);
1719     CHECK_SUBPICTURE(obj_subpic);
1720     CHECK_SURFACE(target_surfaces);
1721 
1722     if (flags & ~PSB_SUPPORTED_SUBPIC_FLAGS) {
1723 #ifdef VA_STATUS_ERROR_FLAG_NOT_SUPPORTED
1724         vaStatus = VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
1725 #else
1726         vaStatus = VA_STATUS_ERROR_UNKNOWN;
1727 #endif
1728         DEBUG_FAILURE;
1729         return vaStatus;
1730     } else {
1731 
1732         /* If flags are ok, copy them to the subpicture object */
1733         obj_subpic->flags = flags;
1734 
1735     }
1736 
1737     /* Validate input params */
1738     for (i = 0; i < num_surfaces; i++) {
1739         object_surface_p obj_surface = SURFACE(target_surfaces[i]);
1740         CHECK_SURFACE(obj_surface);
1741     }
1742 
1743     VASurfaceID *surfaces = target_surfaces;
1744     for (i = 0; i < num_surfaces; i++) {
1745         object_surface_p obj_surface = SURFACE(*surfaces);
1746         if (obj_surface) {
1747             vaStatus = psb__LinkSubpictIntoSurface(driver_data, obj_surface, obj_subpic,
1748                                                    src_x, src_y, src_w, src_h,
1749                                                    dest_x, dest_y, dest_w, dest_h, 1);
1750             if (VA_STATUS_SUCCESS == vaStatus) {
1751                 vaStatus = psb__LinkSurfaceIntoSubpict(obj_subpic, *surfaces);
1752             }
1753             CHECK_VASTATUS();/* failed with malloc */
1754         } else {
1755             /* Should never get here */
1756             drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid surfaces,SurfaceID=0x%x\n", *surfaces);
1757         }
1758 
1759         surfaces++;
1760     }
1761 
1762     return VA_STATUS_SUCCESS;
1763 }
1764 
1765 
psb_AssociateSubpicture(VADriverContextP ctx,VASubpictureID subpicture,VASurfaceID * target_surfaces,int num_surfaces,short src_x,short src_y,unsigned short src_width,unsigned short src_height,short dest_x,short dest_y,unsigned short dest_width,unsigned short dest_height,unsigned int flags)1766 VAStatus psb_AssociateSubpicture(
1767     VADriverContextP ctx,
1768     VASubpictureID subpicture,
1769     VASurfaceID *target_surfaces,
1770     int num_surfaces,
1771     short src_x, /* upper left offset in subpicture */
1772     short src_y,
1773     unsigned short src_width,
1774     unsigned short src_height,
1775     short dest_x, /* upper left offset in surface */
1776     short dest_y,
1777     unsigned short dest_width,
1778     unsigned short dest_height,
1779     /*
1780      * whether to enable chroma-keying or global-alpha
1781      * see VA_SUBPICTURE_XXX values
1782      */
1783     unsigned int flags
1784 )
1785 {
1786     return psb__AssociateSubpicture(ctx, subpicture, target_surfaces, num_surfaces,
1787                                     src_x, src_y, src_width, src_height,
1788                                     dest_x, dest_y, dest_width, dest_height,
1789                                     flags
1790                                    );
1791 }
1792 
1793 
psb_DeassociateSubpicture(VADriverContextP ctx,VASubpictureID subpicture,VASurfaceID * target_surfaces,int num_surfaces)1794 VAStatus psb_DeassociateSubpicture(
1795     VADriverContextP ctx,
1796     VASubpictureID subpicture,
1797     VASurfaceID *target_surfaces,
1798     int num_surfaces
1799 )
1800 {
1801     INIT_DRIVER_DATA;
1802 
1803     object_subpic_p obj_subpic;
1804     VAStatus vaStatus = VA_STATUS_SUCCESS;
1805     object_image_p obj_image;
1806     int i;
1807 
1808     CHECK_INVALID_PARAM(num_surfaces <= 0);
1809 
1810     obj_subpic = SUBPIC(subpicture);
1811     CHECK_SUBPICTURE(obj_subpic);
1812     CHECK_SURFACE(target_surfaces);
1813 
1814     VASurfaceID *surfaces = target_surfaces;
1815     for (i = 0; i < num_surfaces; i++) {
1816         object_surface_p obj_surface = SURFACE(*surfaces);
1817 
1818         if (obj_surface) {
1819             psb__DelinkSubpictFromSurface(obj_surface, subpicture);
1820             psb__DelinkSurfaceFromSubpict(obj_subpic, obj_surface->surface_id);
1821         } else {
1822             drv_debug_msg(VIDEO_DEBUG_ERROR, "vaDeassociateSubpicture: Invalid surface, VASurfaceID=0x%08x\n", *surfaces);
1823         }
1824 
1825         surfaces++;
1826     }
1827 
1828     obj_image = IMAGE(obj_subpic->image_id);
1829     if (obj_image)
1830         obj_image->subpic_ref--;/* decrease reference count */
1831 
1832     return VA_STATUS_SUCCESS;
1833 }
1834 
1835 
psb_SurfaceDeassociateSubpict(psb_driver_data_p driver_data,object_surface_p obj_surface)1836 void psb_SurfaceDeassociateSubpict(
1837     psb_driver_data_p driver_data,
1838     object_surface_p obj_surface
1839 )
1840 {
1841     PsbVASurfaceRec *surface_subpic = (PsbVASurfaceRec *)obj_surface->subpictures;
1842 
1843     if (surface_subpic != NULL) {
1844         do  {
1845             PsbVASurfaceRec *tmp = surface_subpic;
1846             object_subpic_p obj_subpic = SUBPIC(surface_subpic->subpic_id);
1847             if (obj_subpic)
1848                 psb__DelinkSurfaceFromSubpict(obj_subpic, obj_surface->surface_id);
1849             surface_subpic = surface_subpic->next;
1850             free(tmp);
1851         } while (surface_subpic);
1852     }
1853 }
1854 
1855 
1856 static  VADisplayAttribute psb__DisplayAttribute[] = {
1857     {
1858         VADisplayAttribBrightness,
1859         BRIGHTNESS_MIN,
1860         BRIGHTNESS_MAX,
1861         BRIGHTNESS_DEFAULT_VALUE,
1862         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1863         NULL
1864     },
1865 
1866     {
1867         VADisplayAttribContrast,
1868         CONTRAST_MIN,
1869         CONTRAST_MAX,
1870         CONTRAST_DEFAULT_VALUE,
1871         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1872         NULL
1873     },
1874 
1875     {
1876         VADisplayAttribHue,
1877         HUE_MIN,
1878         HUE_MAX,
1879         HUE_DEFAULT_VALUE,
1880         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1881         NULL
1882     },
1883 
1884     {
1885         VADisplayAttribSaturation,
1886         SATURATION_MIN,
1887         SATURATION_MAX,
1888         SATURATION_DEFAULT_VALUE,
1889         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1890         NULL
1891     },
1892     {
1893         VADisplayAttribBackgroundColor,
1894         0x00000000,
1895         0xffffffff,
1896         0x00000000,
1897         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1898         NULL
1899     },
1900     {
1901         VADisplayAttribRotation,
1902         VA_ROTATION_NONE,
1903         VA_ROTATION_270,
1904         VA_ROTATION_NONE,
1905         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1906         NULL
1907     },
1908     {
1909         VADisplayAttribOutofLoopDeblock,
1910         VA_OOL_DEBLOCKING_FALSE,
1911         VA_OOL_DEBLOCKING_TRUE,
1912         VA_OOL_DEBLOCKING_FALSE,
1913         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1914         NULL
1915     },
1916     {
1917         VADisplayAttribBlendColor,
1918         0x00000000,
1919         0xffffffff,
1920         0x00000000,
1921         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1922         NULL
1923     },
1924     {
1925         VADisplayAttribOverlayColorKey,
1926         0x00000000,
1927         0xffffffff,
1928         0x00000000,
1929         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1930         NULL
1931     },
1932     {
1933         VADisplayAttribOverlayAutoPaintColorKey,
1934         0x00000000,
1935         0xffffffff,
1936         0x00000000,
1937         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1938         NULL
1939     },
1940     {
1941         VADisplayAttribCSCMatrix,
1942         0x00000000,
1943         0xffffffff,
1944         0x00000000,
1945         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1946         NULL
1947     },
1948     {
1949         VADisplayAttribRenderDevice,
1950         0x00000000,
1951         0xffffffff,
1952         0x00000000,
1953         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1954         NULL
1955     },
1956     {
1957         VADisplayAttribRenderMode,
1958         0x00000000,
1959         0xffffffff,
1960         0x00000000,
1961         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1962         NULL
1963     },
1964     {
1965         VADisplayAttribRenderRect,
1966         0x00000000,
1967         0xffffffff,
1968         0x00000000,
1969         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE,
1970         NULL
1971     }
1972 };
1973 
1974 /*
1975  * Query display attributes
1976  * The caller must provide a "attr_list" array that can hold at
1977  * least vaMaxNumDisplayAttributes() entries. The actual number of attributes
1978  * returned in "attr_list" is returned in "num_attributes".
1979  */
psb_QueryDisplayAttributes(VADriverContextP __maybe_unused ctx,VADisplayAttribute * attr_list,int * num_attributes)1980 VAStatus psb_QueryDisplayAttributes(
1981     VADriverContextP __maybe_unused ctx,
1982     VADisplayAttribute *attr_list,      /* out */
1983     int *num_attributes         /* out */
1984 )
1985 {
1986     VAStatus vaStatus = VA_STATUS_SUCCESS;
1987 
1988     CHECK_INVALID_PARAM(attr_list == NULL);
1989     CHECK_INVALID_PARAM(num_attributes == NULL);
1990 
1991     *num_attributes = min(*num_attributes, PSB_MAX_DISPLAY_ATTRIBUTES);
1992     memcpy(attr_list, psb__DisplayAttribute, (*num_attributes)*sizeof(VADisplayAttribute));
1993     return VA_STATUS_SUCCESS;
1994 }
1995 
1996 /*
1997  * Get display attributes
1998  * This function returns the current attribute values in "attr_list".
1999  * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field
2000  * from vaQueryDisplayAttributes() can have their values retrieved.
2001  */
psb_GetDisplayAttributes(VADriverContextP ctx,VADisplayAttribute * attr_list,int num_attributes)2002 VAStatus psb_GetDisplayAttributes(
2003     VADriverContextP ctx,
2004     VADisplayAttribute *attr_list,      /* in/out */
2005     int num_attributes
2006 )
2007 {
2008     INIT_DRIVER_DATA;
2009     VADisplayAttribute *p = attr_list;
2010     int i;
2011     VAStatus vaStatus = VA_STATUS_SUCCESS;
2012 
2013     CHECK_INVALID_PARAM(attr_list == NULL);
2014     CHECK_INVALID_PARAM(num_attributes <= 0);
2015 
2016     for (i = 0; i < num_attributes; i++) {
2017         switch (p->type) {
2018         case VADisplayAttribBrightness:
2019             /* -50*(1<<10) ~ 50*(1<<10) ==> 0~100*/
2020             p->value = (driver_data->brightness.value / (1 << 10)) + 50;
2021             p->min_value = 0;
2022             p->max_value = 100;
2023             break;
2024         case VADisplayAttribContrast:
2025             /* 0 ~ 2*(1<<25) ==> 0~100 */
2026             p->value = (driver_data->contrast.value / (1 << 25)) * 50;
2027             p->min_value = 0;
2028             p->max_value = 100;
2029             break;
2030         case VADisplayAttribHue:
2031             /* -30*(1<<25) ~ 30*(1<<25) ==> 0~100*/
2032             p->value = ((driver_data->hue.value / (1 << 25)) + 30) * 10 / 6;
2033             p->min_value = 0;
2034             p->max_value = 100;
2035             break;
2036         case VADisplayAttribSaturation:
2037             /* 0 ~ 2*(1<<25) ==> 0~100 */
2038             p->value = (driver_data->saturation.value / (1 << 25)) * 50;
2039             p->min_value = 0;
2040             p->max_value = 100;
2041             break;
2042         case VADisplayAttribBackgroundColor:
2043             p->value = driver_data->clear_color;
2044             break;
2045         case VADisplayAttribBlendColor:
2046             p->value = driver_data->blend_color;
2047             break;
2048         case VADisplayAttribOverlayColorKey:
2049             p->value = driver_data->color_key;
2050             p->min_value = 0;
2051             p->max_value = 0xFFFFFF;
2052             break;
2053         case VADisplayAttribOverlayAutoPaintColorKey:
2054             p->value = driver_data->overlay_auto_paint_color_key;
2055             p->min_value = 0;
2056             p->max_value = 1;
2057             break;
2058         case VADisplayAttribRotation:
2059             p->value = driver_data->va_rotate = p->value;
2060             p->min_value = VA_ROTATION_NONE;
2061             p->max_value = VA_ROTATION_270;
2062             break;
2063         case VADisplayAttribOutofLoopDeblock:
2064             p->value = driver_data->is_oold = p->value;
2065             p->min_value = VA_OOL_DEBLOCKING_FALSE;
2066             p->max_value = VA_OOL_DEBLOCKING_TRUE;
2067             break;
2068         case VADisplayAttribCSCMatrix:
2069             p->value = driver_data->load_csc_matrix = p->value;
2070             p->min_value = 0;
2071             p->max_value = 255;
2072             break;
2073         case VADisplayAttribRenderDevice:
2074             p->value = driver_data->render_device = p->value;
2075             p->min_value = 0;
2076             p->max_value = 255;
2077             break;
2078         case VADisplayAttribRenderMode:
2079             p->value = driver_data->render_mode = p->value;
2080             p->min_value = 0;
2081             p->max_value = 255;
2082             break;
2083         case VADisplayAttribRenderRect:
2084             ((VARectangle *)(p->value))->x = driver_data->render_rect.x = ((VARectangle *)(p->value))->x;
2085             ((VARectangle *)(p->value))->y = driver_data->render_rect.y = ((VARectangle *)(p->value))->y;
2086             ((VARectangle *)(p->value))->width = driver_data->render_rect.width = ((VARectangle *)(p->value))->width;
2087             ((VARectangle *)(p->value))->height = driver_data->render_rect.height = ((VARectangle *)(p->value))->height;
2088             p->min_value = 0;
2089             p->max_value = 255;
2090             break;
2091 
2092         default:
2093             break;
2094         }
2095         p++;
2096     }
2097 
2098     return VA_STATUS_SUCCESS;
2099 }
2100 
2101 /*
2102  * Set display attributes
2103  * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field
2104  * from vaQueryDisplayAttributes() can be set.  If the attribute is not settable or
2105  * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED
2106  */
2107 #define CLAMP_ATTR(a,max,min) (a>max?max:(a<min?min:a))
psb_SetDisplayAttributes(VADriverContextP ctx,VADisplayAttribute * attr_list,int num_attributes)2108 VAStatus psb_SetDisplayAttributes(
2109     VADriverContextP ctx,
2110     VADisplayAttribute *attr_list,
2111     int num_attributes
2112 )
2113 {
2114     INIT_DRIVER_DATA;
2115     VAStatus vaStatus = VA_STATUS_SUCCESS;
2116     struct psb_texture_s *texture_priv = &driver_data->ctexture_priv;
2117     PsbPortPrivPtr overlay_priv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
2118     int j, k;
2119 
2120     CHECK_INVALID_PARAM(attr_list == NULL);
2121 
2122     VADisplayAttribute *p = attr_list;
2123     int i, update_coeffs = 0;
2124     float *p_tmp;
2125 
2126     if (num_attributes <= 0) {
2127         return VA_STATUS_ERROR_INVALID_PARAMETER;
2128     }
2129 
2130     for (i = 0; i < num_attributes; i++) {
2131         switch (p->type) {
2132         case VADisplayAttribBrightness:
2133             /* 0~100 ==> -50*(1<<10) ~ 50*(1<<10)*/
2134             driver_data->brightness.value = (p->value - 50) * (1 << 10);
2135             /* 0~100 ==> -50~50 */
2136             overlay_priv->brightness.Value = texture_priv->brightness.Value = p->value - 50;
2137             update_coeffs = 1;
2138             break;
2139         case VADisplayAttribContrast:
2140             /* 0~100 ==> 0 ~ 2*(1<<25) */
2141             driver_data->contrast.value = (p->value / 50) * (1 << 25);
2142             /* 0~100 ==> -100~100 */
2143             overlay_priv->contrast.Value = texture_priv->contrast.Value = p->value * 2 - 100;
2144             update_coeffs = 1;
2145             break;
2146         case VADisplayAttribHue:
2147             /* 0~100 ==> -30*(1<<25) ~ 30*(1<<25) */
2148             driver_data->hue.value = ((p->value * 2 - 100) * 3 / 10) * (1 << 25);
2149             /* 0~100 ==> -30~30 */
2150             overlay_priv->hue.Value = texture_priv->hue.Value = (p->value * 2 - 100) * 3 / 10;
2151             update_coeffs = 1;
2152             break;
2153         case VADisplayAttribSaturation:
2154             /* 0~100 ==> 0 ~ 2*(1<<25) */
2155             driver_data->contrast.value = (p->value / 50) * (1 << 25);
2156             /* 0~100 ==> 100~200 */
2157             overlay_priv->saturation.Value = texture_priv->saturation.Value = p->value + 100;
2158             update_coeffs = 1;
2159             break;
2160         case VADisplayAttribBackgroundColor:
2161             driver_data->clear_color = p->value;
2162             break;
2163         case VADisplayAttribOutofLoopDeblock:
2164             driver_data->is_oold = p->value;
2165             break;
2166         case VADisplayAttribRotation:
2167             driver_data->va_rotate = p->value;
2168             driver_data->rotation_dirty |= PSB_NEW_VA_ROTATION;
2169             break;
2170 
2171         case VADisplayAttribCSCMatrix:
2172             driver_data->load_csc_matrix = 1;
2173             p_tmp = (float *)(p->attrib_ptr);
2174             for (j = 0; j < CSC_MATRIX_Y; j++)
2175                 for (k = 0; k < CSC_MATRIX_X; k++) {
2176                     if (p_tmp)
2177                         driver_data->csc_matrix[j][k] = *p_tmp;
2178                    p_tmp++;
2179                 }
2180 
2181             for (j = 0; j < CSC_MATRIX_Y; j++)
2182                 for (k = 0; k < CSC_MATRIX_X; k++) {
2183                     if (fabs(s601[j*CSC_MATRIX_X+k] - driver_data->csc_matrix[j][k]) > 1e-6) {
2184                         break;
2185                     }
2186                     if (k < CSC_MATRIX_X) {
2187                         break;
2188                     }
2189                 }
2190 
2191             if (j == CSC_MATRIX_Y && k == CSC_MATRIX_X) {
2192                 driver_data->is_BT601 = 1;
2193             }
2194             break;
2195 
2196         case VADisplayAttribColorRange:
2197             driver_data->set_video_range = 1;
2198             driver_data->video_range = (p->value == VA_SOURCE_RANGE_FULL);
2199             break;
2200 
2201         case VADisplayAttribBlendColor:
2202             driver_data->blend_color = p->value;
2203             break;
2204         case VADisplayAttribOverlayColorKey:
2205             overlay_priv->colorKey = driver_data->color_key = p->value;
2206             break;
2207         case VADisplayAttribOverlayAutoPaintColorKey:
2208             driver_data->overlay_auto_paint_color_key = p->value;
2209             break;
2210 
2211         case VADisplayAttribRenderDevice:
2212             driver_data->render_device = p->value & VA_RENDER_DEVICE_MASK;
2213         case VADisplayAttribRenderMode:
2214 #ifndef ANDROID
2215             if (p->value & VA_RENDER_MODE_EXTERNAL_GPU) {
2216                 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s:Invalid parameter.VARenderModeExternalGPU is not supported.\n", __FUNCTION__);
2217                 return VA_STATUS_ERROR_INVALID_PARAMETER;
2218             }
2219             if (((p->value & VA_RENDER_MODE_LOCAL_OVERLAY) && (p->value & VA_RENDER_MODE_LOCAL_GPU)) ||
2220                 ((p->value & VA_RENDER_MODE_EXTERNAL_OVERLAY) && (p->value & VA_RENDER_MODE_EXTERNAL_GPU))) {
2221                 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s:Invalid parameter. Conflict setting for VADisplayAttribRenderMode.\n", __FUNCTION__);
2222                 return VA_STATUS_ERROR_INVALID_PARAMETER;
2223             }
2224 #endif
2225             driver_data->render_mode = p->value & VA_RENDER_MODE_MASK;
2226             break;
2227         case VADisplayAttribRenderRect:
2228             driver_data->render_rect.x = ((VARectangle *)(p->attrib_ptr))->x;
2229             driver_data->render_rect.y = ((VARectangle *)(p->attrib_ptr))->y;
2230             driver_data->render_rect.width = ((VARectangle *)(p->attrib_ptr))->width;
2231             driver_data->render_rect.height = ((VARectangle *)(p->attrib_ptr))->height;
2232             break;
2233 
2234         default:
2235             break;
2236         }
2237         p++;
2238     }
2239 
2240     if (update_coeffs) {
2241         /* TODO */
2242 #ifndef ANDROID
2243         texture_priv->update_coeffs = 1;
2244 #endif
2245     }
2246 
2247     return VA_STATUS_SUCCESS;
2248 }
2249 
2250