OSDN Git Service

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