OSDN Git Service

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