2 * Copyright © 2011 Intel Corporation
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:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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.
25 * Li Xiaowei <xiaowei.a.li@intel.com>
33 #include "intel_batchbuffer.h"
34 #include "intel_driver.h"
35 #include "i965_defines.h"
36 #include "i965_structs.h"
38 #include "i965_drv_video.h"
39 #include "i965_post_processing.h"
40 #include "gen75_picture_process.h"
41 #include "gen8_post_processing.h"
43 extern struct hw_context *
44 i965_proc_context_init(VADriverContextP ctx,
45 struct object_config *obj_config);
48 gen75_vpp_fmt_cvt(VADriverContextP ctx,
50 union codec_state *codec_state,
51 struct hw_context *hw_context)
53 VAStatus va_status = VA_STATUS_SUCCESS;
54 struct intel_video_process_context *proc_ctx =
55 (struct intel_video_process_context *)hw_context;
57 va_status = i965_proc_picture(ctx, profile, codec_state,
58 proc_ctx->vpp_fmt_cvt_ctx);
64 gen75_vpp_vebox(VADriverContextP ctx,
65 struct intel_video_process_context* proc_ctx)
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);
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);
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;
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);
90 static int intel_gpe_support_10bit_scaling(struct intel_video_process_context *proc_ctx)
92 struct i965_proc_context *gpe_proc_ctx;
94 if (!proc_ctx || !proc_ctx->vpp_fmt_cvt_ctx)
97 gpe_proc_ctx = (struct i965_proc_context *)proc_ctx->vpp_fmt_cvt_ctx;
99 if (gpe_proc_ctx->pp_context.scaling_context_initialized)
106 gen75_proc_picture(VADriverContextP ctx,
108 union codec_state *codec_state,
109 struct hw_context *hw_context)
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;
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;
130 proc_ctx->pipeline_param = pipeline_param;
132 if (proc_st->current_render_target == VA_INVALID_SURFACE ||
133 pipeline_param->surface == VA_INVALID_SURFACE) {
134 status = VA_STATUS_ERROR_INVALID_SURFACE;
138 obj_dst_surf = SURFACE(proc_st->current_render_target);
141 status = VA_STATUS_ERROR_INVALID_SURFACE;
145 obj_src_surf = SURFACE(proc_ctx->pipeline_param->surface);
148 status = VA_STATUS_ERROR_INVALID_SURFACE;
152 if (!obj_src_surf->bo) {
153 status = VA_STATUS_ERROR_INVALID_VALUE; /* The input surface is created without valid content */
157 if (pipeline_param->num_filters && !pipeline_param->filters) {
158 status = VA_STATUS_ERROR_INVALID_PARAMETER;
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);
168 if (!obj_dst_surf->bo) {
169 unsigned int is_tiled = 1;
170 unsigned int fourcc = VA_FOURCC_NV12;
171 int sampling = SUBSAMPLE_YUV420;
173 if (obj_dst_surf->expected_format == VA_RT_FORMAT_YUV420_10BPP)
174 fourcc = VA_FOURCC_P010;
176 i965_check_alloc_surface_bo(ctx, obj_dst_surf, is_tiled, fourcc, sampling);
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;
187 src_rect.width = obj_src_surf->orig_width;
188 src_rect.height = obj_src_surf->orig_height;
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;
199 dst_rect.width = obj_dst_surf->orig_width;
200 dst_rect.height = obj_dst_surf->orig_height;
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
207 #define SRC_10BIT_420 (5 << 0)
208 #define SRC_10BIT_422 (6 << 0)
209 #define SRC_10BIT_444 (7 << 0)
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
214 #define DST_10BIT_420 (5 << 4)
215 #define DST_10BIT_422 (6 << 4)
216 #define DST_10BIT_444 (7 << 4)
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)
222 #define MASK_CSC (0xFF)
223 #define SCALE_10BIT_420 (SRC_10BIT_420 | DST_10BIT_420)
225 unsigned int scale_flag;
228 if (obj_src_surf->fourcc == VA_FOURCC_P010 ||
229 obj_src_surf->fourcc == VA_FOURCC_I010)
230 scale_flag |= SRC_10BIT_420;
232 if (obj_dst_surf->fourcc == VA_FOURCC_P010 ||
233 obj_dst_surf->fourcc == VA_FOURCC_I010)
234 scale_flag |= DST_10BIT_420;
236 /* If P010 is converted without resolution change,
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))
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;
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;
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;
263 dst_rect.width = tmp_width;
265 return gen9_p010_scaling_post_processing(ctx, &gpe_proc_ctx->pp_context,
266 &src_surface, &src_rect,
267 &dst_surface, &dst_rect);
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);
275 int vpp_stage1 = 0, vpp_stage2 = 1, vpp_stage3 = 0;
278 if(obj_src_surf->fourcc == VA_FOURCC_P010) {
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)
289 if(obj_dst_surf->fourcc != VA_FOURCC_NV12 &&
290 obj_dst_surf->fourcc != VA_FOURCC_P010)
296 if(vpp_stage2 == 1) {
297 if(obj_dst_surf->fourcc == VA_FOURCC_P010)
301 else if(obj_dst_surf->fourcc == VA_FOURCC_P010) {
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))
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;
323 proc_ctx->pipeline_param = &pipeline_param2;
325 if(vpp_stage2 == 1) {
326 status = i965_CreateSurfaces(ctx,
327 obj_src_surf->orig_width,
328 obj_src_surf->orig_height,
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);
338 proc_ctx->surface_render_output_object = stage1_dst_surf;
341 gen75_vpp_vebox(ctx, proc_ctx);
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,
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);
358 VABufferID *filter_id = (VABufferID*) pipeline_param->filters;
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;
365 pipeline_param->surface = out_surface_id1;
368 if(stage2_dst_surf != NULL) {
369 proc_ctx->surface_render_output_object = stage2_dst_surf;
371 proc_st->current_render_target = out_surface_id2;
374 proc_ctx->pipeline_param = pipeline_param;
376 if(pipeline_param->num_filters == 0 || pipeline_param->filters == NULL ){
377 /* implicity surface format coversion and scaling */
379 status = gen75_vpp_fmt_cvt(ctx, profile, codec_state, hw_context);
380 if(status != VA_STATUS_SUCCESS)
382 }else if(pipeline_param->num_filters == 1) {
383 struct object_buffer * obj_buf = BUFFER((*filter_id) + 0);
385 assert(obj_buf && obj_buf->buffer_store && obj_buf->buffer_store->buffer);
388 !obj_buf->buffer_store ||
389 !obj_buf->buffer_store->buffer) {
390 status = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
394 VAProcFilterParameterBuffer* filter =
395 (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
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);
404 }else if (pipeline_param->num_filters >= 2) {
406 for (i = 0; i < pipeline_param->num_filters; i++){
407 struct object_buffer * obj_buf = BUFFER(pipeline_param->filters[i]);
410 !obj_buf->buffer_store ||
411 !obj_buf->buffer_store->buffer) {
412 status = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
416 VAProcFilterParameterBuffer* filter =
417 (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
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");
427 gen75_vpp_vebox(ctx, proc_ctx);
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;
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;
446 gen75_vpp_vebox(ctx, proc_ctx);
449 if (num_tmp_surfaces)
450 i965_DestroySurfaces(ctx,
454 return VA_STATUS_SUCCESS;
457 if (num_tmp_surfaces)
458 i965_DestroySurfaces(ctx,
466 gen75_proc_context_destroy(void *hw_context)
468 struct intel_video_process_context *proc_ctx =
469 (struct intel_video_process_context *)hw_context;
470 VADriverContextP ctx = (VADriverContextP)(proc_ctx->driver_context);
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;
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;
486 gen75_proc_context_init(VADriverContextP ctx,
487 struct object_config *obj_config)
489 struct intel_video_process_context *proc_context
490 = calloc(1, sizeof(struct intel_video_process_context));
492 assert(proc_context);
493 proc_context->base.destroy = gen75_proc_context_destroy;
494 proc_context->base.run = gen75_proc_picture;
496 proc_context->vpp_vebox_ctx = NULL;
497 proc_context->vpp_fmt_cvt_ctx = NULL;
499 proc_context->driver_context = ctx;
501 return (struct hw_context *)proc_context;