2 * Copyright © 2011 Intel Corporation
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:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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.
25 * Li Xiaowei <xiaowei.a.li@intel.com>
26 * Li Zhong <zhong.li@intel.com>
35 #include "intel_batchbuffer.h"
36 #include "intel_driver.h"
37 #include "i965_defines.h"
38 #include "i965_structs.h"
39 #include "gen75_vpp_vebox.h"
40 #include "intel_media.h"
45 i965_MapBuffer(VADriverContextP ctx, VABufferID buf_id, void **);
48 i965_UnmapBuffer(VADriverContextP ctx, VABufferID buf_id);
51 i965_DeriveImage(VADriverContextP ctx, VABufferID surface, VAImage *out_image);
54 i965_DestroyImage(VADriverContextP ctx, VAImageID image);
58 i965_CreateSurfaces(VADriverContextP ctx,
63 VASurfaceID *surfaces);
65 VAStatus vpp_surface_convert(VADriverContextP ctx,
66 struct object_surface *src_obj_surf,
67 struct object_surface *dst_obj_surf)
69 VAStatus va_status = VA_STATUS_SUCCESS;
71 assert(src_obj_surf->orig_width == dst_obj_surf->orig_width);
72 assert(src_obj_surf->orig_height == dst_obj_surf->orig_height);
74 VARectangle src_rect, dst_rect;
75 src_rect.x = dst_rect.x = 0;
76 src_rect.y = dst_rect.y = 0;
77 src_rect.width = dst_rect.width = src_obj_surf->orig_width;
78 src_rect.height = dst_rect.height = dst_obj_surf->orig_height;
80 struct i965_surface src_surface, dst_surface;
81 src_surface.base = (struct object_base *)src_obj_surf;
82 src_surface.type = I965_SURFACE_TYPE_SURFACE;
83 src_surface.flags = I965_SURFACE_FLAG_FRAME;
85 dst_surface.base = (struct object_base *)dst_obj_surf;
86 dst_surface.type = I965_SURFACE_TYPE_SURFACE;
87 dst_surface.flags = I965_SURFACE_FLAG_FRAME;
89 va_status = i965_image_processing(ctx,
97 VAStatus vpp_surface_scaling(VADriverContextP ctx,
98 struct object_surface *dst_obj_surf,
99 struct object_surface *src_obj_surf)
101 VAStatus va_status = VA_STATUS_SUCCESS;
102 int flags = I965_PP_FLAG_AVS;
104 assert(src_obj_surf->fourcc == VA_FOURCC_NV12);
105 assert(dst_obj_surf->fourcc == VA_FOURCC_NV12);
107 VARectangle src_rect, dst_rect;
110 src_rect.width = src_obj_surf->orig_width;
111 src_rect.height = src_obj_surf->orig_height;
115 dst_rect.width = dst_obj_surf->orig_width;
116 dst_rect.height = dst_obj_surf->orig_height;
118 va_status = i965_scaling_processing(ctx,
128 void hsw_veb_dndi_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
130 struct i965_driver_data *i965 = i965_driver_data(ctx);
131 unsigned int* p_table ;
132 int progressive_dn = 1;
133 int dndi_top_first = 0;
134 int motion_compensated_enable = 0;
136 if (proc_ctx->filters_mask & VPP_DNDI_DI) {
137 VAProcFilterParameterBufferDeinterlacing *di_param =
138 (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
142 dndi_top_first = !(di_param->flags & VA_DEINTERLACING_BOTTOM_FIELD);
143 motion_compensated_enable = (di_param->algorithm == VAProcDeinterlacingMotionCompensated);
147 VAProcFilterParameterBufferDeinterlacing *di_param =
148 (VAProcFilterParameterBufferDeinterlacing *) proc_ctx->filter_di;
150 VAProcFilterParameterBuffer * dn_param =
151 (VAProcFilterParameterBuffer *) proc_ctx->filter_dn;
153 p_table = (unsigned int *)proc_ctx->dndi_state_table.ptr;
155 if (IS_HASWELL(i965->intel.device_info))
156 *p_table ++ = 0; // reserved . w0
158 *p_table ++ = ( 140 << 24 | // denoise STAD threshold . w1
159 192 << 16 | // dnmh_history_max
160 0 << 12 | // reserved
161 7 << 8 | // dnmh_delta[3:0]
162 38 ); // denoise ASD threshold
164 *p_table ++ = ( 0 << 30 | // reserved . w2
165 0 << 24 | // temporal diff th
166 0 << 22 | // reserved.
167 0 << 16 | // low temporal diff th
169 1 << 8 | // denoise moving pixel th
170 38 ); // denoise th for sum of complexity measure
172 *p_table ++ = ( 0 << 30 | // reserved . w3
173 12<< 24 | // good neighbor th[5:0]
174 9 << 20 | // CAT slope minus 1
175 5 << 16 | // SAD Tight in
176 0 << 14 | // smooth mv th
177 0 << 12 | // reserved
178 1 << 8 | // bne_edge_th[3:0]
179 20 ); // block noise estimate noise th
181 *p_table ++ = ( 0 << 31 | // STMM blending constant select. w4
182 64 << 24 | // STMM trc1
183 125<< 16 | // STMM trc2
184 0 << 14 | // reserved
185 30 << 8 | // VECM_mul
186 150 ); // maximum STMM
188 *p_table ++ = ( 118<< 24 | // minumum STMM . W5
189 0 << 22 | // STMM shift down
190 1 << 20 | // STMM shift up
191 5 << 16 | // STMM output shift
192 100 << 8 | // SDI threshold
195 *p_table ++ = ( 50 << 24 | // SDI fallback mode 1 T1 constant . W6
196 100 << 16 | // SDI fallback mode 1 T2 constant
197 37 << 8 | // SDI fallback mode 2 constant(angle2x1)
198 175 ); // FMD temporal difference threshold
200 *p_table ++ = ( 16 << 24 | // FMD #1 vertical difference th . w7
201 100<< 16 | // FMD #2 vertical difference th
203 2 << 8 | // FMD tear threshold
204 motion_compensated_enable << 7 | // MCDI Enable, use motion compensated deinterlace algorithm
205 progressive_dn << 6 | // progressive DN
207 dndi_top_first << 3 | // DN/DI Top First
210 *p_table ++ = ( 0 << 29 | // reserved . W8
211 32 << 23 | // dnmh_history_init[5:0]
212 10 << 19 | // neighborPixel th
213 0 << 18 | // reserved
214 0 << 16 | // FMD for 2nd field of previous frame
215 25 << 10 | // MC pixel consistency th
216 0 << 8 | // FMD for 1st field for current frame
220 *p_table ++ = ( 0 << 24 | // reserved
221 140<< 16 | // chr_dnmh_stad_th
222 0 << 13 | // reserved
223 1 << 12 | // chrome denoise enable
224 13 << 6 | // chr temp diff th
225 7 ); // chr temp diff low
227 if (IS_GEN8(i965->intel.device_info))
228 *p_table ++ = 0; // parameters for hot pixel,
231 void hsw_veb_iecp_std_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
233 unsigned int *p_table = proc_ctx->iecp_state_table.ptr + 0 ;
234 //VAProcFilterParameterBuffer * std_param =
235 // (VAProcFilterParameterBuffer *) proc_ctx->filter_std;
237 if(!(proc_ctx->filters_mask & VPP_IECP_STD_STE)){
238 memset(p_table, 0, 29 * 4);
241 *p_table ++ = ( 154 << 24 | // V_Mid
243 14 << 10 | // Hue_Max
246 0 << 2 | // Output Control is set to output the 1=STD score /0=Output Pixels
247 1 << 1 | // Set STE Enable
248 1 ); // Set STD Enable
251 *p_table ++ = ( 0 << 31 | // Reserved
252 4 << 28 | // Diamond Margin
253 0 << 21 | // Diamond_du
254 3 << 18 | // HS_Margin
255 79 << 10 | // Cos(alpha)
260 *p_table ++ = ( 0 << 21 | // Reserved
261 100 << 13 | // Diamond_alpha
262 35 << 7 | // Diamond_Th
266 *p_table ++ = ( 254 << 24 | // Y_point_3
267 47 << 16 | // Y_point_2
268 46 << 8 | // Y_point_1
269 1 << 7 | // VY_STD_Enable
273 *p_table ++ = ( 0 << 18 | // Reserved
274 31 << 13 | // Y_slope_2
275 31 << 8 | // Y_slope_1
279 *p_table ++ = ( 400 << 16 | // INV_Skin_types_margin = 20* Skin_Type_margin => 20*20
280 3300 ); // INV_Margin_VYL => 1/Margin_VYL
283 *p_table ++ = ( 216 << 24 | // P1L
285 1600 ); // INV_Margin_VYU
288 *p_table ++ = ( 130 << 24 | // B1L
294 *p_table ++ = ( 0 << 27 | // Reserved
295 0x7FB << 16 | // S0L (11 bits, Default value: -5 = FBh, pad it with 1s to make it 11bits)
300 *p_table ++ = ( 0 << 22 | // Reserved
305 *p_table ++ = ( 0 << 27 | // Reserved
311 *p_table ++ = ( 163 << 24 | // B1U
317 *p_table ++ = ( 0 << 27 | // Reserved
323 *p_table ++ = ( 0 << 22 | // Reserved
324 0x74D << 11 | // S2U (11 bits, Default value -179 = F4Dh)
328 *p_table ++ = ( 0 << 28 | // Reserved
329 20 << 20 | // Skin_types_margin
330 120 << 12 | // Skin_types_thresh
331 1 << 11 | // Skin_Types_Enable
335 *p_table ++ = ( 0 << 31 | // Reserved
336 0x3F8 << 21 | // SATB1 (10 bits, default 8, optimized value -8)
339 0x7A ); // SATP1 (7 bits, default 6, optimized value -6)
342 *p_table ++ = ( 0 << 31 | // Reserved
348 *p_table ++ = ( 0 << 22 | // Reserved
353 *p_table ++ = ( 14 << 25 | // HUEP3
355 0x7A << 11 | // HUEP1 (7 bits, default value -6 = 7Ah)
359 *p_table ++ = ( 0 << 30 | // Reserved
362 0x3F8 ); // HUEB1 (10 bits, default value 8, optimized value -8)
365 *p_table ++ = ( 0 << 22 | // Reserved
370 *p_table ++ = ( 0 << 22 | // Reserved
375 *p_table ++ = ( 0 << 31 | // Reserved
376 0 << 21 | // SATB1_DARK
377 31 << 14 | // SATP3_DARK
378 31 << 7 | // SATP2_DARK
379 0x7B ); // SATP1_DARK (7 bits, default value -11 = FF5h, optimized value -5)
382 *p_table ++ = ( 0 << 31 | // Reserved
383 305 << 20 | // SATS0_DARK
384 124 << 10 | // SATB3_DARK
388 *p_table ++ = ( 0 << 22 | // Reserved
389 256 << 11 | // SATS2_DARK
393 *p_table ++ = ( 14 << 25 | // HUEP3_DARK
394 14 << 18 | // HUEP2_DARK
395 14 << 11 | // HUEP1_DARK
399 *p_table ++ = ( 0 << 30 | // Reserved
400 56 << 20 | // HUEB3_DARK
401 56 << 10 | // HUEB2_DARK
405 *p_table ++ = ( 0 << 22 | // Reserved
406 256 << 11 | // HUES1_DARK
410 *p_table ++ = ( 0 << 22 | // Reserved
411 256 << 11 | // HUES3_DARK
416 void hsw_veb_iecp_ace_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
418 unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 116);
420 if(!(proc_ctx->filters_mask & VPP_IECP_ACE)){
421 memset(p_table, 0, 13 * 4);
423 *p_table ++ = 0x00000068;
424 *p_table ++ = 0x4c382410;
425 *p_table ++ = 0x9c887460;
426 *p_table ++ = 0xebd8c4b0;
427 *p_table ++ = 0x604c3824;
429 *p_table ++ = 0xb09c8874;
430 *p_table ++ = 0x0000d8c4;
431 *p_table ++ = 0x00000000;
432 *p_table ++ = 0x00000000;
433 *p_table ++ = 0x00000000;
435 *p_table ++ = 0x00000000;
436 *p_table ++ = 0x00000000;
437 *p_table ++ = 0x00000000;
441 void hsw_veb_iecp_tcc_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
443 unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 168);
444 // VAProcFilterParameterBuffer * tcc_param =
445 // (VAProcFilterParameterBuffer *) proc_ctx->filter_iecp_tcc;
447 if(!(proc_ctx->filters_mask & VPP_IECP_TCC)){
448 memset(p_table, 0, 11 * 4);
450 *p_table ++ = 0x00000000;
451 *p_table ++ = 0x00000000;
452 *p_table ++ = 0x1e34cc91;
453 *p_table ++ = 0x3e3cce91;
454 *p_table ++ = 0x02e80195;
456 *p_table ++ = 0x0197046b;
457 *p_table ++ = 0x01790174;
458 *p_table ++ = 0x00000000;
459 *p_table ++ = 0x00000000;
460 *p_table ++ = 0x03030000;
462 *p_table ++ = 0x009201c0;
466 void hsw_veb_iecp_pro_amp_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
468 unsigned int contrast = 0x80; //default
469 int brightness = 0x00; //default
470 int cos_c_s = 256 ; //default
471 int sin_c_s = 0; //default
472 unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 212);
474 if(!(proc_ctx->filters_mask & VPP_IECP_PRO_AMP)){
475 memset(p_table, 0, 2 * 4);
477 float src_saturation = 1.0;
479 float src_contrast = 1.0;
480 float src_brightness = 0.0;
481 float tmp_value = 0.0;
484 VAProcFilterParameterBufferColorBalance * amp_params =
485 (VAProcFilterParameterBufferColorBalance *) proc_ctx->filter_iecp_amp;
487 for (i = 0; i < proc_ctx->filter_iecp_amp_num_elements; i++){
488 VAProcColorBalanceType attrib = amp_params[i].attrib;
490 if(attrib == VAProcColorBalanceHue) {
491 src_hue = amp_params[i].value; //(-180.0, 180.0)
492 }else if(attrib == VAProcColorBalanceSaturation) {
493 src_saturation = amp_params[i].value; //(0.0, 10.0)
494 }else if(attrib == VAProcColorBalanceBrightness) {
495 src_brightness = amp_params[i].value; // (-100.0, 100.0)
496 brightness = intel_format_convert(src_brightness, 7, 4, 1);
497 }else if(attrib == VAProcColorBalanceContrast) {
498 src_contrast = amp_params[i].value; // (0.0, 10.0)
499 contrast = intel_format_convert(src_contrast, 4, 7, 0);
503 tmp_value = cos(src_hue/180*PI) * src_contrast * src_saturation;
504 cos_c_s = intel_format_convert(tmp_value, 7, 8, 1);
506 tmp_value = sin(src_hue/180*PI) * src_contrast * src_saturation;
507 sin_c_s = intel_format_convert(tmp_value, 7, 8, 1);
509 *p_table ++ = ( 0 << 28 | //reserved
510 contrast << 17 | //contrast value (U4.7 format)
512 brightness << 1| // S7.4 format
515 *p_table ++ = ( cos_c_s << 16 | // cos(h) * contrast * saturation
516 sin_c_s); // sin(h) * contrast * saturation
522 void hsw_veb_iecp_csc_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
524 unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 220);
525 float tran_coef[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
526 float v_coef[3] = {0.0, 0.0, 0.0};
527 float u_coef[3] = {0.0, 0.0, 0.0};
528 int is_transform_enabled = 0;
530 if(!(proc_ctx->filters_mask & VPP_IECP_CSC)){
531 memset(p_table, 0, 8 * 4);
535 if(proc_ctx->fourcc_input == VA_FOURCC_RGBA &&
536 (proc_ctx->fourcc_output == VA_FOURCC_NV12 ||
537 proc_ctx->fourcc_output == VA_FOURCC_YV12 ||
538 proc_ctx->fourcc_output == VA_FOURCC_YVY2 ||
539 proc_ctx->fourcc_output == VA_FOURCC_AYUV)) {
541 tran_coef[0] = 0.257;
542 tran_coef[1] = 0.504;
543 tran_coef[2] = 0.098;
544 tran_coef[3] = -0.148;
545 tran_coef[4] = -0.291;
546 tran_coef[5] = 0.439;
547 tran_coef[6] = 0.439;
548 tran_coef[7] = -0.368;
549 tran_coef[8] = -0.071;
555 is_transform_enabled = 1;
556 }else if((proc_ctx->fourcc_input == VA_FOURCC_NV12 ||
557 proc_ctx->fourcc_input == VA_FOURCC_YV12 ||
558 proc_ctx->fourcc_input == VA_FOURCC_YUY2 ||
559 proc_ctx->fourcc_input == VA_FOURCC_AYUV) &&
560 proc_ctx->fourcc_output == VA_FOURCC_RGBA) {
561 tran_coef[0] = 1.164;
562 tran_coef[1] = 0.000;
563 tran_coef[2] = 1.569;
564 tran_coef[3] = 1.164;
565 tran_coef[4] = -0.813;
566 tran_coef[5] = -0.392;
567 tran_coef[6] = 1.164;
568 tran_coef[7] = 2.017;
569 tran_coef[8] = 0.000;
572 v_coef[1] = -128 * 4;
573 v_coef[2] = -128 * 4;
575 is_transform_enabled = 1;
576 }else if(proc_ctx->fourcc_input != proc_ctx->fourcc_output){
577 //enable when input and output format are different.
578 is_transform_enabled = 1;
581 if(is_transform_enabled == 0){
582 memset(p_table, 0, 8 * 4);
584 *p_table ++ = ( 0 << 29 | //reserved
585 intel_format_convert(tran_coef[1], 2, 10, 1) << 16 | //c1, s2.10 format
586 intel_format_convert(tran_coef[0], 2, 10, 1) << 3 | //c0, s2.10 format
588 0 << 1 | // yuv_channel swap
589 is_transform_enabled);
591 *p_table ++ = ( 0 << 26 | //reserved
592 intel_format_convert(tran_coef[3], 2, 10, 1) << 13 |
593 intel_format_convert(tran_coef[2], 2, 10, 1));
595 *p_table ++ = ( 0 << 26 | //reserved
596 intel_format_convert(tran_coef[5], 2, 10, 1) << 13 |
597 intel_format_convert(tran_coef[4], 2, 10, 1));
599 *p_table ++ = ( 0 << 26 | //reserved
600 intel_format_convert(tran_coef[7], 2, 10, 1) << 13 |
601 intel_format_convert(tran_coef[6], 2, 10, 1));
603 *p_table ++ = ( 0 << 13 | //reserved
604 intel_format_convert(tran_coef[8], 2, 10, 1));
606 *p_table ++ = ( 0 << 22 | //reserved
607 intel_format_convert(u_coef[0], 10, 0, 1) << 11 |
608 intel_format_convert(v_coef[0], 10, 0, 1));
610 *p_table ++ = ( 0 << 22 | //reserved
611 intel_format_convert(u_coef[1], 10, 0, 1) << 11 |
612 intel_format_convert(v_coef[1], 10, 0, 1));
614 *p_table ++ = ( 0 << 22 | //reserved
615 intel_format_convert(u_coef[2], 10, 0, 1) << 11 |
616 intel_format_convert(v_coef[2], 10, 0, 1));
620 void hsw_veb_iecp_aoi_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
622 unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 252);
623 // VAProcFilterParameterBuffer * tcc_param =
624 // (VAProcFilterParameterBuffer *) proc_ctx->filter_iecp_tcc;
626 if(!(proc_ctx->filters_mask & VPP_IECP_AOI)){
627 memset(p_table, 0, 3 * 4);
629 *p_table ++ = 0x00000000;
630 *p_table ++ = 0x00030000;
631 *p_table ++ = 0x00030000;
635 void hsw_veb_state_table_setup(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
637 if(proc_ctx->filters_mask & 0x000000ff) {
638 dri_bo *dndi_bo = proc_ctx->dndi_state_table.bo;
639 dri_bo_map(dndi_bo, 1);
640 proc_ctx->dndi_state_table.ptr = dndi_bo->virtual;
642 hsw_veb_dndi_table(ctx, proc_ctx);
644 dri_bo_unmap(dndi_bo);
647 if(proc_ctx->filters_mask & 0x0000ff00) {
648 dri_bo *iecp_bo = proc_ctx->iecp_state_table.bo;
649 dri_bo_map(iecp_bo, 1);
650 proc_ctx->iecp_state_table.ptr = iecp_bo->virtual;
652 hsw_veb_iecp_std_table(ctx, proc_ctx);
653 hsw_veb_iecp_ace_table(ctx, proc_ctx);
654 hsw_veb_iecp_tcc_table(ctx, proc_ctx);
655 hsw_veb_iecp_pro_amp_table(ctx, proc_ctx);
656 hsw_veb_iecp_csc_table(ctx, proc_ctx);
657 hsw_veb_iecp_aoi_table(ctx, proc_ctx);
659 dri_bo_unmap(iecp_bo);
663 void hsw_veb_state_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
665 struct intel_batchbuffer *batch = proc_ctx->batch;
666 unsigned int is_dn_enabled = (proc_ctx->filters_mask & 0x01)? 1: 0;
667 unsigned int is_di_enabled = (proc_ctx->filters_mask & 0x02)? 1: 0;
668 unsigned int is_iecp_enabled = (proc_ctx->filters_mask & 0xff00)?1:0;
669 unsigned int is_first_frame = !!((proc_ctx->frame_order == -1) &&
672 unsigned int di_output_frames_flag = 2; /* Output Current Frame Only */
674 if(proc_ctx->fourcc_input != proc_ctx->fourcc_output ||
675 (is_dn_enabled == 0 && is_di_enabled == 0)){
680 VAProcFilterParameterBufferDeinterlacing *di_param =
681 (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
685 if (di_param->algorithm == VAProcDeinterlacingBob)
688 if ((di_param->algorithm == VAProcDeinterlacingMotionAdaptive ||
689 di_param->algorithm == VAProcDeinterlacingMotionCompensated) &&
690 proc_ctx->frame_order != -1)
691 di_output_frames_flag = 0; /* Output both Current Frame and Previous Frame */
694 BEGIN_VEB_BATCH(batch, 6);
695 OUT_VEB_BATCH(batch, VEB_STATE | (6 - 2));
697 0 << 26 | // state surface control bits
698 0 << 11 | // reserved.
699 0 << 10 | // pipe sync disable
700 di_output_frames_flag << 8 | // DI output frame
701 1 << 7 | // 444->422 downsample method
702 1 << 6 | // 422->420 downsample method
703 is_first_frame << 5 | // DN/DI first frame
704 is_di_enabled << 4 | // DI enable
705 is_dn_enabled << 3 | // DN enable
706 is_iecp_enabled << 2 | // global IECP enabled
707 0 << 1 | // ColorGamutCompressionEnable
708 0 ) ; // ColorGamutExpansionEnable.
711 proc_ctx->dndi_state_table.bo,
712 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
715 proc_ctx->iecp_state_table.bo,
716 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
719 proc_ctx->gamut_state_table.bo,
720 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
723 proc_ctx->vertex_state_table.bo,
724 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
726 ADVANCE_VEB_BATCH(batch);
729 void hsw_veb_surface_state(VADriverContextP ctx, struct intel_vebox_context *proc_ctx, unsigned int is_output)
731 struct intel_batchbuffer *batch = proc_ctx->batch;
732 unsigned int u_offset_y = 0, v_offset_y = 0;
733 unsigned int is_uv_interleaved = 0, tiling = 0, swizzle = 0;
734 unsigned int surface_format = PLANAR_420_8;
735 struct object_surface* obj_surf = NULL;
736 unsigned int surface_pitch = 0;
737 unsigned int half_pitch_chroma = 0;
740 obj_surf = proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface;
742 obj_surf = proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface;
745 assert(obj_surf->fourcc == VA_FOURCC_NV12 ||
746 obj_surf->fourcc == VA_FOURCC_YUY2 ||
747 obj_surf->fourcc == VA_FOURCC_AYUV ||
748 obj_surf->fourcc == VA_FOURCC_RGBA);
750 if (obj_surf->fourcc == VA_FOURCC_NV12) {
751 surface_format = PLANAR_420_8;
752 surface_pitch = obj_surf->width;
753 is_uv_interleaved = 1;
754 half_pitch_chroma = 0;
755 } else if (obj_surf->fourcc == VA_FOURCC_YUY2) {
756 surface_format = YCRCB_NORMAL;
757 surface_pitch = obj_surf->width * 2;
758 is_uv_interleaved = 0;
759 half_pitch_chroma = 0;
760 } else if (obj_surf->fourcc == VA_FOURCC_AYUV) {
761 surface_format = PACKED_444A_8;
762 surface_pitch = obj_surf->width * 4;
763 is_uv_interleaved = 0;
764 half_pitch_chroma = 0;
765 } else if (obj_surf->fourcc == VA_FOURCC_RGBA) {
766 surface_format = R8G8B8A8_UNORM_SRGB;
767 surface_pitch = obj_surf->width * 4;
768 is_uv_interleaved = 0;
769 half_pitch_chroma = 0;
772 u_offset_y = obj_surf->y_cb_offset;
773 v_offset_y = obj_surf->y_cr_offset;
775 dri_bo_get_tiling(obj_surf->bo, &tiling, &swizzle);
777 BEGIN_VEB_BATCH(batch, 6);
778 OUT_VEB_BATCH(batch, VEB_SURFACE_STATE | (6 - 2));
781 is_output); // surface indentification.
784 (obj_surf->height - 1) << 18 | // height . w3
785 (obj_surf->width -1 ) << 4 | // width
789 surface_format << 28 | // surface format, YCbCr420. w4
790 is_uv_interleaved << 27 | // interleave chrome , two seperate palar
791 0 << 20 | // reserved
792 (surface_pitch - 1) << 3 | // surface pitch, 64 align
793 half_pitch_chroma << 2 | // half pitch for chrome
794 !!tiling << 1 | // tiled surface, linear surface used
795 (tiling == I915_TILING_Y)); // tiled walk, ignored when liner surface
798 0 << 29 | // reserved . w5
799 0 << 16 | // X offset for V(Cb)
800 0 << 15 | // reserved
801 u_offset_y); // Y offset for V(Cb)
804 0 << 29 | // reserved . w6
805 0 << 16 | // X offset for V(Cr)
806 0 << 15 | // reserved
807 v_offset_y ); // Y offset for V(Cr)
809 ADVANCE_VEB_BATCH(batch);
812 void hsw_veb_dndi_iecp_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
814 struct intel_batchbuffer *batch = proc_ctx->batch;
815 unsigned char frame_ctrl_bits = 0;
816 unsigned int startingX = 0;
817 unsigned int endingX = (proc_ctx->width_input + 63 ) / 64 * 64;
819 /* s1:update the previous and current input */
820 /* tempFrame = proc_ctx->frame_store[FRAME_IN_PREVIOUS];
821 proc_ctx->frame_store[FRAME_IN_PREVIOUS] = proc_ctx->frame_store[FRAME_IN_CURRENT]; ;
822 proc_ctx->frame_store[FRAME_IN_CURRENT] = tempFrame;
824 if(proc_ctx->surface_input_vebox != -1){
825 vpp_surface_copy(ctx, proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id,
826 proc_ctx->surface_input_vebox);
828 vpp_surface_copy(ctx, proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id,
829 proc_ctx->surface_input);
832 /*s2: update the STMM input and output */
833 /* tempFrame = proc_ctx->frame_store[FRAME_IN_STMM];
834 proc_ctx->frame_store[FRAME_IN_STMM] = proc_ctx->frame_store[FRAME_OUT_STMM]; ;
835 proc_ctx->frame_store[FRAME_OUT_STMM] = tempFrame;
837 /*s3:set reloc buffer address */
838 BEGIN_VEB_BATCH(batch, 10);
839 OUT_VEB_BATCH(batch, VEB_DNDI_IECP_STATE | (10 - 2));
844 proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface->bo,
845 I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);
847 proc_ctx->frame_store[FRAME_IN_PREVIOUS].obj_surface->bo,
848 I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);
850 proc_ctx->frame_store[FRAME_IN_STMM].obj_surface->bo,
851 I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);
853 proc_ctx->frame_store[FRAME_OUT_STMM].obj_surface->bo,
854 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
856 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface->bo,
857 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
859 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface->bo,
860 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
862 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].obj_surface->bo,
863 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
865 proc_ctx->frame_store[FRAME_OUT_STATISTIC].obj_surface->bo,
866 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
868 ADVANCE_VEB_BATCH(batch);
871 void hsw_veb_resource_prepare(VADriverContextP ctx,
872 struct intel_vebox_context *proc_ctx)
876 struct i965_driver_data *i965 = i965_driver_data(ctx);
877 unsigned int input_fourcc, output_fourcc;
878 unsigned int input_sampling, output_sampling;
879 unsigned int input_tiling, output_tiling;
880 unsigned int i, swizzle;
881 struct object_surface *obj_surf_out = NULL, *obj_surf_in = NULL;
883 if (proc_ctx->surface_input_vebox_object != NULL) {
884 obj_surf_in = proc_ctx->surface_input_vebox_object;
886 obj_surf_in = proc_ctx->surface_input_object;
889 if (proc_ctx->surface_output_vebox_object != NULL) {
890 obj_surf_out = proc_ctx->surface_output_vebox_object;
892 obj_surf_out = proc_ctx->surface_output_object;
895 if(obj_surf_in->bo == NULL){
896 input_fourcc = VA_FOURCC_NV12;
897 input_sampling = SUBSAMPLE_YUV420;
899 i965_check_alloc_surface_bo(ctx, obj_surf_in, input_tiling, input_fourcc, input_sampling);
901 input_fourcc = obj_surf_in->fourcc;
902 input_sampling = obj_surf_in->subsampling;
903 dri_bo_get_tiling(obj_surf_in->bo, &input_tiling, &swizzle);
904 input_tiling = !!input_tiling;
907 if(obj_surf_out->bo == NULL){
908 output_fourcc = VA_FOURCC_NV12;
909 output_sampling = SUBSAMPLE_YUV420;
911 i965_check_alloc_surface_bo(ctx, obj_surf_out, output_tiling, output_fourcc, output_sampling);
913 output_fourcc = obj_surf_out->fourcc;
914 output_sampling = obj_surf_out->subsampling;
915 dri_bo_get_tiling(obj_surf_out->bo, &output_tiling, &swizzle);
916 output_tiling = !!output_tiling;
919 /* vebox pipelien input surface format info */
920 proc_ctx->fourcc_input = input_fourcc;
921 proc_ctx->fourcc_output = output_fourcc;
923 /* create pipeline surfaces */
924 for(i = 0; i < FRAME_STORE_SUM; i ++) {
925 if(proc_ctx->frame_store[i].obj_surface){
926 continue; //refer external surface for vebox pipeline
929 VASurfaceID new_surface;
930 struct object_surface *obj_surf = NULL;
932 va_status = i965_CreateSurfaces(ctx,
933 proc_ctx ->width_input,
934 proc_ctx ->height_input,
938 assert(va_status == VA_STATUS_SUCCESS);
940 obj_surf = SURFACE(new_surface);
943 if( i <= FRAME_IN_PREVIOUS || i == FRAME_OUT_CURRENT_DN) {
944 i965_check_alloc_surface_bo(ctx, obj_surf, input_tiling, input_fourcc, input_sampling);
945 } else if( i == FRAME_IN_STMM || i == FRAME_OUT_STMM){
946 i965_check_alloc_surface_bo(ctx, obj_surf, 1, input_fourcc, input_sampling);
947 } else if( i >= FRAME_OUT_CURRENT){
948 i965_check_alloc_surface_bo(ctx, obj_surf, output_tiling, output_fourcc, output_sampling);
951 proc_ctx->frame_store[i].surface_id = new_surface;
952 proc_ctx->frame_store[i].is_internal_surface = 1;
953 proc_ctx->frame_store[i].obj_surface = obj_surf;
956 /* alloc dndi state table */
957 dri_bo_unreference(proc_ctx->dndi_state_table.bo);
958 bo = dri_bo_alloc(i965->intel.bufmgr,
959 "vebox: dndi state Buffer",
961 proc_ctx->dndi_state_table.bo = bo;
962 dri_bo_reference(proc_ctx->dndi_state_table.bo);
964 /* alloc iecp state table */
965 dri_bo_unreference(proc_ctx->iecp_state_table.bo);
966 bo = dri_bo_alloc(i965->intel.bufmgr,
967 "vebox: iecp state Buffer",
969 proc_ctx->iecp_state_table.bo = bo;
970 dri_bo_reference(proc_ctx->iecp_state_table.bo);
972 /* alloc gamut state table */
973 dri_bo_unreference(proc_ctx->gamut_state_table.bo);
974 bo = dri_bo_alloc(i965->intel.bufmgr,
975 "vebox: gamut state Buffer",
977 proc_ctx->gamut_state_table.bo = bo;
978 dri_bo_reference(proc_ctx->gamut_state_table.bo);
980 /* alloc vertex state table */
981 dri_bo_unreference(proc_ctx->vertex_state_table.bo);
982 bo = dri_bo_alloc(i965->intel.bufmgr,
983 "vertex: iecp state Buffer",
985 proc_ctx->vertex_state_table.bo = bo;
986 dri_bo_reference(proc_ctx->vertex_state_table.bo);
991 hsw_veb_surface_reference(VADriverContextP ctx,
992 struct intel_vebox_context *proc_ctx)
994 struct object_surface * obj_surf;
995 VEBFrameStore tmp_store;
997 if (proc_ctx->surface_input_vebox_object != NULL) {
998 obj_surf = proc_ctx->surface_input_vebox_object;
1000 obj_surf = proc_ctx->surface_input_object;
1003 /* update the input surface */
1004 proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id = VA_INVALID_ID;
1005 proc_ctx->frame_store[FRAME_IN_CURRENT].is_internal_surface = 0;
1006 proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface = obj_surf;
1008 /* update the previous input surface */
1009 if (proc_ctx->frame_order != -1) {
1010 if (proc_ctx->filters_mask == VPP_DNDI_DN) {
1011 proc_ctx->frame_store[FRAME_IN_PREVIOUS] = proc_ctx->frame_store[FRAME_OUT_CURRENT_DN];
1012 } else if (proc_ctx->filters_mask & VPP_DNDI_DI) {
1013 VAProcFilterParameterBufferDeinterlacing *di_param =
1014 (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
1017 (di_param->algorithm == VAProcDeinterlacingMotionAdaptive ||
1018 di_param->algorithm == VAProcDeinterlacingMotionCompensated)) {
1019 if ((proc_ctx->filters_mask & VPP_DNDI_DN) &&
1020 proc_ctx->frame_order == 0) { /* DNDI */
1021 tmp_store = proc_ctx->frame_store[FRAME_OUT_CURRENT_DN];
1022 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN] = proc_ctx->frame_store[FRAME_IN_PREVIOUS];
1023 proc_ctx->frame_store[FRAME_IN_PREVIOUS] = tmp_store;
1024 } else { /* DI only */
1025 VAProcPipelineParameterBuffer *pipe = proc_ctx->pipeline_param;
1026 struct object_surface *obj_surf = NULL;
1027 struct i965_driver_data * const i965 = i965_driver_data(ctx);
1030 !pipe->num_forward_references ||
1031 pipe->forward_references[0] == VA_INVALID_ID) {
1032 WARN_ONCE("A forward temporal reference is needed for Motion adaptive/compensated deinterlacing !!!\n");
1034 return VA_STATUS_ERROR_INVALID_PARAMETER;
1037 obj_surf = SURFACE(pipe->forward_references[0]);
1038 assert(obj_surf && obj_surf->bo);
1040 proc_ctx->frame_store[FRAME_IN_PREVIOUS].surface_id = pipe->forward_references[0];
1041 proc_ctx->frame_store[FRAME_IN_PREVIOUS].is_internal_surface = 0;
1042 proc_ctx->frame_store[FRAME_IN_PREVIOUS].obj_surface = obj_surf;
1048 /* update STMM surface */
1049 if (proc_ctx->frame_order != -1) {
1050 tmp_store = proc_ctx->frame_store[FRAME_IN_STMM];
1051 proc_ctx->frame_store[FRAME_IN_STMM] = proc_ctx->frame_store[FRAME_OUT_STMM];
1052 proc_ctx->frame_store[FRAME_OUT_STMM] = tmp_store;
1055 /* update the output surface */
1056 if (proc_ctx->surface_output_vebox_object != NULL) {
1057 obj_surf = proc_ctx->surface_output_vebox_object;
1059 obj_surf = proc_ctx->surface_output_object;
1062 if (proc_ctx->filters_mask == VPP_DNDI_DN) {
1063 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].surface_id = VA_INVALID_ID;
1064 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].is_internal_surface = 0;
1065 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface = obj_surf;
1066 proc_ctx->current_output = FRAME_OUT_CURRENT_DN;
1067 } else if (proc_ctx->filters_mask & VPP_DNDI_DI) {
1068 VAProcFilterParameterBufferDeinterlacing *di_param =
1069 (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
1072 (di_param->algorithm == VAProcDeinterlacingMotionAdaptive ||
1073 di_param->algorithm == VAProcDeinterlacingMotionCompensated)) {
1074 if (proc_ctx->frame_order == -1) {
1075 proc_ctx->frame_store[FRAME_OUT_CURRENT].surface_id = VA_INVALID_ID;
1076 proc_ctx->frame_store[FRAME_OUT_CURRENT].is_internal_surface = 0;
1077 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface = obj_surf;
1078 proc_ctx->current_output = FRAME_OUT_CURRENT;
1079 } else if (proc_ctx->frame_order == 0) {
1080 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].surface_id = VA_INVALID_ID;
1081 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].is_internal_surface = 0;
1082 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].obj_surface = obj_surf;
1083 proc_ctx->current_output = FRAME_OUT_PREVIOUS;
1085 proc_ctx->current_output = FRAME_OUT_CURRENT;
1086 proc_ctx->format_convert_flags |= POST_COPY_CONVERT;
1089 proc_ctx->frame_store[FRAME_OUT_CURRENT].surface_id = VA_INVALID_ID;
1090 proc_ctx->frame_store[FRAME_OUT_CURRENT].is_internal_surface = 0;
1091 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface = obj_surf;
1092 proc_ctx->current_output = FRAME_OUT_CURRENT;
1095 proc_ctx->frame_store[FRAME_OUT_CURRENT].surface_id = VA_INVALID_ID;
1096 proc_ctx->frame_store[FRAME_OUT_CURRENT].is_internal_surface = 0;
1097 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface = obj_surf;
1098 proc_ctx->current_output = FRAME_OUT_CURRENT;
1101 return VA_STATUS_SUCCESS;
1104 void hsw_veb_surface_unreference(VADriverContextP ctx,
1105 struct intel_vebox_context *proc_ctx)
1107 /* unreference the input surface */
1108 proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id = VA_INVALID_ID;
1109 proc_ctx->frame_store[FRAME_IN_CURRENT].is_internal_surface = 0;
1110 proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface = NULL;
1112 /* unreference the shared output surface */
1113 if (proc_ctx->filters_mask == VPP_DNDI_DN) {
1114 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].surface_id = VA_INVALID_ID;
1115 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].is_internal_surface = 0;
1116 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface = NULL;
1118 proc_ctx->frame_store[FRAME_OUT_CURRENT].surface_id = VA_INVALID_ID;
1119 proc_ctx->frame_store[FRAME_OUT_CURRENT].is_internal_surface = 0;
1120 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface = NULL;
1124 int hsw_veb_pre_format_convert(VADriverContextP ctx,
1125 struct intel_vebox_context *proc_ctx)
1128 struct i965_driver_data *i965 = i965_driver_data(ctx);
1129 struct object_surface* obj_surf_input = proc_ctx->surface_input_object;
1130 struct object_surface* obj_surf_output = proc_ctx->surface_output_object;
1131 struct object_surface* obj_surf_input_vebox;
1132 struct object_surface* obj_surf_output_vebox;
1134 proc_ctx->format_convert_flags = 0;
1136 proc_ctx->width_input = obj_surf_input->orig_width;
1137 proc_ctx->height_input = obj_surf_input->orig_height;
1138 proc_ctx->width_output = obj_surf_output->orig_width;
1139 proc_ctx->height_output = obj_surf_output->orig_height;
1141 /* only partial frame is not supported to be processed */
1143 assert(proc_ctx->width_input == proc_ctx->pipeline_param->surface_region->width);
1144 assert(proc_ctx->height_input == proc_ctx->pipeline_param->surface_region->height);
1145 assert(proc_ctx->width_output == proc_ctx->pipeline_param->output_region->width);
1146 assert(proc_ctx->height_output == proc_ctx->pipeline_param->output_region->height);
1149 if(proc_ctx->width_output != proc_ctx->width_input ||
1150 proc_ctx->height_output != proc_ctx->height_input){
1151 proc_ctx->format_convert_flags |= POST_SCALING_CONVERT;
1154 /* convert the following format to NV12 format */
1155 if(obj_surf_input->fourcc == VA_FOURCC_YV12 ||
1156 obj_surf_input->fourcc == VA_FOURCC_I420 ||
1157 obj_surf_input->fourcc == VA_FOURCC_IMC1 ||
1158 obj_surf_input->fourcc == VA_FOURCC_IMC3 ||
1159 obj_surf_input->fourcc == VA_FOURCC_RGBA){
1161 proc_ctx->format_convert_flags |= PRE_FORMAT_CONVERT;
1163 } else if(obj_surf_input->fourcc == VA_FOURCC_AYUV ||
1164 obj_surf_input->fourcc == VA_FOURCC_YUY2 ||
1165 obj_surf_input->fourcc == VA_FOURCC_NV12){
1166 // nothing to do here
1168 /* not support other format as input */
1172 if (proc_ctx->format_convert_flags & PRE_FORMAT_CONVERT) {
1173 if(proc_ctx->surface_input_vebox_object == NULL){
1174 va_status = i965_CreateSurfaces(ctx,
1175 proc_ctx->width_input,
1176 proc_ctx->height_input,
1177 VA_RT_FORMAT_YUV420,
1179 &(proc_ctx->surface_input_vebox));
1180 assert(va_status == VA_STATUS_SUCCESS);
1181 obj_surf_input_vebox = SURFACE(proc_ctx->surface_input_vebox);
1182 assert(obj_surf_input_vebox);
1184 if (obj_surf_input_vebox) {
1185 proc_ctx->surface_input_vebox_object = obj_surf_input_vebox;
1186 i965_check_alloc_surface_bo(ctx, obj_surf_input_vebox, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
1190 vpp_surface_convert(ctx, proc_ctx->surface_input_vebox_object, proc_ctx->surface_input_object);
1193 /* create one temporary NV12 surfaces for conversion*/
1194 if(obj_surf_output->fourcc == VA_FOURCC_YV12 ||
1195 obj_surf_output->fourcc == VA_FOURCC_I420 ||
1196 obj_surf_output->fourcc == VA_FOURCC_IMC1 ||
1197 obj_surf_output->fourcc == VA_FOURCC_IMC3 ||
1198 obj_surf_output->fourcc == VA_FOURCC_RGBA) {
1200 proc_ctx->format_convert_flags |= POST_FORMAT_CONVERT;
1201 } else if(obj_surf_output->fourcc == VA_FOURCC_AYUV ||
1202 obj_surf_output->fourcc == VA_FOURCC_YUY2 ||
1203 obj_surf_output->fourcc == VA_FOURCC_NV12){
1204 /* Nothing to do here */
1206 /* not support other format as input */
1210 if(proc_ctx->format_convert_flags & POST_FORMAT_CONVERT ||
1211 proc_ctx->format_convert_flags & POST_SCALING_CONVERT){
1212 if(proc_ctx->surface_output_vebox_object == NULL){
1213 va_status = i965_CreateSurfaces(ctx,
1214 proc_ctx->width_input,
1215 proc_ctx->height_input,
1216 VA_RT_FORMAT_YUV420,
1218 &(proc_ctx->surface_output_vebox));
1219 assert(va_status == VA_STATUS_SUCCESS);
1220 obj_surf_output_vebox = SURFACE(proc_ctx->surface_output_vebox);
1221 assert(obj_surf_output_vebox);
1223 if (obj_surf_output_vebox) {
1224 proc_ctx->surface_output_vebox_object = obj_surf_output_vebox;
1225 i965_check_alloc_surface_bo(ctx, obj_surf_output_vebox, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
1230 if(proc_ctx->format_convert_flags & POST_SCALING_CONVERT){
1231 if(proc_ctx->surface_output_scaled_object == NULL){
1232 va_status = i965_CreateSurfaces(ctx,
1233 proc_ctx->width_output,
1234 proc_ctx->height_output,
1235 VA_RT_FORMAT_YUV420,
1237 &(proc_ctx->surface_output_scaled));
1238 assert(va_status == VA_STATUS_SUCCESS);
1239 obj_surf_output_vebox = SURFACE(proc_ctx->surface_output_scaled);
1240 assert(obj_surf_output_vebox);
1242 if (obj_surf_output_vebox) {
1243 proc_ctx->surface_output_scaled_object = obj_surf_output_vebox;
1244 i965_check_alloc_surface_bo(ctx, obj_surf_output_vebox, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
1252 int hsw_veb_post_format_convert(VADriverContextP ctx,
1253 struct intel_vebox_context *proc_ctx)
1255 struct object_surface *obj_surface = NULL;
1257 obj_surface = proc_ctx->frame_store[proc_ctx->current_output].obj_surface;
1259 if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) {
1260 /* copy the saved frame in the second call */
1261 vpp_surface_convert(ctx,proc_ctx->surface_output_object, obj_surface);
1262 } else if(!(proc_ctx->format_convert_flags & POST_FORMAT_CONVERT) &&
1263 !(proc_ctx->format_convert_flags & POST_SCALING_CONVERT)){
1264 /* Output surface format is covered by vebox pipeline and
1265 * processed picture is already store in output surface
1266 * so nothing will be done here */
1267 } else if ((proc_ctx->format_convert_flags & POST_FORMAT_CONVERT) &&
1268 !(proc_ctx->format_convert_flags & POST_SCALING_CONVERT)){
1269 /* convert and copy NV12 to YV12/IMC3/IMC2/RGBA output*/
1270 vpp_surface_convert(ctx,proc_ctx->surface_output_object, obj_surface);
1272 } else if(proc_ctx->format_convert_flags & POST_SCALING_CONVERT) {
1273 /* scaling, convert and copy NV12 to YV12/IMC3/IMC2/RGBA output*/
1274 assert(obj_surface->fourcc == VA_FOURCC_NV12);
1276 /* first step :surface scaling */
1277 vpp_surface_scaling(ctx,proc_ctx->surface_output_scaled_object, obj_surface);
1279 /* second step: color format convert and copy to output */
1280 obj_surface = proc_ctx->surface_output_object;
1282 if(obj_surface->fourcc == VA_FOURCC_NV12 ||
1283 obj_surface->fourcc == VA_FOURCC_YV12 ||
1284 obj_surface->fourcc == VA_FOURCC_I420 ||
1285 obj_surface->fourcc == VA_FOURCC_YUY2 ||
1286 obj_surface->fourcc == VA_FOURCC_IMC1 ||
1287 obj_surface->fourcc == VA_FOURCC_IMC3 ||
1288 obj_surface->fourcc == VA_FOURCC_RGBA) {
1289 vpp_surface_convert(ctx, proc_ctx->surface_output_object, proc_ctx->surface_output_scaled_object);
1298 VAStatus gen75_vebox_process_picture(VADriverContextP ctx,
1299 struct intel_vebox_context *proc_ctx)
1301 struct i965_driver_data *i965 = i965_driver_data(ctx);
1303 VAProcPipelineParameterBuffer *pipe = proc_ctx->pipeline_param;
1304 VAProcFilterParameterBuffer* filter = NULL;
1305 struct object_buffer *obj_buf = NULL;
1308 for (i = 0; i < pipe->num_filters; i ++) {
1309 obj_buf = BUFFER(pipe->filters[i]);
1311 assert(obj_buf && obj_buf->buffer_store);
1313 if (!obj_buf || !obj_buf->buffer_store)
1316 filter = (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
1318 if (filter->type == VAProcFilterNoiseReduction) {
1319 proc_ctx->filters_mask |= VPP_DNDI_DN;
1320 proc_ctx->filter_dn = filter;
1321 } else if (filter->type == VAProcFilterDeinterlacing) {
1322 proc_ctx->filters_mask |= VPP_DNDI_DI;
1323 proc_ctx->filter_di = filter;
1324 } else if (filter->type == VAProcFilterColorBalance) {
1325 proc_ctx->filters_mask |= VPP_IECP_PRO_AMP;
1326 proc_ctx->filter_iecp_amp = filter;
1327 proc_ctx->filter_iecp_amp_num_elements = obj_buf->num_elements;
1328 } else if (filter->type == VAProcFilterSkinToneEnhancement) {
1329 proc_ctx->filters_mask |= VPP_IECP_STD_STE;
1330 proc_ctx->filter_iecp_std = filter;
1334 hsw_veb_pre_format_convert(ctx, proc_ctx);
1335 hsw_veb_surface_reference(ctx, proc_ctx);
1337 if (proc_ctx->frame_order == -1) {
1338 hsw_veb_resource_prepare(ctx, proc_ctx);
1341 if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) {
1342 assert(proc_ctx->frame_order == 1);
1343 /* directly copy the saved frame in the second call */
1345 intel_batchbuffer_start_atomic_veb(proc_ctx->batch, 0x1000);
1346 intel_batchbuffer_emit_mi_flush(proc_ctx->batch);
1347 hsw_veb_surface_state(ctx, proc_ctx, INPUT_SURFACE);
1348 hsw_veb_surface_state(ctx, proc_ctx, OUTPUT_SURFACE);
1349 hsw_veb_state_table_setup(ctx, proc_ctx);
1351 hsw_veb_state_command(ctx, proc_ctx);
1352 hsw_veb_dndi_iecp_command(ctx, proc_ctx);
1353 intel_batchbuffer_end_atomic(proc_ctx->batch);
1354 intel_batchbuffer_flush(proc_ctx->batch);
1357 hsw_veb_post_format_convert(ctx, proc_ctx);
1358 // hsw_veb_surface_unreference(ctx, proc_ctx);
1360 proc_ctx->frame_order = (proc_ctx->frame_order + 1) % 2;
1362 return VA_STATUS_SUCCESS;
1365 return VA_STATUS_ERROR_INVALID_PARAMETER;
1368 void gen75_vebox_context_destroy(VADriverContextP ctx,
1369 struct intel_vebox_context *proc_ctx)
1373 if(proc_ctx->surface_input_vebox != VA_INVALID_ID){
1374 i965_DestroySurfaces(ctx, &proc_ctx->surface_input_vebox, 1);
1375 proc_ctx->surface_input_vebox = VA_INVALID_ID;
1376 proc_ctx->surface_input_vebox_object = NULL;
1379 if(proc_ctx->surface_output_vebox != VA_INVALID_ID){
1380 i965_DestroySurfaces(ctx, &proc_ctx->surface_output_vebox, 1);
1381 proc_ctx->surface_output_vebox = VA_INVALID_ID;
1382 proc_ctx->surface_output_vebox_object = NULL;
1385 if(proc_ctx->surface_output_scaled != VA_INVALID_ID){
1386 i965_DestroySurfaces(ctx, &proc_ctx->surface_output_scaled, 1);
1387 proc_ctx->surface_output_scaled = VA_INVALID_ID;
1388 proc_ctx->surface_output_scaled_object = NULL;
1391 for(i = 0; i < FRAME_STORE_SUM; i ++) {
1392 if (proc_ctx->frame_store[i].is_internal_surface == 1) {
1393 assert(proc_ctx->frame_store[i].surface_id != VA_INVALID_ID);
1395 if (proc_ctx->frame_store[i].surface_id != VA_INVALID_ID)
1396 i965_DestroySurfaces(ctx, &proc_ctx->frame_store[i].surface_id, 1);
1399 proc_ctx->frame_store[i].surface_id = VA_INVALID_ID;
1400 proc_ctx->frame_store[i].is_internal_surface = 0;
1401 proc_ctx->frame_store[i].obj_surface = NULL;
1404 /* dndi state table */
1405 dri_bo_unreference(proc_ctx->dndi_state_table.bo);
1406 proc_ctx->dndi_state_table.bo = NULL;
1408 /* iecp state table */
1409 dri_bo_unreference(proc_ctx->iecp_state_table.bo);
1410 proc_ctx->dndi_state_table.bo = NULL;
1412 /* gamut statu table */
1413 dri_bo_unreference(proc_ctx->gamut_state_table.bo);
1414 proc_ctx->gamut_state_table.bo = NULL;
1416 /* vertex state table */
1417 dri_bo_unreference(proc_ctx->vertex_state_table.bo);
1418 proc_ctx->vertex_state_table.bo = NULL;
1420 intel_batchbuffer_free(proc_ctx->batch);
1425 struct intel_vebox_context * gen75_vebox_context_init(VADriverContextP ctx)
1427 struct intel_driver_data *intel = intel_driver_data(ctx);
1428 struct intel_vebox_context *proc_context = calloc(1, sizeof(struct intel_vebox_context));
1431 proc_context->batch = intel_batchbuffer_new(intel, I915_EXEC_VEBOX, 0);
1432 memset(proc_context->frame_store, 0, sizeof(VEBFrameStore)*FRAME_STORE_SUM);
1434 for (i = 0; i < FRAME_STORE_SUM; i ++) {
1435 proc_context->frame_store[i].surface_id = VA_INVALID_ID;
1436 proc_context->frame_store[i].is_internal_surface = 0;
1437 proc_context->frame_store[i].obj_surface = NULL;
1440 proc_context->filters_mask = 0;
1441 proc_context->frame_order = -1; /* the first frame */
1442 proc_context->surface_output_object = NULL;
1443 proc_context->surface_input_object = NULL;
1444 proc_context->surface_input_vebox = VA_INVALID_ID;
1445 proc_context->surface_input_vebox_object = NULL;
1446 proc_context->surface_output_vebox = VA_INVALID_ID;
1447 proc_context->surface_output_vebox_object = NULL;
1448 proc_context->surface_output_scaled = VA_INVALID_ID;
1449 proc_context->surface_output_scaled_object = NULL;
1450 proc_context->filters_mask = 0;
1451 proc_context->format_convert_flags = 0;
1453 return proc_context;
1456 void bdw_veb_state_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
1458 struct intel_batchbuffer *batch = proc_ctx->batch;
1459 unsigned int is_dn_enabled = (proc_ctx->filters_mask & 0x01)? 1: 0;
1460 unsigned int is_di_enabled = (proc_ctx->filters_mask & 0x02)? 1: 0;
1461 unsigned int is_iecp_enabled = (proc_ctx->filters_mask & 0xff00)?1:0;
1462 unsigned int is_first_frame = !!((proc_ctx->frame_order == -1) &&
1465 unsigned int di_output_frames_flag = 2; /* Output Current Frame Only */
1467 if(proc_ctx->fourcc_input != proc_ctx->fourcc_output ||
1468 (is_dn_enabled == 0 && is_di_enabled == 0)){
1469 is_iecp_enabled = 1;
1472 if (is_di_enabled) {
1473 VAProcFilterParameterBufferDeinterlacing *di_param =
1474 (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
1478 if (di_param->algorithm == VAProcDeinterlacingBob)
1481 if ((di_param->algorithm == VAProcDeinterlacingMotionAdaptive ||
1482 di_param->algorithm == VAProcDeinterlacingMotionCompensated) &&
1483 proc_ctx->frame_order != -1)
1484 di_output_frames_flag = 0; /* Output both Current Frame and Previous Frame */
1487 BEGIN_VEB_BATCH(batch, 0xc);
1488 OUT_VEB_BATCH(batch, VEB_STATE | (0xc - 2));
1489 OUT_VEB_BATCH(batch,
1490 0 << 25 | // state surface control bits
1491 0 << 23 | // reserved.
1492 0 << 22 | // gamut expansion position
1493 0 << 15 | // reserved.
1494 0 << 14 | // single slice vebox enable
1495 0 << 13 | // hot pixel filter enable
1496 0 << 12 | // alpha plane enable
1497 0 << 11 | // vignette enable
1498 0 << 10 | // demosaic enable
1499 di_output_frames_flag << 8 | // DI output frame
1500 1 << 7 | // 444->422 downsample method
1501 1 << 6 | // 422->420 downsample method
1502 is_first_frame << 5 | // DN/DI first frame
1503 is_di_enabled << 4 | // DI enable
1504 is_dn_enabled << 3 | // DN enable
1505 is_iecp_enabled << 2 | // global IECP enabled
1506 0 << 1 | // ColorGamutCompressionEnable
1507 0 ) ; // ColorGamutExpansionEnable.
1510 proc_ctx->dndi_state_table.bo,
1511 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
1513 OUT_VEB_BATCH(batch, 0);
1516 proc_ctx->iecp_state_table.bo,
1517 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
1519 OUT_VEB_BATCH(batch, 0);
1522 proc_ctx->gamut_state_table.bo,
1523 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
1525 OUT_VEB_BATCH(batch, 0);
1528 proc_ctx->vertex_state_table.bo,
1529 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
1531 OUT_VEB_BATCH(batch, 0);
1533 OUT_VEB_BATCH(batch, 0);/*caputre pipe state pointer*/
1534 OUT_VEB_BATCH(batch, 0);
1536 ADVANCE_VEB_BATCH(batch);
1539 void bdw_veb_dndi_iecp_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
1541 struct intel_batchbuffer *batch = proc_ctx->batch;
1542 unsigned char frame_ctrl_bits = 0;
1543 unsigned int startingX = 0;
1544 unsigned int endingX = (proc_ctx->width_input + 63 ) / 64 * 64;
1546 BEGIN_VEB_BATCH(batch, 0x14);
1547 OUT_VEB_BATCH(batch, VEB_DNDI_IECP_STATE | (0x14 - 2));//DWord 0
1548 OUT_VEB_BATCH(batch,
1550 endingX -1);//DWord 1
1553 proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface->bo,
1554 I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);//DWord 2
1555 OUT_VEB_BATCH(batch,0);//DWord 3
1558 proc_ctx->frame_store[FRAME_IN_PREVIOUS].obj_surface->bo,
1559 I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);//DWord 4
1560 OUT_VEB_BATCH(batch,0);//DWord 5
1563 proc_ctx->frame_store[FRAME_IN_STMM].obj_surface->bo,
1564 I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);//DWord 6
1565 OUT_VEB_BATCH(batch,0);//DWord 7
1568 proc_ctx->frame_store[FRAME_OUT_STMM].obj_surface->bo,
1569 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 8
1570 OUT_VEB_BATCH(batch,0);//DWord 9
1573 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface->bo,
1574 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 10
1575 OUT_VEB_BATCH(batch,0);//DWord 11
1578 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface->bo,
1579 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 12
1580 OUT_VEB_BATCH(batch,0);//DWord 13
1583 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].obj_surface->bo,
1584 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 14
1585 OUT_VEB_BATCH(batch,0);//DWord 15
1588 proc_ctx->frame_store[FRAME_OUT_STATISTIC].obj_surface->bo,
1589 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 16
1590 OUT_VEB_BATCH(batch,0);//DWord 17
1592 OUT_VEB_BATCH(batch,0);//DWord 18
1593 OUT_VEB_BATCH(batch,0);//DWord 19
1595 ADVANCE_VEB_BATCH(batch);
1598 VAStatus gen8_vebox_process_picture(VADriverContextP ctx,
1599 struct intel_vebox_context *proc_ctx)
1601 struct i965_driver_data *i965 = i965_driver_data(ctx);
1603 VAProcPipelineParameterBuffer *pipe = proc_ctx->pipeline_param;
1604 VAProcFilterParameterBuffer* filter = NULL;
1605 struct object_buffer *obj_buf = NULL;
1608 for (i = 0; i < pipe->num_filters; i ++) {
1609 obj_buf = BUFFER(pipe->filters[i]);
1611 assert(obj_buf && obj_buf->buffer_store);
1613 if (!obj_buf || !obj_buf->buffer_store)
1616 filter = (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
1618 if (filter->type == VAProcFilterNoiseReduction) {
1619 proc_ctx->filters_mask |= VPP_DNDI_DN;
1620 proc_ctx->filter_dn = filter;
1621 } else if (filter->type == VAProcFilterDeinterlacing) {
1622 proc_ctx->filters_mask |= VPP_DNDI_DI;
1623 proc_ctx->filter_di = filter;
1624 } else if (filter->type == VAProcFilterColorBalance) {
1625 proc_ctx->filters_mask |= VPP_IECP_PRO_AMP;
1626 proc_ctx->filter_iecp_amp = filter;
1627 proc_ctx->filter_iecp_amp_num_elements = obj_buf->num_elements;
1628 } else if (filter->type == VAProcFilterSkinToneEnhancement) {
1629 proc_ctx->filters_mask |= VPP_IECP_STD_STE;
1630 proc_ctx->filter_iecp_std = filter;
1634 hsw_veb_pre_format_convert(ctx, proc_ctx);
1635 hsw_veb_surface_reference(ctx, proc_ctx);
1637 if (proc_ctx->frame_order == -1) {
1638 hsw_veb_resource_prepare(ctx, proc_ctx);
1641 if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) {
1642 assert(proc_ctx->frame_order == 1);
1643 /* directly copy the saved frame in the second call */
1645 intel_batchbuffer_start_atomic_veb(proc_ctx->batch, 0x1000);
1646 intel_batchbuffer_emit_mi_flush(proc_ctx->batch);
1647 hsw_veb_surface_state(ctx, proc_ctx, INPUT_SURFACE);
1648 hsw_veb_surface_state(ctx, proc_ctx, OUTPUT_SURFACE);
1649 hsw_veb_state_table_setup(ctx, proc_ctx);
1651 bdw_veb_state_command(ctx, proc_ctx);
1652 bdw_veb_dndi_iecp_command(ctx, proc_ctx);
1653 intel_batchbuffer_end_atomic(proc_ctx->batch);
1654 intel_batchbuffer_flush(proc_ctx->batch);
1657 hsw_veb_post_format_convert(ctx, proc_ctx);
1658 // hsw_veb_surface_unreference(ctx, proc_ctx);
1660 proc_ctx->frame_order = (proc_ctx->frame_order + 1) % 2;
1662 return VA_STATUS_SUCCESS;
1665 return VA_STATUS_ERROR_INVALID_PARAMETER;