OSDN Git Service

Move the sharpening into the whole virtual VEBOX process
[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
42 extern struct hw_context *
43 i965_proc_context_init(VADriverContextP ctx,
44                        struct object_config *obj_config);
45
46 static VAStatus 
47 gen75_vpp_fmt_cvt(VADriverContextP ctx, 
48                   VAProfile profile, 
49                   union codec_state *codec_state,
50                   struct hw_context *hw_context)
51 {
52     VAStatus va_status = VA_STATUS_SUCCESS;
53     struct intel_video_process_context *proc_ctx = 
54              (struct intel_video_process_context *)hw_context;
55   
56     /* implicity surface format coversion and scaling */
57     if(proc_ctx->vpp_fmt_cvt_ctx == NULL){
58          proc_ctx->vpp_fmt_cvt_ctx = i965_proc_context_init(ctx, NULL);
59     }
60
61     va_status = i965_proc_picture(ctx, profile, codec_state,
62                                   proc_ctx->vpp_fmt_cvt_ctx);
63
64     return va_status;
65 }
66
67 static VAStatus 
68 gen75_vpp_vebox(VADriverContextP ctx, 
69                 struct intel_video_process_context* proc_ctx)
70 {
71      VAStatus va_status = VA_STATUS_SUCCESS;
72      VAProcPipelineParameterBuffer* pipeline_param = proc_ctx->pipeline_param; 
73      struct i965_driver_data *i965 = i965_driver_data(ctx); 
74  
75      /* vpp features based on VEBox fixed function */
76      if(proc_ctx->vpp_vebox_ctx == NULL) {
77          proc_ctx->vpp_vebox_ctx = gen75_vebox_context_init(ctx);
78      }
79
80      proc_ctx->vpp_vebox_ctx->pipeline_param  = pipeline_param;
81      proc_ctx->vpp_vebox_ctx->surface_input_object = proc_ctx->surface_pipeline_input_object;
82      proc_ctx->vpp_vebox_ctx->surface_output_object  = proc_ctx->surface_render_output_object;
83
84      if (IS_HASWELL(i965->intel.device_info))
85          va_status = gen75_vebox_process_picture(ctx, proc_ctx->vpp_vebox_ctx);
86      else if (IS_GEN8(i965->intel.device_info))
87          va_status = gen8_vebox_process_picture(ctx, proc_ctx->vpp_vebox_ctx);
88      else if (IS_GEN9(i965->intel.device_info))
89          va_status = gen9_vebox_process_picture(ctx, proc_ctx->vpp_vebox_ctx);
90
91      return va_status;
92
93
94 VAStatus 
95 gen75_proc_picture(VADriverContextP ctx,
96                    VAProfile profile,
97                    union codec_state *codec_state,
98                    struct hw_context *hw_context)
99 {
100     struct i965_driver_data *i965 = i965_driver_data(ctx);
101     struct proc_state* proc_st = &(codec_state->proc);
102     struct intel_video_process_context *proc_ctx = 
103              (struct intel_video_process_context *)hw_context;
104     VAProcPipelineParameterBuffer *pipeline_param = 
105              (VAProcPipelineParameterBuffer *)proc_st->pipeline_param->buffer;
106     struct object_surface *obj_dst_surf = NULL;
107     struct object_surface *obj_src_surf = NULL;
108
109     VAProcPipelineParameterBuffer pipeline_param2;
110     struct object_surface *stage1_dst_surf = NULL;
111     struct object_surface *stage2_dst_surf = NULL;
112     VARectangle src_rect, dst_rect;
113     VASurfaceID tmp_surfaces[2];
114     VASurfaceID out_surface_id1 = VA_INVALID_ID, out_surface_id2 = VA_INVALID_ID;
115     int num_tmp_surfaces = 0;
116
117     VAStatus status;
118
119     proc_ctx->pipeline_param = pipeline_param;
120
121     if (proc_st->current_render_target == VA_INVALID_SURFACE ||
122         pipeline_param->surface == VA_INVALID_SURFACE) {
123         status = VA_STATUS_ERROR_INVALID_SURFACE;
124         goto error;
125     }
126
127     obj_dst_surf = SURFACE(proc_st->current_render_target);
128
129     if (!obj_dst_surf) {
130         status = VA_STATUS_ERROR_INVALID_SURFACE;
131         goto error;
132     }
133
134     obj_src_surf = SURFACE(proc_ctx->pipeline_param->surface);
135
136     if (!obj_src_surf) {
137         status = VA_STATUS_ERROR_INVALID_SURFACE;
138         goto error;
139     }
140
141     if (!obj_src_surf->bo) {
142         status = VA_STATUS_ERROR_INVALID_VALUE; /* The input surface is created without valid content */
143         goto error;
144     }
145
146     if (pipeline_param->num_filters && !pipeline_param->filters) {
147         status = VA_STATUS_ERROR_INVALID_PARAMETER;
148         goto error;
149     }
150
151     if (!obj_dst_surf->bo) {
152         unsigned int is_tiled = 1;
153         unsigned int fourcc = VA_FOURCC_NV12;
154         int sampling = SUBSAMPLE_YUV420;
155         i965_check_alloc_surface_bo(ctx, obj_dst_surf, is_tiled, fourcc, sampling);
156     }  
157
158     proc_ctx->surface_render_output_object = obj_dst_surf;
159     proc_ctx->surface_pipeline_input_object = obj_src_surf;
160     assert(pipeline_param->num_filters <= 4);
161
162     int vpp_stage1 = 0, vpp_stage2 = 1, vpp_stage3 = 0;
163
164     if (pipeline_param->surface_region) {
165         src_rect.x = pipeline_param->surface_region->x;
166         src_rect.y = pipeline_param->surface_region->y;
167         src_rect.width = pipeline_param->surface_region->width;
168         src_rect.height = pipeline_param->surface_region->height;
169     } else {
170         src_rect.x = 0;
171         src_rect.y = 0;
172         src_rect.width = obj_src_surf->orig_width;
173         src_rect.height = obj_src_surf->orig_height;
174     }
175
176     if (pipeline_param->output_region) {
177         dst_rect.x = pipeline_param->output_region->x;
178         dst_rect.y = pipeline_param->output_region->y;
179         dst_rect.width = pipeline_param->output_region->width;
180         dst_rect.height = pipeline_param->output_region->height;
181     } else {
182         dst_rect.x = 0;
183         dst_rect.y = 0;
184         dst_rect.width = obj_dst_surf->orig_width;
185         dst_rect.height = obj_dst_surf->orig_height;
186     }
187
188     if(obj_src_surf->fourcc == VA_FOURCC_P010) {
189         vpp_stage1 = 1;
190         vpp_stage2 = 0;
191         vpp_stage3 = 0;
192         if(pipeline_param->num_filters == 0 || pipeline_param->filters == NULL) {
193             if(src_rect.x != dst_rect.x ||
194                 src_rect.y != dst_rect.y ||
195                 src_rect.width != dst_rect.width ||
196                 src_rect.height != dst_rect.height)
197               vpp_stage2 = 1;
198
199             if(obj_dst_surf->fourcc != VA_FOURCC_NV12 &&
200                 obj_dst_surf->fourcc != VA_FOURCC_P010)
201               vpp_stage2 = 1;
202         }
203         else
204           vpp_stage2 = 1;
205
206         if(vpp_stage2 == 1) {
207           if(obj_dst_surf->fourcc == VA_FOURCC_P010)
208             vpp_stage3 = 1;
209         }
210     }
211     else if(obj_dst_surf->fourcc == VA_FOURCC_P010) {
212         vpp_stage2 = 1;
213         vpp_stage3 = 1;
214
215         if((obj_src_surf->fourcc == VA_FOURCC_NV12) &&
216             (pipeline_param->num_filters == 0 || pipeline_param->filters == NULL)) {
217             if((src_rect.x == dst_rect.x) &&
218                 (src_rect.y == dst_rect.y) &&
219                 (src_rect.width == dst_rect.width) &&
220                 (src_rect.height == dst_rect.height))
221                 vpp_stage2 = 0;
222         }
223     }
224
225     if(vpp_stage1 == 1){
226         memset((void *)&pipeline_param2, 0, sizeof(pipeline_param2));
227         pipeline_param2.surface = pipeline_param->surface;
228         pipeline_param2.surface_region = &src_rect;
229         pipeline_param2.output_region = &src_rect;
230         pipeline_param2.filter_flags = 0;
231         pipeline_param2.num_filters  = 0;
232
233         proc_ctx->pipeline_param = &pipeline_param2;
234
235         if(vpp_stage2 == 1) {
236             status = i965_CreateSurfaces(ctx,
237                                          obj_src_surf->orig_width,
238                                          obj_src_surf->orig_height,
239                                          VA_RT_FORMAT_YUV420,
240                                          1,
241                                          &out_surface_id1);
242             assert(status == VA_STATUS_SUCCESS);
243             tmp_surfaces[num_tmp_surfaces++] = out_surface_id1;
244             stage1_dst_surf = SURFACE(out_surface_id1);
245             assert(stage1_dst_surf);
246             i965_check_alloc_surface_bo(ctx, stage1_dst_surf, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
247
248             proc_ctx->surface_render_output_object = stage1_dst_surf;
249         }
250
251         gen75_vpp_vebox(ctx, proc_ctx);
252     }
253
254     if((vpp_stage3 == 1) && (vpp_stage2 == 1)) {
255         status = i965_CreateSurfaces(ctx,
256                                      obj_dst_surf->orig_width,
257                                      obj_dst_surf->orig_height,
258                                      VA_RT_FORMAT_YUV420,
259                                      1,
260                                      &out_surface_id2);
261         assert(status == VA_STATUS_SUCCESS);
262         tmp_surfaces[num_tmp_surfaces++] = out_surface_id2;
263         stage2_dst_surf = SURFACE(out_surface_id2);
264         assert(stage2_dst_surf);
265         i965_check_alloc_surface_bo(ctx, stage2_dst_surf, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
266     }
267
268     VABufferID *filter_id = (VABufferID*) pipeline_param->filters;
269
270     if(vpp_stage2 == 1) {
271         if(stage1_dst_surf != NULL) {
272             proc_ctx->surface_pipeline_input_object = stage1_dst_surf;
273             proc_ctx->surface_render_output_object = obj_dst_surf;
274
275             pipeline_param->surface = out_surface_id1;
276         }
277
278         if(stage2_dst_surf != NULL) {
279             proc_ctx->surface_render_output_object = stage2_dst_surf;
280
281             proc_st->current_render_target = out_surface_id2;
282         }
283
284         proc_ctx->pipeline_param = pipeline_param;
285
286         if(pipeline_param->num_filters == 0 || pipeline_param->filters == NULL ){
287             /* implicity surface format coversion and scaling */
288
289             gen75_vpp_fmt_cvt(ctx, profile, codec_state, hw_context);
290         }else if(pipeline_param->num_filters == 1) {
291            struct object_buffer * obj_buf = BUFFER((*filter_id) + 0);
292
293            assert(obj_buf && obj_buf->buffer_store && obj_buf->buffer_store->buffer);
294
295            if (!obj_buf ||
296                !obj_buf->buffer_store ||
297                !obj_buf->buffer_store->buffer) {
298                status = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
299                goto error;
300            }
301
302            VAProcFilterParameterBuffer* filter =
303                (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
304
305            if (filter->type == VAProcFilterNoiseReduction         ||
306                filter->type == VAProcFilterDeinterlacing          ||
307                filter->type == VAProcFilterSkinToneEnhancement    ||
308                filter->type == VAProcFilterSharpening             ||
309                filter->type == VAProcFilterColorBalance){
310                gen75_vpp_vebox(ctx, proc_ctx);
311            }
312         }else if (pipeline_param->num_filters >= 2) {
313              unsigned int i = 0;
314              for (i = 0; i < pipeline_param->num_filters; i++){
315                  struct object_buffer * obj_buf = BUFFER(pipeline_param->filters[i]);
316
317                  if (!obj_buf ||
318                      !obj_buf->buffer_store ||
319                      !obj_buf->buffer_store->buffer) {
320                      status = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
321                      goto error;
322                  }
323
324                  VAProcFilterParameterBuffer* filter =
325                      (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
326
327                  if (filter->type != VAProcFilterNoiseReduction       &&
328                      filter->type != VAProcFilterDeinterlacing        &&
329                      filter->type != VAProcFilterSkinToneEnhancement  &&
330                      filter->type != VAProcFilterColorBalance) {
331                      fprintf(stderr, "Do not support multiply filters outside vebox pipeline \n");
332                      assert(0);
333                  }
334              }
335              gen75_vpp_vebox(ctx, proc_ctx);
336         }
337     }
338
339     if(vpp_stage3 == 1)
340     {
341         if(vpp_stage2 == 1) {
342             memset(&pipeline_param2, 0, sizeof(pipeline_param2));
343             pipeline_param2.surface = out_surface_id2;
344             pipeline_param2.surface_region = &dst_rect;
345             pipeline_param2.output_region = &dst_rect;
346             pipeline_param2.filter_flags = 0;
347             pipeline_param2.num_filters  = 0;
348
349             proc_ctx->pipeline_param = &pipeline_param2;
350             proc_ctx->surface_pipeline_input_object = proc_ctx->surface_render_output_object;
351             proc_ctx->surface_render_output_object = obj_dst_surf;
352         }
353
354         gen75_vpp_vebox(ctx, proc_ctx);
355     }
356
357     if (num_tmp_surfaces)
358         i965_DestroySurfaces(ctx,
359                              tmp_surfaces,
360                              num_tmp_surfaces);
361
362     return VA_STATUS_SUCCESS;
363
364 error:
365     if (num_tmp_surfaces)
366         i965_DestroySurfaces(ctx,
367                              tmp_surfaces,
368                              num_tmp_surfaces);
369
370     return status;
371 }
372
373 static void 
374 gen75_proc_context_destroy(void *hw_context)
375 {
376     struct intel_video_process_context *proc_ctx =
377                       (struct intel_video_process_context *)hw_context;
378     VADriverContextP ctx = (VADriverContextP)(proc_ctx->driver_context);
379
380     if(proc_ctx->vpp_fmt_cvt_ctx){
381         proc_ctx->vpp_fmt_cvt_ctx->destroy(proc_ctx->vpp_fmt_cvt_ctx);
382         proc_ctx->vpp_fmt_cvt_ctx = NULL;
383     }
384
385     if(proc_ctx->vpp_vebox_ctx){
386        gen75_vebox_context_destroy(ctx,proc_ctx->vpp_vebox_ctx);
387        proc_ctx->vpp_vebox_ctx = NULL;
388     }
389
390     free(proc_ctx);
391 }
392
393 struct hw_context * 
394 gen75_proc_context_init(VADriverContextP ctx, 
395                         struct object_config *obj_config)
396 {
397    struct intel_video_process_context *proc_context 
398            = calloc(1, sizeof(struct intel_video_process_context));
399
400     assert(proc_context);
401     proc_context->base.destroy = gen75_proc_context_destroy;
402     proc_context->base.run     = gen75_proc_picture;
403
404     proc_context->vpp_vebox_ctx    = NULL;
405     proc_context->vpp_fmt_cvt_ctx  = NULL;
406  
407     proc_context->driver_context = ctx;
408
409     return (struct hw_context *)proc_context;
410 }
411