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