/* * Copyright © 2011 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Li Xiaowei * Li Zhong */ #include #include #include #include #include #include "intel_batchbuffer.h" #include "intel_driver.h" #include "i965_defines.h" #include "i965_structs.h" #include "gen75_vpp_vebox.h" #include "intel_media.h" #include "i965_post_processing.h" #define PI 3.1415926 extern VAStatus i965_MapBuffer(VADriverContextP ctx, VABufferID buf_id, void **); extern VAStatus i965_UnmapBuffer(VADriverContextP ctx, VABufferID buf_id); extern VAStatus i965_DeriveImage(VADriverContextP ctx, VABufferID surface, VAImage *out_image); extern VAStatus i965_DestroyImage(VADriverContextP ctx, VAImageID image); VAStatus vpp_surface_convert(VADriverContextP ctx, struct object_surface *src_obj_surf, struct object_surface *dst_obj_surf) { VAStatus va_status = VA_STATUS_SUCCESS; assert(src_obj_surf->orig_width == dst_obj_surf->orig_width); assert(src_obj_surf->orig_height == dst_obj_surf->orig_height); VARectangle src_rect, dst_rect; src_rect.x = dst_rect.x = 0; src_rect.y = dst_rect.y = 0; src_rect.width = dst_rect.width = src_obj_surf->orig_width; src_rect.height = dst_rect.height = dst_obj_surf->orig_height; struct i965_surface src_surface, dst_surface; src_surface.base = (struct object_base *)src_obj_surf; src_surface.type = I965_SURFACE_TYPE_SURFACE; src_surface.flags = I965_SURFACE_FLAG_FRAME; dst_surface.base = (struct object_base *)dst_obj_surf; dst_surface.type = I965_SURFACE_TYPE_SURFACE; dst_surface.flags = I965_SURFACE_FLAG_FRAME; va_status = i965_image_processing(ctx, &src_surface, &src_rect, &dst_surface, &dst_rect); return va_status; } static VAStatus vpp_surface_scaling(VADriverContextP ctx, struct object_surface *src_obj_surf, struct object_surface *dst_obj_surf, uint32_t flags) { VAStatus va_status = VA_STATUS_SUCCESS; assert(src_obj_surf->fourcc == VA_FOURCC_NV12); assert(dst_obj_surf->fourcc == VA_FOURCC_NV12); VARectangle src_rect, dst_rect; src_rect.x = 0; src_rect.y = 0; src_rect.width = src_obj_surf->orig_width; src_rect.height = src_obj_surf->orig_height; dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = dst_obj_surf->orig_width; dst_rect.height = dst_obj_surf->orig_height; va_status = i965_scaling_processing(ctx, src_obj_surf, &src_rect, dst_obj_surf, &dst_rect, flags); return va_status; } static VAStatus vpp_sharpness_filtering(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { VAStatus va_status = VA_STATUS_SUCCESS; if(proc_ctx->vpp_gpe_ctx == NULL){ proc_ctx->vpp_gpe_ctx = vpp_gpe_context_init(ctx); } proc_ctx->vpp_gpe_ctx->pipeline_param = proc_ctx->pipeline_param; proc_ctx->vpp_gpe_ctx->surface_pipeline_input_object = proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface; proc_ctx->vpp_gpe_ctx->surface_output_object = proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface; va_status = vpp_gpe_process_picture(ctx, proc_ctx->vpp_gpe_ctx); return va_status; } void hsw_veb_dndi_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { struct i965_driver_data *i965 = i965_driver_data(ctx); unsigned int* p_table ; unsigned int progressive_dn = 1; unsigned int dndi_top_first = 0; unsigned int is_mcdi_enabled = 0; if (proc_ctx->is_di_enabled) { const VAProcFilterParameterBufferDeinterlacing * const deint_params = proc_ctx->filter_di; progressive_dn = 0; /* If we are in "First Frame" mode, i.e. past frames are not available for motion measure, then don't use the TFF flag */ dndi_top_first = !(deint_params->flags & (proc_ctx->is_first_frame ? VA_DEINTERLACING_BOTTOM_FIELD : VA_DEINTERLACING_BOTTOM_FIELD_FIRST)); is_mcdi_enabled = (deint_params->algorithm == VAProcDeinterlacingMotionCompensated); } /* VAProcFilterParameterBufferDeinterlacing *di_param = (VAProcFilterParameterBufferDeinterlacing *) proc_ctx->filter_di; VAProcFilterParameterBuffer * dn_param = (VAProcFilterParameterBuffer *) proc_ctx->filter_dn; */ p_table = (unsigned int *)proc_ctx->dndi_state_table.ptr; if (IS_HASWELL(i965->intel.device_info)) *p_table ++ = 0; // reserved . w0 *p_table ++ = ( 140 << 24 | // denoise STAD threshold . w1 192 << 16 | // dnmh_history_max 0 << 12 | // reserved 7 << 8 | // dnmh_delta[3:0] 38 ); // denoise ASD threshold *p_table ++ = ( 0 << 30 | // reserved . w2 0 << 24 | // temporal diff th 0 << 22 | // reserved. 0 << 16 | // low temporal diff th 2 << 13 | // STMM C2 1 << 8 | // denoise moving pixel th 38 ); // denoise th for sum of complexity measure *p_table ++ = ( 0 << 30 | // reserved . w3 12<< 24 | // good neighbor th[5:0] 9 << 20 | // CAT slope minus 1 5 << 16 | // SAD Tight in 0 << 14 | // smooth mv th 0 << 12 | // reserved 1 << 8 | // bne_edge_th[3:0] 20 ); // block noise estimate noise th *p_table ++ = ( 0 << 31 | // STMM blending constant select. w4 64 << 24 | // STMM trc1 125<< 16 | // STMM trc2 0 << 14 | // reserved 30 << 8 | // VECM_mul 150 ); // maximum STMM *p_table ++ = ( 118<< 24 | // minumum STMM . W5 0 << 22 | // STMM shift down 1 << 20 | // STMM shift up 5 << 16 | // STMM output shift 100 << 8 | // SDI threshold 5 ); // SDI delta *p_table ++ = ( 50 << 24 | // SDI fallback mode 1 T1 constant . W6 100 << 16 | // SDI fallback mode 1 T2 constant 37 << 8 | // SDI fallback mode 2 constant(angle2x1) 175 ); // FMD temporal difference threshold *p_table ++ = ( 16 << 24 | // FMD #1 vertical difference th . w7 100<< 16 | // FMD #2 vertical difference th 0 << 14 | // CAT th1 2 << 8 | // FMD tear threshold is_mcdi_enabled << 7 | // MCDI Enable, use motion compensated deinterlace algorithm progressive_dn << 6 | // progressive DN 0 << 4 | // reserved dndi_top_first << 3 | // DN/DI Top First 0 ); // reserved *p_table ++ = ( 0 << 29 | // reserved . W8 32 << 23 | // dnmh_history_init[5:0] 10 << 19 | // neighborPixel th 0 << 18 | // reserved 0 << 16 | // FMD for 2nd field of previous frame 25 << 10 | // MC pixel consistency th 0 << 8 | // FMD for 1st field for current frame 10 << 4 | // SAD THB 5 ); // SAD THA *p_table ++ = ( 0 << 24 | // reserved 140<< 16 | // chr_dnmh_stad_th 0 << 13 | // reserved 1 << 12 | // chrome denoise enable 13 << 6 | // chr temp diff th 7 ); // chr temp diff low if (IS_GEN8(i965->intel.device_info) || IS_GEN9(i965->intel.device_info)) *p_table ++ = 0; // parameters for hot pixel, } //Set default values for STDE void set_std_table_default(struct intel_vebox_context *proc_ctx, unsigned int *p_table) { //DWord 15 *p_table ++ = ( 0 << 31 | // Reserved 0x3F8 << 21 | // SATB1 (10 bits, default 8, optimized value -8) 31 << 14 | // SATP3 6 << 7 | // SATP2 0x7A ); // SATP1 (7 bits, default 6, optimized value -6) //DWord 16 *p_table ++ = ( 0 << 31 | // Reserved 297 << 20 | // SATS0 124 << 10 | // SATB3 8 ); // SATB2 //DWord 17 *p_table ++ = ( 0 << 22 | // Reserved 297 << 11 | // SATS2 85 ); // SATS1 //DWord 18 *p_table ++ = ( 14 << 25 | // HUEP3 6 << 18 | // HUEP2 0x7A << 11 | // HUEP1 (7 bits, default value -6 = 7Ah) 256 ); // SATS3 //DWord 19 *p_table ++ = ( 0 << 30 | // Reserved 256 << 20 | // HUEB3 8 << 10 | // HUEB2 0x3F8 ); // HUEB1 (10 bits, default value 8, optimized value -8) //DWord 20 *p_table ++ = ( 0 << 22 | // Reserved 85 << 11 | // HUES1 384 ); // HUES0 //DWord 21 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES3 384 ); // HUES2 //DWord 22 *p_table ++ = ( 0 << 31 | // Reserved 0 << 21 | // SATB1_DARK 31 << 14 | // SATP3_DARK 31 << 7 | // SATP2_DARK 0x7B ); // SATP1_DARK (7 bits, default value -11 = FF5h, optimized value -5) //DWord 23 *p_table ++ = ( 0 << 31 | // Reserved 305 << 20 | // SATS0_DARK 124 << 10 | // SATB3_DARK 124 ); // SATB2_DARK //DWord 24 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // SATS2_DARK 220 ); // SATS1_DARK //DWord 25 *p_table ++ = ( 14 << 25 | // HUEP3_DARK 14 << 18 | // HUEP2_DARK 14 << 11 | // HUEP1_DARK 256 ); // SATS3_DARK //DWord 26 *p_table ++ = ( 0 << 30 | // Reserved 56 << 20 | // HUEB3_DARK 56 << 10 | // HUEB2_DARK 56 ); // HUEB1_DARK //DWord 27 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES1_DARK 256 ); // HUES0_DARK //DWord 28 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES3_DARK 256 ); // HUES2_DARK } //Set values for STDE factor 3 void set_std_table_3(struct intel_vebox_context *proc_ctx, unsigned int *p_table) { //DWord 15 *p_table ++ = ( 0 << 31 | // Reserved 1016 << 21 | // SATB1 (10 bits, default 8, optimized value 1016) 31 << 14 | // SATP3 6 << 7 | // SATP2 122 ); // SATP1 (7 bits, default 6, optimized value 122) //DWord 16 *p_table ++ = ( 0 << 31 | // Reserved 297 << 20 | // SATS0 124 << 10 | // SATB3 8 ); // SATB2 //DWord 17 *p_table ++ = ( 0 << 22 | // Reserved 297 << 11 | // SATS2 85 ); // SATS1 //DWord 18 *p_table ++ = ( 14 << 25 | // HUEP3 6 << 18 | // HUEP2 122 << 11 | // HUEP1 (7 bits, default value -6 = 7Ah, optimized 122) 256 ); // SATS3 //DWord 19 *p_table ++ = ( 0 << 30 | // Reserved 56 << 20 | // HUEB3 (default 256, optimized 56) 8 << 10 | // HUEB2 1016 ); // HUEB1 (10 bits, default value 8, optimized value 1016) //DWord 20 *p_table ++ = ( 0 << 22 | // Reserved 85 << 11 | // HUES1 384 ); // HUES0 //DWord 21 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES3 384 ); // HUES2 //DWord 22 *p_table ++ = ( 0 << 31 | // Reserved 0 << 21 | // SATB1_DARK 31 << 14 | // SATP3_DARK 31 << 7 | // SATP2_DARK 123 ); // SATP1_DARK (7 bits, default value -11 = FF5h, optimized value 123) //DWord 23 *p_table ++ = ( 0 << 31 | // Reserved 305 << 20 | // SATS0_DARK 124 << 10 | // SATB3_DARK 124 ); // SATB2_DARK //DWord 24 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // SATS2_DARK 220 ); // SATS1_DARK //DWord 25 *p_table ++ = ( 14 << 25 | // HUEP3_DARK 14 << 18 | // HUEP2_DARK 14 << 11 | // HUEP1_DARK 256 ); // SATS3_DARK //DWord 26 *p_table ++ = ( 0 << 30 | // Reserved 56 << 20 | // HUEB3_DARK 56 << 10 | // HUEB2_DARK 56 ); // HUEB1_DARK //DWord 27 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES1_DARK 256 ); // HUES0_DARK //DWord 28 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES3_DARK 256 ); // HUES2_DARK } //Set values for STDE factor 6 void set_std_table_6(struct intel_vebox_context *proc_ctx, unsigned int *p_table) { //DWord 15 *p_table ++ = ( 0 << 31 | // Reserved 0 << 21 | // SATB1 (10 bits, default 8, optimized value 0) 31 << 14 | // SATP3 31 << 7 | // SATP2 (default 6, optimized 31) 114 ); // SATP1 (7 bits, default 6, optimized value 114) //DWord 16 *p_table ++ = ( 0 << 31 | // Reserved 467 << 20 | // SATS0 (default 297, optimized 467) 124 << 10 | // SATB3 124 ); // SATB2 //DWord 17 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // SATS2 (default 297, optimized 256) 176 ); // SATS1 //DWord 18 *p_table ++ = ( 14 << 25 | // HUEP3 14 << 18 | // HUEP2 14 << 11 | // HUEP1 (7 bits, default value -6 = 7Ah, optimized value 14) 256 ); // SATS3 //DWord 19 *p_table ++ = ( 0 << 30 | // Reserved 56 << 20 | // HUEB3 56 << 10 | // HUEB2 56 ); // HUEB1 (10 bits, default value 8, optimized value 56) //DWord 20 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES1 256 ); // HUES0 //DWord 21 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES3 256 ); // HUES2 //DWord 22 *p_table ++ = ( 0 << 31 | // Reserved 0 << 21 | // SATB1_DARK 31 << 14 | // SATP3_DARK 31 << 7 | // SATP2_DARK 123 ); // SATP1_DARK (7 bits, default value -11 = FF5h, optimized value 123) //DWord 23 *p_table ++ = ( 0 << 31 | // Reserved 305 << 20 | // SATS0_DARK 124 << 10 | // SATB3_DARK 124 ); // SATB2_DARK //DWord 24 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // SATS2_DARK 220 ); // SATS1_DARK //DWord 25 *p_table ++ = ( 14 << 25 | // HUEP3_DARK 14 << 18 | // HUEP2_DARK 14 << 11 | // HUEP1_DARK 256 ); // SATS3_DARK //DWord 26 *p_table ++ = ( 0 << 30 | // Reserved 56 << 20 | // HUEB3_DARK 56 << 10 | // HUEB2_DARK 56 ); // HUEB1_DARK //DWord 27 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES1_DARK 256 ); // HUES0_DARK //DWord 28 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES3_DARK 256 ); // HUES2_DARK } //Set values for STDE factor 9 void set_std_table_9(struct intel_vebox_context *proc_ctx, unsigned int *p_table) { //DWord 15 *p_table ++ = ( 0 << 31 | // Reserved 0 << 21 | // SATB1 (10 bits, default 8, optimized value 0) 31 << 14 | // SATP3 31 << 7 | // SATP2 (default 6, optimized 31) 108 ); // SATP1 (7 bits, default 6, optimized value 108) //DWord 16 *p_table ++ = ( 0 << 31 | // Reserved 721 << 20 | // SATS0 (default 297, optimized 721) 124 << 10 | // SATB3 124 ); // SATB2 //DWord 17 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // SATS2 (default 297, optimized 256) 156 ); // SATS1 (default 176, optimized 156) //DWord 18 *p_table ++ = ( 14 << 25 | // HUEP3 14 << 18 | // HUEP2 14 << 11 | // HUEP1 (7 bits, default value -6 = 7Ah, optimized value 14) 256 ); // SATS3 //DWord 19 *p_table ++ = ( 0 << 30 | // Reserved 56 << 20 | // HUEB3 56 << 10 | // HUEB2 56 ); // HUEB1 (10 bits, default value 8, optimized value 56) //DWord 20 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES1 256 ); // HUES0 //DWord 21 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES3 256 ); // HUES2 //DWord 22 *p_table ++ = ( 0 << 31 | // Reserved 0 << 21 | // SATB1_DARK 31 << 14 | // SATP3_DARK 31 << 7 | // SATP2_DARK 123 ); // SATP1_DARK (7 bits, default value -11 = FF5h, optimized value 123) //DWord 23 *p_table ++ = ( 0 << 31 | // Reserved 305 << 20 | // SATS0_DARK 124 << 10 | // SATB3_DARK 124 ); // SATB2_DARK //DWord 24 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // SATS2_DARK 220 ); // SATS1_DARK //DWord 25 *p_table ++ = ( 14 << 25 | // HUEP3_DARK 14 << 18 | // HUEP2_DARK 14 << 11 | // HUEP1_DARK 256 ); // SATS3_DARK //DWord 26 *p_table ++ = ( 0 << 30 | // Reserved 56 << 20 | // HUEB3_DARK 56 << 10 | // HUEB2_DARK 56 ); // HUEB1_DARK //DWord 27 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES1_DARK 256 ); // HUES0_DARK //DWord 28 *p_table ++ = ( 0 << 22 | // Reserved 256 << 11 | // HUES3_DARK 256 ); // HUES2_DARK } void hsw_veb_iecp_std_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { unsigned int *p_table = (unsigned int *)proc_ctx->iecp_state_table.ptr; if(!(proc_ctx->filters_mask & VPP_IECP_STD_STE)){ memset(p_table, 0, 29 * 4); }else{ int stde_factor = 0; //default value VAProcFilterParameterBuffer * std_param = (VAProcFilterParameterBuffer *) proc_ctx->filter_iecp_std; stde_factor = std_param->value; //DWord 0 *p_table ++ = ( 154 << 24 | // V_Mid 110 << 16 | // U_Mid 14 << 10 | // Hue_Max 31 << 4 | // Sat_Max 0 << 3 | // Reserved 0 << 2 | // Output Control is set to output the 1=STD score /0=Output Pixels 1 << 1 | // Set STE Enable 1 ); // Set STD Enable //DWord 1 *p_table ++ = ( 0 << 31 | // Reserved 4 << 28 | // Diamond Margin 0 << 21 | // Diamond_du 3 << 18 | // HS_Margin 79 << 10 | // Cos(alpha) 0 << 8 | // Reserved 101 ); // Sin(alpha) //DWord 2 *p_table ++ = ( 0 << 21 | // Reserved 100 << 13 | // Diamond_alpha 35 << 7 | // Diamond_Th 0 ); //DWord 3 *p_table ++ = ( 254 << 24 | // Y_point_3 47 << 16 | // Y_point_2 46 << 8 | // Y_point_1 1 << 7 | // VY_STD_Enable 0 ); // Reserved //DWord 4 *p_table ++ = ( 0 << 18 | // Reserved 31 << 13 | // Y_slope_2 31 << 8 | // Y_slope_1 255 ); // Y_point_4 //DWord 5 *p_table ++ = ( 400 << 16 | // INV_Skin_types_margin = 20* Skin_Type_margin => 20*20 3300 ); // INV_Margin_VYL => 1/Margin_VYL //DWord 6 *p_table ++ = ( 216 << 24 | // P1L 46 << 16 | // P0L 1600 ); // INV_Margin_VYU //DWord 7 *p_table ++ = ( 130 << 24 | // B1L 133 << 16 | // B0L 236 << 8 | // P3L 236 ); // P2L //DWord 8 *p_table ++ = ( 0 << 27 | // Reserved 0x7FB << 16 | // S0L (11 bits, Default value: -5 = FBh, pad it with 1s to make it 11bits) 130 << 8 | // B3L 130 ); //DWord 9 *p_table ++ = ( 0 << 22 | // Reserved 0 << 11 | // S2L 0); // S1L //DWord 10 *p_table ++ = ( 0 << 27 | // Reserved 66 << 19 | // P1U 46 << 11 | // P0U 0 ); // S3 //DWord 11 *p_table ++ = ( 163 << 24 | // B1U 143 << 16 | // B0U 236 << 8 | // P3U 150 ); // P2U //DWord 12 *p_table ++ = ( 0 << 27 | // Reserved 256 << 16 | // S0U 200 << 8 | // B3U 200 ); // B2U //DWord 13 *p_table ++ = ( 0 << 22 | // Reserved 0x74D << 11 | // S2U (11 bits, Default value -179 = F4Dh) 113 ); // S1U //DWoord 14 *p_table ++ = ( 0 << 28 | // Reserved 20 << 20 | // Skin_types_margin 120 << 12 | // Skin_types_thresh 1 << 11 | // Skin_Types_Enable 0 ); // S3U //Set DWord 15 through DWord 28 in their respective methods. switch(stde_factor) { case 3: set_std_table_3(proc_ctx, p_table); break; case 6: set_std_table_6(proc_ctx, p_table); break; case 9: set_std_table_9(proc_ctx, p_table); break; default: set_std_table_default(proc_ctx, p_table); break; } }//end of else } void hsw_veb_iecp_ace_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 116); if(!(proc_ctx->filters_mask & VPP_IECP_ACE)){ memset(p_table, 0, 13 * 4); }else{ *p_table ++ = 0x00000068; *p_table ++ = 0x4c382410; *p_table ++ = 0x9c887460; *p_table ++ = 0xebd8c4b0; *p_table ++ = 0x604c3824; *p_table ++ = 0xb09c8874; *p_table ++ = 0x0000d8c4; *p_table ++ = 0x00000000; *p_table ++ = 0x00000000; *p_table ++ = 0x00000000; *p_table ++ = 0x00000000; *p_table ++ = 0x00000000; *p_table ++ = 0x00000000; } } void hsw_veb_iecp_tcc_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 168); // VAProcFilterParameterBuffer * tcc_param = // (VAProcFilterParameterBuffer *) proc_ctx->filter_iecp_tcc; if(!(proc_ctx->filters_mask & VPP_IECP_TCC)){ memset(p_table, 0, 11 * 4); }else{ *p_table ++ = 0x00000000; *p_table ++ = 0x00000000; *p_table ++ = 0x1e34cc91; *p_table ++ = 0x3e3cce91; *p_table ++ = 0x02e80195; *p_table ++ = 0x0197046b; *p_table ++ = 0x01790174; *p_table ++ = 0x00000000; *p_table ++ = 0x00000000; *p_table ++ = 0x03030000; *p_table ++ = 0x009201c0; } } void hsw_veb_iecp_pro_amp_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { unsigned int contrast = 0x80; //default int brightness = 0x00; //default int cos_c_s = 256 ; //default int sin_c_s = 0; //default unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 212); if(!(proc_ctx->filters_mask & VPP_IECP_PRO_AMP)){ memset(p_table, 0, 2 * 4); }else { float src_saturation = 1.0; float src_hue = 0.0; float src_contrast = 1.0; float src_brightness = 0.0; float tmp_value = 0.0; unsigned int i = 0; VAProcFilterParameterBufferColorBalance * amp_params = (VAProcFilterParameterBufferColorBalance *) proc_ctx->filter_iecp_amp; for (i = 0; i < proc_ctx->filter_iecp_amp_num_elements; i++){ VAProcColorBalanceType attrib = amp_params[i].attrib; if(attrib == VAProcColorBalanceHue) { src_hue = amp_params[i].value; //(-180.0, 180.0) }else if(attrib == VAProcColorBalanceSaturation) { src_saturation = amp_params[i].value; //(0.0, 10.0) }else if(attrib == VAProcColorBalanceBrightness) { src_brightness = amp_params[i].value; // (-100.0, 100.0) brightness = intel_format_convert(src_brightness, 7, 4, 1); }else if(attrib == VAProcColorBalanceContrast) { src_contrast = amp_params[i].value; // (0.0, 10.0) contrast = intel_format_convert(src_contrast, 4, 7, 0); } } tmp_value = cos(src_hue/180*PI) * src_contrast * src_saturation; cos_c_s = intel_format_convert(tmp_value, 7, 8, 1); tmp_value = sin(src_hue/180*PI) * src_contrast * src_saturation; sin_c_s = intel_format_convert(tmp_value, 7, 8, 1); *p_table ++ = ( 0 << 28 | //reserved contrast << 17 | //contrast value (U4.7 format) 0 << 13 | //reserved brightness << 1| // S7.4 format 1); *p_table ++ = ( cos_c_s << 16 | // cos(h) * contrast * saturation sin_c_s); // sin(h) * contrast * saturation } } void hsw_veb_iecp_csc_transform_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 220); float tran_coef[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; float v_coef[3] = {0.0, 0.0, 0.0}; float u_coef[3] = {0.0, 0.0, 0.0}; int is_transform_enabled = 0; if(!(proc_ctx->filters_mask & VPP_IECP_CSC_TRANSFORM)){ memset(p_table, 0, 8 * 4); return; } if(proc_ctx->fourcc_input == VA_FOURCC_RGBA && (proc_ctx->fourcc_output == VA_FOURCC_NV12 || proc_ctx->fourcc_output == VA_FOURCC_YV12 || proc_ctx->fourcc_output == VA_FOURCC_YVY2 || proc_ctx->fourcc_output == VA_FOURCC_AYUV)) { tran_coef[0] = 0.257; tran_coef[1] = 0.504; tran_coef[2] = 0.098; tran_coef[3] = -0.148; tran_coef[4] = -0.291; tran_coef[5] = 0.439; tran_coef[6] = 0.439; tran_coef[7] = -0.368; tran_coef[8] = -0.071; u_coef[0] = 16 * 4; u_coef[1] = 128 * 4; u_coef[2] = 128 * 4; is_transform_enabled = 1; }else if((proc_ctx->fourcc_input == VA_FOURCC_NV12 || proc_ctx->fourcc_input == VA_FOURCC_YV12 || proc_ctx->fourcc_input == VA_FOURCC_YUY2 || proc_ctx->fourcc_input == VA_FOURCC_AYUV) && proc_ctx->fourcc_output == VA_FOURCC_RGBA) { tran_coef[0] = 1.164; tran_coef[1] = 0.000; tran_coef[2] = 1.569; tran_coef[3] = 1.164; tran_coef[4] = -0.813; tran_coef[5] = -0.392; tran_coef[6] = 1.164; tran_coef[7] = 2.017; tran_coef[8] = 0.000; v_coef[0] = -16 * 4; v_coef[1] = -128 * 4; v_coef[2] = -128 * 4; is_transform_enabled = 1; }else if(proc_ctx->fourcc_input != proc_ctx->fourcc_output){ //enable when input and output format are different. is_transform_enabled = 1; } if(is_transform_enabled == 0){ memset(p_table, 0, 8 * 4); }else{ *p_table ++ = ( 0 << 29 | //reserved intel_format_convert(tran_coef[1], 2, 10, 1) << 16 | //c1, s2.10 format intel_format_convert(tran_coef[0], 2, 10, 1) << 3 | //c0, s2.10 format 0 << 2 | //reserved 0 << 1 | // yuv_channel swap is_transform_enabled); *p_table ++ = ( 0 << 26 | //reserved intel_format_convert(tran_coef[3], 2, 10, 1) << 13 | intel_format_convert(tran_coef[2], 2, 10, 1)); *p_table ++ = ( 0 << 26 | //reserved intel_format_convert(tran_coef[5], 2, 10, 1) << 13 | intel_format_convert(tran_coef[4], 2, 10, 1)); *p_table ++ = ( 0 << 26 | //reserved intel_format_convert(tran_coef[7], 2, 10, 1) << 13 | intel_format_convert(tran_coef[6], 2, 10, 1)); *p_table ++ = ( 0 << 13 | //reserved intel_format_convert(tran_coef[8], 2, 10, 1)); *p_table ++ = ( 0 << 22 | //reserved intel_format_convert(u_coef[0], 10, 0, 1) << 11 | intel_format_convert(v_coef[0], 10, 0, 1)); *p_table ++ = ( 0 << 22 | //reserved intel_format_convert(u_coef[1], 10, 0, 1) << 11 | intel_format_convert(v_coef[1], 10, 0, 1)); *p_table ++ = ( 0 << 22 | //reserved intel_format_convert(u_coef[2], 10, 0, 1) << 11 | intel_format_convert(v_coef[2], 10, 0, 1)); } } void hsw_veb_iecp_aoi_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 252); // VAProcFilterParameterBuffer * tcc_param = // (VAProcFilterParameterBuffer *) proc_ctx->filter_iecp_tcc; if(!(proc_ctx->filters_mask & VPP_IECP_AOI)){ memset(p_table, 0, 3 * 4); }else{ *p_table ++ = 0x00000000; *p_table ++ = 0x00030000; *p_table ++ = 0x00030000; } } void hsw_veb_state_table_setup(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { if(proc_ctx->filters_mask & VPP_DNDI_MASK) { dri_bo *dndi_bo = proc_ctx->dndi_state_table.bo; dri_bo_map(dndi_bo, 1); proc_ctx->dndi_state_table.ptr = dndi_bo->virtual; hsw_veb_dndi_table(ctx, proc_ctx); dri_bo_unmap(dndi_bo); } if(proc_ctx->filters_mask & VPP_IECP_MASK) { dri_bo *iecp_bo = proc_ctx->iecp_state_table.bo; dri_bo_map(iecp_bo, 1); proc_ctx->iecp_state_table.ptr = iecp_bo->virtual; memset(proc_ctx->iecp_state_table.ptr, 0, 97 * 4); hsw_veb_iecp_std_table(ctx, proc_ctx); hsw_veb_iecp_ace_table(ctx, proc_ctx); hsw_veb_iecp_tcc_table(ctx, proc_ctx); hsw_veb_iecp_pro_amp_table(ctx, proc_ctx); hsw_veb_iecp_csc_transform_table(ctx, proc_ctx); hsw_veb_iecp_aoi_table(ctx, proc_ctx); dri_bo_unmap(iecp_bo); } } void hsw_veb_state_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { struct intel_batchbuffer *batch = proc_ctx->batch; BEGIN_VEB_BATCH(batch, 6); OUT_VEB_BATCH(batch, VEB_STATE | (6 - 2)); OUT_VEB_BATCH(batch, 0 << 26 | // state surface control bits 0 << 11 | // reserved. 0 << 10 | // pipe sync disable proc_ctx->current_output_type << 8 | // DI output frame 1 << 7 | // 444->422 downsample method 1 << 6 | // 422->420 downsample method proc_ctx->is_first_frame << 5 | // DN/DI first frame proc_ctx->is_di_enabled << 4 | // DI enable proc_ctx->is_dn_enabled << 3 | // DN enable proc_ctx->is_iecp_enabled << 2 | // global IECP enabled 0 << 1 | // ColorGamutCompressionEnable 0 ) ; // ColorGamutExpansionEnable. OUT_RELOC(batch, proc_ctx->dndi_state_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_RELOC(batch, proc_ctx->iecp_state_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_RELOC(batch, proc_ctx->gamut_state_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_RELOC(batch, proc_ctx->vertex_state_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); ADVANCE_VEB_BATCH(batch); } void hsw_veb_surface_state(VADriverContextP ctx, struct intel_vebox_context *proc_ctx, unsigned int is_output) { struct intel_batchbuffer *batch = proc_ctx->batch; unsigned int u_offset_y = 0, v_offset_y = 0; unsigned int is_uv_interleaved = 0, tiling = 0, swizzle = 0; unsigned int surface_format = PLANAR_420_8; struct object_surface* obj_surf = NULL; unsigned int surface_pitch = 0; unsigned int half_pitch_chroma = 0; if(is_output){ obj_surf = proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface; }else { obj_surf = proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface; } assert(obj_surf->fourcc == VA_FOURCC_NV12 || obj_surf->fourcc == VA_FOURCC_YUY2 || obj_surf->fourcc == VA_FOURCC_AYUV || obj_surf->fourcc == VA_FOURCC_RGBA); if (obj_surf->fourcc == VA_FOURCC_NV12) { surface_format = PLANAR_420_8; surface_pitch = obj_surf->width; is_uv_interleaved = 1; half_pitch_chroma = 0; } else if (obj_surf->fourcc == VA_FOURCC_YUY2) { surface_format = YCRCB_NORMAL; surface_pitch = obj_surf->width * 2; is_uv_interleaved = 0; half_pitch_chroma = 0; } else if (obj_surf->fourcc == VA_FOURCC_AYUV) { surface_format = PACKED_444A_8; surface_pitch = obj_surf->width * 4; is_uv_interleaved = 0; half_pitch_chroma = 0; } else if (obj_surf->fourcc == VA_FOURCC_RGBA) { surface_format = R8G8B8A8_UNORM_SRGB; surface_pitch = obj_surf->width * 4; is_uv_interleaved = 0; half_pitch_chroma = 0; } u_offset_y = obj_surf->y_cb_offset; v_offset_y = obj_surf->y_cr_offset; dri_bo_get_tiling(obj_surf->bo, &tiling, &swizzle); BEGIN_VEB_BATCH(batch, 6); OUT_VEB_BATCH(batch, VEB_SURFACE_STATE | (6 - 2)); OUT_VEB_BATCH(batch, 0 << 1 | // reserved is_output); // surface indentification. OUT_VEB_BATCH(batch, (obj_surf->orig_height - 1) << 18 | // height . w3 (obj_surf->orig_width - 1) << 4 | // width 0); // reserve OUT_VEB_BATCH(batch, surface_format << 28 | // surface format, YCbCr420. w4 is_uv_interleaved << 27 | // interleave chrome , two seperate palar 0 << 20 | // reserved (surface_pitch - 1) << 3 | // surface pitch, 64 align half_pitch_chroma << 2 | // half pitch for chrome !!tiling << 1 | // tiled surface, linear surface used (tiling == I915_TILING_Y)); // tiled walk, ignored when liner surface OUT_VEB_BATCH(batch, 0 << 29 | // reserved . w5 0 << 16 | // X offset for V(Cb) 0 << 15 | // reserved u_offset_y); // Y offset for V(Cb) OUT_VEB_BATCH(batch, 0 << 29 | // reserved . w6 0 << 16 | // X offset for V(Cr) 0 << 15 | // reserved v_offset_y ); // Y offset for V(Cr) ADVANCE_VEB_BATCH(batch); } void hsw_veb_dndi_iecp_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { struct intel_batchbuffer *batch = proc_ctx->batch; unsigned char frame_ctrl_bits = 0; struct object_surface *obj_surface = proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface; unsigned int width64 = ALIGN(proc_ctx->width_input, 64); assert(obj_surface); if (width64 > obj_surface->orig_width) width64 = obj_surface->orig_width; /* s1:update the previous and current input */ /* tempFrame = proc_ctx->frame_store[FRAME_IN_PREVIOUS]; proc_ctx->frame_store[FRAME_IN_PREVIOUS] = proc_ctx->frame_store[FRAME_IN_CURRENT]; ; proc_ctx->frame_store[FRAME_IN_CURRENT] = tempFrame; if(proc_ctx->surface_input_vebox != -1){ vpp_surface_copy(ctx, proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id, proc_ctx->surface_input_vebox); } else { vpp_surface_copy(ctx, proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id, proc_ctx->surface_input); } */ /*s2: update the STMM input and output */ /* tempFrame = proc_ctx->frame_store[FRAME_IN_STMM]; proc_ctx->frame_store[FRAME_IN_STMM] = proc_ctx->frame_store[FRAME_OUT_STMM]; ; proc_ctx->frame_store[FRAME_OUT_STMM] = tempFrame; */ /*s3:set reloc buffer address */ BEGIN_VEB_BATCH(batch, 10); OUT_VEB_BATCH(batch, VEB_DNDI_IECP_STATE | (10 - 2)); OUT_VEB_BATCH(batch, (width64 - 1)); OUT_RELOC(batch, proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface->bo, I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits); OUT_RELOC(batch, proc_ctx->frame_store[FRAME_IN_PREVIOUS].obj_surface->bo, I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits); OUT_RELOC(batch, proc_ctx->frame_store[FRAME_IN_STMM].obj_surface->bo, I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits); OUT_RELOC(batch, proc_ctx->frame_store[FRAME_OUT_STMM].obj_surface->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits); OUT_RELOC(batch, proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits); OUT_RELOC(batch, proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits); OUT_RELOC(batch, proc_ctx->frame_store[FRAME_OUT_PREVIOUS].obj_surface->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits); OUT_RELOC(batch, proc_ctx->frame_store[FRAME_OUT_STATISTIC].obj_surface->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits); ADVANCE_VEB_BATCH(batch); } static void frame_store_reset(VEBFrameStore *fs) { fs->obj_surface = NULL; fs->surface_id = VA_INVALID_ID; fs->is_internal_surface = 0; fs->is_scratch_surface = 0; } static void frame_store_clear(VEBFrameStore *fs, VADriverContextP ctx) { if (fs->obj_surface && fs->is_scratch_surface) { VASurfaceID surface_id = fs->obj_surface->base.id; i965_DestroySurfaces(ctx, &surface_id, 1); } frame_store_reset(fs); } static VAStatus gen75_vebox_ensure_surfaces_storage(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { struct i965_driver_data * const i965 = i965_driver_data(ctx); struct object_surface *input_obj_surface, *output_obj_surface; unsigned int input_fourcc, output_fourcc; unsigned int input_sampling, output_sampling; unsigned int input_tiling, output_tiling; unsigned int i, swizzle; drm_intel_bo *bo; VAStatus status; /* Determine input surface info. Use native VEBOX format whenever possible. i.e. when the input surface format is not supported by the VEBOX engine, then allocate a temporary surface (live during the whole VPP pipeline lifetime) XXX: derive an actual surface format compatible with the input surface chroma format */ input_obj_surface = proc_ctx->surface_input_vebox_object ? proc_ctx->surface_input_vebox_object : proc_ctx->surface_input_object; if (input_obj_surface->bo) { input_fourcc = input_obj_surface->fourcc; input_sampling = input_obj_surface->subsampling; dri_bo_get_tiling(input_obj_surface->bo, &input_tiling, &swizzle); input_tiling = !!input_tiling; } else { input_fourcc = VA_FOURCC_NV12; input_sampling = SUBSAMPLE_YUV420; input_tiling = 1; status = i965_check_alloc_surface_bo(ctx, input_obj_surface, input_tiling, input_fourcc, input_sampling); if (status != VA_STATUS_SUCCESS) return status; } /* Determine output surface info. XXX: derive an actual surface format compatible with the input surface chroma format */ output_obj_surface = proc_ctx->surface_output_vebox_object ? proc_ctx->surface_output_vebox_object : proc_ctx->surface_output_object; if (output_obj_surface->bo) { output_fourcc = output_obj_surface->fourcc; output_sampling = output_obj_surface->subsampling; dri_bo_get_tiling(output_obj_surface->bo, &output_tiling, &swizzle); output_tiling = !!output_tiling; } else { output_fourcc = VA_FOURCC_NV12; output_sampling = SUBSAMPLE_YUV420; output_tiling = 1; status = i965_check_alloc_surface_bo(ctx, output_obj_surface, output_tiling, output_fourcc, output_sampling); if (status != VA_STATUS_SUCCESS) return status; } /* Update VEBOX pipeline formats */ proc_ctx->fourcc_input = input_fourcc; proc_ctx->fourcc_output = output_fourcc; if (input_fourcc != output_fourcc) { proc_ctx->filters_mask |= VPP_IECP_CSC; if (input_fourcc == VA_FOURCC_RGBA && (output_fourcc == VA_FOURCC_NV12 || output_fourcc == VA_FOURCC_P010)) { proc_ctx->filters_mask |= VPP_IECP_CSC_TRANSFORM; } else if (output_fourcc == VA_FOURCC_RGBA && (input_fourcc == VA_FOURCC_NV12 || input_fourcc == VA_FOURCC_P010)) { proc_ctx->filters_mask |= VPP_IECP_CSC_TRANSFORM; } } proc_ctx->is_iecp_enabled = (proc_ctx->filters_mask & VPP_IECP_MASK) != 0; /* Create pipeline surfaces */ for (i = 0; i < ARRAY_ELEMS(proc_ctx->frame_store); i ++) { struct object_surface *obj_surface; VASurfaceID new_surface; if (proc_ctx->frame_store[i].obj_surface) continue; // user allocated surface, not VEBOX internal status = i965_CreateSurfaces(ctx, proc_ctx->width_input, proc_ctx->height_input, VA_RT_FORMAT_YUV420, 1, &new_surface); if (status != VA_STATUS_SUCCESS) return status; obj_surface = SURFACE(new_surface); assert(obj_surface != NULL); if (i <= FRAME_IN_PREVIOUS || i == FRAME_OUT_CURRENT_DN) { status = i965_check_alloc_surface_bo(ctx, obj_surface, input_tiling, input_fourcc, input_sampling); } else if (i == FRAME_IN_STMM || i == FRAME_OUT_STMM) { status = i965_check_alloc_surface_bo(ctx, obj_surface, 1, input_fourcc, input_sampling); } else if (i >= FRAME_OUT_CURRENT) { status = i965_check_alloc_surface_bo(ctx, obj_surface, output_tiling, output_fourcc, output_sampling); } if (status != VA_STATUS_SUCCESS) return status; proc_ctx->frame_store[i].obj_surface = obj_surface; proc_ctx->frame_store[i].is_internal_surface = 1; proc_ctx->frame_store[i].is_scratch_surface = 1; } /* Allocate DNDI state table */ drm_intel_bo_unreference(proc_ctx->dndi_state_table.bo); bo = drm_intel_bo_alloc(i965->intel.bufmgr, "vebox: dndi state Buffer", 0x1000, 0x1000); proc_ctx->dndi_state_table.bo = bo; if (!bo) return VA_STATUS_ERROR_ALLOCATION_FAILED; /* Allocate IECP state table */ drm_intel_bo_unreference(proc_ctx->iecp_state_table.bo); bo = drm_intel_bo_alloc(i965->intel.bufmgr, "vebox: iecp state Buffer", 0x1000, 0x1000); proc_ctx->iecp_state_table.bo = bo; if (!bo) return VA_STATUS_ERROR_ALLOCATION_FAILED; /* Allocate Gamut state table */ drm_intel_bo_unreference(proc_ctx->gamut_state_table.bo); bo = drm_intel_bo_alloc(i965->intel.bufmgr, "vebox: gamut state Buffer", 0x1000, 0x1000); proc_ctx->gamut_state_table.bo = bo; if (!bo) return VA_STATUS_ERROR_ALLOCATION_FAILED; /* Allocate vertex state table */ drm_intel_bo_unreference(proc_ctx->vertex_state_table.bo); bo = drm_intel_bo_alloc(i965->intel.bufmgr, "vebox: vertex state Buffer", 0x1000, 0x1000); proc_ctx->vertex_state_table.bo = bo; if (!bo) return VA_STATUS_ERROR_ALLOCATION_FAILED; return VA_STATUS_SUCCESS; } static VAStatus gen75_vebox_ensure_surfaces(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { struct i965_driver_data * const i965 = i965_driver_data(ctx); struct object_surface *obj_surface; VEBFrameStore *ifs, *ofs; bool is_new_frame = 0; int i; /* Update the previous input surface */ obj_surface = proc_ctx->surface_input_object; is_new_frame = proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id != obj_surface->base.id; if (is_new_frame) { ifs = &proc_ctx->frame_store[FRAME_IN_PREVIOUS]; ofs = &proc_ctx->frame_store[proc_ctx->is_dn_enabled ? FRAME_OUT_CURRENT_DN : FRAME_IN_CURRENT]; do { const VAProcPipelineParameterBuffer * const pipe = proc_ctx->pipeline_param; if (pipe->num_forward_references < 1) break; if (pipe->forward_references[0] == VA_INVALID_ID) break; obj_surface = SURFACE(pipe->forward_references[0]); if (!obj_surface || obj_surface->base.id == ifs->surface_id) break; frame_store_clear(ifs, ctx); if (obj_surface->base.id == ofs->surface_id) { *ifs = *ofs; frame_store_reset(ofs); } else { ifs->obj_surface = obj_surface; ifs->surface_id = obj_surface->base.id; ifs->is_internal_surface = 0; ifs->is_scratch_surface = 0; } } while (0); } /* Update the input surface */ obj_surface = proc_ctx->surface_input_vebox_object ? proc_ctx->surface_input_vebox_object : proc_ctx->surface_input_object; ifs = &proc_ctx->frame_store[FRAME_IN_CURRENT]; frame_store_clear(ifs, ctx); ifs->obj_surface = obj_surface; ifs->surface_id = proc_ctx->surface_input_object->base.id; ifs->is_internal_surface = proc_ctx->surface_input_vebox_object != NULL; ifs->is_scratch_surface = 0; /* Update the Spatial Temporal Motion Measure (STMM) surfaces */ if (is_new_frame) { const VEBFrameStore tmpfs = proc_ctx->frame_store[FRAME_IN_STMM]; proc_ctx->frame_store[FRAME_IN_STMM] = proc_ctx->frame_store[FRAME_OUT_STMM]; proc_ctx->frame_store[FRAME_OUT_STMM] = tmpfs; } /* Reset the output surfaces to defaults. i.e. clean from user surfaces */ for (i = FRAME_OUT_CURRENT_DN; i <= FRAME_OUT_PREVIOUS; i++) { ofs = &proc_ctx->frame_store[i]; if (!ofs->is_scratch_surface) ofs->obj_surface = NULL; ofs->surface_id = proc_ctx->surface_input_object->base.id; } /* Update the output surfaces */ obj_surface = proc_ctx->surface_output_vebox_object ? proc_ctx->surface_output_vebox_object : proc_ctx->surface_output_object; proc_ctx->current_output_type = 2; if (proc_ctx->filters_mask == VPP_DNDI_DN && !proc_ctx->is_iecp_enabled) proc_ctx->current_output = FRAME_OUT_CURRENT_DN; else if (proc_ctx->is_di_adv_enabled && !proc_ctx->is_first_frame) { proc_ctx->current_output_type = 0; proc_ctx->current_output = proc_ctx->is_second_field ? FRAME_OUT_CURRENT : FRAME_OUT_PREVIOUS; } else proc_ctx->current_output = FRAME_OUT_CURRENT; ofs = &proc_ctx->frame_store[proc_ctx->current_output]; frame_store_clear(ofs, ctx); ofs->obj_surface = obj_surface; ofs->surface_id = proc_ctx->surface_input_object->base.id; ofs->is_internal_surface = proc_ctx->surface_output_vebox_object != NULL; ofs->is_scratch_surface = 0; return VA_STATUS_SUCCESS; } VAStatus hsw_veb_pre_format_convert(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { VAStatus va_status; struct i965_driver_data *i965 = i965_driver_data(ctx); struct object_surface* obj_surf_input = proc_ctx->surface_input_object; struct object_surface* obj_surf_output = proc_ctx->surface_output_object; struct object_surface* obj_surf_input_vebox; struct object_surface* obj_surf_output_vebox; proc_ctx->format_convert_flags = 0; if ((obj_surf_input == NULL) && (proc_ctx->pipeline_param->surface_region == NULL)) ASSERT_RET(0, VA_STATUS_ERROR_INVALID_PARAMETER); if ((obj_surf_output == NULL) && (proc_ctx->pipeline_param->output_region == NULL)) ASSERT_RET(0, VA_STATUS_ERROR_INVALID_PARAMETER); if (proc_ctx->pipeline_param->surface_region) { proc_ctx->width_input = proc_ctx->pipeline_param->surface_region->width; proc_ctx->height_input = proc_ctx->pipeline_param->surface_region->height; } else { proc_ctx->width_input = obj_surf_input->orig_width; proc_ctx->height_input = obj_surf_input->orig_height; } if (proc_ctx->pipeline_param->output_region) { proc_ctx->width_output = proc_ctx->pipeline_param->output_region->width; proc_ctx->height_output = proc_ctx->pipeline_param->output_region->height; } else { proc_ctx->width_output = obj_surf_output->orig_width; proc_ctx->height_output = obj_surf_output->orig_height; } /* only partial frame is not supported to be processed */ /* assert(proc_ctx->width_input == proc_ctx->pipeline_param->surface_region->width); assert(proc_ctx->height_input == proc_ctx->pipeline_param->surface_region->height); assert(proc_ctx->width_output == proc_ctx->pipeline_param->output_region->width); assert(proc_ctx->height_output == proc_ctx->pipeline_param->output_region->height); */ if(proc_ctx->width_output != proc_ctx->width_input || proc_ctx->height_output != proc_ctx->height_input){ proc_ctx->format_convert_flags |= POST_SCALING_CONVERT; } /* convert the following format to NV12 format */ if(obj_surf_input->fourcc == VA_FOURCC_YV12 || obj_surf_input->fourcc == VA_FOURCC_I420 || obj_surf_input->fourcc == VA_FOURCC_IMC1 || obj_surf_input->fourcc == VA_FOURCC_IMC3 || obj_surf_input->fourcc == VA_FOURCC_RGBA || obj_surf_input->fourcc == VA_FOURCC_BGRA){ proc_ctx->format_convert_flags |= PRE_FORMAT_CONVERT; } else if(obj_surf_input->fourcc == VA_FOURCC_AYUV || obj_surf_input->fourcc == VA_FOURCC_YUY2 || obj_surf_input->fourcc == VA_FOURCC_NV12 || obj_surf_input->fourcc == VA_FOURCC_P010){ // nothing to do here } else { /* not support other format as input */ ASSERT_RET(0, VA_STATUS_ERROR_UNIMPLEMENTED); } if (proc_ctx->format_convert_flags & PRE_FORMAT_CONVERT) { if(proc_ctx->surface_input_vebox_object == NULL){ va_status = i965_CreateSurfaces(ctx, proc_ctx->width_input, proc_ctx->height_input, VA_RT_FORMAT_YUV420, 1, &(proc_ctx->surface_input_vebox)); assert(va_status == VA_STATUS_SUCCESS); obj_surf_input_vebox = SURFACE(proc_ctx->surface_input_vebox); assert(obj_surf_input_vebox); if (obj_surf_input_vebox) { proc_ctx->surface_input_vebox_object = obj_surf_input_vebox; i965_check_alloc_surface_bo(ctx, obj_surf_input_vebox, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420); } } vpp_surface_convert(ctx, proc_ctx->surface_input_object, proc_ctx->surface_input_vebox_object); } /* create one temporary NV12 surfaces for conversion*/ if(obj_surf_output->fourcc == VA_FOURCC_YV12 || obj_surf_output->fourcc == VA_FOURCC_I420 || obj_surf_output->fourcc == VA_FOURCC_IMC1 || obj_surf_output->fourcc == VA_FOURCC_IMC3 || obj_surf_output->fourcc == VA_FOURCC_RGBA || obj_surf_output->fourcc == VA_FOURCC_BGRA) { proc_ctx->format_convert_flags |= POST_FORMAT_CONVERT; } else if(obj_surf_output->fourcc == VA_FOURCC_AYUV || obj_surf_output->fourcc == VA_FOURCC_YUY2 || obj_surf_output->fourcc == VA_FOURCC_NV12 || obj_surf_output->fourcc == VA_FOURCC_P010) { /* Nothing to do here */ } else { /* not support other format as input */ ASSERT_RET(0, VA_STATUS_ERROR_UNIMPLEMENTED); } if(proc_ctx->format_convert_flags & POST_FORMAT_CONVERT || proc_ctx->format_convert_flags & POST_SCALING_CONVERT){ if(proc_ctx->surface_output_vebox_object == NULL){ va_status = i965_CreateSurfaces(ctx, proc_ctx->width_input, proc_ctx->height_input, VA_RT_FORMAT_YUV420, 1, &(proc_ctx->surface_output_vebox)); assert(va_status == VA_STATUS_SUCCESS); obj_surf_output_vebox = SURFACE(proc_ctx->surface_output_vebox); assert(obj_surf_output_vebox); if (obj_surf_output_vebox) { proc_ctx->surface_output_vebox_object = obj_surf_output_vebox; i965_check_alloc_surface_bo(ctx, obj_surf_output_vebox, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420); } } } if(proc_ctx->format_convert_flags & POST_SCALING_CONVERT){ if(proc_ctx->surface_output_scaled_object == NULL){ va_status = i965_CreateSurfaces(ctx, proc_ctx->width_output, proc_ctx->height_output, VA_RT_FORMAT_YUV420, 1, &(proc_ctx->surface_output_scaled)); assert(va_status == VA_STATUS_SUCCESS); obj_surf_output_vebox = SURFACE(proc_ctx->surface_output_scaled); assert(obj_surf_output_vebox); if (obj_surf_output_vebox) { proc_ctx->surface_output_scaled_object = obj_surf_output_vebox; i965_check_alloc_surface_bo(ctx, obj_surf_output_vebox, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420); } } } return VA_STATUS_SUCCESS; } VAStatus hsw_veb_post_format_convert(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { struct object_surface *obj_surface = NULL; VAStatus va_status = VA_STATUS_SUCCESS; obj_surface = proc_ctx->frame_store[proc_ctx->current_output].obj_surface; if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) { /* copy the saved frame in the second call */ va_status = vpp_surface_convert(ctx, obj_surface, proc_ctx->surface_output_object); } else if(!(proc_ctx->format_convert_flags & POST_FORMAT_CONVERT) && !(proc_ctx->format_convert_flags & POST_SCALING_CONVERT)){ /* Output surface format is covered by vebox pipeline and * processed picture is already store in output surface * so nothing will be done here */ } else if ((proc_ctx->format_convert_flags & POST_FORMAT_CONVERT) && !(proc_ctx->format_convert_flags & POST_SCALING_CONVERT)){ /* convert and copy NV12 to YV12/IMC3/IMC2/RGBA output*/ va_status = vpp_surface_convert(ctx, obj_surface, proc_ctx->surface_output_object); } else if(proc_ctx->format_convert_flags & POST_SCALING_CONVERT) { VAProcPipelineParameterBuffer * const pipe = proc_ctx->pipeline_param; /* scaling, convert and copy NV12 to YV12/IMC3/IMC2/RGBA output*/ assert(obj_surface->fourcc == VA_FOURCC_NV12); /* first step :surface scaling */ vpp_surface_scaling(ctx, obj_surface, proc_ctx->surface_output_scaled_object, pipe->filter_flags); /* second step: color format convert and copy to output */ obj_surface = proc_ctx->surface_output_object; va_status = vpp_surface_convert(ctx, proc_ctx->surface_output_scaled_object, obj_surface); } return va_status; } static VAStatus gen75_vebox_init_pipe_params(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { struct i965_driver_data * const i965 = i965_driver_data(ctx); const VAProcPipelineParameterBuffer * const pipe = proc_ctx->pipeline_param; VAProcFilterParameterBuffer *filter; unsigned int i; proc_ctx->filters_mask = 0; for (i = 0; i < pipe->num_filters; i++) { struct object_buffer * const obj_buffer = BUFFER(pipe->filters[i]); assert(obj_buffer && obj_buffer->buffer_store); if (!obj_buffer || !obj_buffer->buffer_store) return VA_STATUS_ERROR_INVALID_PARAMETER; filter = (VAProcFilterParameterBuffer *) obj_buffer->buffer_store->buffer; switch (filter->type) { case VAProcFilterNoiseReduction: proc_ctx->filters_mask |= VPP_DNDI_DN; proc_ctx->filter_dn = filter; break; case VAProcFilterDeinterlacing: proc_ctx->filters_mask |= VPP_DNDI_DI; proc_ctx->filter_di = filter; break; case VAProcFilterColorBalance: proc_ctx->filters_mask |= VPP_IECP_PRO_AMP; proc_ctx->filter_iecp_amp = filter; proc_ctx->filter_iecp_amp_num_elements = obj_buffer->num_elements; break; case VAProcFilterSkinToneEnhancement: proc_ctx->filters_mask |= VPP_IECP_STD_STE; proc_ctx->filter_iecp_std = filter; break; case VAProcFilterSharpening: proc_ctx->filters_mask |= VPP_SHARP; break; default: WARN_ONCE("unsupported filter (type: %d)\n", filter->type); return VA_STATUS_ERROR_UNSUPPORTED_FILTER; } } if(proc_ctx->filters_mask == 0) proc_ctx->filters_mask |= VPP_IECP_CSC; return VA_STATUS_SUCCESS; } static VAStatus gen75_vebox_init_filter_params(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { proc_ctx->format_convert_flags = 0; /* initialized in hsw_veb_pre_format_convert() */ proc_ctx->is_iecp_enabled = (proc_ctx->filters_mask & VPP_IECP_MASK) != 0; proc_ctx->is_dn_enabled = (proc_ctx->filters_mask & VPP_DNDI_DN) != 0; proc_ctx->is_di_enabled = (proc_ctx->filters_mask & VPP_DNDI_DI) != 0; proc_ctx->is_di_adv_enabled = 0; proc_ctx->is_first_frame = 0; proc_ctx->is_second_field = 0; /* Check whether we are deinterlacing the second field */ if (proc_ctx->is_di_enabled) { const VAProcFilterParameterBufferDeinterlacing * const deint_params = proc_ctx->filter_di; const unsigned int tff = !(deint_params->flags & VA_DEINTERLACING_BOTTOM_FIELD_FIRST); const unsigned int is_top_field = !(deint_params->flags & VA_DEINTERLACING_BOTTOM_FIELD); if ((tff ^ is_top_field) != 0) { struct object_surface * const obj_surface = proc_ctx->surface_input_object; if (proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id != obj_surface->base.id) { WARN_ONCE("invalid surface provided for second field\n"); return VA_STATUS_ERROR_INVALID_PARAMETER; } proc_ctx->is_second_field = 1; } } /* Check whether we are deinterlacing the first frame */ if (proc_ctx->is_di_enabled) { const VAProcFilterParameterBufferDeinterlacing * const deint_params = proc_ctx->filter_di; switch (deint_params->algorithm) { case VAProcDeinterlacingBob: proc_ctx->is_first_frame = 1; break; case VAProcDeinterlacingMotionAdaptive: case VAProcDeinterlacingMotionCompensated: if (proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id == VA_INVALID_ID) proc_ctx->is_first_frame = 1; else if (proc_ctx->is_second_field) { /* At this stage, we have already deinterlaced the first field successfully. So, the first frame flag is trigerred if the previous field was deinterlaced without reference frame */ if (proc_ctx->frame_store[FRAME_IN_PREVIOUS].surface_id == VA_INVALID_ID) proc_ctx->is_first_frame = 1; } else { const VAProcPipelineParameterBuffer * const pipe = proc_ctx->pipeline_param; if (pipe->num_forward_references < 1 || pipe->forward_references[0] == VA_INVALID_ID) { WARN_ONCE("A forward temporal reference is needed for Motion adaptive/compensated deinterlacing !!!\n"); return VA_STATUS_ERROR_INVALID_PARAMETER; } } proc_ctx->is_di_adv_enabled = 1; break; default: WARN_ONCE("unsupported deinterlacing algorithm (%d)\n", deint_params->algorithm); return VA_STATUS_ERROR_UNSUPPORTED_FILTER; } } return VA_STATUS_SUCCESS; } VAStatus gen75_vebox_process_picture(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { VAStatus status; status = gen75_vebox_init_pipe_params(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; status = gen75_vebox_init_filter_params(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; status = hsw_veb_pre_format_convert(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; status = gen75_vebox_ensure_surfaces(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; status = gen75_vebox_ensure_surfaces_storage(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; if (proc_ctx->filters_mask & VPP_SHARP_MASK) { vpp_sharpness_filtering(ctx, proc_ctx); } else if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) { assert(proc_ctx->is_second_field); /* directly copy the saved frame in the second call */ } else { intel_batchbuffer_start_atomic_veb(proc_ctx->batch, 0x1000); intel_batchbuffer_emit_mi_flush(proc_ctx->batch); hsw_veb_state_table_setup(ctx, proc_ctx); hsw_veb_state_command(ctx, proc_ctx); hsw_veb_surface_state(ctx, proc_ctx, INPUT_SURFACE); hsw_veb_surface_state(ctx, proc_ctx, OUTPUT_SURFACE); hsw_veb_dndi_iecp_command(ctx, proc_ctx); intel_batchbuffer_end_atomic(proc_ctx->batch); intel_batchbuffer_flush(proc_ctx->batch); } status = hsw_veb_post_format_convert(ctx, proc_ctx); return status; } void gen75_vebox_context_destroy(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { int i; if(proc_ctx->vpp_gpe_ctx){ vpp_gpe_context_destroy(ctx,proc_ctx->vpp_gpe_ctx); proc_ctx->vpp_gpe_ctx = NULL; } if(proc_ctx->surface_input_vebox != VA_INVALID_ID){ i965_DestroySurfaces(ctx, &proc_ctx->surface_input_vebox, 1); proc_ctx->surface_input_vebox = VA_INVALID_ID; proc_ctx->surface_input_vebox_object = NULL; } if(proc_ctx->surface_output_vebox != VA_INVALID_ID){ i965_DestroySurfaces(ctx, &proc_ctx->surface_output_vebox, 1); proc_ctx->surface_output_vebox = VA_INVALID_ID; proc_ctx->surface_output_vebox_object = NULL; } if(proc_ctx->surface_output_scaled != VA_INVALID_ID){ i965_DestroySurfaces(ctx, &proc_ctx->surface_output_scaled, 1); proc_ctx->surface_output_scaled = VA_INVALID_ID; proc_ctx->surface_output_scaled_object = NULL; } for (i = 0; i < ARRAY_ELEMS(proc_ctx->frame_store); i++) frame_store_clear(&proc_ctx->frame_store[i], ctx); /* dndi state table */ drm_intel_bo_unreference(proc_ctx->dndi_state_table.bo); proc_ctx->dndi_state_table.bo = NULL; /* iecp state table */ drm_intel_bo_unreference(proc_ctx->iecp_state_table.bo); proc_ctx->iecp_state_table.bo = NULL; /* gamut statu table */ drm_intel_bo_unreference(proc_ctx->gamut_state_table.bo); proc_ctx->gamut_state_table.bo = NULL; /* vertex state table */ drm_intel_bo_unreference(proc_ctx->vertex_state_table.bo); proc_ctx->vertex_state_table.bo = NULL; intel_batchbuffer_free(proc_ctx->batch); free(proc_ctx); } struct intel_vebox_context * gen75_vebox_context_init(VADriverContextP ctx) { struct intel_driver_data *intel = intel_driver_data(ctx); struct intel_vebox_context *proc_context = calloc(1, sizeof(struct intel_vebox_context)); int i; assert(proc_context); proc_context->batch = intel_batchbuffer_new(intel, I915_EXEC_VEBOX, 0); for (i = 0; i < ARRAY_ELEMS(proc_context->frame_store); i++) proc_context->frame_store[i].surface_id = VA_INVALID_ID; proc_context->filters_mask = 0; proc_context->surface_output_object = NULL; proc_context->surface_input_object = NULL; proc_context->surface_input_vebox = VA_INVALID_ID; proc_context->surface_input_vebox_object = NULL; proc_context->surface_output_vebox = VA_INVALID_ID; proc_context->surface_output_vebox_object = NULL; proc_context->surface_output_scaled = VA_INVALID_ID; proc_context->surface_output_scaled_object = NULL; proc_context->filters_mask = 0; proc_context->format_convert_flags = 0; proc_context->vpp_gpe_ctx = NULL; return proc_context; } void bdw_veb_state_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { struct intel_batchbuffer *batch = proc_ctx->batch; BEGIN_VEB_BATCH(batch, 0xc); OUT_VEB_BATCH(batch, VEB_STATE | (0xc - 2)); OUT_VEB_BATCH(batch, 0 << 25 | // state surface control bits 0 << 23 | // reserved. 0 << 22 | // gamut expansion position 0 << 15 | // reserved. 0 << 14 | // single slice vebox enable 0 << 13 | // hot pixel filter enable 0 << 12 | // alpha plane enable 0 << 11 | // vignette enable 0 << 10 | // demosaic enable proc_ctx->current_output_type << 8 | // DI output frame 1 << 7 | // 444->422 downsample method 1 << 6 | // 422->420 downsample method proc_ctx->is_first_frame << 5 | // DN/DI first frame proc_ctx->is_di_enabled << 4 | // DI enable proc_ctx->is_dn_enabled << 3 | // DN enable proc_ctx->is_iecp_enabled << 2 | // global IECP enabled 0 << 1 | // ColorGamutCompressionEnable 0 ) ; // ColorGamutExpansionEnable. OUT_RELOC(batch, proc_ctx->dndi_state_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_VEB_BATCH(batch, 0); OUT_RELOC(batch, proc_ctx->iecp_state_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_VEB_BATCH(batch, 0); OUT_RELOC(batch, proc_ctx->gamut_state_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_VEB_BATCH(batch, 0); OUT_RELOC(batch, proc_ctx->vertex_state_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_VEB_BATCH(batch, 0); OUT_VEB_BATCH(batch, 0);/*caputre pipe state pointer*/ OUT_VEB_BATCH(batch, 0); ADVANCE_VEB_BATCH(batch); } void bdw_veb_dndi_iecp_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { struct intel_batchbuffer *batch = proc_ctx->batch; unsigned char frame_ctrl_bits = 0; struct object_surface *obj_surface = proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface; unsigned int width64 = ALIGN(proc_ctx->width_input, 64); assert(obj_surface); if (width64 > obj_surface->orig_width) width64 = obj_surface->orig_width; BEGIN_VEB_BATCH(batch, 0x14); OUT_VEB_BATCH(batch, VEB_DNDI_IECP_STATE | (0x14 - 2));//DWord 0 OUT_VEB_BATCH(batch, (width64 - 1)); OUT_RELOC(batch, proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface->bo, I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);//DWord 2 OUT_VEB_BATCH(batch,0);//DWord 3 OUT_RELOC(batch, proc_ctx->frame_store[FRAME_IN_PREVIOUS].obj_surface->bo, I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);//DWord 4 OUT_VEB_BATCH(batch,0);//DWord 5 OUT_RELOC(batch, proc_ctx->frame_store[FRAME_IN_STMM].obj_surface->bo, I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);//DWord 6 OUT_VEB_BATCH(batch,0);//DWord 7 OUT_RELOC(batch, proc_ctx->frame_store[FRAME_OUT_STMM].obj_surface->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 8 OUT_VEB_BATCH(batch,0);//DWord 9 OUT_RELOC(batch, proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 10 OUT_VEB_BATCH(batch,0);//DWord 11 OUT_RELOC(batch, proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 12 OUT_VEB_BATCH(batch,0);//DWord 13 OUT_RELOC(batch, proc_ctx->frame_store[FRAME_OUT_PREVIOUS].obj_surface->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 14 OUT_VEB_BATCH(batch,0);//DWord 15 OUT_RELOC(batch, proc_ctx->frame_store[FRAME_OUT_STATISTIC].obj_surface->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 16 OUT_VEB_BATCH(batch,0);//DWord 17 OUT_VEB_BATCH(batch,0);//DWord 18 OUT_VEB_BATCH(batch,0);//DWord 19 ADVANCE_VEB_BATCH(batch); } VAStatus gen8_vebox_process_picture(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { VAStatus status; status = gen75_vebox_init_pipe_params(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; status = gen75_vebox_init_filter_params(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; status = hsw_veb_pre_format_convert(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; status = gen75_vebox_ensure_surfaces(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; status = gen75_vebox_ensure_surfaces_storage(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; if (proc_ctx->filters_mask & VPP_SHARP_MASK) { vpp_sharpness_filtering(ctx, proc_ctx); } else if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) { assert(proc_ctx->is_second_field); /* directly copy the saved frame in the second call */ } else { intel_batchbuffer_start_atomic_veb(proc_ctx->batch, 0x1000); intel_batchbuffer_emit_mi_flush(proc_ctx->batch); hsw_veb_state_table_setup(ctx, proc_ctx); bdw_veb_state_command(ctx, proc_ctx); hsw_veb_surface_state(ctx, proc_ctx, INPUT_SURFACE); hsw_veb_surface_state(ctx, proc_ctx, OUTPUT_SURFACE); bdw_veb_dndi_iecp_command(ctx, proc_ctx); intel_batchbuffer_end_atomic(proc_ctx->batch); intel_batchbuffer_flush(proc_ctx->batch); } status = hsw_veb_post_format_convert(ctx, proc_ctx); return status; } void skl_veb_dndi_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { unsigned int* p_table ; unsigned int progressive_dn = 1; unsigned int dndi_top_first = 0; unsigned int is_mcdi_enabled = 0; if (proc_ctx->is_di_enabled) { const VAProcFilterParameterBufferDeinterlacing * const deint_params = proc_ctx->filter_di; progressive_dn = 0; /* If we are in "First Frame" mode, i.e. past frames are not available for motion measure, then don't use the TFF flag */ dndi_top_first = !(deint_params->flags & (proc_ctx->is_first_frame ? VA_DEINTERLACING_BOTTOM_FIELD : VA_DEINTERLACING_BOTTOM_FIELD_FIRST)); is_mcdi_enabled = (deint_params->algorithm == VAProcDeinterlacingMotionCompensated); } /* VAProcFilterParameterBufferDeinterlacing *di_param = (VAProcFilterParameterBufferDeinterlacing *) proc_ctx->filter_di; VAProcFilterParameterBuffer * dn_param = (VAProcFilterParameterBuffer *) proc_ctx->filter_dn; */ p_table = (unsigned int *)proc_ctx->dndi_state_table.ptr; *p_table ++ = ( 140 << 20 | // denoise stad threshold . w1 192 << 12 | // dnmh_history_max 7 << 8 | // dnmh_delta[3:0] 1 ); // denoise moving pixel threshold *p_table ++ = ( 38 << 20 | // denoise asd threshold 0 << 10 | // temporal diff th 0 ); // low temporal diff th *p_table ++ = ( progressive_dn << 28 | // progressive dn 38 << 16 | // denoise th for sum of complexity measure 32 << 10 | // dnmh_history_init[5:0] 0 ); // reserved *p_table ++ = ( 0 << 28 | // hot pixel count 0 << 20 | // hot pixel threshold 1 << 12 | // block noise estimate edge threshold 20 ); // block noise estimate noise threshold *p_table ++ = ( 140<< 16 | // chroma denoise stad threshold 0 << 13 | // reserved 1 << 12 | // chrome denoise enable 13 << 6 | // chr temp diff th 7 ); // chr temp diff low *p_table ++ = 0; // weight *p_table ++ = ( 0 << 16 | // dn_thmax 0 ); // dn_thmin *p_table ++ = ( 0 << 16 | // dn_prt5 0 ); // dn_dyn_thmin *p_table ++ = ( 0 << 16 | // dn_prt4 0 ); // dn_prt3 *p_table ++ = ( 0 << 16 | // dn_prt2 0 ); // dn_prt1 *p_table ++ = ( 0 << 16 | // dn_prt0 0 << 10 | // dn_wd22 0 << 5 | // dh_wd21 0 ); // dh_wd20 *p_table ++ = ( 0 << 25 | // dn_wd12 0 << 20 | // dn_wd11 0 << 15 | // dn_wd10 0 << 10 | // dn_wd02 0 << 5 | // dn_wd01 0 ); // dn_wd00 *p_table ++ = ( 2 << 10 | // stmm c2 9 << 6 | // cat slope minus 1 5 << 2 | // sad tight threshold 0 ); // smooth mv th *p_table ++ = ( 0 << 31 | // stmm blending constant select 64 << 24 | // stmm trc1 125<< 16 | // stmm trc2 0 << 14 | // reserved 30 << 8 | // multiplier for vecm 150 ); // maximum stmm *p_table ++ = ( 118<< 24 | // minumum stmm 0 << 22 | // stmm shift down 1 << 20 | // stmm shift up 5 << 16 | // stmm output shift 100 << 8 | // sdi threshold 5 ); // sdi delta *p_table ++ = ( 50 << 24 | // sdi fallback mode 1 t1 constant 100 << 16 | // sdi fallback mode 1 t2 constant 37 << 8 | // sdi fallback mode 2 constant(angle2x1) 175 ); // fmd temporal difference threshold *p_table ++ = ( 16 << 24 | // fmd #1 vertical difference th . w7 100<< 16 | // fmd #2 vertical difference th 0 << 14 | // cat threshold 2 << 8 | // fmd tear threshold is_mcdi_enabled << 7 | // mcdi enable, use motion compensated deinterlace algorithm dndi_top_first << 3 | // dn/di top first 0 ); // reserved *p_table ++ = ( 10 << 19 | // neighbor pixel threshold 0 << 16 | // fmd for 2nd field of previous frame 25 << 10 | // mc pixel consistency threshold 0 << 8 | // fmd for 1st field for current frame 10 << 4 | // sad thb 5 ); // sad tha } void skl_veb_iecp_csc_transform_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 220); float tran_coef[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; float v_coef[3] = {0.0, 0.0, 0.0}; float u_coef[3] = {0.0, 0.0, 0.0}; int is_transform_enabled = 0; if(!(proc_ctx->filters_mask & VPP_IECP_CSC_TRANSFORM)){ memset(p_table, 0, 12 * 4); return; } if(proc_ctx->fourcc_input == VA_FOURCC_RGBA && (proc_ctx->fourcc_output == VA_FOURCC_NV12 || proc_ctx->fourcc_output == VA_FOURCC_YV12 || proc_ctx->fourcc_output == VA_FOURCC_YVY2 || proc_ctx->fourcc_output == VA_FOURCC_AYUV)) { tran_coef[0] = 0.257; tran_coef[1] = 0.504; tran_coef[2] = 0.098; tran_coef[3] = -0.148; tran_coef[4] = -0.291; tran_coef[5] = 0.439; tran_coef[6] = 0.439; tran_coef[7] = -0.368; tran_coef[8] = -0.071; u_coef[0] = 16 * 4; u_coef[1] = 128 * 4; u_coef[2] = 128 * 4; is_transform_enabled = 1; }else if((proc_ctx->fourcc_input == VA_FOURCC_NV12 || proc_ctx->fourcc_input == VA_FOURCC_YV12 || proc_ctx->fourcc_input == VA_FOURCC_YUY2 || proc_ctx->fourcc_input == VA_FOURCC_AYUV) && proc_ctx->fourcc_output == VA_FOURCC_RGBA) { tran_coef[0] = 1.164; tran_coef[1] = 0.000; tran_coef[2] = 1.569; tran_coef[3] = 1.164; tran_coef[4] = -0.813; tran_coef[5] = -0.392; tran_coef[6] = 1.164; tran_coef[7] = 2.017; tran_coef[8] = 0.000; v_coef[0] = -16 * 4; v_coef[1] = -128 * 4; v_coef[2] = -128 * 4; is_transform_enabled = 1; }else if(proc_ctx->fourcc_input != proc_ctx->fourcc_output){ //enable when input and output format are different. is_transform_enabled = 1; } if(is_transform_enabled == 0){ memset(p_table, 0, 12 * 4); }else{ *p_table ++ = ( is_transform_enabled << 31 | 0 << 29 | // yuv_channel swap intel_format_convert(tran_coef[0], 2, 16, 1)); //c0, s2.16 format *p_table ++ = ( 0 << 19 | //reserved intel_format_convert(tran_coef[1], 2, 16, 1)); //c1, s2.16 format *p_table ++ = ( 0 << 19 | //reserved intel_format_convert(tran_coef[2], 2, 16, 1)); //c2, s2.16 format *p_table ++ = ( 0 << 19 | //reserved intel_format_convert(tran_coef[3], 2, 16, 1)); //c3, s2.16 format *p_table ++ = ( 0 << 19 | //reserved intel_format_convert(tran_coef[4], 2, 16, 1)); //c4, s2.16 format *p_table ++ = ( 0 << 19 | //reserved intel_format_convert(tran_coef[5], 2, 16, 1)); //c5, s2.16 format *p_table ++ = ( 0 << 19 | //reserved intel_format_convert(tran_coef[6], 2, 16, 1)); //c6, s2.16 format *p_table ++ = ( 0 << 19 | //reserved intel_format_convert(tran_coef[7], 2, 16, 1)); //c7, s2.16 format *p_table ++ = ( 0 << 19 | //reserved intel_format_convert(tran_coef[8], 2, 16, 1)); //c8, s2.16 format *p_table ++ = ( intel_format_convert(u_coef[0], 16, 0, 1) << 16 | intel_format_convert(v_coef[0], 16, 0, 1)); *p_table ++ = ( intel_format_convert(u_coef[1], 16, 0, 1) << 16 | intel_format_convert(v_coef[1], 16, 0, 1)); *p_table ++ = ( intel_format_convert(u_coef[2], 16, 0, 1) << 16 | intel_format_convert(v_coef[2], 16, 0, 1)); } } void skl_veb_iecp_aoi_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 27 * sizeof(unsigned int)); if (!(proc_ctx->filters_mask & VPP_IECP_AOI)) { memset(p_table, 0, 3 * 4); } else { *p_table ++ = 0x00000000; *p_table ++ = 0x00030000; *p_table ++ = 0x00030000; } } void skl_veb_state_table_setup(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { if(proc_ctx->filters_mask & VPP_DNDI_MASK) { dri_bo *dndi_bo = proc_ctx->dndi_state_table.bo; dri_bo_map(dndi_bo, 1); proc_ctx->dndi_state_table.ptr = dndi_bo->virtual; skl_veb_dndi_table(ctx, proc_ctx); dri_bo_unmap(dndi_bo); } if(proc_ctx->filters_mask & VPP_IECP_MASK) { dri_bo *iecp_bo = proc_ctx->iecp_state_table.bo; dri_bo_map(iecp_bo, 1); proc_ctx->iecp_state_table.ptr = iecp_bo->virtual; memset(proc_ctx->iecp_state_table.ptr, 0, 90 * 4); hsw_veb_iecp_std_table(ctx, proc_ctx); hsw_veb_iecp_ace_table(ctx, proc_ctx); hsw_veb_iecp_tcc_table(ctx, proc_ctx); hsw_veb_iecp_pro_amp_table(ctx, proc_ctx); skl_veb_iecp_csc_transform_table(ctx, proc_ctx); skl_veb_iecp_aoi_table(ctx, proc_ctx); dri_bo_unmap(iecp_bo); } } void skl_veb_state_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { struct intel_batchbuffer *batch = proc_ctx->batch; BEGIN_VEB_BATCH(batch, 0x10); OUT_VEB_BATCH(batch, VEB_STATE | (0x10 - 2)); OUT_VEB_BATCH(batch, 0 << 25 | // state surface control bits 0 << 23 | // reserved. 0 << 22 | // gamut expansion position 0 << 15 | // reserved. 0 << 14 | // single slice vebox enable 0 << 13 | // hot pixel filter enable 0 << 12 | // alpha plane enable 0 << 11 | // vignette enable 0 << 10 | // demosaic enable proc_ctx->current_output_type << 8 | // DI output frame 1 << 7 | // 444->422 downsample method 1 << 6 | // 422->420 downsample method proc_ctx->is_first_frame << 5 | // DN/DI first frame proc_ctx->is_di_enabled << 4 | // DI enable proc_ctx->is_dn_enabled << 3 | // DN enable proc_ctx->is_iecp_enabled << 2 | // global IECP enabled 0 << 1 | // ColorGamutCompressionEnable 0 ) ; // ColorGamutExpansionEnable. OUT_RELOC(batch, proc_ctx->dndi_state_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_VEB_BATCH(batch, 0); OUT_RELOC(batch, proc_ctx->iecp_state_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_VEB_BATCH(batch, 0); OUT_RELOC(batch, proc_ctx->gamut_state_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_VEB_BATCH(batch, 0); OUT_RELOC(batch, proc_ctx->vertex_state_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_VEB_BATCH(batch, 0); OUT_VEB_BATCH(batch, 0);/*caputre pipe state pointer*/ OUT_VEB_BATCH(batch, 0); OUT_VEB_BATCH(batch, 0);/*lace lut table state pointer*/ OUT_VEB_BATCH(batch, 0); OUT_VEB_BATCH(batch, 0);/*gamma correction values address*/ OUT_VEB_BATCH(batch, 0); ADVANCE_VEB_BATCH(batch); } void skl_veb_surface_state(VADriverContextP ctx, struct intel_vebox_context *proc_ctx, unsigned int is_output) { struct intel_batchbuffer *batch = proc_ctx->batch; unsigned int u_offset_y = 0, v_offset_y = 0; unsigned int is_uv_interleaved = 0, tiling = 0, swizzle = 0; unsigned int surface_format = PLANAR_420_8; struct object_surface* obj_surf = NULL; unsigned int surface_pitch = 0; unsigned int half_pitch_chroma = 0; unsigned int derived_pitch; if (is_output) { obj_surf = proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface; } else { obj_surf = proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface; } assert(obj_surf->fourcc == VA_FOURCC_NV12 || obj_surf->fourcc == VA_FOURCC_YUY2 || obj_surf->fourcc == VA_FOURCC_AYUV || obj_surf->fourcc == VA_FOURCC_RGBA || obj_surf->fourcc == VA_FOURCC_P010); if (obj_surf->fourcc == VA_FOURCC_NV12) { surface_format = PLANAR_420_8; surface_pitch = obj_surf->width; is_uv_interleaved = 1; half_pitch_chroma = 0; } else if (obj_surf->fourcc == VA_FOURCC_YUY2) { surface_format = YCRCB_NORMAL; surface_pitch = obj_surf->width * 2; is_uv_interleaved = 0; half_pitch_chroma = 0; } else if (obj_surf->fourcc == VA_FOURCC_AYUV) { surface_format = PACKED_444A_8; surface_pitch = obj_surf->width * 4; is_uv_interleaved = 0; half_pitch_chroma = 0; } else if (obj_surf->fourcc == VA_FOURCC_RGBA) { surface_format = R8G8B8A8_UNORM_SRGB; surface_pitch = obj_surf->width * 4; is_uv_interleaved = 0; half_pitch_chroma = 0; } else if (obj_surf->fourcc == VA_FOURCC_P010) { surface_format = PLANAR_420_16; surface_pitch = obj_surf->width; is_uv_interleaved = 1; half_pitch_chroma = 0; } derived_pitch = surface_pitch; u_offset_y = obj_surf->y_cb_offset; v_offset_y = obj_surf->y_cr_offset; dri_bo_get_tiling(obj_surf->bo, &tiling, &swizzle); BEGIN_VEB_BATCH(batch, 9); OUT_VEB_BATCH(batch, VEB_SURFACE_STATE | (9 - 2)); OUT_VEB_BATCH(batch, 0 << 1 | // reserved is_output); // surface indentification. OUT_VEB_BATCH(batch, (obj_surf->orig_height - 1) << 18 | // height . w3 (obj_surf->orig_width - 1) << 4 | // width 0); // reserve OUT_VEB_BATCH(batch, surface_format << 28 | // surface format, YCbCr420. w4 is_uv_interleaved << 27 | // interleave chrome , two seperate palar 0 << 20 | // reserved (surface_pitch - 1) << 3 | // surface pitch, 64 align half_pitch_chroma << 2 | // half pitch for chrome !!tiling << 1 | // tiled surface, linear surface used (tiling == I915_TILING_Y)); // tiled walk, ignored when liner surface OUT_VEB_BATCH(batch, 0 << 16 | // X offset for V(Cb) u_offset_y); // Y offset for V(Cb) OUT_VEB_BATCH(batch, 0 << 16 | // X offset for V(Cr) v_offset_y ); // Y offset for V(Cr) OUT_VEB_BATCH(batch, 0); OUT_VEB_BATCH(batch, derived_pitch - 1); OUT_VEB_BATCH(batch, 0); ADVANCE_VEB_BATCH(batch); } VAStatus gen9_vebox_process_picture(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { VAStatus status; status = gen75_vebox_init_pipe_params(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; status = gen75_vebox_init_filter_params(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; status = hsw_veb_pre_format_convert(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; status = gen75_vebox_ensure_surfaces(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; status = gen75_vebox_ensure_surfaces_storage(ctx, proc_ctx); if (status != VA_STATUS_SUCCESS) return status; if (proc_ctx->filters_mask & VPP_SHARP_MASK) { vpp_sharpness_filtering(ctx, proc_ctx); } else if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) { assert(proc_ctx->is_second_field); /* directly copy the saved frame in the second call */ } else { intel_batchbuffer_start_atomic_veb(proc_ctx->batch, 0x1000); intel_batchbuffer_emit_mi_flush(proc_ctx->batch); skl_veb_state_table_setup(ctx, proc_ctx); skl_veb_state_command(ctx, proc_ctx); skl_veb_surface_state(ctx, proc_ctx, INPUT_SURFACE); skl_veb_surface_state(ctx, proc_ctx, OUTPUT_SURFACE); bdw_veb_dndi_iecp_command(ctx, proc_ctx); intel_batchbuffer_end_atomic(proc_ctx->batch); intel_batchbuffer_flush(proc_ctx->batch); } status = hsw_veb_post_format_convert(ctx, proc_ctx); return status; }