OSDN Git Service

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