OSDN Git Service

Add the 10bit-scaling conversion for I010 format
[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 /* The Bit 2 is used to indicate that it is 10bit or 8bit.
205  * The Bit 0/1 is used to indicate the 420/422/444 format
206  */
207 #define SRC_10BIT_420    (5 << 0)
208 #define SRC_10BIT_422    (6 << 0)
209 #define SRC_10BIT_444    (7 << 0)
210
211 /* The Bit 6 is used to indicate that it is 10bit or 8bit.
212  * The Bit 5/4 is used to indicate the 420/422/444 format
213  */
214 #define DST_10BIT_420    (5 << 4)
215 #define DST_10BIT_422    (6 << 4)
216 #define DST_10BIT_444    (7 << 4)
217
218 /* This is mainly for YUY2/RGBA. It is reserved for further */
219 #define SRC_YUV_PACKED   (1 << 3)
220 #define DST_YUV_PACKED   (1 << 7)
221
222 #define MASK_CSC         (0xFF)
223 #define SCALE_10BIT_420  (SRC_10BIT_420 | DST_10BIT_420)
224
225         unsigned int scale_flag;
226
227         scale_flag = 0;
228         if (obj_src_surf->fourcc == VA_FOURCC_P010 ||
229             obj_src_surf->fourcc == VA_FOURCC_I010)
230             scale_flag |= SRC_10BIT_420;
231
232         if (obj_dst_surf->fourcc == VA_FOURCC_P010 ||
233             obj_dst_surf->fourcc == VA_FOURCC_I010)
234             scale_flag |= DST_10BIT_420;
235
236         /* If P010 is converted without resolution change,
237          * fall back to VEBOX
238          */
239         if (i965->intel.has_vebox &&
240             (obj_src_surf->fourcc == VA_FOURCC_P010) &&
241             (obj_dst_surf->fourcc == VA_FOURCC_P010) &&
242             (src_rect.width == dst_rect.width) &&
243             (src_rect.height == dst_rect.height))
244             scale_flag = 0;
245
246         if (((scale_flag & MASK_CSC) == SCALE_10BIT_420) &&
247             intel_gpe_support_10bit_scaling(proc_ctx)) {
248             struct i965_proc_context *gpe_proc_ctx;
249             struct i965_surface src_surface, dst_surface;
250             unsigned int tmp_width, tmp_x;
251
252
253             src_surface.base = (struct object_base *)obj_src_surf;
254             src_surface.type = I965_SURFACE_TYPE_SURFACE;
255             dst_surface.base = (struct object_base *)obj_dst_surf;
256             dst_surface.type = I965_SURFACE_TYPE_SURFACE;
257             gpe_proc_ctx = (struct i965_proc_context *)proc_ctx->vpp_fmt_cvt_ctx;
258
259             tmp_x = ALIGN_FLOOR(dst_rect.x, 2);
260             tmp_width = dst_rect.x + dst_rect.width;
261             tmp_width = tmp_width - tmp_x;
262             dst_rect.x = tmp_x;
263             dst_rect.width = tmp_width;
264
265             return gen9_p010_scaling_post_processing(ctx, &gpe_proc_ctx->pp_context,
266                                                      &src_surface, &src_rect,
267                                                      &dst_surface, &dst_rect);
268         }
269     }
270
271     proc_ctx->surface_render_output_object = obj_dst_surf;
272     proc_ctx->surface_pipeline_input_object = obj_src_surf;
273     assert(pipeline_param->num_filters <= 4);
274
275     int vpp_stage1 = 0, vpp_stage2 = 1, vpp_stage3 = 0;
276
277
278     if(obj_src_surf->fourcc == VA_FOURCC_P010) {
279         vpp_stage1 = 1;
280         vpp_stage2 = 0;
281         vpp_stage3 = 0;
282         if(pipeline_param->num_filters == 0 || pipeline_param->filters == NULL) {
283             if(src_rect.x != dst_rect.x ||
284                 src_rect.y != dst_rect.y ||
285                 src_rect.width != dst_rect.width ||
286                 src_rect.height != dst_rect.height)
287               vpp_stage2 = 1;
288
289             if(obj_dst_surf->fourcc != VA_FOURCC_NV12 &&
290                 obj_dst_surf->fourcc != VA_FOURCC_P010)
291               vpp_stage2 = 1;
292         }
293         else
294           vpp_stage2 = 1;
295
296         if(vpp_stage2 == 1) {
297           if(obj_dst_surf->fourcc == VA_FOURCC_P010)
298             vpp_stage3 = 1;
299         }
300     }
301     else if(obj_dst_surf->fourcc == VA_FOURCC_P010) {
302         vpp_stage2 = 1;
303         vpp_stage3 = 1;
304
305         if((obj_src_surf->fourcc == VA_FOURCC_NV12) &&
306             (pipeline_param->num_filters == 0 || pipeline_param->filters == NULL)) {
307             if((src_rect.x == dst_rect.x) &&
308                 (src_rect.y == dst_rect.y) &&
309                 (src_rect.width == dst_rect.width) &&
310                 (src_rect.height == dst_rect.height))
311                 vpp_stage2 = 0;
312         }
313     }
314
315     if(vpp_stage1 == 1){
316         memset((void *)&pipeline_param2, 0, sizeof(pipeline_param2));
317         pipeline_param2.surface = pipeline_param->surface;
318         pipeline_param2.surface_region = &src_rect;
319         pipeline_param2.output_region = &src_rect;
320         pipeline_param2.filter_flags = 0;
321         pipeline_param2.num_filters  = 0;
322
323         proc_ctx->pipeline_param = &pipeline_param2;
324
325         if(vpp_stage2 == 1) {
326             status = i965_CreateSurfaces(ctx,
327                                          obj_src_surf->orig_width,
328                                          obj_src_surf->orig_height,
329                                          VA_RT_FORMAT_YUV420,
330                                          1,
331                                          &out_surface_id1);
332             assert(status == VA_STATUS_SUCCESS);
333             tmp_surfaces[num_tmp_surfaces++] = out_surface_id1;
334             stage1_dst_surf = SURFACE(out_surface_id1);
335             assert(stage1_dst_surf);
336             i965_check_alloc_surface_bo(ctx, stage1_dst_surf, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
337
338             proc_ctx->surface_render_output_object = stage1_dst_surf;
339         }
340
341         gen75_vpp_vebox(ctx, proc_ctx);
342     }
343
344     if((vpp_stage3 == 1) && (vpp_stage2 == 1)) {
345         status = i965_CreateSurfaces(ctx,
346                                      obj_dst_surf->orig_width,
347                                      obj_dst_surf->orig_height,
348                                      VA_RT_FORMAT_YUV420,
349                                      1,
350                                      &out_surface_id2);
351         assert(status == VA_STATUS_SUCCESS);
352         tmp_surfaces[num_tmp_surfaces++] = out_surface_id2;
353         stage2_dst_surf = SURFACE(out_surface_id2);
354         assert(stage2_dst_surf);
355         i965_check_alloc_surface_bo(ctx, stage2_dst_surf, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
356     }
357
358     VABufferID *filter_id = (VABufferID*) pipeline_param->filters;
359
360     if(vpp_stage2 == 1) {
361         if(stage1_dst_surf != NULL) {
362             proc_ctx->surface_pipeline_input_object = stage1_dst_surf;
363             proc_ctx->surface_render_output_object = obj_dst_surf;
364
365             pipeline_param->surface = out_surface_id1;
366         }
367
368         if(stage2_dst_surf != NULL) {
369             proc_ctx->surface_render_output_object = stage2_dst_surf;
370
371             proc_st->current_render_target = out_surface_id2;
372         }
373
374         proc_ctx->pipeline_param = pipeline_param;
375
376         if(pipeline_param->num_filters == 0 || pipeline_param->filters == NULL ){
377             /* implicity surface format coversion and scaling */
378
379             status = gen75_vpp_fmt_cvt(ctx, profile, codec_state, hw_context);
380             if(status != VA_STATUS_SUCCESS)
381                 goto error;
382         }else if(pipeline_param->num_filters == 1) {
383            struct object_buffer * obj_buf = BUFFER((*filter_id) + 0);
384
385            assert(obj_buf && obj_buf->buffer_store && obj_buf->buffer_store->buffer);
386
387            if (!obj_buf ||
388                !obj_buf->buffer_store ||
389                !obj_buf->buffer_store->buffer) {
390                status = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
391                goto error;
392            }
393
394            VAProcFilterParameterBuffer* filter =
395                (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
396
397            if (filter->type == VAProcFilterNoiseReduction         ||
398                filter->type == VAProcFilterDeinterlacing          ||
399                filter->type == VAProcFilterSkinToneEnhancement    ||
400                filter->type == VAProcFilterSharpening             ||
401                filter->type == VAProcFilterColorBalance){
402                gen75_vpp_vebox(ctx, proc_ctx);
403            }
404         }else if (pipeline_param->num_filters >= 2) {
405              unsigned int i = 0;
406              for (i = 0; i < pipeline_param->num_filters; i++){
407                  struct object_buffer * obj_buf = BUFFER(pipeline_param->filters[i]);
408
409                  if (!obj_buf ||
410                      !obj_buf->buffer_store ||
411                      !obj_buf->buffer_store->buffer) {
412                      status = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
413                      goto error;
414                  }
415
416                  VAProcFilterParameterBuffer* filter =
417                      (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
418
419                  if (filter->type != VAProcFilterNoiseReduction       &&
420                      filter->type != VAProcFilterDeinterlacing        &&
421                      filter->type != VAProcFilterSkinToneEnhancement  &&
422                      filter->type != VAProcFilterColorBalance) {
423                      fprintf(stderr, "Do not support multiply filters outside vebox pipeline \n");
424                      assert(0);
425                  }
426              }
427              gen75_vpp_vebox(ctx, proc_ctx);
428         }
429     }
430
431     if(vpp_stage3 == 1)
432     {
433         if(vpp_stage2 == 1) {
434             memset(&pipeline_param2, 0, sizeof(pipeline_param2));
435             pipeline_param2.surface = out_surface_id2;
436             pipeline_param2.surface_region = &dst_rect;
437             pipeline_param2.output_region = &dst_rect;
438             pipeline_param2.filter_flags = 0;
439             pipeline_param2.num_filters  = 0;
440
441             proc_ctx->pipeline_param = &pipeline_param2;
442             proc_ctx->surface_pipeline_input_object = proc_ctx->surface_render_output_object;
443             proc_ctx->surface_render_output_object = obj_dst_surf;
444         }
445
446         gen75_vpp_vebox(ctx, proc_ctx);
447     }
448
449     if (num_tmp_surfaces)
450         i965_DestroySurfaces(ctx,
451                              tmp_surfaces,
452                              num_tmp_surfaces);
453
454     return VA_STATUS_SUCCESS;
455
456 error:
457     if (num_tmp_surfaces)
458         i965_DestroySurfaces(ctx,
459                              tmp_surfaces,
460                              num_tmp_surfaces);
461
462     return status;
463 }
464
465 static void 
466 gen75_proc_context_destroy(void *hw_context)
467 {
468     struct intel_video_process_context *proc_ctx =
469                       (struct intel_video_process_context *)hw_context;
470     VADriverContextP ctx = (VADriverContextP)(proc_ctx->driver_context);
471
472     if(proc_ctx->vpp_fmt_cvt_ctx){
473         proc_ctx->vpp_fmt_cvt_ctx->destroy(proc_ctx->vpp_fmt_cvt_ctx);
474         proc_ctx->vpp_fmt_cvt_ctx = NULL;
475     }
476
477     if(proc_ctx->vpp_vebox_ctx){
478        gen75_vebox_context_destroy(ctx,proc_ctx->vpp_vebox_ctx);
479        proc_ctx->vpp_vebox_ctx = NULL;
480     }
481
482     free(proc_ctx);
483 }
484
485 struct hw_context * 
486 gen75_proc_context_init(VADriverContextP ctx, 
487                         struct object_config *obj_config)
488 {
489    struct intel_video_process_context *proc_context 
490            = calloc(1, sizeof(struct intel_video_process_context));
491
492     assert(proc_context);
493     proc_context->base.destroy = gen75_proc_context_destroy;
494     proc_context->base.run     = gen75_proc_picture;
495
496     proc_context->vpp_vebox_ctx    = NULL;
497     proc_context->vpp_fmt_cvt_ctx  = NULL;
498  
499     proc_context->driver_context = ctx;
500
501     return (struct hw_context *)proc_context;
502 }
503