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