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