BDW doesn't support H.264 Baseline profile
[platform/upstream/libva-intel-driver.git] / src / gen75_vpp_vebox.c
1 /*
2  * Copyright © 2011 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *   Li Xiaowei <xiaowei.a.li@intel.com>
26  *   Li Zhong <zhong.li@intel.com>
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
33 #include <math.h>
34
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"
41
42 #define PI  3.1415926
43
44 extern VAStatus
45 i965_MapBuffer(VADriverContextP ctx, VABufferID buf_id, void **);
46
47 extern VAStatus
48 i965_UnmapBuffer(VADriverContextP ctx, VABufferID buf_id);
49
50 extern VAStatus
51 i965_DeriveImage(VADriverContextP ctx, VABufferID surface, VAImage *out_image);
52
53 extern VAStatus
54 i965_DestroyImage(VADriverContextP ctx, VAImageID image);
55
56 extern VAStatus
57 i965_DestroySurfaces(VADriverContextP ctx,
58                      VASurfaceID *surface_list,
59                      int num_surfaces);
60
61 extern VAStatus
62 i965_CreateSurfaces(VADriverContextP ctx,
63                     int width,
64                     int height,
65                     int format,
66                     int num_surfaces,
67                     VASurfaceID *surfaces);
68
69 VAStatus vpp_surface_convert(VADriverContextP ctx,
70                              struct object_surface *src_obj_surf,
71                              struct object_surface *dst_obj_surf)
72 {
73     VAStatus va_status = VA_STATUS_SUCCESS;
74
75     assert(src_obj_surf->orig_width  == dst_obj_surf->orig_width);
76     assert(src_obj_surf->orig_height == dst_obj_surf->orig_height);
77
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;
83
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;
88
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;
92
93     va_status = i965_image_processing(ctx,
94                                      &src_surface,
95                                      &src_rect,
96                                      &dst_surface,
97                                      &dst_rect);
98     return va_status;
99 }
100
101 VAStatus vpp_surface_scaling(VADriverContextP ctx,
102                              struct object_surface *dst_obj_surf,
103                              struct object_surface *src_obj_surf)
104 {
105     VAStatus va_status = VA_STATUS_SUCCESS;
106     int flags = I965_PP_FLAG_AVS;
107
108     assert(src_obj_surf->fourcc == VA_FOURCC('N','V','1','2'));
109     assert(dst_obj_surf->fourcc == VA_FOURCC('N','V','1','2'));
110
111     VARectangle src_rect, dst_rect;
112     src_rect.x = 0;
113     src_rect.y = 0; 
114     src_rect.width  = src_obj_surf->orig_width; 
115     src_rect.height = src_obj_surf->orig_height;
116
117     dst_rect.x = 0;
118     dst_rect.y = 0; 
119     dst_rect.width  = dst_obj_surf->orig_width; 
120     dst_rect.height = dst_obj_surf->orig_height;
121
122     va_status = i965_scaling_processing(ctx,
123                                        src_obj_surf,
124                                        &src_rect,
125                                        dst_obj_surf,
126                                        &dst_rect,
127                                        flags);
128      
129     return va_status;
130 }
131
132 void hsw_veb_dndi_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
133 {
134     unsigned int* p_table ;
135     int progressive_dn = 1;
136     int dndi_top_first = 0;
137     int motion_compensated_enable = 0;
138
139     if (proc_ctx->filters_mask & VPP_DNDI_DI) {
140         VAProcFilterParameterBufferDeinterlacing *di_param =
141             (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
142         assert(di_param);
143
144         progressive_dn = 0;
145         dndi_top_first = !(di_param->flags & VA_DEINTERLACING_BOTTOM_FIELD);
146         motion_compensated_enable = (di_param->algorithm == VAProcDeinterlacingMotionCompensated);
147     }
148
149     /*
150     VAProcFilterParameterBufferDeinterlacing *di_param =
151             (VAProcFilterParameterBufferDeinterlacing *) proc_ctx->filter_di;
152
153     VAProcFilterParameterBuffer * dn_param =
154             (VAProcFilterParameterBuffer *) proc_ctx->filter_dn;
155     */
156     p_table = (unsigned int *)proc_ctx->dndi_state_table.ptr;
157
158     *p_table ++ = 0;               // reserved  . w0
159     *p_table ++ = ( 140 << 24 |    // denoise STAD threshold . w1
160                     192 << 16 |    // dnmh_history_max
161                     0   << 12 |    // reserved
162                     7   << 8  |    // dnmh_delta[3:0]
163                     38 );          // denoise ASD threshold
164
165     *p_table ++ = ( 0  << 30 |    // reserved . w2
166                     0  << 24 |    // temporal diff th
167                     0  << 22 |    // reserved.
168                     0  << 16 |    // low temporal diff th
169                     2  << 13 |    // STMM C2
170                     1  << 8  |    // denoise moving pixel th
171                     38 );         // denoise th for sum of complexity measure
172
173     *p_table ++ = ( 0 << 30  |   // reserved . w3
174                     12<< 24  |   // good neighbor th[5:0]
175                     9 << 20  |   // CAT slope minus 1
176                     5 << 16  |   // SAD Tight in
177                     0 << 14  |   // smooth mv th
178                     0 << 12  |   // reserved
179                     1 << 8   |   // bne_edge_th[3:0]
180                     20 );        // block noise estimate noise th
181
182     *p_table ++ = ( 0  << 31  |  // STMM blending constant select. w4
183                     64 << 24  |  // STMM trc1
184                     125<< 16  |  // STMM trc2
185                     0  << 14  |  // reserved
186                     30 << 8   |  // VECM_mul
187                     150 );       // maximum STMM
188
189     *p_table ++ = ( 118<< 24  |  // minumum STMM  . W5
190                     0  << 22  |  // STMM shift down
191                     1  << 20  |  // STMM shift up
192                     5  << 16  |  // STMM output shift
193                     100 << 8  |  // SDI threshold
194                     5 );         // SDI delta
195
196     *p_table ++ = ( 50  << 24 |  // SDI fallback mode 1 T1 constant . W6
197                     100 << 16 |  // SDI fallback mode 1 T2 constant
198                     37  << 8  |  // SDI fallback mode 2 constant(angle2x1)
199                     175 );       // FMD temporal difference threshold
200
201     *p_table ++ = ( 16 << 24  |  // FMD #1 vertical difference th . w7
202                     100<< 16  |  // FMD #2 vertical difference th
203                     0  << 14  |  // CAT th1
204                     2  << 8   |  // FMD tear threshold
205                     motion_compensated_enable  << 7   |  // MCDI Enable, use motion compensated deinterlace algorithm
206                     progressive_dn  << 6   |  // progressive DN
207                     0  << 4   |  // reserved
208                     dndi_top_first  << 3   |  // DN/DI Top First
209                     0 );         // reserved
210
211     *p_table ++ = ( 0  << 29  |  // reserved . W8
212                     32 << 23  |  // dnmh_history_init[5:0]
213                     10 << 19  |  // neighborPixel th
214                     0  << 18  |  // reserved
215                     0  << 16  |  // FMD for 2nd field of previous frame
216                     25 << 10  |  // MC pixel consistency th
217                     0  << 8   |  // FMD for 1st field for current frame
218                     10 << 4   |  // SAD THB
219                     5 );         // SAD THA
220
221     *p_table ++ = ( 0  << 24  |  // reserved
222                     140<< 16  |  // chr_dnmh_stad_th
223                     0  << 13  |  // reserved
224                     1  << 12  |  // chrome denoise enable
225                     13 << 6   |  // chr temp diff th
226                     7 );         // chr temp diff low
227
228 }
229
230 void hsw_veb_iecp_std_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
231 {
232     unsigned int *p_table = proc_ctx->iecp_state_table.ptr + 0 ;
233     //VAProcFilterParameterBuffer * std_param =
234     //        (VAProcFilterParameterBuffer *) proc_ctx->filter_std;
235
236     if(!(proc_ctx->filters_mask & VPP_IECP_STD_STE)){ 
237         memset(p_table, 0, 29 * 4);
238     }else{
239         *p_table ++ = 0x9a6e39f0;
240         *p_table ++ = 0x400c0000;
241         *p_table ++ = 0x00001180;
242         *p_table ++ = 0xfe2f2e00;
243         *p_table ++ = 0x000000ff;
244
245         *p_table ++ = 0x00140000;
246         *p_table ++ = 0xd82e0000;
247         *p_table ++ = 0x8285ecec;
248         *p_table ++ = 0x00008282;
249         *p_table ++ = 0x00000000;
250
251         *p_table ++ = 0x02117000;
252         *p_table ++ = 0xa38fec96;
253         *p_table ++ = 0x0000c8c8;
254         *p_table ++ = 0x00000000;
255         *p_table ++ = 0x01478000;
256  
257         *p_table ++ = 0x0007c306;
258         *p_table ++ = 0x00000000;
259         *p_table ++ = 0x00000000;
260         *p_table ++ = 0x1c1bd000;
261         *p_table ++ = 0x00000000;
262
263         *p_table ++ = 0x00000000;
264         *p_table ++ = 0x00000000;
265         *p_table ++ = 0x0007cf80;
266         *p_table ++ = 0x00000000;
267         *p_table ++ = 0x00000000;
268
269         *p_table ++ = 0x1c080000;
270         *p_table ++ = 0x00000000;
271         *p_table ++ = 0x00000000;
272         *p_table ++ = 0x00000000;
273     }
274 }
275
276 void hsw_veb_iecp_ace_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
277 {
278    unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 116);
279
280     if(!(proc_ctx->filters_mask & VPP_IECP_ACE)){ 
281         memset(p_table, 0, 13 * 4);
282     }else{
283         *p_table ++ = 0x00000068;
284         *p_table ++ = 0x4c382410;
285         *p_table ++ = 0x9c887460;
286         *p_table ++ = 0xebd8c4b0;
287         *p_table ++ = 0x604c3824;
288
289         *p_table ++ = 0xb09c8874;
290         *p_table ++ = 0x0000d8c4;
291         *p_table ++ = 0x00000000;
292         *p_table ++ = 0x00000000;
293         *p_table ++ = 0x00000000;
294
295         *p_table ++ = 0x00000000;
296         *p_table ++ = 0x00000000;
297         *p_table ++ = 0x00000000;
298    }
299 }
300
301 void hsw_veb_iecp_tcc_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
302 {
303     unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 168);
304 //    VAProcFilterParameterBuffer * tcc_param =
305 //            (VAProcFilterParameterBuffer *) proc_ctx->filter_iecp_tcc;
306
307    if(!(proc_ctx->filters_mask & VPP_IECP_TCC)){ 
308         memset(p_table, 0, 11 * 4);
309     }else{
310         *p_table ++ = 0x00000000;
311         *p_table ++ = 0x00000000;
312         *p_table ++ = 0x1e34cc91;
313         *p_table ++ = 0x3e3cce91;
314         *p_table ++ = 0x02e80195;
315
316         *p_table ++ = 0x0197046b;
317         *p_table ++ = 0x01790174;
318         *p_table ++ = 0x00000000;
319         *p_table ++ = 0x00000000;
320         *p_table ++ = 0x03030000;
321
322         *p_table ++ = 0x009201c0;
323    }
324 }
325
326 void hsw_veb_iecp_pro_amp_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
327 {
328     unsigned int contrast = 0x80;  //default 
329     int brightness = 0x00;         //default
330     int cos_c_s    = 256 ;         //default
331     int sin_c_s    = 0;            //default 
332     unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 212);
333
334     if(!(proc_ctx->filters_mask & VPP_IECP_PRO_AMP)){
335         memset(p_table, 0, 2 * 4);
336     }else {
337         float  src_saturation = 1.0;
338         float  src_hue = 0.0;
339         float  src_contrast = 1.0;
340         float  src_brightness = 0.0;
341         float  tmp_value = 0.0;
342         unsigned int i = 0;
343
344         VAProcFilterParameterBufferColorBalance * amp_params =
345             (VAProcFilterParameterBufferColorBalance *) proc_ctx->filter_iecp_amp;
346  
347         for (i = 0; i < proc_ctx->filter_iecp_amp_num_elements; i++){
348             VAProcColorBalanceType attrib = amp_params[i].attrib;
349
350             if(attrib == VAProcColorBalanceHue) {
351                src_hue = amp_params[i].value;         //(-180.0, 180.0)
352             }else if(attrib == VAProcColorBalanceSaturation) {
353                src_saturation = amp_params[i].value; //(0.0, 10.0)
354             }else if(attrib == VAProcColorBalanceBrightness) {
355                src_brightness = amp_params[i].value; // (-100.0, 100.0)
356                brightness = intel_format_convert(src_brightness, 7, 4, 1);
357             }else if(attrib == VAProcColorBalanceContrast) {
358                src_contrast = amp_params[i].value;  //  (0.0, 10.0)
359                contrast = intel_format_convert(src_contrast, 4, 7, 0);
360             }
361         }
362
363         tmp_value = cos(src_hue/180*PI) * src_contrast * src_saturation;
364         cos_c_s = intel_format_convert(tmp_value, 7, 8, 1);
365         
366         tmp_value = sin(src_hue/180*PI) * src_contrast * src_saturation;
367         sin_c_s = intel_format_convert(tmp_value, 7, 8, 1);
368      
369         *p_table ++ = ( 0 << 28 |         //reserved
370                         contrast << 17 |  //contrast value (U4.7 format)
371                         0 << 13 |         //reserved
372                         brightness << 1|  // S7.4 format
373                         1);
374
375         *p_table ++ = ( cos_c_s << 16 |  // cos(h) * contrast * saturation
376                         sin_c_s);        // sin(h) * contrast * saturation
377                  
378     }
379 }
380
381
382 void hsw_veb_iecp_csc_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
383 {
384     unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 220);
385     float tran_coef[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
386     float v_coef[3]    = {0.0, 0.0, 0.0};
387     float u_coef[3]    = {0.0, 0.0, 0.0};
388     int   is_transform_enabled = 0;
389
390     if(!(proc_ctx->filters_mask & VPP_IECP_CSC)){
391         memset(p_table, 0, 8 * 4);
392         return;
393     }
394
395     if(proc_ctx->fourcc_input == VA_FOURCC('R','G','B','A') &&
396        (proc_ctx->fourcc_output == VA_FOURCC('N','V','1','2') ||
397         proc_ctx->fourcc_output == VA_FOURCC('Y','V','1','2') ||
398         proc_ctx->fourcc_output == VA_FOURCC('Y','V','Y','2') ||
399         proc_ctx->fourcc_output == VA_FOURCC('A','Y','U','V'))) {
400
401          tran_coef[0] = 0.257;
402          tran_coef[1] = 0.504;
403          tran_coef[2] = 0.098;
404          tran_coef[3] = -0.148;
405          tran_coef[4] = -0.291;
406          tran_coef[5] = 0.439;
407          tran_coef[6] = 0.439;
408          tran_coef[7] = -0.368;
409          tran_coef[8] = -0.071; 
410
411          u_coef[0] = 16 * 4;
412          u_coef[1] = 128 * 4;
413          u_coef[2] = 128 * 4;
414  
415          is_transform_enabled = 1; 
416     }else if((proc_ctx->fourcc_input  == VA_FOURCC('N','V','1','2') || 
417               proc_ctx->fourcc_input  == VA_FOURCC('Y','V','1','2') || 
418               proc_ctx->fourcc_input  == VA_FOURCC('Y','U','Y','2') ||
419               proc_ctx->fourcc_input  == VA_FOURCC('A','Y','U','V'))&&
420               proc_ctx->fourcc_output == VA_FOURCC('R','G','B','A')) {
421
422          tran_coef[0] = 1.164;
423          tran_coef[1] = 0.000;
424          tran_coef[2] = 1.569;
425          tran_coef[3] = 1.164;
426          tran_coef[4] = -0.813;
427          tran_coef[5] = -0.392;
428          tran_coef[6] = 1.164;
429          tran_coef[7] = 2.017;
430          tran_coef[8] = 0.000; 
431
432          v_coef[0] = -16 * 4;
433          v_coef[1] = -128 * 4;
434          v_coef[2] = -128 * 4;
435
436         is_transform_enabled = 1; 
437     }else if(proc_ctx->fourcc_input != proc_ctx->fourcc_output){
438          //enable when input and output format are different.
439          is_transform_enabled = 1;
440     }
441
442     if(is_transform_enabled == 0){
443         memset(p_table, 0, 8 * 4);
444     }else{
445         *p_table ++ = ( 0 << 29 | //reserved
446                         intel_format_convert(tran_coef[1], 2, 10, 1) << 16 | //c1, s2.10 format
447                         intel_format_convert(tran_coef[0], 2, 10, 1) << 3 |  //c0, s2.10 format
448                         0 << 2 | //reserved
449                         0 << 1 | // yuv_channel swap
450                         is_transform_enabled);                
451
452         *p_table ++ = ( 0 << 26 | //reserved
453                         intel_format_convert(tran_coef[3], 2, 10, 1) << 13 | 
454                         intel_format_convert(tran_coef[2], 2, 10, 1));
455     
456         *p_table ++ = ( 0 << 26 | //reserved
457                         intel_format_convert(tran_coef[5], 2, 10, 1) << 13 | 
458                         intel_format_convert(tran_coef[4], 2, 10, 1));
459
460         *p_table ++ = ( 0 << 26 | //reserved
461                         intel_format_convert(tran_coef[7], 2, 10, 1) << 13 | 
462                         intel_format_convert(tran_coef[6], 2, 10, 1));
463
464         *p_table ++ = ( 0 << 13 | //reserved
465                         intel_format_convert(tran_coef[8], 2, 10, 1));
466
467         *p_table ++ = ( 0 << 22 | //reserved
468                         intel_format_convert(u_coef[0], 10, 0, 1) << 11 | 
469                         intel_format_convert(v_coef[0], 10, 0, 1));
470
471         *p_table ++ = ( 0 << 22 | //reserved
472                         intel_format_convert(u_coef[1], 10, 0, 1) << 11 | 
473                         intel_format_convert(v_coef[1], 10, 0, 1));
474
475         *p_table ++ = ( 0 << 22 | //reserved
476                         intel_format_convert(u_coef[2], 10, 0, 1) << 11 | 
477                         intel_format_convert(v_coef[2], 10, 0, 1));
478     }
479 }
480
481 void hsw_veb_iecp_aoi_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
482 {
483     unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 252);
484    // VAProcFilterParameterBuffer * tcc_param =
485    //         (VAProcFilterParameterBuffer *) proc_ctx->filter_iecp_tcc;
486
487     if(!(proc_ctx->filters_mask & VPP_IECP_AOI)){ 
488         memset(p_table, 0, 3 * 4);
489     }else{
490         *p_table ++ = 0x00000000;
491         *p_table ++ = 0x00030000;
492         *p_table ++ = 0x00030000;
493    }
494 }
495
496 void hsw_veb_state_table_setup(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
497 {
498     if(proc_ctx->filters_mask & 0x000000ff) {
499         dri_bo *dndi_bo = proc_ctx->dndi_state_table.bo;
500         dri_bo_map(dndi_bo, 1);
501         proc_ctx->dndi_state_table.ptr = dndi_bo->virtual;
502
503         hsw_veb_dndi_table(ctx, proc_ctx);
504
505         dri_bo_unmap(dndi_bo);
506     }
507
508     if(proc_ctx->filters_mask & 0x0000ff00) {
509         dri_bo *iecp_bo = proc_ctx->iecp_state_table.bo;
510         dri_bo_map(iecp_bo, 1);
511         proc_ctx->iecp_state_table.ptr = iecp_bo->virtual;
512
513         hsw_veb_iecp_std_table(ctx, proc_ctx);
514         hsw_veb_iecp_ace_table(ctx, proc_ctx);
515         hsw_veb_iecp_tcc_table(ctx, proc_ctx);
516         hsw_veb_iecp_pro_amp_table(ctx, proc_ctx);
517         hsw_veb_iecp_csc_table(ctx, proc_ctx);
518         hsw_veb_iecp_aoi_table(ctx, proc_ctx);
519    
520         dri_bo_unmap(iecp_bo);
521     }
522 }
523
524 void hsw_veb_state_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
525 {
526     struct intel_batchbuffer *batch = proc_ctx->batch;
527     unsigned int is_dn_enabled   = (proc_ctx->filters_mask & 0x01)? 1: 0;
528     unsigned int is_di_enabled   = (proc_ctx->filters_mask & 0x02)? 1: 0;
529     unsigned int is_iecp_enabled = (proc_ctx->filters_mask & 0xff00)?1:0;
530     unsigned int is_first_frame  = !!((proc_ctx->frame_order == -1) &&
531                                       (is_di_enabled ||
532                                        is_dn_enabled));
533     unsigned int di_output_frames_flag = 2; /* Output Current Frame Only */
534
535     if(proc_ctx->fourcc_input != proc_ctx->fourcc_output ||
536        (is_dn_enabled == 0 && is_di_enabled == 0)){
537        is_iecp_enabled = 1;
538     }
539
540     if (is_di_enabled) {
541         VAProcFilterParameterBufferDeinterlacing *di_param =
542             (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
543
544         assert(di_param);
545         
546         if (di_param->algorithm == VAProcDeinterlacingBob)
547             is_first_frame = 1;
548
549         if ((di_param->algorithm == VAProcDeinterlacingMotionAdaptive ||
550             di_param->algorithm == VAProcDeinterlacingMotionCompensated) &&
551             proc_ctx->frame_order != -1)
552             di_output_frames_flag = 0; /* Output both Current Frame and Previous Frame */
553     }
554
555     BEGIN_VEB_BATCH(batch, 6);
556     OUT_VEB_BATCH(batch, VEB_STATE | (6 - 2));
557     OUT_VEB_BATCH(batch,
558                   0 << 26 |       // state surface control bits
559                   0 << 11 |       // reserved.
560                   0 << 10 |       // pipe sync disable
561                   di_output_frames_flag << 8  |       // DI output frame
562                   1 << 7  |       // 444->422 downsample method
563                   1 << 6  |       // 422->420 downsample method
564                   is_first_frame  << 5  |   // DN/DI first frame
565                   is_di_enabled   << 4  |             // DI enable
566                   is_dn_enabled   << 3  |             // DN enable
567                   is_iecp_enabled << 2  |             // global IECP enabled
568                   0 << 1  |       // ColorGamutCompressionEnable
569                   0 ) ;           // ColorGamutExpansionEnable.
570
571     OUT_RELOC(batch, 
572               proc_ctx->dndi_state_table.bo,
573               I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
574
575     OUT_RELOC(batch,
576               proc_ctx->iecp_state_table.bo, 
577               I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
578
579     OUT_RELOC(batch,
580               proc_ctx->gamut_state_table.bo, 
581               I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
582
583     OUT_RELOC(batch,
584               proc_ctx->vertex_state_table.bo, 
585               I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
586
587     ADVANCE_VEB_BATCH(batch);
588 }
589
590 void hsw_veb_surface_state(VADriverContextP ctx, struct intel_vebox_context *proc_ctx, unsigned int is_output)
591 {
592     struct intel_batchbuffer *batch = proc_ctx->batch;
593     unsigned int u_offset_y = 0, v_offset_y = 0;
594     unsigned int is_uv_interleaved = 0, tiling = 0, swizzle = 0;
595     unsigned int surface_format = PLANAR_420_8;
596     struct object_surface* obj_surf = NULL;
597     unsigned int surface_pitch = 0;
598     unsigned int half_pitch_chroma = 0;
599
600     if(is_output){   
601         obj_surf = proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface;
602     }else {
603         obj_surf = proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface;
604     }
605
606     assert(obj_surf->fourcc == VA_FOURCC_NV12 ||
607            obj_surf->fourcc == VA_FOURCC_YUY2 ||
608            obj_surf->fourcc == VA_FOURCC_AYUV ||
609            obj_surf->fourcc == VA_FOURCC_RGBA);
610
611     if (obj_surf->fourcc == VA_FOURCC_NV12) {
612         surface_format = PLANAR_420_8;
613         surface_pitch = obj_surf->width; 
614         is_uv_interleaved = 1;
615         half_pitch_chroma = 0;
616     } else if (obj_surf->fourcc == VA_FOURCC_YUY2) {
617         surface_format = YCRCB_NORMAL;
618         surface_pitch = obj_surf->width * 2; 
619         is_uv_interleaved = 0;
620         half_pitch_chroma = 0;
621     } else if (obj_surf->fourcc == VA_FOURCC_AYUV) {
622         surface_format = PACKED_444A_8;
623         surface_pitch = obj_surf->width * 4; 
624         is_uv_interleaved = 0;
625         half_pitch_chroma = 0;
626     } else if (obj_surf->fourcc == VA_FOURCC_RGBA) {
627         surface_format = R8G8B8A8_UNORM_SRGB;
628         surface_pitch = obj_surf->width * 4; 
629         is_uv_interleaved = 0;
630         half_pitch_chroma = 0;
631     }
632
633     u_offset_y = obj_surf->y_cb_offset;
634     v_offset_y = obj_surf->y_cr_offset;
635      
636     dri_bo_get_tiling(obj_surf->bo, &tiling, &swizzle);
637
638     BEGIN_VEB_BATCH(batch, 6);
639     OUT_VEB_BATCH(batch, VEB_SURFACE_STATE | (6 - 2));
640     OUT_VEB_BATCH(batch,
641                   0 << 1 |         // reserved
642                   is_output);      // surface indentification.
643
644     OUT_VEB_BATCH(batch,
645                   (obj_surf->height - 1) << 18 |  // height . w3
646                   (obj_surf->width -1 )  << 4  |  // width
647                   0);                             // reserve
648
649     OUT_VEB_BATCH(batch,
650                   surface_format      << 28  |  // surface format, YCbCr420. w4
651                   is_uv_interleaved   << 27  |  // interleave chrome , two seperate palar
652                   0                   << 20  |  // reserved
653                   (surface_pitch - 1) << 3   |  // surface pitch, 64 align
654                   half_pitch_chroma   << 2   |  // half pitch for chrome
655                   !!tiling            << 1   |  // tiled surface, linear surface used
656                   (tiling == I915_TILING_Y));   // tiled walk, ignored when liner surface
657
658     OUT_VEB_BATCH(batch,
659                   0 << 29  |     // reserved . w5
660                   0 << 16  |     // X offset for V(Cb)
661                   0 << 15  |     // reserved
662                   u_offset_y);   // Y offset for V(Cb)
663
664     OUT_VEB_BATCH(batch,
665                   0 << 29  |     // reserved . w6
666                   0 << 16  |     // X offset for V(Cr)
667                   0 << 15  |     // reserved
668                   v_offset_y );  // Y offset for V(Cr)
669
670     ADVANCE_VEB_BATCH(batch);
671 }
672
673 void hsw_veb_dndi_iecp_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
674 {
675     struct intel_batchbuffer *batch = proc_ctx->batch;
676     unsigned char frame_ctrl_bits = 0;
677     unsigned int startingX = 0;
678     unsigned int endingX = (proc_ctx->width_input + 63 ) / 64 * 64;
679
680     /* s1:update the previous and current input */
681 /*    tempFrame = proc_ctx->frame_store[FRAME_IN_PREVIOUS];
682     proc_ctx->frame_store[FRAME_IN_PREVIOUS] = proc_ctx->frame_store[FRAME_IN_CURRENT]; ;
683     proc_ctx->frame_store[FRAME_IN_CURRENT] = tempFrame;
684
685     if(proc_ctx->surface_input_vebox != -1){
686         vpp_surface_copy(ctx, proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id,
687                      proc_ctx->surface_input_vebox);
688     } else {
689         vpp_surface_copy(ctx, proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id,
690                      proc_ctx->surface_input);
691     }
692 */
693     /*s2: update the STMM input and output */
694 /*    tempFrame = proc_ctx->frame_store[FRAME_IN_STMM];
695     proc_ctx->frame_store[FRAME_IN_STMM] = proc_ctx->frame_store[FRAME_OUT_STMM]; ;
696     proc_ctx->frame_store[FRAME_OUT_STMM] = tempFrame;
697 */      
698     /*s3:set reloc buffer address */
699     BEGIN_VEB_BATCH(batch, 10);
700     OUT_VEB_BATCH(batch, VEB_DNDI_IECP_STATE | (10 - 2));
701     OUT_VEB_BATCH(batch,
702                   startingX << 16 |
703                   (endingX-1));
704     OUT_RELOC(batch,
705               proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface->bo,
706               I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);
707     OUT_RELOC(batch,
708               proc_ctx->frame_store[FRAME_IN_PREVIOUS].obj_surface->bo,
709               I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);
710     OUT_RELOC(batch,
711               proc_ctx->frame_store[FRAME_IN_STMM].obj_surface->bo,
712               I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);
713     OUT_RELOC(batch,
714               proc_ctx->frame_store[FRAME_OUT_STMM].obj_surface->bo,
715               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
716     OUT_RELOC(batch,
717               proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface->bo,
718               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
719     OUT_RELOC(batch,
720               proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface->bo,
721               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
722     OUT_RELOC(batch,
723               proc_ctx->frame_store[FRAME_OUT_PREVIOUS].obj_surface->bo,
724               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
725     OUT_RELOC(batch,
726               proc_ctx->frame_store[FRAME_OUT_STATISTIC].obj_surface->bo,
727               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);
728
729     ADVANCE_VEB_BATCH(batch);
730 }
731
732 void hsw_veb_resource_prepare(VADriverContextP ctx,
733                               struct intel_vebox_context *proc_ctx)
734 {
735     VAStatus va_status;
736     dri_bo *bo;
737     struct i965_driver_data *i965 = i965_driver_data(ctx);
738     unsigned int input_fourcc, output_fourcc;
739     unsigned int input_sampling, output_sampling;
740     unsigned int input_tiling, output_tiling;
741     unsigned int i, swizzle;
742     struct object_surface *obj_surf_out = NULL, *obj_surf_in = NULL;
743
744     if (proc_ctx->surface_input_vebox_object != NULL) {
745         obj_surf_in = proc_ctx->surface_input_vebox_object;
746     } else {
747         obj_surf_in = proc_ctx->surface_input_object;
748     } 
749
750     if (proc_ctx->surface_output_vebox_object != NULL) {
751         obj_surf_out = proc_ctx->surface_output_vebox_object;
752     } else {
753         obj_surf_out = proc_ctx->surface_output_object;
754     } 
755
756     if(obj_surf_in->bo == NULL){
757           input_fourcc = VA_FOURCC('N','V','1','2');
758           input_sampling = SUBSAMPLE_YUV420;
759           input_tiling = 0;
760           i965_check_alloc_surface_bo(ctx, obj_surf_in, input_tiling, input_fourcc, input_sampling);
761     } else {
762         input_fourcc = obj_surf_in->fourcc;
763         input_sampling = obj_surf_in->subsampling;
764         dri_bo_get_tiling(obj_surf_in->bo, &input_tiling, &swizzle);
765         input_tiling = !!input_tiling;
766     }
767
768     if(obj_surf_out->bo == NULL){
769           output_fourcc = VA_FOURCC('N','V','1','2');
770           output_sampling = SUBSAMPLE_YUV420;
771           output_tiling = 0;
772           i965_check_alloc_surface_bo(ctx, obj_surf_out, output_tiling, output_fourcc, output_sampling);
773     }else {
774         output_fourcc   = obj_surf_out->fourcc;
775         output_sampling = obj_surf_out->subsampling;
776         dri_bo_get_tiling(obj_surf_out->bo, &output_tiling, &swizzle);
777         output_tiling = !!output_tiling;
778     }
779
780     /* vebox pipelien input surface format info */
781     proc_ctx->fourcc_input = input_fourcc;
782     proc_ctx->fourcc_output = output_fourcc;
783    
784     /* create pipeline surfaces */
785     for(i = 0; i < FRAME_STORE_SUM; i ++) {
786         if(proc_ctx->frame_store[i].obj_surface){
787             continue; //refer external surface for vebox pipeline
788         }
789     
790         VASurfaceID new_surface;
791         struct object_surface *obj_surf = NULL;
792
793         va_status =   i965_CreateSurfaces(ctx,
794                                           proc_ctx ->width_input,
795                                           proc_ctx ->height_input,
796                                           VA_RT_FORMAT_YUV420,
797                                           1,
798                                           &new_surface);
799         assert(va_status == VA_STATUS_SUCCESS);
800
801         obj_surf = SURFACE(new_surface);
802         assert(obj_surf);
803
804         if( i <= FRAME_IN_PREVIOUS || i == FRAME_OUT_CURRENT_DN) {
805             i965_check_alloc_surface_bo(ctx, obj_surf, input_tiling, input_fourcc, input_sampling);
806         } else if( i == FRAME_IN_STMM || i == FRAME_OUT_STMM){
807             i965_check_alloc_surface_bo(ctx, obj_surf, 1, input_fourcc, input_sampling);
808         } else if( i >= FRAME_OUT_CURRENT){
809             i965_check_alloc_surface_bo(ctx, obj_surf, output_tiling, output_fourcc, output_sampling);
810         }
811
812         proc_ctx->frame_store[i].surface_id = new_surface;
813         proc_ctx->frame_store[i].is_internal_surface = 1;
814         proc_ctx->frame_store[i].obj_surface = obj_surf;
815     }
816
817     /* alloc dndi state table  */
818     dri_bo_unreference(proc_ctx->dndi_state_table.bo);
819     bo = dri_bo_alloc(i965->intel.bufmgr,
820                       "vebox: dndi state Buffer",
821                       0x1000, 0x1000);
822     proc_ctx->dndi_state_table.bo = bo;
823     dri_bo_reference(proc_ctx->dndi_state_table.bo);
824  
825     /* alloc iecp state table  */
826     dri_bo_unreference(proc_ctx->iecp_state_table.bo);
827     bo = dri_bo_alloc(i965->intel.bufmgr,
828                       "vebox: iecp state Buffer",
829                       0x1000, 0x1000);
830     proc_ctx->iecp_state_table.bo = bo;
831     dri_bo_reference(proc_ctx->iecp_state_table.bo);
832
833     /* alloc gamut state table  */
834     dri_bo_unreference(proc_ctx->gamut_state_table.bo);
835     bo = dri_bo_alloc(i965->intel.bufmgr,
836                       "vebox: gamut state Buffer",
837                       0x1000, 0x1000);
838     proc_ctx->gamut_state_table.bo = bo;
839     dri_bo_reference(proc_ctx->gamut_state_table.bo);
840
841     /* alloc vertex state table  */
842     dri_bo_unreference(proc_ctx->vertex_state_table.bo);
843     bo = dri_bo_alloc(i965->intel.bufmgr,
844                       "vertex: iecp state Buffer",
845                       0x1000, 0x1000);
846     proc_ctx->vertex_state_table.bo = bo;
847     dri_bo_reference(proc_ctx->vertex_state_table.bo);
848
849 }
850
851 static VAStatus
852 hsw_veb_surface_reference(VADriverContextP ctx,
853                           struct intel_vebox_context *proc_ctx)
854 {
855     struct object_surface * obj_surf; 
856     VEBFrameStore tmp_store;
857
858     if (proc_ctx->surface_input_vebox_object != NULL) {
859         obj_surf = proc_ctx->surface_input_vebox_object;
860     } else {
861         obj_surf = proc_ctx->surface_input_object;
862     } 
863
864     /* update the input surface */ 
865     proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id = VA_INVALID_ID;
866     proc_ctx->frame_store[FRAME_IN_CURRENT].is_internal_surface = 0;
867     proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface = obj_surf;
868
869     /* update the previous input surface */
870     if (proc_ctx->frame_order != -1) {
871         if (proc_ctx->filters_mask == VPP_DNDI_DN) {
872             proc_ctx->frame_store[FRAME_IN_PREVIOUS] = proc_ctx->frame_store[FRAME_OUT_CURRENT_DN];
873         } else if (proc_ctx->filters_mask & VPP_DNDI_DI) {
874             VAProcFilterParameterBufferDeinterlacing *di_param =
875                 (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
876
877             if (di_param && 
878                 (di_param->algorithm == VAProcDeinterlacingMotionAdaptive ||
879                 di_param->algorithm == VAProcDeinterlacingMotionCompensated)) {
880                 if ((proc_ctx->filters_mask & VPP_DNDI_DN) &&
881                     proc_ctx->frame_order == 0) { /* DNDI */
882                     tmp_store = proc_ctx->frame_store[FRAME_OUT_CURRENT_DN];
883                     proc_ctx->frame_store[FRAME_OUT_CURRENT_DN] = proc_ctx->frame_store[FRAME_IN_PREVIOUS];
884                     proc_ctx->frame_store[FRAME_IN_PREVIOUS] = tmp_store;
885                 } else { /* DI only */
886                     VAProcPipelineParameterBuffer *pipe = proc_ctx->pipeline_param;
887                     struct object_surface *obj_surf = NULL;
888                     struct i965_driver_data * const i965 = i965_driver_data(ctx);
889
890                     if (!pipe ||
891                         !pipe->num_forward_references ||
892                         pipe->forward_references[0] == VA_INVALID_ID) {
893                         WARN_ONCE("A forward temporal reference is needed for Motion adaptive/compensated deinterlacing !!!\n");
894
895                         return VA_STATUS_ERROR_INVALID_PARAMETER;
896                     }
897
898                     obj_surf = SURFACE(pipe->forward_references[0]);
899                     assert(obj_surf && obj_surf->bo);
900                 
901                     proc_ctx->frame_store[FRAME_IN_PREVIOUS].surface_id = pipe->forward_references[0];
902                     proc_ctx->frame_store[FRAME_IN_PREVIOUS].is_internal_surface = 0;
903                     proc_ctx->frame_store[FRAME_IN_PREVIOUS].obj_surface = obj_surf;
904                 }
905             }
906         }
907     }
908
909     /* update STMM surface */
910     if (proc_ctx->frame_order != -1) {
911         tmp_store = proc_ctx->frame_store[FRAME_IN_STMM];
912         proc_ctx->frame_store[FRAME_IN_STMM] = proc_ctx->frame_store[FRAME_OUT_STMM];
913         proc_ctx->frame_store[FRAME_OUT_STMM] = tmp_store;
914     }
915
916     /* update the output surface */ 
917     if (proc_ctx->surface_output_vebox_object != NULL) {
918         obj_surf = proc_ctx->surface_output_vebox_object;
919     } else {
920         obj_surf = proc_ctx->surface_output_object;
921     } 
922
923     if (proc_ctx->filters_mask == VPP_DNDI_DN) {
924         proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].surface_id = VA_INVALID_ID;
925         proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].is_internal_surface = 0;
926         proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface = obj_surf;
927         proc_ctx->current_output = FRAME_OUT_CURRENT_DN;
928     } else if (proc_ctx->filters_mask & VPP_DNDI_DI) {
929         VAProcFilterParameterBufferDeinterlacing *di_param =
930             (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
931
932         if (di_param && 
933             (di_param->algorithm == VAProcDeinterlacingMotionAdaptive ||
934             di_param->algorithm == VAProcDeinterlacingMotionCompensated)) {
935             if (proc_ctx->frame_order == -1) {
936                 proc_ctx->frame_store[FRAME_OUT_CURRENT].surface_id = VA_INVALID_ID;
937                 proc_ctx->frame_store[FRAME_OUT_CURRENT].is_internal_surface = 0;
938                 proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface = obj_surf;
939                 proc_ctx->current_output = FRAME_OUT_CURRENT;
940             } else if (proc_ctx->frame_order == 0) {
941                 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].surface_id = VA_INVALID_ID;
942                 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].is_internal_surface = 0;
943                 proc_ctx->frame_store[FRAME_OUT_PREVIOUS].obj_surface = obj_surf;
944                 proc_ctx->current_output = FRAME_OUT_PREVIOUS;
945             } else {
946                 proc_ctx->current_output = FRAME_OUT_CURRENT;
947                 proc_ctx->format_convert_flags |= POST_COPY_CONVERT;
948             }
949         } else {
950             proc_ctx->frame_store[FRAME_OUT_CURRENT].surface_id = VA_INVALID_ID;
951             proc_ctx->frame_store[FRAME_OUT_CURRENT].is_internal_surface = 0;
952             proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface = obj_surf;
953             proc_ctx->current_output = FRAME_OUT_CURRENT;
954         }
955     } else {
956         proc_ctx->frame_store[FRAME_OUT_CURRENT].surface_id = VA_INVALID_ID;
957         proc_ctx->frame_store[FRAME_OUT_CURRENT].is_internal_surface = 0;
958         proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface = obj_surf;
959         proc_ctx->current_output = FRAME_OUT_CURRENT;
960     }
961
962     return VA_STATUS_SUCCESS;
963 }
964
965 void hsw_veb_surface_unreference(VADriverContextP ctx,
966                                  struct intel_vebox_context *proc_ctx)
967 {
968     /* unreference the input surface */ 
969     proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id = VA_INVALID_ID;
970     proc_ctx->frame_store[FRAME_IN_CURRENT].is_internal_surface = 0;
971     proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface = NULL;
972
973     /* unreference the shared output surface */ 
974     if (proc_ctx->filters_mask == VPP_DNDI_DN) {
975         proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].surface_id = VA_INVALID_ID;
976         proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].is_internal_surface = 0;
977         proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface = NULL;
978     } else {
979         proc_ctx->frame_store[FRAME_OUT_CURRENT].surface_id = VA_INVALID_ID;
980         proc_ctx->frame_store[FRAME_OUT_CURRENT].is_internal_surface = 0;
981         proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface = NULL;
982     }
983 }
984
985 int hsw_veb_pre_format_convert(VADriverContextP ctx,
986                            struct intel_vebox_context *proc_ctx)
987 {
988     VAStatus va_status;
989     struct i965_driver_data *i965 = i965_driver_data(ctx);
990     struct object_surface* obj_surf_input = proc_ctx->surface_input_object;
991     struct object_surface* obj_surf_output = proc_ctx->surface_output_object;
992     struct object_surface* obj_surf_input_vebox;
993     struct object_surface* obj_surf_output_vebox;
994
995     proc_ctx->format_convert_flags = 0;
996
997     proc_ctx->width_input   = obj_surf_input->orig_width;
998     proc_ctx->height_input  = obj_surf_input->orig_height;
999     proc_ctx->width_output  = obj_surf_output->orig_width;
1000     proc_ctx->height_output = obj_surf_output->orig_height;
1001    
1002     /* only partial frame is not supported to be processed */
1003     /*
1004     assert(proc_ctx->width_input   == proc_ctx->pipeline_param->surface_region->width);
1005     assert(proc_ctx->height_input  == proc_ctx->pipeline_param->surface_region->height);
1006     assert(proc_ctx->width_output  == proc_ctx->pipeline_param->output_region->width);
1007     assert(proc_ctx->height_output == proc_ctx->pipeline_param->output_region->height);
1008     */
1009
1010     if(proc_ctx->width_output  != proc_ctx->width_input ||
1011        proc_ctx->height_output != proc_ctx->height_input){
1012         proc_ctx->format_convert_flags |= POST_SCALING_CONVERT;
1013     }
1014
1015      /* convert the following format to NV12 format */
1016      if(obj_surf_input->fourcc ==  VA_FOURCC('Y','V','1','2') ||
1017         obj_surf_input->fourcc ==  VA_FOURCC('I','4','2','0') ||
1018         obj_surf_input->fourcc ==  VA_FOURCC('I','M','C','1') ||
1019         obj_surf_input->fourcc ==  VA_FOURCC('I','M','C','3') ||
1020         obj_surf_input->fourcc ==  VA_FOURCC('R','G','B','A')){
1021
1022          proc_ctx->format_convert_flags |= PRE_FORMAT_CONVERT;
1023
1024       } else if(obj_surf_input->fourcc ==  VA_FOURCC('A','Y','U','V') ||
1025                 obj_surf_input->fourcc ==  VA_FOURCC('Y','U','Y','2') ||
1026                 obj_surf_input->fourcc ==  VA_FOURCC('N','V','1','2')){
1027                 // nothing to do here
1028      } else {
1029            /* not support other format as input */ 
1030            assert(0);
1031      }
1032     
1033      if (proc_ctx->format_convert_flags & PRE_FORMAT_CONVERT) {
1034          if(proc_ctx->surface_input_vebox_object == NULL){
1035              va_status = i965_CreateSurfaces(ctx,
1036                                             proc_ctx->width_input,
1037                                             proc_ctx->height_input,
1038                                             VA_RT_FORMAT_YUV420,
1039                                             1,
1040                                             &(proc_ctx->surface_input_vebox));
1041              assert(va_status == VA_STATUS_SUCCESS);
1042              obj_surf_input_vebox = SURFACE(proc_ctx->surface_input_vebox);
1043              assert(obj_surf_input_vebox);
1044
1045              if (obj_surf_input_vebox) {
1046                  proc_ctx->surface_input_vebox_object = obj_surf_input_vebox;
1047                  i965_check_alloc_surface_bo(ctx, obj_surf_input_vebox, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
1048              }
1049          }
1050        
1051          vpp_surface_convert(ctx, proc_ctx->surface_input_vebox_object, proc_ctx->surface_input_object);
1052       }
1053
1054       /* create one temporary NV12 surfaces for conversion*/
1055      if(obj_surf_output->fourcc ==  VA_FOURCC('Y','V','1','2') ||
1056         obj_surf_output->fourcc ==  VA_FOURCC('I','4','2','0') ||
1057         obj_surf_output->fourcc ==  VA_FOURCC('I','M','C','1') ||
1058         obj_surf_output->fourcc ==  VA_FOURCC('I','M','C','3') ||
1059         obj_surf_output->fourcc ==  VA_FOURCC('R','G','B','A')) {
1060
1061         proc_ctx->format_convert_flags |= POST_FORMAT_CONVERT;
1062     } else if(obj_surf_output->fourcc ==  VA_FOURCC('A','Y','U','V') ||
1063               obj_surf_output->fourcc ==  VA_FOURCC('Y','U','Y','2') ||
1064               obj_surf_output->fourcc ==  VA_FOURCC('N','V','1','2')){
1065               /* Nothing to do here */
1066      } else {
1067            /* not support other format as input */ 
1068            assert(0);
1069      }
1070   
1071      if(proc_ctx->format_convert_flags & POST_FORMAT_CONVERT ||
1072         proc_ctx->format_convert_flags & POST_SCALING_CONVERT){
1073        if(proc_ctx->surface_output_vebox_object == NULL){
1074              va_status = i965_CreateSurfaces(ctx,
1075                                             proc_ctx->width_input,
1076                                             proc_ctx->height_input,
1077                                             VA_RT_FORMAT_YUV420,
1078                                             1,
1079                                             &(proc_ctx->surface_output_vebox));
1080              assert(va_status == VA_STATUS_SUCCESS);
1081              obj_surf_output_vebox = SURFACE(proc_ctx->surface_output_vebox);
1082              assert(obj_surf_output_vebox);
1083
1084              if (obj_surf_output_vebox) {
1085                  proc_ctx->surface_output_vebox_object = obj_surf_output_vebox;
1086                  i965_check_alloc_surface_bo(ctx, obj_surf_output_vebox, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
1087              }
1088        }
1089      }   
1090
1091      if(proc_ctx->format_convert_flags & POST_SCALING_CONVERT){
1092        if(proc_ctx->surface_output_scaled_object == NULL){
1093              va_status = i965_CreateSurfaces(ctx,
1094                                             proc_ctx->width_output,
1095                                             proc_ctx->height_output,
1096                                             VA_RT_FORMAT_YUV420,
1097                                             1,
1098                                             &(proc_ctx->surface_output_scaled));
1099              assert(va_status == VA_STATUS_SUCCESS);
1100              obj_surf_output_vebox = SURFACE(proc_ctx->surface_output_scaled);
1101              assert(obj_surf_output_vebox);
1102
1103              if (obj_surf_output_vebox) {
1104                  proc_ctx->surface_output_scaled_object = obj_surf_output_vebox;
1105                  i965_check_alloc_surface_bo(ctx, obj_surf_output_vebox, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
1106              }
1107        }
1108      } 
1109     
1110      return 0;
1111 }
1112
1113 int hsw_veb_post_format_convert(VADriverContextP ctx,
1114                            struct intel_vebox_context *proc_ctx)
1115 {
1116     struct object_surface *obj_surface = NULL;
1117     
1118     obj_surface = proc_ctx->frame_store[proc_ctx->current_output].obj_surface;
1119
1120     if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) {
1121         /* copy the saved frame in the second call */
1122         vpp_surface_convert(ctx,proc_ctx->surface_output_object, obj_surface);
1123     } else if(!(proc_ctx->format_convert_flags & POST_FORMAT_CONVERT) &&
1124        !(proc_ctx->format_convert_flags & POST_SCALING_CONVERT)){
1125         /* Output surface format is covered by vebox pipeline and 
1126          * processed picture is already store in output surface 
1127          * so nothing will be done here */
1128     } else if ((proc_ctx->format_convert_flags & POST_FORMAT_CONVERT) &&
1129                !(proc_ctx->format_convert_flags & POST_SCALING_CONVERT)){
1130        /* convert and copy NV12 to YV12/IMC3/IMC2/RGBA output*/
1131         vpp_surface_convert(ctx,proc_ctx->surface_output_object, obj_surface);
1132
1133     } else if(proc_ctx->format_convert_flags & POST_SCALING_CONVERT) {
1134        /* scaling, convert and copy NV12 to YV12/IMC3/IMC2/RGBA output*/
1135         assert(obj_surface->fourcc == VA_FOURCC('N','V','1','2'));
1136      
1137         /* first step :surface scaling */
1138         vpp_surface_scaling(ctx,proc_ctx->surface_output_scaled_object, obj_surface);
1139
1140         /* second step: color format convert and copy to output */
1141         obj_surface = proc_ctx->surface_output_object;
1142
1143         if(obj_surface->fourcc ==  VA_FOURCC('N','V','1','2') ||
1144            obj_surface->fourcc ==  VA_FOURCC('Y','V','1','2') ||
1145            obj_surface->fourcc ==  VA_FOURCC('I','4','2','0') ||
1146            obj_surface->fourcc ==  VA_FOURCC('Y','U','Y','2') ||
1147            obj_surface->fourcc ==  VA_FOURCC('I','M','C','1') ||
1148            obj_surface->fourcc ==  VA_FOURCC('I','M','C','3') ||
1149            obj_surface->fourcc ==  VA_FOURCC('R','G','B','A')) {
1150            vpp_surface_convert(ctx, proc_ctx->surface_output_object, proc_ctx->surface_output_scaled_object);
1151        }else {
1152            assert(0); 
1153        }
1154    }
1155
1156     return 0;
1157 }
1158
1159 VAStatus gen75_vebox_process_picture(VADriverContextP ctx,
1160                          struct intel_vebox_context *proc_ctx)
1161 {
1162     struct i965_driver_data *i965 = i965_driver_data(ctx);
1163  
1164     VAProcPipelineParameterBuffer *pipe = proc_ctx->pipeline_param;
1165     VAProcFilterParameterBuffer* filter = NULL;
1166     struct object_buffer *obj_buf = NULL;
1167     unsigned int i;
1168
1169     for (i = 0; i < pipe->num_filters; i ++) {
1170          obj_buf = BUFFER(pipe->filters[i]);
1171          
1172          assert(obj_buf && obj_buf->buffer_store);
1173
1174          if (!obj_buf || !obj_buf->buffer_store)
1175              goto error;
1176
1177          filter = (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
1178             
1179          if (filter->type == VAProcFilterNoiseReduction) {
1180              proc_ctx->filters_mask |= VPP_DNDI_DN;
1181              proc_ctx->filter_dn = filter;
1182          } else if (filter->type == VAProcFilterDeinterlacing) {
1183              proc_ctx->filters_mask |= VPP_DNDI_DI;
1184              proc_ctx->filter_di = filter;
1185          } else if (filter->type == VAProcFilterColorBalance) {
1186              proc_ctx->filters_mask |= VPP_IECP_PRO_AMP;
1187              proc_ctx->filter_iecp_amp = filter;
1188              proc_ctx->filter_iecp_amp_num_elements = obj_buf->num_elements;
1189          }
1190     }
1191
1192     hsw_veb_pre_format_convert(ctx, proc_ctx);
1193     hsw_veb_surface_reference(ctx, proc_ctx);
1194
1195     if (proc_ctx->frame_order == -1) {
1196         hsw_veb_resource_prepare(ctx, proc_ctx);
1197     }
1198
1199     if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) {
1200         assert(proc_ctx->frame_order == 1);
1201         /* directly copy the saved frame in the second call */
1202     } else {
1203         intel_batchbuffer_start_atomic_veb(proc_ctx->batch, 0x1000);
1204         intel_batchbuffer_emit_mi_flush(proc_ctx->batch);
1205         hsw_veb_surface_state(ctx, proc_ctx, INPUT_SURFACE); 
1206         hsw_veb_surface_state(ctx, proc_ctx, OUTPUT_SURFACE); 
1207         hsw_veb_state_table_setup(ctx, proc_ctx);
1208
1209         hsw_veb_state_command(ctx, proc_ctx);           
1210         hsw_veb_dndi_iecp_command(ctx, proc_ctx);
1211         intel_batchbuffer_end_atomic(proc_ctx->batch);
1212         intel_batchbuffer_flush(proc_ctx->batch);
1213     }
1214
1215     hsw_veb_post_format_convert(ctx, proc_ctx);
1216     // hsw_veb_surface_unreference(ctx, proc_ctx);
1217
1218     proc_ctx->frame_order = (proc_ctx->frame_order + 1) % 2;
1219      
1220     return VA_STATUS_SUCCESS;
1221
1222 error:
1223     return VA_STATUS_ERROR_INVALID_PARAMETER;
1224 }
1225
1226 void gen75_vebox_context_destroy(VADriverContextP ctx, 
1227                           struct intel_vebox_context *proc_ctx)
1228 {
1229     int i;
1230
1231     if(proc_ctx->surface_input_vebox != VA_INVALID_ID){
1232        i965_DestroySurfaces(ctx, &proc_ctx->surface_input_vebox, 1);
1233        proc_ctx->surface_input_vebox = VA_INVALID_ID;
1234        proc_ctx->surface_input_vebox_object = NULL;
1235      }
1236
1237     if(proc_ctx->surface_output_vebox != VA_INVALID_ID){
1238        i965_DestroySurfaces(ctx, &proc_ctx->surface_output_vebox, 1);
1239        proc_ctx->surface_output_vebox = VA_INVALID_ID;
1240        proc_ctx->surface_output_vebox_object = NULL;
1241      }
1242
1243     if(proc_ctx->surface_output_scaled != VA_INVALID_ID){
1244        i965_DestroySurfaces(ctx, &proc_ctx->surface_output_scaled, 1);
1245        proc_ctx->surface_output_scaled = VA_INVALID_ID;
1246        proc_ctx->surface_output_scaled_object = NULL;
1247      }
1248
1249     for(i = 0; i < FRAME_STORE_SUM; i ++) {
1250         if (proc_ctx->frame_store[i].is_internal_surface == 1) {
1251             assert(proc_ctx->frame_store[i].surface_id != VA_INVALID_ID);
1252
1253             if (proc_ctx->frame_store[i].surface_id != VA_INVALID_ID)
1254                 i965_DestroySurfaces(ctx, &proc_ctx->frame_store[i].surface_id, 1);
1255         }
1256
1257         proc_ctx->frame_store[i].surface_id = VA_INVALID_ID;
1258         proc_ctx->frame_store[i].is_internal_surface = 0;
1259         proc_ctx->frame_store[i].obj_surface = NULL;
1260     }
1261
1262     /* dndi state table  */
1263     dri_bo_unreference(proc_ctx->dndi_state_table.bo);
1264     proc_ctx->dndi_state_table.bo = NULL;
1265
1266     /* iecp state table  */
1267     dri_bo_unreference(proc_ctx->iecp_state_table.bo);
1268     proc_ctx->dndi_state_table.bo = NULL;
1269  
1270     /* gamut statu table */
1271     dri_bo_unreference(proc_ctx->gamut_state_table.bo);
1272     proc_ctx->gamut_state_table.bo = NULL;
1273
1274     /* vertex state table  */
1275     dri_bo_unreference(proc_ctx->vertex_state_table.bo);
1276     proc_ctx->vertex_state_table.bo = NULL;
1277
1278     intel_batchbuffer_free(proc_ctx->batch);
1279
1280     free(proc_ctx);
1281 }
1282
1283 struct intel_vebox_context * gen75_vebox_context_init(VADriverContextP ctx)
1284 {
1285     struct intel_driver_data *intel = intel_driver_data(ctx);
1286     struct intel_vebox_context *proc_context = calloc(1, sizeof(struct intel_vebox_context));
1287     int i;
1288
1289     proc_context->batch = intel_batchbuffer_new(intel, I915_EXEC_VEBOX, 0);
1290     memset(proc_context->frame_store, 0, sizeof(VEBFrameStore)*FRAME_STORE_SUM);
1291
1292     for (i = 0; i < FRAME_STORE_SUM; i ++) {
1293         proc_context->frame_store[i].surface_id = VA_INVALID_ID;
1294         proc_context->frame_store[i].is_internal_surface = 0;
1295         proc_context->frame_store[i].obj_surface = NULL;
1296     }
1297   
1298     proc_context->filters_mask          = 0;
1299     proc_context->frame_order           = -1; /* the first frame */
1300     proc_context->surface_output_object = NULL;
1301     proc_context->surface_input_object  = NULL;
1302     proc_context->surface_input_vebox   = VA_INVALID_ID;
1303     proc_context->surface_input_vebox_object = NULL;
1304     proc_context->surface_output_vebox  = VA_INVALID_ID;
1305     proc_context->surface_output_vebox_object = NULL;
1306     proc_context->surface_output_scaled = VA_INVALID_ID;
1307     proc_context->surface_output_scaled_object = NULL;
1308     proc_context->filters_mask          = 0;
1309     proc_context->format_convert_flags  = 0;
1310
1311     return proc_context;
1312 }
1313
1314 void bdw_veb_state_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
1315 {
1316     struct intel_batchbuffer *batch = proc_ctx->batch;
1317     unsigned int is_dn_enabled   = (proc_ctx->filters_mask & 0x01)? 1: 0;
1318     unsigned int is_di_enabled   = (proc_ctx->filters_mask & 0x02)? 1: 0;
1319     unsigned int is_iecp_enabled = (proc_ctx->filters_mask & 0xff00)?1:0;
1320     unsigned int is_first_frame  = !!((proc_ctx->frame_order == -1) &&
1321                                       (is_di_enabled ||
1322                                        is_dn_enabled));
1323     unsigned int di_output_frames_flag = 2; /* Output Current Frame Only */
1324
1325     if(proc_ctx->fourcc_input != proc_ctx->fourcc_output ||
1326        (is_dn_enabled == 0 && is_di_enabled == 0)){
1327        is_iecp_enabled = 1;
1328     }
1329
1330     if (is_di_enabled) {
1331         VAProcFilterParameterBufferDeinterlacing *di_param =
1332             (VAProcFilterParameterBufferDeinterlacing *)proc_ctx->filter_di;
1333
1334         assert(di_param);
1335         
1336         if (di_param->algorithm == VAProcDeinterlacingBob)
1337             is_first_frame = 1;
1338
1339         if ((di_param->algorithm == VAProcDeinterlacingMotionAdaptive ||
1340             di_param->algorithm == VAProcDeinterlacingMotionCompensated) &&
1341             proc_ctx->frame_order != -1)
1342             di_output_frames_flag = 0; /* Output both Current Frame and Previous Frame */
1343     }
1344
1345     BEGIN_VEB_BATCH(batch, 0xc);
1346     OUT_VEB_BATCH(batch, VEB_STATE | (0xc - 2));
1347     OUT_VEB_BATCH(batch,
1348                   0 << 25 |       // state surface control bits
1349                   0 << 23 |       // reserved.
1350                   0 << 22 |       // gamut expansion position
1351                   0 << 15 |       // reserved.
1352                   0 << 14 |       // single slice vebox enable
1353                   0 << 13 |       // hot pixel filter enable
1354                   0 << 12 |       // alpha plane enable
1355                   0 << 11 |       // vignette enable
1356                   0 << 10 |       // demosaic enable
1357                   di_output_frames_flag << 8  |       // DI output frame
1358                   0 << 7  |       // 444->422 downsample method
1359                   0 << 6  |       // 422->420 downsample method
1360                   is_first_frame  << 5  |   // DN/DI first frame
1361                   is_di_enabled   << 4  |             // DI enable
1362                   is_dn_enabled   << 3  |             // DN enable
1363                   is_iecp_enabled << 2  |             // global IECP enabled
1364                   0 << 1  |       // ColorGamutCompressionEnable
1365                   0 ) ;           // ColorGamutExpansionEnable.
1366
1367     OUT_RELOC(batch,
1368               proc_ctx->dndi_state_table.bo,
1369               I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
1370
1371     OUT_VEB_BATCH(batch, 0);
1372
1373     OUT_RELOC(batch,
1374               proc_ctx->iecp_state_table.bo,
1375               I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
1376
1377     OUT_VEB_BATCH(batch, 0);
1378
1379     OUT_RELOC(batch,
1380               proc_ctx->gamut_state_table.bo,
1381               I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
1382
1383     OUT_VEB_BATCH(batch, 0);
1384
1385     OUT_RELOC(batch,
1386               proc_ctx->vertex_state_table.bo,
1387               I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
1388
1389     OUT_VEB_BATCH(batch, 0);
1390
1391     OUT_VEB_BATCH(batch, 0);/*caputre pipe state pointer*/
1392     OUT_VEB_BATCH(batch, 0);
1393
1394     ADVANCE_VEB_BATCH(batch);
1395 }
1396
1397 void bdw_veb_dndi_iecp_command(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
1398 {
1399     struct intel_batchbuffer *batch = proc_ctx->batch;
1400     unsigned char frame_ctrl_bits = 0;
1401     unsigned int startingX = 0;
1402     unsigned int endingX = (proc_ctx->width_input + 63 ) / 64 * 64;
1403
1404     BEGIN_VEB_BATCH(batch, 0x14);
1405     OUT_VEB_BATCH(batch, VEB_DNDI_IECP_STATE | (0x14 - 2));//DWord 0
1406     OUT_VEB_BATCH(batch,
1407                   startingX << 16 |
1408                   endingX -1);//DWord 1
1409
1410     OUT_RELOC(batch,
1411               proc_ctx->frame_store[FRAME_IN_CURRENT].obj_surface->bo,
1412               I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);//DWord 2
1413     OUT_VEB_BATCH(batch,0);//DWord 3
1414
1415     OUT_RELOC(batch,
1416               proc_ctx->frame_store[FRAME_IN_PREVIOUS].obj_surface->bo,
1417               I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);//DWord 4
1418     OUT_VEB_BATCH(batch,0);//DWord 5
1419
1420     OUT_RELOC(batch,
1421               proc_ctx->frame_store[FRAME_IN_STMM].obj_surface->bo,
1422               I915_GEM_DOMAIN_RENDER, 0, frame_ctrl_bits);//DWord 6
1423     OUT_VEB_BATCH(batch,0);//DWord 7
1424
1425     OUT_RELOC(batch,
1426               proc_ctx->frame_store[FRAME_OUT_STMM].obj_surface->bo,
1427               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 8
1428     OUT_VEB_BATCH(batch,0);//DWord 9
1429
1430     OUT_RELOC(batch,
1431               proc_ctx->frame_store[FRAME_OUT_CURRENT_DN].obj_surface->bo,
1432               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 10
1433     OUT_VEB_BATCH(batch,0);//DWord 11
1434
1435     OUT_RELOC(batch,
1436               proc_ctx->frame_store[FRAME_OUT_CURRENT].obj_surface->bo,
1437               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 12
1438     OUT_VEB_BATCH(batch,0);//DWord 13
1439
1440     OUT_RELOC(batch,
1441               proc_ctx->frame_store[FRAME_OUT_PREVIOUS].obj_surface->bo,
1442               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 14
1443     OUT_VEB_BATCH(batch,0);//DWord 15
1444
1445     OUT_RELOC(batch,
1446               proc_ctx->frame_store[FRAME_OUT_STATISTIC].obj_surface->bo,
1447               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, frame_ctrl_bits);//DWord 16
1448     OUT_VEB_BATCH(batch,0);//DWord 17
1449
1450     OUT_VEB_BATCH(batch,0);//DWord 18
1451     OUT_VEB_BATCH(batch,0);//DWord 19
1452
1453     ADVANCE_VEB_BATCH(batch);
1454 }
1455
1456 VAStatus gen8_vebox_process_picture(VADriverContextP ctx,
1457                          struct intel_vebox_context *proc_ctx)
1458 {
1459     struct i965_driver_data *i965 = i965_driver_data(ctx);
1460  
1461     VAProcPipelineParameterBuffer *pipe = proc_ctx->pipeline_param;
1462     VAProcFilterParameterBuffer* filter = NULL;
1463     struct object_buffer *obj_buf = NULL;
1464     unsigned int i;
1465
1466     for (i = 0; i < pipe->num_filters; i ++) {
1467          obj_buf = BUFFER(pipe->filters[i]);
1468          
1469          assert(obj_buf && obj_buf->buffer_store);
1470
1471          if (!obj_buf || !obj_buf->buffer_store)
1472              goto error;
1473
1474          filter = (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
1475             
1476          if (filter->type == VAProcFilterNoiseReduction) {
1477              proc_ctx->filters_mask |= VPP_DNDI_DN;
1478              proc_ctx->filter_dn = filter;
1479          } else if (filter->type == VAProcFilterDeinterlacing) {
1480              proc_ctx->filters_mask |= VPP_DNDI_DI;
1481              proc_ctx->filter_di = filter;
1482          } else if (filter->type == VAProcFilterColorBalance) {
1483              proc_ctx->filters_mask |= VPP_IECP_PRO_AMP;
1484              proc_ctx->filter_iecp_amp = filter;
1485              proc_ctx->filter_iecp_amp_num_elements = obj_buf->num_elements;
1486          }
1487     }
1488
1489     hsw_veb_pre_format_convert(ctx, proc_ctx);
1490     hsw_veb_surface_reference(ctx, proc_ctx);
1491
1492     if (proc_ctx->frame_order == -1) {
1493         hsw_veb_resource_prepare(ctx, proc_ctx);
1494     }
1495
1496     if (proc_ctx->format_convert_flags & POST_COPY_CONVERT) {
1497         assert(proc_ctx->frame_order == 1);
1498         /* directly copy the saved frame in the second call */
1499     } else {
1500         intel_batchbuffer_start_atomic_veb(proc_ctx->batch, 0x1000);
1501         intel_batchbuffer_emit_mi_flush(proc_ctx->batch);
1502         hsw_veb_surface_state(ctx, proc_ctx, INPUT_SURFACE); 
1503         hsw_veb_surface_state(ctx, proc_ctx, OUTPUT_SURFACE); 
1504         hsw_veb_state_table_setup(ctx, proc_ctx);
1505
1506         bdw_veb_state_command(ctx, proc_ctx);           
1507         bdw_veb_dndi_iecp_command(ctx, proc_ctx);
1508         intel_batchbuffer_end_atomic(proc_ctx->batch);
1509         intel_batchbuffer_flush(proc_ctx->batch);
1510     }
1511
1512     hsw_veb_post_format_convert(ctx, proc_ctx);
1513     // hsw_veb_surface_unreference(ctx, proc_ctx);
1514
1515     proc_ctx->frame_order = (proc_ctx->frame_order + 1) % 2;
1516      
1517     return VA_STATUS_SUCCESS;
1518
1519 error:
1520     return VA_STATUS_ERROR_INVALID_PARAMETER;
1521 }
1522