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