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);
57 i965_DestroySurfaces(VADriverContextP ctx,
58 VASurfaceID *surface_list,
62 i965_CreateSurfaces(VADriverContextP ctx,
67 VASurfaceID *surfaces);
69 VAStatus vpp_surface_convert(VADriverContextP ctx,
70 struct object_surface *src_obj_surf,
71 struct object_surface *dst_obj_surf)
73 VAStatus va_status = VA_STATUS_SUCCESS;
75 assert(src_obj_surf->orig_width == dst_obj_surf->orig_width);
76 assert(src_obj_surf->orig_height == dst_obj_surf->orig_height);
78 VARectangle src_rect, dst_rect;
79 src_rect.x = dst_rect.x = 0;
80 src_rect.y = dst_rect.y = 0;
81 src_rect.width = dst_rect.width = src_obj_surf->orig_width;
82 src_rect.height = dst_rect.height = dst_obj_surf->orig_height;
84 struct i965_surface src_surface, dst_surface;
85 src_surface.base = (struct object_base *)src_obj_surf;
86 src_surface.type = I965_SURFACE_TYPE_SURFACE;
87 src_surface.flags = I965_SURFACE_FLAG_FRAME;
89 dst_surface.base = (struct object_base *)dst_obj_surf;
90 dst_surface.type = I965_SURFACE_TYPE_SURFACE;
91 dst_surface.flags = I965_SURFACE_FLAG_FRAME;
93 va_status = i965_image_processing(ctx,
101 VAStatus vpp_surface_scaling(VADriverContextP ctx,
102 struct object_surface *dst_obj_surf,
103 struct object_surface *src_obj_surf)
105 VAStatus va_status = VA_STATUS_SUCCESS;
106 int flags = I965_PP_FLAG_AVS;
108 assert(src_obj_surf->fourcc == VA_FOURCC('N','V','1','2'));
109 assert(dst_obj_surf->fourcc == VA_FOURCC('N','V','1','2'));
111 VARectangle src_rect, dst_rect;
114 src_rect.width = src_obj_surf->orig_width;
115 src_rect.height = src_obj_surf->orig_height;
119 dst_rect.width = dst_obj_surf->orig_width;
120 dst_rect.height = dst_obj_surf->orig_height;
122 va_status = i965_scaling_processing(ctx,
132 void hsw_veb_dndi_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
134 struct i965_driver_data *i965 = i965_driver_data(ctx);
135 unsigned int* p_table ;
136 int progressive_dn = 1;
137 int dndi_top_first = 0;
138 int motion_compensated_enable = 0;
140 if (proc_ctx->filters_mask & VPP_DNDI_DI) {
141 VAProcFilterParameterBufferDeinterlacing *di_param =
142 (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
146 dndi_top_first = !(di_param->flags & VA_DEINTERLACING_BOTTOM_FIELD);
147 motion_compensated_enable = (di_param->algorithm == VAProcDeinterlacingMotionCompensated);
151 VAProcFilterParameterBufferDeinterlacing *di_param =
152 (VAProcFilterParameterBufferDeinterlacing *) proc_ctx->filter_di;
154 VAProcFilterParameterBuffer * dn_param =
155 (VAProcFilterParameterBuffer *) proc_ctx->filter_dn;
157 p_table = (unsigned int *)proc_ctx->dndi_state_table.ptr;
159 if (IS_HASWELL(i965->intel.device_id))
160 *p_table ++ = 0; // reserved . w0
162 *p_table ++ = ( 140 << 24 | // denoise STAD threshold . w1
163 192 << 16 | // dnmh_history_max
164 0 << 12 | // reserved
165 7 << 8 | // dnmh_delta[3:0]
166 38 ); // denoise ASD threshold
168 *p_table ++ = ( 0 << 30 | // reserved . w2
169 0 << 24 | // temporal diff th
170 0 << 22 | // reserved.
171 0 << 16 | // low temporal diff th
173 1 << 8 | // denoise moving pixel th
174 38 ); // denoise th for sum of complexity measure
176 *p_table ++ = ( 0 << 30 | // reserved . w3
177 12<< 24 | // good neighbor th[5:0]
178 9 << 20 | // CAT slope minus 1
179 5 << 16 | // SAD Tight in
180 0 << 14 | // smooth mv th
181 0 << 12 | // reserved
182 1 << 8 | // bne_edge_th[3:0]
183 20 ); // block noise estimate noise th
185 *p_table ++ = ( 0 << 31 | // STMM blending constant select. w4
186 64 << 24 | // STMM trc1
187 125<< 16 | // STMM trc2
188 0 << 14 | // reserved
189 30 << 8 | // VECM_mul
190 150 ); // maximum STMM
192 *p_table ++ = ( 118<< 24 | // minumum STMM . W5
193 0 << 22 | // STMM shift down
194 1 << 20 | // STMM shift up
195 5 << 16 | // STMM output shift
196 100 << 8 | // SDI threshold
199 *p_table ++ = ( 50 << 24 | // SDI fallback mode 1 T1 constant . W6
200 100 << 16 | // SDI fallback mode 1 T2 constant
201 37 << 8 | // SDI fallback mode 2 constant(angle2x1)
202 175 ); // FMD temporal difference threshold
204 *p_table ++ = ( 16 << 24 | // FMD #1 vertical difference th . w7
205 100<< 16 | // FMD #2 vertical difference th
207 2 << 8 | // FMD tear threshold
208 motion_compensated_enable << 7 | // MCDI Enable, use motion compensated deinterlace algorithm
209 progressive_dn << 6 | // progressive DN
211 dndi_top_first << 3 | // DN/DI Top First
214 *p_table ++ = ( 0 << 29 | // reserved . W8
215 32 << 23 | // dnmh_history_init[5:0]
216 10 << 19 | // neighborPixel th
217 0 << 18 | // reserved
218 0 << 16 | // FMD for 2nd field of previous frame
219 25 << 10 | // MC pixel consistency th
220 0 << 8 | // FMD for 1st field for current frame
224 *p_table ++ = ( 0 << 24 | // reserved
225 140<< 16 | // chr_dnmh_stad_th
226 0 << 13 | // reserved
227 1 << 12 | // chrome denoise enable
228 13 << 6 | // chr temp diff th
229 7 ); // chr temp diff low
231 if (IS_GEN8(i965->intel.device_id))
232 *p_table ++ = 0; // parameters for hot pixel,
235 void hsw_veb_iecp_std_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
237 unsigned int *p_table = proc_ctx->iecp_state_table.ptr + 0 ;
238 //VAProcFilterParameterBuffer * std_param =
239 // (VAProcFilterParameterBuffer *) proc_ctx->filter_std;
241 if(!(proc_ctx->filters_mask & VPP_IECP_STD_STE)){
242 memset(p_table, 0, 29 * 4);
244 *p_table ++ = 0x9a6e39f0;
245 *p_table ++ = 0x400c0000;
246 *p_table ++ = 0x00001180;
247 *p_table ++ = 0xfe2f2e00;
248 *p_table ++ = 0x000000ff;
250 *p_table ++ = 0x00140000;
251 *p_table ++ = 0xd82e0000;
252 *p_table ++ = 0x8285ecec;
253 *p_table ++ = 0x00008282;
254 *p_table ++ = 0x00000000;
256 *p_table ++ = 0x02117000;
257 *p_table ++ = 0xa38fec96;
258 *p_table ++ = 0x0000c8c8;
259 *p_table ++ = 0x00000000;
260 *p_table ++ = 0x01478000;
262 *p_table ++ = 0x0007c306;
263 *p_table ++ = 0x00000000;
264 *p_table ++ = 0x00000000;
265 *p_table ++ = 0x1c1bd000;
266 *p_table ++ = 0x00000000;
268 *p_table ++ = 0x00000000;
269 *p_table ++ = 0x00000000;
270 *p_table ++ = 0x0007cf80;
271 *p_table ++ = 0x00000000;
272 *p_table ++ = 0x00000000;
274 *p_table ++ = 0x1c080000;
275 *p_table ++ = 0x00000000;
276 *p_table ++ = 0x00000000;
277 *p_table ++ = 0x00000000;
281 void hsw_veb_iecp_ace_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
283 unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 116);
285 if(!(proc_ctx->filters_mask & VPP_IECP_ACE)){
286 memset(p_table, 0, 13 * 4);
288 *p_table ++ = 0x00000068;
289 *p_table ++ = 0x4c382410;
290 *p_table ++ = 0x9c887460;
291 *p_table ++ = 0xebd8c4b0;
292 *p_table ++ = 0x604c3824;
294 *p_table ++ = 0xb09c8874;
295 *p_table ++ = 0x0000d8c4;
296 *p_table ++ = 0x00000000;
297 *p_table ++ = 0x00000000;
298 *p_table ++ = 0x00000000;
300 *p_table ++ = 0x00000000;
301 *p_table ++ = 0x00000000;
302 *p_table ++ = 0x00000000;
306 void hsw_veb_iecp_tcc_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
308 unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 168);
309 // VAProcFilterParameterBuffer * tcc_param =
310 // (VAProcFilterParameterBuffer *) proc_ctx->filter_iecp_tcc;
312 if(!(proc_ctx->filters_mask & VPP_IECP_TCC)){
313 memset(p_table, 0, 11 * 4);
315 *p_table ++ = 0x00000000;
316 *p_table ++ = 0x00000000;
317 *p_table ++ = 0x1e34cc91;
318 *p_table ++ = 0x3e3cce91;
319 *p_table ++ = 0x02e80195;
321 *p_table ++ = 0x0197046b;
322 *p_table ++ = 0x01790174;
323 *p_table ++ = 0x00000000;
324 *p_table ++ = 0x00000000;
325 *p_table ++ = 0x03030000;
327 *p_table ++ = 0x009201c0;
331 void hsw_veb_iecp_pro_amp_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
333 unsigned int contrast = 0x80; //default
334 int brightness = 0x00; //default
335 int cos_c_s = 256 ; //default
336 int sin_c_s = 0; //default
337 unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 212);
339 if(!(proc_ctx->filters_mask & VPP_IECP_PRO_AMP)){
340 memset(p_table, 0, 2 * 4);
342 float src_saturation = 1.0;
344 float src_contrast = 1.0;
345 float src_brightness = 0.0;
346 float tmp_value = 0.0;
349 VAProcFilterParameterBufferColorBalance * amp_params =
350 (VAProcFilterParameterBufferColorBalance *) proc_ctx->filter_iecp_amp;
352 for (i = 0; i < proc_ctx->filter_iecp_amp_num_elements; i++){
353 VAProcColorBalanceType attrib = amp_params[i].attrib;
355 if(attrib == VAProcColorBalanceHue) {
356 src_hue = amp_params[i].value; //(-180.0, 180.0)
357 }else if(attrib == VAProcColorBalanceSaturation) {
358 src_saturation = amp_params[i].value; //(0.0, 10.0)
359 }else if(attrib == VAProcColorBalanceBrightness) {
360 src_brightness = amp_params[i].value; // (-100.0, 100.0)
361 brightness = intel_format_convert(src_brightness, 7, 4, 1);
362 }else if(attrib == VAProcColorBalanceContrast) {
363 src_contrast = amp_params[i].value; // (0.0, 10.0)
364 contrast = intel_format_convert(src_contrast, 4, 7, 0);
368 tmp_value = cos(src_hue/180*PI) * src_contrast * src_saturation;
369 cos_c_s = intel_format_convert(tmp_value, 7, 8, 1);
371 tmp_value = sin(src_hue/180*PI) * src_contrast * src_saturation;
372 sin_c_s = intel_format_convert(tmp_value, 7, 8, 1);
374 *p_table ++ = ( 0 << 28 | //reserved
375 contrast << 17 | //contrast value (U4.7 format)
377 brightness << 1| // S7.4 format
380 *p_table ++ = ( cos_c_s << 16 | // cos(h) * contrast * saturation
381 sin_c_s); // sin(h) * contrast * saturation
387 void hsw_veb_iecp_csc_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
389 unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 220);
390 float tran_coef[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
391 float v_coef[3] = {0.0, 0.0, 0.0};
392 float u_coef[3] = {0.0, 0.0, 0.0};
393 int is_transform_enabled = 0;
395 if(!(proc_ctx->filters_mask & VPP_IECP_CSC)){
396 memset(p_table, 0, 8 * 4);
400 if(proc_ctx->fourcc_input == VA_FOURCC('R','G','B','A') &&
401 (proc_ctx->fourcc_output == VA_FOURCC('N','V','1','2') ||
402 proc_ctx->fourcc_output == VA_FOURCC('Y','V','1','2') ||
403 proc_ctx->fourcc_output == VA_FOURCC('Y','V','Y','2') ||
404 proc_ctx->fourcc_output == VA_FOURCC('A','Y','U','V'))) {
406 tran_coef[0] = 0.257;
407 tran_coef[1] = 0.504;
408 tran_coef[2] = 0.098;
409 tran_coef[3] = -0.148;
410 tran_coef[4] = -0.291;
411 tran_coef[5] = 0.439;
412 tran_coef[6] = 0.439;
413 tran_coef[7] = -0.368;
414 tran_coef[8] = -0.071;
420 is_transform_enabled = 1;
421 }else if((proc_ctx->fourcc_input == VA_FOURCC('N','V','1','2') ||
422 proc_ctx->fourcc_input == VA_FOURCC('Y','V','1','2') ||
423 proc_ctx->fourcc_input == VA_FOURCC('Y','U','Y','2') ||
424 proc_ctx->fourcc_input == VA_FOURCC('A','Y','U','V'))&&
425 proc_ctx->fourcc_output == VA_FOURCC('R','G','B','A')) {
427 tran_coef[0] = 1.164;
428 tran_coef[1] = 0.000;
429 tran_coef[2] = 1.569;
430 tran_coef[3] = 1.164;
431 tran_coef[4] = -0.813;
432 tran_coef[5] = -0.392;
433 tran_coef[6] = 1.164;
434 tran_coef[7] = 2.017;
435 tran_coef[8] = 0.000;
438 v_coef[1] = -128 * 4;
439 v_coef[2] = -128 * 4;
441 is_transform_enabled = 1;
442 }else if(proc_ctx->fourcc_input != proc_ctx->fourcc_output){
443 //enable when input and output format are different.
444 is_transform_enabled = 1;
447 if(is_transform_enabled == 0){
448 memset(p_table, 0, 8 * 4);
450 *p_table ++ = ( 0 << 29 | //reserved
451 intel_format_convert(tran_coef[1], 2, 10, 1) << 16 | //c1, s2.10 format
452 intel_format_convert(tran_coef[0], 2, 10, 1) << 3 | //c0, s2.10 format
454 0 << 1 | // yuv_channel swap
455 is_transform_enabled);
457 *p_table ++ = ( 0 << 26 | //reserved
458 intel_format_convert(tran_coef[3], 2, 10, 1) << 13 |
459 intel_format_convert(tran_coef[2], 2, 10, 1));
461 *p_table ++ = ( 0 << 26 | //reserved
462 intel_format_convert(tran_coef[5], 2, 10, 1) << 13 |
463 intel_format_convert(tran_coef[4], 2, 10, 1));
465 *p_table ++ = ( 0 << 26 | //reserved
466 intel_format_convert(tran_coef[7], 2, 10, 1) << 13 |
467 intel_format_convert(tran_coef[6], 2, 10, 1));
469 *p_table ++ = ( 0 << 13 | //reserved
470 intel_format_convert(tran_coef[8], 2, 10, 1));
472 *p_table ++ = ( 0 << 22 | //reserved
473 intel_format_convert(u_coef[0], 10, 0, 1) << 11 |
474 intel_format_convert(v_coef[0], 10, 0, 1));
476 *p_table ++ = ( 0 << 22 | //reserved
477 intel_format_convert(u_coef[1], 10, 0, 1) << 11 |
478 intel_format_convert(v_coef[1], 10, 0, 1));
480 *p_table ++ = ( 0 << 22 | //reserved
481 intel_format_convert(u_coef[2], 10, 0, 1) << 11 |
482 intel_format_convert(v_coef[2], 10, 0, 1));
486 void hsw_veb_iecp_aoi_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
488 unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 252);
489 // VAProcFilterParameterBuffer * tcc_param =
490 // (VAProcFilterParameterBuffer *) proc_ctx->filter_iecp_tcc;
492 if(!(proc_ctx->filters_mask & VPP_IECP_AOI)){
493 memset(p_table, 0, 3 * 4);
495 *p_table ++ = 0x00000000;
496 *p_table ++ = 0x00030000;
497 *p_table ++ = 0x00030000;
501 void hsw_veb_state_table_setup(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
503 if(proc_ctx->filters_mask & 0x000000ff) {
504 dri_bo *dndi_bo = proc_ctx->dndi_state_table.bo;
505 dri_bo_map(dndi_bo, 1);
506 proc_ctx->dndi_state_table.ptr = dndi_bo->virtual;
508 hsw_veb_dndi_table(ctx, proc_ctx);
510 dri_bo_unmap(dndi_bo);
513 if(proc_ctx->filters_mask & 0x0000ff00) {
514 dri_bo *iecp_bo = proc_ctx->iecp_state_table.bo;
515 dri_bo_map(iecp_bo, 1);
516 proc_ctx->iecp_state_table.ptr = iecp_bo->virtual;
518 hsw_veb_iecp_std_table(ctx, proc_ctx);
519 hsw_veb_iecp_ace_table(ctx, proc_ctx);
520 hsw_veb_iecp_tcc_table(ctx, proc_ctx);
521 hsw_veb_iecp_pro_amp_table(ctx, proc_ctx);
522 hsw_veb_iecp_csc_table(ctx, proc_ctx);
523 hsw_veb_iecp_aoi_table(ctx, proc_ctx);
525 dri_bo_unmap(iecp_bo);
529 void hsw_veb_state_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
531 struct intel_batchbuffer *batch = proc_ctx->batch;
532 unsigned int is_dn_enabled = (proc_ctx->filters_mask & 0x01)? 1: 0;
533 unsigned int is_di_enabled = (proc_ctx->filters_mask & 0x02)? 1: 0;
534 unsigned int is_iecp_enabled = (proc_ctx->filters_mask & 0xff00)?1:0;
535 unsigned int is_first_frame = !!((proc_ctx->frame_order == -1) &&
538 unsigned int di_output_frames_flag = 2; /* Output Current Frame Only */
540 if(proc_ctx->fourcc_input != proc_ctx->fourcc_output ||
541 (is_dn_enabled == 0 && is_di_enabled == 0)){
546 VAProcFilterParameterBufferDeinterlacing *di_param =
547 (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
551 if (di_param->algorithm == VAProcDeinterlacingBob)
554 if ((di_param->algorithm == VAProcDeinterlacingMotionAdaptive ||
555 di_param->algorithm == VAProcDeinterlacingMotionCompensated) &&
556 proc_ctx->frame_order != -1)
557 di_output_frames_flag = 0; /* Output both Current Frame and Previous Frame */
560 BEGIN_VEB_BATCH(batch, 6);
561 OUT_VEB_BATCH(batch, VEB_STATE | (6 - 2));
563 0 << 26 | // state surface control bits
564 0 << 11 | // reserved.
565 0 << 10 | // pipe sync disable
566 di_output_frames_flag << 8 | // DI output frame
567 1 << 7 | // 444->422 downsample method
568 1 << 6 | // 422->420 downsample method
569 is_first_frame << 5 | // DN/DI first frame
570 is_di_enabled << 4 | // DI enable
571 is_dn_enabled << 3 | // DN enable
572 is_iecp_enabled << 2 | // global IECP enabled
573 0 << 1 | // ColorGamutCompressionEnable
574 0 ) ; // ColorGamutExpansionEnable.
577 proc_ctx->dndi_state_table.bo,
578 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
581 proc_ctx->iecp_state_table.bo,
582 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
585 proc_ctx->gamut_state_table.bo,
586 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
589 proc_ctx->vertex_state_table.bo,
590 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
592 ADVANCE_VEB_BATCH(batch);
595 void hsw_veb_surface_state(VADriverContextP ctx, struct intel_vebox_context *proc_ctx, unsigned int is_output)
597 struct intel_batchbuffer *batch = proc_ctx->batch;
598 unsigned int u_offset_y = 0, v_offset_y = 0;
599 unsigned int is_uv_interleaved = 0, tiling = 0, swizzle = 0;
600 unsigned int surface_format = PLANAR_420_8;
601 struct object_surface* obj_surf = NULL;
602 unsigned int surface_pitch = 0;
603 unsigned int half_pitch_chroma = 0;
606 obj_surf = proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface;
608 obj_surf = proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface;
611 assert(obj_surf->fourcc == VA_FOURCC_NV12 ||
612 obj_surf->fourcc == VA_FOURCC_YUY2 ||
613 obj_surf->fourcc == VA_FOURCC_AYUV ||
614 obj_surf->fourcc == VA_FOURCC_RGBA);
616 if (obj_surf->fourcc == VA_FOURCC_NV12) {
617 surface_format = PLANAR_420_8;
618 surface_pitch = obj_surf->width;
619 is_uv_interleaved = 1;
620 half_pitch_chroma = 0;
621 } else if (obj_surf->fourcc == VA_FOURCC_YUY2) {
622 surface_format = YCRCB_NORMAL;
623 surface_pitch = obj_surf->width * 2;
624 is_uv_interleaved = 0;
625 half_pitch_chroma = 0;
626 } else if (obj_surf->fourcc == VA_FOURCC_AYUV) {
627 surface_format = PACKED_444A_8;
628 surface_pitch = obj_surf->width * 4;
629 is_uv_interleaved = 0;
630 half_pitch_chroma = 0;
631 } else if (obj_surf->fourcc == VA_FOURCC_RGBA) {
632 surface_format = R8G8B8A8_UNORM_SRGB;
633 surface_pitch = obj_surf->width * 4;
634 is_uv_interleaved = 0;
635 half_pitch_chroma = 0;
638 u_offset_y = obj_surf->y_cb_offset;
639 v_offset_y = obj_surf->y_cr_offset;
641 dri_bo_get_tiling(obj_surf->bo, &tiling, &swizzle);
643 BEGIN_VEB_BATCH(batch, 6);
644 OUT_VEB_BATCH(batch, VEB_SURFACE_STATE | (6 - 2));
647 is_output); // surface indentification.
650 (obj_surf->height - 1) << 18 | // height . w3
651 (obj_surf->width -1 ) << 4 | // width
655 surface_format << 28 | // surface format, YCbCr420. w4
656 is_uv_interleaved << 27 | // interleave chrome , two seperate palar
657 0 << 20 | // reserved
658 (surface_pitch - 1) << 3 | // surface pitch, 64 align
659 half_pitch_chroma << 2 | // half pitch for chrome
660 !!tiling << 1 | // tiled surface, linear surface used
661 (tiling == I915_TILING_Y)); // tiled walk, ignored when liner surface
664 0 << 29 | // reserved . w5
665 0 << 16 | // X offset for V(Cb)
666 0 << 15 | // reserved
667 u_offset_y); // Y offset for V(Cb)
670 0 << 29 | // reserved . w6
671 0 << 16 | // X offset for V(Cr)
672 0 << 15 | // reserved
673 v_offset_y ); // Y offset for V(Cr)
675 ADVANCE_VEB_BATCH(batch);
678 void hsw_veb_dndi_iecp_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
680 struct intel_batchbuffer *batch = proc_ctx->batch;
681 unsigned char frame_ctrl_bits = 0;
682 unsigned int startingX = 0;
683 unsigned int endingX = (proc_ctx->width_input + 63 ) / 64 * 64;
685 /* s1:update the previous and current input */
686 /* tempFrame = proc_ctx->frame_store[FRAME_IN_PREVIOUS];
687 proc_ctx->frame_store[FRAME_IN_PREVIOUS] = proc_ctx->frame_store[FRAME_IN_CURRENT]; ;
688 proc_ctx->frame_store[FRAME_IN_CURRENT] = tempFrame;
690 if(proc_ctx->surface_input_vebox != -1){
691 vpp_surface_copy(ctx, proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id,
692 proc_ctx->surface_input_vebox);
694 vpp_surface_copy(ctx, proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id,
695 proc_ctx->surface_input);
698 /*s2: update the STMM input and output */
699 /* tempFrame = proc_ctx->frame_store[FRAME_IN_STMM];
700 proc_ctx->frame_store[FRAME_IN_STMM] = proc_ctx->frame_store[FRAME_OUT_STMM]; ;
701 proc_ctx->frame_store[FRAME_OUT_STMM] = tempFrame;
703 /*s3:set reloc buffer address */
704 BEGIN_VEB_BATCH(batch, 10);
705 OUT_VEB_BATCH(batch, VEB_DNDI_IECP_STATE | (10 - 2));
710 proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface->bo,
711 I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);
713 proc_ctx->frame_store[FRAME_IN_PREVIOUS].obj_surface->bo,
714 I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);
716 proc_ctx->frame_store[FRAME_IN_STMM].obj_surface->bo,
717 I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);
719 proc_ctx->frame_store[FRAME_OUT_STMM].obj_surface->bo,
720 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
722 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface->bo,
723 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
725 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface->bo,
726 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
728 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].obj_surface->bo,
729 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
731 proc_ctx->frame_store[FRAME_OUT_STATISTIC].obj_surface->bo,
732 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
734 ADVANCE_VEB_BATCH(batch);
737 void hsw_veb_resource_prepare(VADriverContextP ctx,
738 struct intel_vebox_context *proc_ctx)
742 struct i965_driver_data *i965 = i965_driver_data(ctx);
743 unsigned int input_fourcc, output_fourcc;
744 unsigned int input_sampling, output_sampling;
745 unsigned int input_tiling, output_tiling;
746 unsigned int i, swizzle;
747 struct object_surface *obj_surf_out = NULL, *obj_surf_in = NULL;
749 if (proc_ctx->surface_input_vebox_object != NULL) {
750 obj_surf_in = proc_ctx->surface_input_vebox_object;
752 obj_surf_in = proc_ctx->surface_input_object;
755 if (proc_ctx->surface_output_vebox_object != NULL) {
756 obj_surf_out = proc_ctx->surface_output_vebox_object;
758 obj_surf_out = proc_ctx->surface_output_object;
761 if(obj_surf_in->bo == NULL){
762 input_fourcc = VA_FOURCC('N','V','1','2');
763 input_sampling = SUBSAMPLE_YUV420;
765 i965_check_alloc_surface_bo(ctx, obj_surf_in, input_tiling, input_fourcc, input_sampling);
767 input_fourcc = obj_surf_in->fourcc;
768 input_sampling = obj_surf_in->subsampling;
769 dri_bo_get_tiling(obj_surf_in->bo, &input_tiling, &swizzle);
770 input_tiling = !!input_tiling;
773 if(obj_surf_out->bo == NULL){
774 output_fourcc = VA_FOURCC('N','V','1','2');
775 output_sampling = SUBSAMPLE_YUV420;
777 i965_check_alloc_surface_bo(ctx, obj_surf_out, output_tiling, output_fourcc, output_sampling);
779 output_fourcc = obj_surf_out->fourcc;
780 output_sampling = obj_surf_out->subsampling;
781 dri_bo_get_tiling(obj_surf_out->bo, &output_tiling, &swizzle);
782 output_tiling = !!output_tiling;
785 /* vebox pipelien input surface format info */
786 proc_ctx->fourcc_input = input_fourcc;
787 proc_ctx->fourcc_output = output_fourcc;
789 /* create pipeline surfaces */
790 for(i = 0; i < FRAME_STORE_SUM; i ++) {
791 if(proc_ctx->frame_store[i].obj_surface){
792 continue; //refer external surface for vebox pipeline
795 VASurfaceID new_surface;
796 struct object_surface *obj_surf = NULL;
798 va_status = i965_CreateSurfaces(ctx,
799 proc_ctx ->width_input,
800 proc_ctx ->height_input,
804 assert(va_status == VA_STATUS_SUCCESS);
806 obj_surf = SURFACE(new_surface);
809 if( i <= FRAME_IN_PREVIOUS || i == FRAME_OUT_CURRENT_DN) {
810 i965_check_alloc_surface_bo(ctx, obj_surf, input_tiling, input_fourcc, input_sampling);
811 } else if( i == FRAME_IN_STMM || i == FRAME_OUT_STMM){
812 i965_check_alloc_surface_bo(ctx, obj_surf, 1, input_fourcc, input_sampling);
813 } else if( i >= FRAME_OUT_CURRENT){
814 i965_check_alloc_surface_bo(ctx, obj_surf, output_tiling, output_fourcc, output_sampling);
817 proc_ctx->frame_store[i].surface_id = new_surface;
818 proc_ctx->frame_store[i].is_internal_surface = 1;
819 proc_ctx->frame_store[i].obj_surface = obj_surf;
822 /* alloc dndi state table */
823 dri_bo_unreference(proc_ctx->dndi_state_table.bo);
824 bo = dri_bo_alloc(i965->intel.bufmgr,
825 "vebox: dndi state Buffer",
827 proc_ctx->dndi_state_table.bo = bo;
828 dri_bo_reference(proc_ctx->dndi_state_table.bo);
830 /* alloc iecp state table */
831 dri_bo_unreference(proc_ctx->iecp_state_table.bo);
832 bo = dri_bo_alloc(i965->intel.bufmgr,
833 "vebox: iecp state Buffer",
835 proc_ctx->iecp_state_table.bo = bo;
836 dri_bo_reference(proc_ctx->iecp_state_table.bo);
838 /* alloc gamut state table */
839 dri_bo_unreference(proc_ctx->gamut_state_table.bo);
840 bo = dri_bo_alloc(i965->intel.bufmgr,
841 "vebox: gamut state Buffer",
843 proc_ctx->gamut_state_table.bo = bo;
844 dri_bo_reference(proc_ctx->gamut_state_table.bo);
846 /* alloc vertex state table */
847 dri_bo_unreference(proc_ctx->vertex_state_table.bo);
848 bo = dri_bo_alloc(i965->intel.bufmgr,
849 "vertex: iecp state Buffer",
851 proc_ctx->vertex_state_table.bo = bo;
852 dri_bo_reference(proc_ctx->vertex_state_table.bo);
857 hsw_veb_surface_reference(VADriverContextP ctx,
858 struct intel_vebox_context *proc_ctx)
860 struct object_surface * obj_surf;
861 VEBFrameStore tmp_store;
863 if (proc_ctx->surface_input_vebox_object != NULL) {
864 obj_surf = proc_ctx->surface_input_vebox_object;
866 obj_surf = proc_ctx->surface_input_object;
869 /* update the input surface */
870 proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id = VA_INVALID_ID;
871 proc_ctx->frame_store[FRAME_IN_CURRENT].is_internal_surface = 0;
872 proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface = obj_surf;
874 /* update the previous input surface */
875 if (proc_ctx->frame_order != -1) {
876 if (proc_ctx->filters_mask == VPP_DNDI_DN) {
877 proc_ctx->frame_store[FRAME_IN_PREVIOUS] = proc_ctx->frame_store[FRAME_OUT_CURRENT_DN];
878 } else if (proc_ctx->filters_mask & VPP_DNDI_DI) {
879 VAProcFilterParameterBufferDeinterlacing *di_param =
880 (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
883 (di_param->algorithm == VAProcDeinterlacingMotionAdaptive ||
884 di_param->algorithm == VAProcDeinterlacingMotionCompensated)) {
885 if ((proc_ctx->filters_mask & VPP_DNDI_DN) &&
886 proc_ctx->frame_order == 0) { /* DNDI */
887 tmp_store = proc_ctx->frame_store[FRAME_OUT_CURRENT_DN];
888 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN] = proc_ctx->frame_store[FRAME_IN_PREVIOUS];
889 proc_ctx->frame_store[FRAME_IN_PREVIOUS] = tmp_store;
890 } else { /* DI only */
891 VAProcPipelineParameterBuffer *pipe = proc_ctx->pipeline_param;
892 struct object_surface *obj_surf = NULL;
893 struct i965_driver_data * const i965 = i965_driver_data(ctx);
896 !pipe->num_forward_references ||
897 pipe->forward_references[0] == VA_INVALID_ID) {
898 WARN_ONCE("A forward temporal reference is needed for Motion adaptive/compensated deinterlacing !!!\n");
900 return VA_STATUS_ERROR_INVALID_PARAMETER;
903 obj_surf = SURFACE(pipe->forward_references[0]);
904 assert(obj_surf && obj_surf->bo);
906 proc_ctx->frame_store[FRAME_IN_PREVIOUS].surface_id = pipe->forward_references[0];
907 proc_ctx->frame_store[FRAME_IN_PREVIOUS].is_internal_surface = 0;
908 proc_ctx->frame_store[FRAME_IN_PREVIOUS].obj_surface = obj_surf;
914 /* update STMM surface */
915 if (proc_ctx->frame_order != -1) {
916 tmp_store = proc_ctx->frame_store[FRAME_IN_STMM];
917 proc_ctx->frame_store[FRAME_IN_STMM] = proc_ctx->frame_store[FRAME_OUT_STMM];
918 proc_ctx->frame_store[FRAME_OUT_STMM] = tmp_store;
921 /* update the output surface */
922 if (proc_ctx->surface_output_vebox_object != NULL) {
923 obj_surf = proc_ctx->surface_output_vebox_object;
925 obj_surf = proc_ctx->surface_output_object;
928 if (proc_ctx->filters_mask == VPP_DNDI_DN) {
929 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].surface_id = VA_INVALID_ID;
930 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].is_internal_surface = 0;
931 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface = obj_surf;
932 proc_ctx->current_output = FRAME_OUT_CURRENT_DN;
933 } else if (proc_ctx->filters_mask & VPP_DNDI_DI) {
934 VAProcFilterParameterBufferDeinterlacing *di_param =
935 (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
938 (di_param->algorithm == VAProcDeinterlacingMotionAdaptive ||
939 di_param->algorithm == VAProcDeinterlacingMotionCompensated)) {
940 if (proc_ctx->frame_order == -1) {
941 proc_ctx->frame_store[FRAME_OUT_CURRENT].surface_id = VA_INVALID_ID;
942 proc_ctx->frame_store[FRAME_OUT_CURRENT].is_internal_surface = 0;
943 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface = obj_surf;
944 proc_ctx->current_output = FRAME_OUT_CURRENT;
945 } else if (proc_ctx->frame_order == 0) {
946 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].surface_id = VA_INVALID_ID;
947 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].is_internal_surface = 0;
948 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].obj_surface = obj_surf;
949 proc_ctx->current_output = FRAME_OUT_PREVIOUS;
951 proc_ctx->current_output = FRAME_OUT_CURRENT;
952 proc_ctx->format_convert_flags |= POST_COPY_CONVERT;
955 proc_ctx->frame_store[FRAME_OUT_CURRENT].surface_id = VA_INVALID_ID;
956 proc_ctx->frame_store[FRAME_OUT_CURRENT].is_internal_surface = 0;
957 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface = obj_surf;
958 proc_ctx->current_output = FRAME_OUT_CURRENT;
961 proc_ctx->frame_store[FRAME_OUT_CURRENT].surface_id = VA_INVALID_ID;
962 proc_ctx->frame_store[FRAME_OUT_CURRENT].is_internal_surface = 0;
963 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface = obj_surf;
964 proc_ctx->current_output = FRAME_OUT_CURRENT;
967 return VA_STATUS_SUCCESS;
970 void hsw_veb_surface_unreference(VADriverContextP ctx,
971 struct intel_vebox_context *proc_ctx)
973 /* unreference the input surface */
974 proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id = VA_INVALID_ID;
975 proc_ctx->frame_store[FRAME_IN_CURRENT].is_internal_surface = 0;
976 proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface = NULL;
978 /* unreference the shared output surface */
979 if (proc_ctx->filters_mask == VPP_DNDI_DN) {
980 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].surface_id = VA_INVALID_ID;
981 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].is_internal_surface = 0;
982 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface = NULL;
984 proc_ctx->frame_store[FRAME_OUT_CURRENT].surface_id = VA_INVALID_ID;
985 proc_ctx->frame_store[FRAME_OUT_CURRENT].is_internal_surface = 0;
986 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface = NULL;
990 int hsw_veb_pre_format_convert(VADriverContextP ctx,
991 struct intel_vebox_context *proc_ctx)
994 struct i965_driver_data *i965 = i965_driver_data(ctx);
995 struct object_surface* obj_surf_input = proc_ctx->surface_input_object;
996 struct object_surface* obj_surf_output = proc_ctx->surface_output_object;
997 struct object_surface* obj_surf_input_vebox;
998 struct object_surface* obj_surf_output_vebox;
1000 proc_ctx->format_convert_flags = 0;
1002 proc_ctx->width_input = obj_surf_input->orig_width;
1003 proc_ctx->height_input = obj_surf_input->orig_height;
1004 proc_ctx->width_output = obj_surf_output->orig_width;
1005 proc_ctx->height_output = obj_surf_output->orig_height;
1007 /* only partial frame is not supported to be processed */
1009 assert(proc_ctx->width_input == proc_ctx->pipeline_param->surface_region->width);
1010 assert(proc_ctx->height_input == proc_ctx->pipeline_param->surface_region->height);
1011 assert(proc_ctx->width_output == proc_ctx->pipeline_param->output_region->width);
1012 assert(proc_ctx->height_output == proc_ctx->pipeline_param->output_region->height);
1015 if(proc_ctx->width_output != proc_ctx->width_input ||
1016 proc_ctx->height_output != proc_ctx->height_input){
1017 proc_ctx->format_convert_flags |= POST_SCALING_CONVERT;
1020 /* convert the following format to NV12 format */
1021 if(obj_surf_input->fourcc == VA_FOURCC('Y','V','1','2') ||
1022 obj_surf_input->fourcc == VA_FOURCC('I','4','2','0') ||
1023 obj_surf_input->fourcc == VA_FOURCC('I','M','C','1') ||
1024 obj_surf_input->fourcc == VA_FOURCC('I','M','C','3') ||
1025 obj_surf_input->fourcc == VA_FOURCC('R','G','B','A')){
1027 proc_ctx->format_convert_flags |= PRE_FORMAT_CONVERT;
1029 } else if(obj_surf_input->fourcc == VA_FOURCC('A','Y','U','V') ||
1030 obj_surf_input->fourcc == VA_FOURCC('Y','U','Y','2') ||
1031 obj_surf_input->fourcc == VA_FOURCC('N','V','1','2')){
1032 // nothing to do here
1034 /* not support other format as input */
1038 if (proc_ctx->format_convert_flags & PRE_FORMAT_CONVERT) {
1039 if(proc_ctx->surface_input_vebox_object == NULL){
1040 va_status = i965_CreateSurfaces(ctx,
1041 proc_ctx->width_input,
1042 proc_ctx->height_input,
1043 VA_RT_FORMAT_YUV420,
1045 &(proc_ctx->surface_input_vebox));
1046 assert(va_status == VA_STATUS_SUCCESS);
1047 obj_surf_input_vebox = SURFACE(proc_ctx->surface_input_vebox);
1048 assert(obj_surf_input_vebox);
1050 if (obj_surf_input_vebox) {
1051 proc_ctx->surface_input_vebox_object = obj_surf_input_vebox;
1052 i965_check_alloc_surface_bo(ctx, obj_surf_input_vebox, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
1056 vpp_surface_convert(ctx, proc_ctx->surface_input_vebox_object, proc_ctx->surface_input_object);
1059 /* create one temporary NV12 surfaces for conversion*/
1060 if(obj_surf_output->fourcc == VA_FOURCC('Y','V','1','2') ||
1061 obj_surf_output->fourcc == VA_FOURCC('I','4','2','0') ||
1062 obj_surf_output->fourcc == VA_FOURCC('I','M','C','1') ||
1063 obj_surf_output->fourcc == VA_FOURCC('I','M','C','3') ||
1064 obj_surf_output->fourcc == VA_FOURCC('R','G','B','A')) {
1066 proc_ctx->format_convert_flags |= POST_FORMAT_CONVERT;
1067 } else if(obj_surf_output->fourcc == VA_FOURCC('A','Y','U','V') ||
1068 obj_surf_output->fourcc == VA_FOURCC('Y','U','Y','2') ||
1069 obj_surf_output->fourcc == VA_FOURCC('N','V','1','2')){
1070 /* Nothing to do here */
1072 /* not support other format as input */
1076 if(proc_ctx->format_convert_flags & POST_FORMAT_CONVERT ||
1077 proc_ctx->format_convert_flags & POST_SCALING_CONVERT){
1078 if(proc_ctx->surface_output_vebox_object == NULL){
1079 va_status = i965_CreateSurfaces(ctx,
1080 proc_ctx->width_input,
1081 proc_ctx->height_input,
1082 VA_RT_FORMAT_YUV420,
1084 &(proc_ctx->surface_output_vebox));
1085 assert(va_status == VA_STATUS_SUCCESS);
1086 obj_surf_output_vebox = SURFACE(proc_ctx->surface_output_vebox);
1087 assert(obj_surf_output_vebox);
1089 if (obj_surf_output_vebox) {
1090 proc_ctx->surface_output_vebox_object = obj_surf_output_vebox;
1091 i965_check_alloc_surface_bo(ctx, obj_surf_output_vebox, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
1096 if(proc_ctx->format_convert_flags & POST_SCALING_CONVERT){
1097 if(proc_ctx->surface_output_scaled_object == NULL){
1098 va_status = i965_CreateSurfaces(ctx,
1099 proc_ctx->width_output,
1100 proc_ctx->height_output,
1101 VA_RT_FORMAT_YUV420,
1103 &(proc_ctx->surface_output_scaled));
1104 assert(va_status == VA_STATUS_SUCCESS);
1105 obj_surf_output_vebox = SURFACE(proc_ctx->surface_output_scaled);
1106 assert(obj_surf_output_vebox);
1108 if (obj_surf_output_vebox) {
1109 proc_ctx->surface_output_scaled_object = obj_surf_output_vebox;
1110 i965_check_alloc_surface_bo(ctx, obj_surf_output_vebox, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
1118 int hsw_veb_post_format_convert(VADriverContextP ctx,
1119 struct intel_vebox_context *proc_ctx)
1121 struct object_surface *obj_surface = NULL;
1123 obj_surface = proc_ctx->frame_store[proc_ctx->current_output].obj_surface;
1125 if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) {
1126 /* copy the saved frame in the second call */
1127 vpp_surface_convert(ctx,proc_ctx->surface_output_object, obj_surface);
1128 } else if(!(proc_ctx->format_convert_flags & POST_FORMAT_CONVERT) &&
1129 !(proc_ctx->format_convert_flags & POST_SCALING_CONVERT)){
1130 /* Output surface format is covered by vebox pipeline and
1131 * processed picture is already store in output surface
1132 * so nothing will be done here */
1133 } else if ((proc_ctx->format_convert_flags & POST_FORMAT_CONVERT) &&
1134 !(proc_ctx->format_convert_flags & POST_SCALING_CONVERT)){
1135 /* convert and copy NV12 to YV12/IMC3/IMC2/RGBA output*/
1136 vpp_surface_convert(ctx,proc_ctx->surface_output_object, obj_surface);
1138 } else if(proc_ctx->format_convert_flags & POST_SCALING_CONVERT) {
1139 /* scaling, convert and copy NV12 to YV12/IMC3/IMC2/RGBA output*/
1140 assert(obj_surface->fourcc == VA_FOURCC('N','V','1','2'));
1142 /* first step :surface scaling */
1143 vpp_surface_scaling(ctx,proc_ctx->surface_output_scaled_object, obj_surface);
1145 /* second step: color format convert and copy to output */
1146 obj_surface = proc_ctx->surface_output_object;
1148 if(obj_surface->fourcc == VA_FOURCC('N','V','1','2') ||
1149 obj_surface->fourcc == VA_FOURCC('Y','V','1','2') ||
1150 obj_surface->fourcc == VA_FOURCC('I','4','2','0') ||
1151 obj_surface->fourcc == VA_FOURCC('Y','U','Y','2') ||
1152 obj_surface->fourcc == VA_FOURCC('I','M','C','1') ||
1153 obj_surface->fourcc == VA_FOURCC('I','M','C','3') ||
1154 obj_surface->fourcc == VA_FOURCC('R','G','B','A')) {
1155 vpp_surface_convert(ctx, proc_ctx->surface_output_object, proc_ctx->surface_output_scaled_object);
1164 VAStatus gen75_vebox_process_picture(VADriverContextP ctx,
1165 struct intel_vebox_context *proc_ctx)
1167 struct i965_driver_data *i965 = i965_driver_data(ctx);
1169 VAProcPipelineParameterBuffer *pipe = proc_ctx->pipeline_param;
1170 VAProcFilterParameterBuffer* filter = NULL;
1171 struct object_buffer *obj_buf = NULL;
1174 for (i = 0; i < pipe->num_filters; i ++) {
1175 obj_buf = BUFFER(pipe->filters[i]);
1177 assert(obj_buf && obj_buf->buffer_store);
1179 if (!obj_buf || !obj_buf->buffer_store)
1182 filter = (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
1184 if (filter->type == VAProcFilterNoiseReduction) {
1185 proc_ctx->filters_mask |= VPP_DNDI_DN;
1186 proc_ctx->filter_dn = filter;
1187 } else if (filter->type == VAProcFilterDeinterlacing) {
1188 proc_ctx->filters_mask |= VPP_DNDI_DI;
1189 proc_ctx->filter_di = filter;
1190 } else if (filter->type == VAProcFilterColorBalance) {
1191 proc_ctx->filters_mask |= VPP_IECP_PRO_AMP;
1192 proc_ctx->filter_iecp_amp = filter;
1193 proc_ctx->filter_iecp_amp_num_elements = obj_buf->num_elements;
1197 hsw_veb_pre_format_convert(ctx, proc_ctx);
1198 hsw_veb_surface_reference(ctx, proc_ctx);
1200 if (proc_ctx->frame_order == -1) {
1201 hsw_veb_resource_prepare(ctx, proc_ctx);
1204 if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) {
1205 assert(proc_ctx->frame_order == 1);
1206 /* directly copy the saved frame in the second call */
1208 intel_batchbuffer_start_atomic_veb(proc_ctx->batch, 0x1000);
1209 intel_batchbuffer_emit_mi_flush(proc_ctx->batch);
1210 hsw_veb_surface_state(ctx, proc_ctx, INPUT_SURFACE);
1211 hsw_veb_surface_state(ctx, proc_ctx, OUTPUT_SURFACE);
1212 hsw_veb_state_table_setup(ctx, proc_ctx);
1214 hsw_veb_state_command(ctx, proc_ctx);
1215 hsw_veb_dndi_iecp_command(ctx, proc_ctx);
1216 intel_batchbuffer_end_atomic(proc_ctx->batch);
1217 intel_batchbuffer_flush(proc_ctx->batch);
1220 hsw_veb_post_format_convert(ctx, proc_ctx);
1221 // hsw_veb_surface_unreference(ctx, proc_ctx);
1223 proc_ctx->frame_order = (proc_ctx->frame_order + 1) % 2;
1225 return VA_STATUS_SUCCESS;
1228 return VA_STATUS_ERROR_INVALID_PARAMETER;
1231 void gen75_vebox_context_destroy(VADriverContextP ctx,
1232 struct intel_vebox_context *proc_ctx)
1236 if(proc_ctx->surface_input_vebox != VA_INVALID_ID){
1237 i965_DestroySurfaces(ctx, &proc_ctx->surface_input_vebox, 1);
1238 proc_ctx->surface_input_vebox = VA_INVALID_ID;
1239 proc_ctx->surface_input_vebox_object = NULL;
1242 if(proc_ctx->surface_output_vebox != VA_INVALID_ID){
1243 i965_DestroySurfaces(ctx, &proc_ctx->surface_output_vebox, 1);
1244 proc_ctx->surface_output_vebox = VA_INVALID_ID;
1245 proc_ctx->surface_output_vebox_object = NULL;
1248 if(proc_ctx->surface_output_scaled != VA_INVALID_ID){
1249 i965_DestroySurfaces(ctx, &proc_ctx->surface_output_scaled, 1);
1250 proc_ctx->surface_output_scaled = VA_INVALID_ID;
1251 proc_ctx->surface_output_scaled_object = NULL;
1254 for(i = 0; i < FRAME_STORE_SUM; i ++) {
1255 if (proc_ctx->frame_store[i].is_internal_surface == 1) {
1256 assert(proc_ctx->frame_store[i].surface_id != VA_INVALID_ID);
1258 if (proc_ctx->frame_store[i].surface_id != VA_INVALID_ID)
1259 i965_DestroySurfaces(ctx, &proc_ctx->frame_store[i].surface_id, 1);
1262 proc_ctx->frame_store[i].surface_id = VA_INVALID_ID;
1263 proc_ctx->frame_store[i].is_internal_surface = 0;
1264 proc_ctx->frame_store[i].obj_surface = NULL;
1267 /* dndi state table */
1268 dri_bo_unreference(proc_ctx->dndi_state_table.bo);
1269 proc_ctx->dndi_state_table.bo = NULL;
1271 /* iecp state table */
1272 dri_bo_unreference(proc_ctx->iecp_state_table.bo);
1273 proc_ctx->dndi_state_table.bo = NULL;
1275 /* gamut statu table */
1276 dri_bo_unreference(proc_ctx->gamut_state_table.bo);
1277 proc_ctx->gamut_state_table.bo = NULL;
1279 /* vertex state table */
1280 dri_bo_unreference(proc_ctx->vertex_state_table.bo);
1281 proc_ctx->vertex_state_table.bo = NULL;
1283 intel_batchbuffer_free(proc_ctx->batch);
1288 struct intel_vebox_context * gen75_vebox_context_init(VADriverContextP ctx)
1290 struct intel_driver_data *intel = intel_driver_data(ctx);
1291 struct intel_vebox_context *proc_context = calloc(1, sizeof(struct intel_vebox_context));
1294 proc_context->batch = intel_batchbuffer_new(intel, I915_EXEC_VEBOX, 0);
1295 memset(proc_context->frame_store, 0, sizeof(VEBFrameStore)*FRAME_STORE_SUM);
1297 for (i = 0; i < FRAME_STORE_SUM; i ++) {
1298 proc_context->frame_store[i].surface_id = VA_INVALID_ID;
1299 proc_context->frame_store[i].is_internal_surface = 0;
1300 proc_context->frame_store[i].obj_surface = NULL;
1303 proc_context->filters_mask = 0;
1304 proc_context->frame_order = -1; /* the first frame */
1305 proc_context->surface_output_object = NULL;
1306 proc_context->surface_input_object = NULL;
1307 proc_context->surface_input_vebox = VA_INVALID_ID;
1308 proc_context->surface_input_vebox_object = NULL;
1309 proc_context->surface_output_vebox = VA_INVALID_ID;
1310 proc_context->surface_output_vebox_object = NULL;
1311 proc_context->surface_output_scaled = VA_INVALID_ID;
1312 proc_context->surface_output_scaled_object = NULL;
1313 proc_context->filters_mask = 0;
1314 proc_context->format_convert_flags = 0;
1316 return proc_context;
1319 void bdw_veb_state_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
1321 struct intel_batchbuffer *batch = proc_ctx->batch;
1322 unsigned int is_dn_enabled = (proc_ctx->filters_mask & 0x01)? 1: 0;
1323 unsigned int is_di_enabled = (proc_ctx->filters_mask & 0x02)? 1: 0;
1324 unsigned int is_iecp_enabled = (proc_ctx->filters_mask & 0xff00)?1:0;
1325 unsigned int is_first_frame = !!((proc_ctx->frame_order == -1) &&
1328 unsigned int di_output_frames_flag = 2; /* Output Current Frame Only */
1330 if(proc_ctx->fourcc_input != proc_ctx->fourcc_output ||
1331 (is_dn_enabled == 0 && is_di_enabled == 0)){
1332 is_iecp_enabled = 1;
1335 if (is_di_enabled) {
1336 VAProcFilterParameterBufferDeinterlacing *di_param =
1337 (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
1341 if (di_param->algorithm == VAProcDeinterlacingBob)
1344 if ((di_param->algorithm == VAProcDeinterlacingMotionAdaptive ||
1345 di_param->algorithm == VAProcDeinterlacingMotionCompensated) &&
1346 proc_ctx->frame_order != -1)
1347 di_output_frames_flag = 0; /* Output both Current Frame and Previous Frame */
1350 BEGIN_VEB_BATCH(batch, 0xc);
1351 OUT_VEB_BATCH(batch, VEB_STATE | (0xc - 2));
1352 OUT_VEB_BATCH(batch,
1353 0 << 25 | // state surface control bits
1354 0 << 23 | // reserved.
1355 0 << 22 | // gamut expansion position
1356 0 << 15 | // reserved.
1357 0 << 14 | // single slice vebox enable
1358 0 << 13 | // hot pixel filter enable
1359 0 << 12 | // alpha plane enable
1360 0 << 11 | // vignette enable
1361 0 << 10 | // demosaic enable
1362 di_output_frames_flag << 8 | // DI output frame
1363 1 << 7 | // 444->422 downsample method
1364 1 << 6 | // 422->420 downsample method
1365 is_first_frame << 5 | // DN/DI first frame
1366 is_di_enabled << 4 | // DI enable
1367 is_dn_enabled << 3 | // DN enable
1368 is_iecp_enabled << 2 | // global IECP enabled
1369 0 << 1 | // ColorGamutCompressionEnable
1370 0 ) ; // ColorGamutExpansionEnable.
1373 proc_ctx->dndi_state_table.bo,
1374 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
1376 OUT_VEB_BATCH(batch, 0);
1379 proc_ctx->iecp_state_table.bo,
1380 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
1382 OUT_VEB_BATCH(batch, 0);
1385 proc_ctx->gamut_state_table.bo,
1386 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
1388 OUT_VEB_BATCH(batch, 0);
1391 proc_ctx->vertex_state_table.bo,
1392 I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
1394 OUT_VEB_BATCH(batch, 0);
1396 OUT_VEB_BATCH(batch, 0);/*caputre pipe state pointer*/
1397 OUT_VEB_BATCH(batch, 0);
1399 ADVANCE_VEB_BATCH(batch);
1402 void bdw_veb_dndi_iecp_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
1404 struct intel_batchbuffer *batch = proc_ctx->batch;
1405 unsigned char frame_ctrl_bits = 0;
1406 unsigned int startingX = 0;
1407 unsigned int endingX = (proc_ctx->width_input + 63 ) / 64 * 64;
1409 BEGIN_VEB_BATCH(batch, 0x14);
1410 OUT_VEB_BATCH(batch, VEB_DNDI_IECP_STATE | (0x14 - 2));//DWord 0
1411 OUT_VEB_BATCH(batch,
1413 endingX -1);//DWord 1
1416 proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface->bo,
1417 I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);//DWord 2
1418 OUT_VEB_BATCH(batch,0);//DWord 3
1421 proc_ctx->frame_store[FRAME_IN_PREVIOUS].obj_surface->bo,
1422 I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);//DWord 4
1423 OUT_VEB_BATCH(batch,0);//DWord 5
1426 proc_ctx->frame_store[FRAME_IN_STMM].obj_surface->bo,
1427 I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);//DWord 6
1428 OUT_VEB_BATCH(batch,0);//DWord 7
1431 proc_ctx->frame_store[FRAME_OUT_STMM].obj_surface->bo,
1432 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 8
1433 OUT_VEB_BATCH(batch,0);//DWord 9
1436 proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface->bo,
1437 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 10
1438 OUT_VEB_BATCH(batch,0);//DWord 11
1441 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface->bo,
1442 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 12
1443 OUT_VEB_BATCH(batch,0);//DWord 13
1446 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].obj_surface->bo,
1447 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 14
1448 OUT_VEB_BATCH(batch,0);//DWord 15
1451 proc_ctx->frame_store[FRAME_OUT_STATISTIC].obj_surface->bo,
1452 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 16
1453 OUT_VEB_BATCH(batch,0);//DWord 17
1455 OUT_VEB_BATCH(batch,0);//DWord 18
1456 OUT_VEB_BATCH(batch,0);//DWord 19
1458 ADVANCE_VEB_BATCH(batch);
1461 VAStatus gen8_vebox_process_picture(VADriverContextP ctx,
1462 struct intel_vebox_context *proc_ctx)
1464 struct i965_driver_data *i965 = i965_driver_data(ctx);
1466 VAProcPipelineParameterBuffer *pipe = proc_ctx->pipeline_param;
1467 VAProcFilterParameterBuffer* filter = NULL;
1468 struct object_buffer *obj_buf = NULL;
1471 for (i = 0; i < pipe->num_filters; i ++) {
1472 obj_buf = BUFFER(pipe->filters[i]);
1474 assert(obj_buf && obj_buf->buffer_store);
1476 if (!obj_buf || !obj_buf->buffer_store)
1479 filter = (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
1481 if (filter->type == VAProcFilterNoiseReduction) {
1482 proc_ctx->filters_mask |= VPP_DNDI_DN;
1483 proc_ctx->filter_dn = filter;
1484 } else if (filter->type == VAProcFilterDeinterlacing) {
1485 proc_ctx->filters_mask |= VPP_DNDI_DI;
1486 proc_ctx->filter_di = filter;
1487 } else if (filter->type == VAProcFilterColorBalance) {
1488 proc_ctx->filters_mask |= VPP_IECP_PRO_AMP;
1489 proc_ctx->filter_iecp_amp = filter;
1490 proc_ctx->filter_iecp_amp_num_elements = obj_buf->num_elements;
1494 hsw_veb_pre_format_convert(ctx, proc_ctx);
1495 hsw_veb_surface_reference(ctx, proc_ctx);
1497 if (proc_ctx->frame_order == -1) {
1498 hsw_veb_resource_prepare(ctx, proc_ctx);
1501 if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) {
1502 assert(proc_ctx->frame_order == 1);
1503 /* directly copy the saved frame in the second call */
1505 intel_batchbuffer_start_atomic_veb(proc_ctx->batch, 0x1000);
1506 intel_batchbuffer_emit_mi_flush(proc_ctx->batch);
1507 hsw_veb_surface_state(ctx, proc_ctx, INPUT_SURFACE);
1508 hsw_veb_surface_state(ctx, proc_ctx, OUTPUT_SURFACE);
1509 hsw_veb_state_table_setup(ctx, proc_ctx);
1511 bdw_veb_state_command(ctx, proc_ctx);
1512 bdw_veb_dndi_iecp_command(ctx, proc_ctx);
1513 intel_batchbuffer_end_atomic(proc_ctx->batch);
1514 intel_batchbuffer_flush(proc_ctx->batch);
1517 hsw_veb_post_format_convert(ctx, proc_ctx);
1518 // hsw_veb_surface_unreference(ctx, proc_ctx);
1520 proc_ctx->frame_order = (proc_ctx->frame_order + 1) % 2;
1522 return VA_STATUS_SUCCESS;
1525 return VA_STATUS_ERROR_INVALID_PARAMETER;