OSDN Git Service

intel-vaapi-driver 1.8.1.pre1
[android-x86/hardware-intel-common-vaapi.git] / src / gen75_picture_process.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 <assert.h>
31 #include <string.h>
32
33 #include "intel_batchbuffer.h"
34 #include "intel_driver.h"
35 #include "i965_defines.h"
36 #include "i965_structs.h"
37
38 #include "i965_drv_video.h"
39 #include "i965_post_processing.h"
40 #include "gen75_picture_process.h"
41 #include "gen8_post_processing.h"
42 #include "intel_gen_vppapi.h"
43
44 extern struct hw_context *
45 i965_proc_context_init(VADriverContextP ctx,
46                        struct object_config *obj_config);
47
48 static VAStatus 
49 gen75_vpp_fmt_cvt(VADriverContextP ctx, 
50                   VAProfile profile, 
51                   union codec_state *codec_state,
52                   struct hw_context *hw_context)
53 {
54     VAStatus va_status = VA_STATUS_SUCCESS;
55     struct intel_video_process_context *proc_ctx = 
56              (struct intel_video_process_context *)hw_context;
57   
58     va_status = i965_proc_picture(ctx, profile, codec_state,
59                                   proc_ctx->vpp_fmt_cvt_ctx);
60
61     return va_status;
62 }
63
64 static VAStatus 
65 gen75_vpp_vebox(VADriverContextP ctx, 
66                 struct intel_video_process_context* proc_ctx)
67 {
68      VAStatus va_status = VA_STATUS_SUCCESS;
69      VAProcPipelineParameterBuffer* pipeline_param = proc_ctx->pipeline_param; 
70      struct i965_driver_data *i965 = i965_driver_data(ctx); 
71  
72      /* vpp features based on VEBox fixed function */
73      if(proc_ctx->vpp_vebox_ctx == NULL) {
74          proc_ctx->vpp_vebox_ctx = gen75_vebox_context_init(ctx);
75      }
76
77      proc_ctx->vpp_vebox_ctx->pipeline_param  = pipeline_param;
78      proc_ctx->vpp_vebox_ctx->surface_input_object = proc_ctx->surface_pipeline_input_object;
79      proc_ctx->vpp_vebox_ctx->surface_output_object  = proc_ctx->surface_render_output_object;
80
81      if (IS_HASWELL(i965->intel.device_info))
82          va_status = gen75_vebox_process_picture(ctx, proc_ctx->vpp_vebox_ctx);
83      else if (IS_GEN8(i965->intel.device_info))
84          va_status = gen8_vebox_process_picture(ctx, proc_ctx->vpp_vebox_ctx);
85      else if (IS_GEN9(i965->intel.device_info))
86          va_status = gen9_vebox_process_picture(ctx, proc_ctx->vpp_vebox_ctx);
87
88      return va_status;
89
90
91 static int intel_gpe_support_10bit_scaling(struct intel_video_process_context *proc_ctx)
92 {
93     struct i965_proc_context *gpe_proc_ctx;
94
95     if (!proc_ctx || !proc_ctx->vpp_fmt_cvt_ctx)
96         return 0;
97
98     gpe_proc_ctx = (struct i965_proc_context *)proc_ctx->vpp_fmt_cvt_ctx;
99
100     if (gpe_proc_ctx->pp_context.scaling_context_initialized)
101         return 1;
102     else
103         return 0;
104 }
105
106 static void
107 rgb_to_yuv(unsigned int argb,
108            unsigned char *y,
109            unsigned char *u,
110            unsigned char *v,
111            unsigned char *a)
112 {
113     int r = ((argb >> 16) & 0xff);
114     int g = ((argb >> 8) & 0xff);
115     int b = ((argb >> 0) & 0xff);
116
117     *y = (257 * r + 504 * g + 98 * b) / 1000 + 16;
118     *v = (439 * r - 368 * g - 71 * b) / 1000 + 128;
119     *u = (-148 * r - 291 * g + 439 * b) / 1000 + 128;
120     *a = ((argb >> 24) & 0xff);
121 }
122
123 static void
124 gen8plus_vpp_clear_surface(VADriverContextP ctx,
125                        struct i965_post_processing_context *pp_context,
126                        struct object_surface *obj_surface,
127                        unsigned int color)
128 {
129     struct intel_batchbuffer *batch = pp_context->batch;
130     unsigned int blt_cmd, br13;
131     unsigned int tiling = 0, swizzle = 0;
132     int pitch;
133     unsigned char y, u, v, a = 0;
134     int region_width, region_height;
135
136     /* Currently only support NV12 surface */
137     if (!obj_surface || obj_surface->fourcc != VA_FOURCC_NV12)
138         return;
139
140     rgb_to_yuv(color, &y, &u, &v, &a);
141
142     if (a == 0)
143         return;
144
145     dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
146     blt_cmd = GEN8_XY_COLOR_BLT_CMD;
147     pitch = obj_surface->width;
148
149     if (tiling != I915_TILING_NONE) {
150         assert(tiling == I915_TILING_Y);
151         // blt_cmd |= XY_COLOR_BLT_DST_TILED;
152         // pitch >>= 2;
153     }
154
155     br13 = 0xf0 << 16;
156     br13 |= BR13_8;
157     br13 |= pitch;
158
159     intel_batchbuffer_start_atomic_blt(batch, 56);
160     BEGIN_BLT_BATCH(batch, 14);
161
162     region_width = obj_surface->width;
163     region_height = obj_surface->height;
164
165     OUT_BATCH(batch, blt_cmd);
166     OUT_BATCH(batch, br13);
167     OUT_BATCH(batch,
168               0 << 16 |
169               0);
170     OUT_BATCH(batch,
171               region_height << 16 |
172               region_width);
173     OUT_RELOC64(batch, obj_surface->bo,
174               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
175               0);
176     OUT_BATCH(batch, y);
177
178     br13 = 0xf0 << 16;
179     br13 |= BR13_565;
180     br13 |= pitch;
181
182     region_width = obj_surface->width / 2;
183     region_height = obj_surface->height / 2;
184
185     if (tiling == I915_TILING_Y) {
186         region_height = ALIGN(obj_surface->height / 2, 32);
187     }
188
189     OUT_BATCH(batch, blt_cmd);
190     OUT_BATCH(batch, br13);
191     OUT_BATCH(batch,
192               0 << 16 |
193               0);
194     OUT_BATCH(batch,
195               region_height << 16 |
196               region_width);
197     OUT_RELOC64(batch, obj_surface->bo,
198               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
199               obj_surface->width * obj_surface->y_cb_offset);
200     OUT_BATCH(batch, v << 8 | u);
201
202     ADVANCE_BATCH(batch);
203     intel_batchbuffer_end_atomic(batch);
204 }
205
206 VAStatus 
207 gen75_proc_picture(VADriverContextP ctx,
208                    VAProfile profile,
209                    union codec_state *codec_state,
210                    struct hw_context *hw_context)
211 {
212     struct i965_driver_data *i965 = i965_driver_data(ctx);
213     struct proc_state* proc_st = &(codec_state->proc);
214     struct intel_video_process_context *proc_ctx = 
215              (struct intel_video_process_context *)hw_context;
216     VAProcPipelineParameterBuffer *pipeline_param = 
217              (VAProcPipelineParameterBuffer *)proc_st->pipeline_param->buffer;
218     struct object_surface *obj_dst_surf = NULL;
219     struct object_surface *obj_src_surf = NULL;
220
221     VAProcPipelineParameterBuffer pipeline_param2;
222     struct object_surface *stage1_dst_surf = NULL;
223     struct object_surface *stage2_dst_surf = NULL;
224     VARectangle src_rect, dst_rect;
225     VASurfaceID tmp_surfaces[2];
226     VASurfaceID out_surface_id1 = VA_INVALID_ID, out_surface_id2 = VA_INVALID_ID;
227     int num_tmp_surfaces = 0;
228
229     VAStatus status;
230
231     proc_ctx->pipeline_param = pipeline_param;
232
233     if (proc_st->current_render_target == VA_INVALID_SURFACE ||
234         pipeline_param->surface == VA_INVALID_SURFACE) {
235         status = VA_STATUS_ERROR_INVALID_SURFACE;
236         goto error;
237     }
238
239     obj_dst_surf = SURFACE(proc_st->current_render_target);
240
241     if (!obj_dst_surf) {
242         status = VA_STATUS_ERROR_INVALID_SURFACE;
243         goto error;
244     }
245
246     obj_src_surf = SURFACE(proc_ctx->pipeline_param->surface);
247
248     if (!obj_src_surf) {
249         status = VA_STATUS_ERROR_INVALID_SURFACE;
250         goto error;
251     }
252
253     if (!obj_src_surf->bo) {
254         status = VA_STATUS_ERROR_INVALID_VALUE; /* The input surface is created without valid content */
255         goto error;
256     }
257
258     if (pipeline_param->num_filters && !pipeline_param->filters) {
259         status = VA_STATUS_ERROR_INVALID_PARAMETER;
260         goto error;
261     }
262
263     if (pipeline_param->num_filters == 0 || pipeline_param->filters == NULL ){
264         /* explicitly initialize the VPP based on Render ring */
265         if (proc_ctx->vpp_fmt_cvt_ctx == NULL)
266             proc_ctx->vpp_fmt_cvt_ctx = i965_proc_context_init(ctx, NULL);
267     }
268
269     if (!obj_dst_surf->bo) {
270         unsigned int is_tiled = 1;
271         unsigned int fourcc = VA_FOURCC_NV12;
272         int sampling = SUBSAMPLE_YUV420;
273
274         if (obj_dst_surf->expected_format == VA_RT_FORMAT_YUV420_10BPP)
275             fourcc = VA_FOURCC_P010;
276
277         i965_check_alloc_surface_bo(ctx, obj_dst_surf, is_tiled, fourcc, sampling);
278     }  
279
280     if (pipeline_param->surface_region) {
281         src_rect.x = pipeline_param->surface_region->x;
282         src_rect.y = pipeline_param->surface_region->y;
283         src_rect.width = pipeline_param->surface_region->width;
284         src_rect.height = pipeline_param->surface_region->height;
285     } else {
286         src_rect.x = 0;
287         src_rect.y = 0;
288         src_rect.width = obj_src_surf->orig_width;
289         src_rect.height = obj_src_surf->orig_height;
290     }
291
292     if (pipeline_param->output_region) {
293         dst_rect.x = pipeline_param->output_region->x;
294         dst_rect.y = pipeline_param->output_region->y;
295         dst_rect.width = pipeline_param->output_region->width;
296         dst_rect.height = pipeline_param->output_region->height;
297     } else {
298         dst_rect.x = 0;
299         dst_rect.y = 0;
300         dst_rect.width = obj_dst_surf->orig_width;
301         dst_rect.height = obj_dst_surf->orig_height;
302     }
303
304     if (pipeline_param->num_filters == 0 || pipeline_param->filters == NULL ) {
305 /* The Bit 2 is used to indicate that it is 10bit or 8bit.
306  * The Bit 0/1 is used to indicate the 420/422/444 format
307  */
308 #define SRC_10BIT_420    (5 << 0)
309 #define SRC_10BIT_422    (6 << 0)
310 #define SRC_10BIT_444    (7 << 0)
311 #define SRC_8BIT_420     (1 << 0)
312
313 /* The Bit 6 is used to indicate that it is 10bit or 8bit.
314  * The Bit 5/4 is used to indicate the 420/422/444 format
315  */
316 #define DST_10BIT_420    (5 << 4)
317 #define DST_10BIT_422    (6 << 4)
318 #define DST_10BIT_444    (7 << 4)
319 #define DST_8BIT_420     (1 << 4)
320
321 /* This is mainly for YUY2/RGBA. It is reserved for further */
322 #define SRC_YUV_PACKED   (1 << 3)
323 #define DST_YUV_PACKED   (1 << 7)
324
325 #define MASK_CSC         (0xFF)
326 #define SCALE_10BIT_420  (SRC_10BIT_420 | DST_10BIT_420)
327 #define SCALE_8BIT_420  (SRC_8BIT_420 | DST_8BIT_420)
328
329         unsigned int scale_flag;
330
331         scale_flag = 0;
332         if (obj_src_surf->fourcc == VA_FOURCC_P010 ||
333             obj_src_surf->fourcc == VA_FOURCC_I010)
334             scale_flag |= SRC_10BIT_420;
335
336         if (obj_dst_surf->fourcc == VA_FOURCC_P010 ||
337             obj_dst_surf->fourcc == VA_FOURCC_I010)
338             scale_flag |= DST_10BIT_420;
339
340         if (obj_src_surf->fourcc == VA_FOURCC_NV12 ||
341             obj_src_surf->fourcc == VA_FOURCC_I420)
342             scale_flag |= SRC_8BIT_420;
343
344         if (obj_dst_surf->fourcc == VA_FOURCC_NV12 ||
345             obj_dst_surf->fourcc == VA_FOURCC_I420)
346             scale_flag |= DST_8BIT_420;
347
348         /* If P010 is converted without resolution change,
349          * fall back to VEBOX
350          */
351         if (i965->intel.has_vebox &&
352             (obj_src_surf->fourcc == VA_FOURCC_P010) &&
353             (obj_dst_surf->fourcc == VA_FOURCC_P010) &&
354             (src_rect.width == dst_rect.width) &&
355             (src_rect.height == dst_rect.height))
356             scale_flag = 0;
357
358         if (((scale_flag & MASK_CSC) == SCALE_10BIT_420) &&
359             intel_gpe_support_10bit_scaling(proc_ctx)) {
360             struct i965_proc_context *gpe_proc_ctx;
361             struct i965_surface src_surface, dst_surface;
362             unsigned int tmp_width, tmp_x;
363
364
365             src_surface.base = (struct object_base *)obj_src_surf;
366             src_surface.type = I965_SURFACE_TYPE_SURFACE;
367             dst_surface.base = (struct object_base *)obj_dst_surf;
368             dst_surface.type = I965_SURFACE_TYPE_SURFACE;
369             gpe_proc_ctx = (struct i965_proc_context *)proc_ctx->vpp_fmt_cvt_ctx;
370
371             tmp_x = ALIGN_FLOOR(dst_rect.x, 2);
372             tmp_width = dst_rect.x + dst_rect.width;
373             tmp_width = tmp_width - tmp_x;
374             dst_rect.x = tmp_x;
375             dst_rect.width = tmp_width;
376
377             return gen9_p010_scaling_post_processing(ctx, &gpe_proc_ctx->pp_context,
378                                                      &src_surface, &src_rect,
379                                                      &dst_surface, &dst_rect);
380         }
381         if (((scale_flag & MASK_CSC) == SCALE_8BIT_420) &&
382              intel_vpp_support_yuv420p8_scaling(proc_ctx)) {
383             struct i965_proc_context *gpe_proc_ctx;
384             struct i965_surface src_surface, dst_surface;
385             unsigned int tmp_width, tmp_x;
386
387
388             src_surface.base = (struct object_base *)obj_src_surf;
389             src_surface.type = I965_SURFACE_TYPE_SURFACE;
390             dst_surface.base = (struct object_base *)obj_dst_surf;
391             dst_surface.type = I965_SURFACE_TYPE_SURFACE;
392             gpe_proc_ctx = (struct i965_proc_context *)proc_ctx->vpp_fmt_cvt_ctx;
393
394             tmp_x = ALIGN_FLOOR(dst_rect.x, 4);
395             tmp_width = dst_rect.x + dst_rect.width;
396             tmp_width = tmp_width - tmp_x;
397             dst_rect.x = tmp_x;
398             dst_rect.width = tmp_width;
399
400             if (obj_dst_surf->fourcc == VA_FOURCC_NV12 &&
401                 pipeline_param->output_background_color)
402                 gen8plus_vpp_clear_surface(ctx, &gpe_proc_ctx->pp_context,
403                                            obj_dst_surf,
404                                            pipeline_param->output_background_color);
405
406             return intel_yuv420p8_scaling_post_processing(ctx, &gpe_proc_ctx->pp_context,
407                                                      &src_surface, &src_rect,
408                                                      &dst_surface, &dst_rect);
409         }
410     }
411
412     proc_ctx->surface_render_output_object = obj_dst_surf;
413     proc_ctx->surface_pipeline_input_object = obj_src_surf;
414     assert(pipeline_param->num_filters <= 4);
415
416     int vpp_stage1 = 0, vpp_stage2 = 1, vpp_stage3 = 0;
417
418
419     if(obj_src_surf->fourcc == VA_FOURCC_P010) {
420         vpp_stage1 = 1;
421         vpp_stage2 = 0;
422         vpp_stage3 = 0;
423         if(pipeline_param->num_filters == 0 || pipeline_param->filters == NULL) {
424             if(src_rect.x != dst_rect.x ||
425                 src_rect.y != dst_rect.y ||
426                 src_rect.width != dst_rect.width ||
427                 src_rect.height != dst_rect.height)
428               vpp_stage2 = 1;
429
430             if(obj_dst_surf->fourcc != VA_FOURCC_NV12 &&
431                 obj_dst_surf->fourcc != VA_FOURCC_P010)
432               vpp_stage2 = 1;
433         }
434         else
435           vpp_stage2 = 1;
436
437         if(vpp_stage2 == 1) {
438           if(obj_dst_surf->fourcc == VA_FOURCC_P010)
439             vpp_stage3 = 1;
440         }
441     }
442     else if(obj_dst_surf->fourcc == VA_FOURCC_P010) {
443         vpp_stage2 = 1;
444         vpp_stage3 = 1;
445
446         if((obj_src_surf->fourcc == VA_FOURCC_NV12) &&
447             (pipeline_param->num_filters == 0 || pipeline_param->filters == NULL)) {
448             if((src_rect.x == dst_rect.x) &&
449                 (src_rect.y == dst_rect.y) &&
450                 (src_rect.width == dst_rect.width) &&
451                 (src_rect.height == dst_rect.height))
452                 vpp_stage2 = 0;
453         }
454     }
455
456     if(vpp_stage1 == 1){
457         memset((void *)&pipeline_param2, 0, sizeof(pipeline_param2));
458         pipeline_param2.surface = pipeline_param->surface;
459         pipeline_param2.surface_region = &src_rect;
460         pipeline_param2.output_region = &src_rect;
461         pipeline_param2.filter_flags = 0;
462         pipeline_param2.num_filters  = 0;
463
464         proc_ctx->pipeline_param = &pipeline_param2;
465
466         if(vpp_stage2 == 1) {
467             status = i965_CreateSurfaces(ctx,
468                                          obj_src_surf->orig_width,
469                                          obj_src_surf->orig_height,
470                                          VA_RT_FORMAT_YUV420,
471                                          1,
472                                          &out_surface_id1);
473             assert(status == VA_STATUS_SUCCESS);
474             tmp_surfaces[num_tmp_surfaces++] = out_surface_id1;
475             stage1_dst_surf = SURFACE(out_surface_id1);
476             assert(stage1_dst_surf);
477             i965_check_alloc_surface_bo(ctx, stage1_dst_surf, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
478
479             proc_ctx->surface_render_output_object = stage1_dst_surf;
480         }
481
482         gen75_vpp_vebox(ctx, proc_ctx);
483     }
484
485     if((vpp_stage3 == 1) && (vpp_stage2 == 1)) {
486         status = i965_CreateSurfaces(ctx,
487                                      obj_dst_surf->orig_width,
488                                      obj_dst_surf->orig_height,
489                                      VA_RT_FORMAT_YUV420,
490                                      1,
491                                      &out_surface_id2);
492         assert(status == VA_STATUS_SUCCESS);
493         tmp_surfaces[num_tmp_surfaces++] = out_surface_id2;
494         stage2_dst_surf = SURFACE(out_surface_id2);
495         assert(stage2_dst_surf);
496         i965_check_alloc_surface_bo(ctx, stage2_dst_surf, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
497     }
498
499     VABufferID *filter_id = (VABufferID*) pipeline_param->filters;
500
501     if(vpp_stage2 == 1) {
502         if(stage1_dst_surf != NULL) {
503             proc_ctx->surface_pipeline_input_object = stage1_dst_surf;
504             proc_ctx->surface_render_output_object = obj_dst_surf;
505
506             pipeline_param->surface = out_surface_id1;
507         }
508
509         if(stage2_dst_surf != NULL) {
510             proc_ctx->surface_render_output_object = stage2_dst_surf;
511
512             proc_st->current_render_target = out_surface_id2;
513         }
514
515         proc_ctx->pipeline_param = pipeline_param;
516
517         if(pipeline_param->num_filters == 0 || pipeline_param->filters == NULL ){
518             /* implicity surface format coversion and scaling */
519
520             status = gen75_vpp_fmt_cvt(ctx, profile, codec_state, hw_context);
521             if(status != VA_STATUS_SUCCESS)
522                 goto error;
523         }else if(pipeline_param->num_filters == 1) {
524            struct object_buffer * obj_buf = BUFFER((*filter_id) + 0);
525
526            assert(obj_buf && obj_buf->buffer_store && obj_buf->buffer_store->buffer);
527
528            if (!obj_buf ||
529                !obj_buf->buffer_store ||
530                !obj_buf->buffer_store->buffer) {
531                status = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
532                goto error;
533            }
534
535            VAProcFilterParameterBuffer* filter =
536                (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
537
538            if (filter->type == VAProcFilterNoiseReduction         ||
539                filter->type == VAProcFilterDeinterlacing          ||
540                filter->type == VAProcFilterSkinToneEnhancement    ||
541                filter->type == VAProcFilterSharpening             ||
542                filter->type == VAProcFilterColorBalance){
543                gen75_vpp_vebox(ctx, proc_ctx);
544            }
545         }else if (pipeline_param->num_filters >= 2) {
546              unsigned int i = 0;
547              for (i = 0; i < pipeline_param->num_filters; i++){
548                  struct object_buffer * obj_buf = BUFFER(pipeline_param->filters[i]);
549
550                  if (!obj_buf ||
551                      !obj_buf->buffer_store ||
552                      !obj_buf->buffer_store->buffer) {
553                      status = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
554                      goto error;
555                  }
556
557                  VAProcFilterParameterBuffer* filter =
558                      (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
559
560                  if (filter->type != VAProcFilterNoiseReduction       &&
561                      filter->type != VAProcFilterDeinterlacing        &&
562                      filter->type != VAProcFilterSkinToneEnhancement  &&
563                      filter->type != VAProcFilterColorBalance) {
564                      fprintf(stderr, "Do not support multiply filters outside vebox pipeline \n");
565                      assert(0);
566                  }
567              }
568              gen75_vpp_vebox(ctx, proc_ctx);
569         }
570     }
571
572     if(vpp_stage3 == 1)
573     {
574         if(vpp_stage2 == 1) {
575             memset(&pipeline_param2, 0, sizeof(pipeline_param2));
576             pipeline_param2.surface = out_surface_id2;
577             pipeline_param2.surface_region = &dst_rect;
578             pipeline_param2.output_region = &dst_rect;
579             pipeline_param2.filter_flags = 0;
580             pipeline_param2.num_filters  = 0;
581
582             proc_ctx->pipeline_param = &pipeline_param2;
583             proc_ctx->surface_pipeline_input_object = proc_ctx->surface_render_output_object;
584             proc_ctx->surface_render_output_object = obj_dst_surf;
585         }
586
587         gen75_vpp_vebox(ctx, proc_ctx);
588     }
589
590     if (num_tmp_surfaces)
591         i965_DestroySurfaces(ctx,
592                              tmp_surfaces,
593                              num_tmp_surfaces);
594
595     return VA_STATUS_SUCCESS;
596
597 error:
598     if (num_tmp_surfaces)
599         i965_DestroySurfaces(ctx,
600                              tmp_surfaces,
601                              num_tmp_surfaces);
602
603     return status;
604 }
605
606 static void 
607 gen75_proc_context_destroy(void *hw_context)
608 {
609     struct intel_video_process_context *proc_ctx =
610                       (struct intel_video_process_context *)hw_context;
611     VADriverContextP ctx = (VADriverContextP)(proc_ctx->driver_context);
612
613     if(proc_ctx->vpp_fmt_cvt_ctx){
614         proc_ctx->vpp_fmt_cvt_ctx->destroy(proc_ctx->vpp_fmt_cvt_ctx);
615         proc_ctx->vpp_fmt_cvt_ctx = NULL;
616     }
617
618     if(proc_ctx->vpp_vebox_ctx){
619        gen75_vebox_context_destroy(ctx,proc_ctx->vpp_vebox_ctx);
620        proc_ctx->vpp_vebox_ctx = NULL;
621     }
622
623     free(proc_ctx);
624 }
625
626 struct hw_context * 
627 gen75_proc_context_init(VADriverContextP ctx, 
628                         struct object_config *obj_config)
629 {
630    struct intel_video_process_context *proc_context 
631            = calloc(1, sizeof(struct intel_video_process_context));
632
633     assert(proc_context);
634     proc_context->base.destroy = gen75_proc_context_destroy;
635     proc_context->base.run     = gen75_proc_picture;
636
637     proc_context->vpp_vebox_ctx    = NULL;
638     proc_context->vpp_fmt_cvt_ctx  = NULL;
639  
640     proc_context->driver_context = ctx;
641
642     return (struct hw_context *)proc_context;
643 }
644