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"
42 #include "intel_gen_vppapi.h"
44 extern struct hw_context *
45 i965_proc_context_init(VADriverContextP ctx,
46 struct object_config *obj_config);
49 gen75_vpp_fmt_cvt(VADriverContextP ctx,
51 union codec_state *codec_state,
52 struct hw_context *hw_context)
54 VAStatus va_status = VA_STATUS_SUCCESS;
55 struct intel_video_process_context *proc_ctx =
56 (struct intel_video_process_context *)hw_context;
58 va_status = i965_proc_picture(ctx, profile, codec_state,
59 proc_ctx->vpp_fmt_cvt_ctx);
65 gen75_vpp_vebox(VADriverContextP ctx,
66 struct intel_video_process_context* proc_ctx)
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);
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);
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;
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);
91 static int intel_gpe_support_10bit_scaling(struct intel_video_process_context *proc_ctx)
93 struct i965_proc_context *gpe_proc_ctx;
95 if (!proc_ctx || !proc_ctx->vpp_fmt_cvt_ctx)
98 gpe_proc_ctx = (struct i965_proc_context *)proc_ctx->vpp_fmt_cvt_ctx;
100 if (gpe_proc_ctx->pp_context.scaling_context_initialized)
107 rgb_to_yuv(unsigned int argb,
113 int r = ((argb >> 16) & 0xff);
114 int g = ((argb >> 8) & 0xff);
115 int b = ((argb >> 0) & 0xff);
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);
124 gen8plus_vpp_clear_surface(VADriverContextP ctx,
125 struct i965_post_processing_context *pp_context,
126 struct object_surface *obj_surface,
129 struct intel_batchbuffer *batch = pp_context->batch;
130 unsigned int blt_cmd, br13;
131 unsigned int tiling = 0, swizzle = 0;
133 unsigned char y, u, v, a = 0;
134 int region_width, region_height;
136 /* Currently only support NV12 surface */
137 if (!obj_surface || obj_surface->fourcc != VA_FOURCC_NV12)
140 rgb_to_yuv(color, &y, &u, &v, &a);
145 dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
146 blt_cmd = GEN8_XY_COLOR_BLT_CMD;
147 pitch = obj_surface->width;
149 if (tiling != I915_TILING_NONE) {
150 assert(tiling == I915_TILING_Y);
151 // blt_cmd |= XY_COLOR_BLT_DST_TILED;
159 intel_batchbuffer_start_atomic_blt(batch, 56);
160 BEGIN_BLT_BATCH(batch, 14);
162 region_width = obj_surface->width;
163 region_height = obj_surface->height;
165 OUT_BATCH(batch, blt_cmd);
166 OUT_BATCH(batch, br13);
171 region_height << 16 |
173 OUT_RELOC64(batch, obj_surface->bo,
174 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
182 region_width = obj_surface->width / 2;
183 region_height = obj_surface->height / 2;
185 if (tiling == I915_TILING_Y) {
186 region_height = ALIGN(obj_surface->height / 2, 32);
189 OUT_BATCH(batch, blt_cmd);
190 OUT_BATCH(batch, br13);
195 region_height << 16 |
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);
202 ADVANCE_BATCH(batch);
203 intel_batchbuffer_end_atomic(batch);
207 gen75_proc_picture(VADriverContextP ctx,
209 union codec_state *codec_state,
210 struct hw_context *hw_context)
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;
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;
231 proc_ctx->pipeline_param = pipeline_param;
233 if (proc_st->current_render_target == VA_INVALID_SURFACE ||
234 pipeline_param->surface == VA_INVALID_SURFACE) {
235 status = VA_STATUS_ERROR_INVALID_SURFACE;
239 obj_dst_surf = SURFACE(proc_st->current_render_target);
242 status = VA_STATUS_ERROR_INVALID_SURFACE;
246 obj_src_surf = SURFACE(proc_ctx->pipeline_param->surface);
249 status = VA_STATUS_ERROR_INVALID_SURFACE;
253 if (!obj_src_surf->bo) {
254 status = VA_STATUS_ERROR_INVALID_VALUE; /* The input surface is created without valid content */
258 if (pipeline_param->num_filters && !pipeline_param->filters) {
259 status = VA_STATUS_ERROR_INVALID_PARAMETER;
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);
269 if (!obj_dst_surf->bo) {
270 unsigned int is_tiled = 1;
271 unsigned int fourcc = VA_FOURCC_NV12;
272 int sampling = SUBSAMPLE_YUV420;
274 if (obj_dst_surf->expected_format == VA_RT_FORMAT_YUV420_10BPP)
275 fourcc = VA_FOURCC_P010;
277 i965_check_alloc_surface_bo(ctx, obj_dst_surf, is_tiled, fourcc, sampling);
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;
288 src_rect.width = obj_src_surf->orig_width;
289 src_rect.height = obj_src_surf->orig_height;
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;
300 dst_rect.width = obj_dst_surf->orig_width;
301 dst_rect.height = obj_dst_surf->orig_height;
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
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)
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
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)
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)
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)
329 unsigned int scale_flag;
332 if (obj_src_surf->fourcc == VA_FOURCC_P010 ||
333 obj_src_surf->fourcc == VA_FOURCC_I010)
334 scale_flag |= SRC_10BIT_420;
336 if (obj_dst_surf->fourcc == VA_FOURCC_P010 ||
337 obj_dst_surf->fourcc == VA_FOURCC_I010)
338 scale_flag |= DST_10BIT_420;
340 if (obj_src_surf->fourcc == VA_FOURCC_NV12 ||
341 obj_src_surf->fourcc == VA_FOURCC_I420)
342 scale_flag |= SRC_8BIT_420;
344 if (obj_dst_surf->fourcc == VA_FOURCC_NV12 ||
345 obj_dst_surf->fourcc == VA_FOURCC_I420)
346 scale_flag |= DST_8BIT_420;
348 /* If P010 is converted without resolution change,
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))
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;
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;
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;
375 dst_rect.width = tmp_width;
377 return gen9_p010_scaling_post_processing(ctx, &gpe_proc_ctx->pp_context,
378 &src_surface, &src_rect,
379 &dst_surface, &dst_rect);
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;
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;
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;
398 dst_rect.width = tmp_width;
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,
404 pipeline_param->output_background_color);
406 return intel_yuv420p8_scaling_post_processing(ctx, &gpe_proc_ctx->pp_context,
407 &src_surface, &src_rect,
408 &dst_surface, &dst_rect);
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);
416 int vpp_stage1 = 0, vpp_stage2 = 1, vpp_stage3 = 0;
419 if(obj_src_surf->fourcc == VA_FOURCC_P010) {
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)
430 if(obj_dst_surf->fourcc != VA_FOURCC_NV12 &&
431 obj_dst_surf->fourcc != VA_FOURCC_P010)
437 if(vpp_stage2 == 1) {
438 if(obj_dst_surf->fourcc == VA_FOURCC_P010)
442 else if(obj_dst_surf->fourcc == VA_FOURCC_P010) {
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))
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;
464 proc_ctx->pipeline_param = &pipeline_param2;
466 if(vpp_stage2 == 1) {
467 status = i965_CreateSurfaces(ctx,
468 obj_src_surf->orig_width,
469 obj_src_surf->orig_height,
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);
479 proc_ctx->surface_render_output_object = stage1_dst_surf;
482 gen75_vpp_vebox(ctx, proc_ctx);
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,
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);
499 VABufferID *filter_id = (VABufferID*) pipeline_param->filters;
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;
506 pipeline_param->surface = out_surface_id1;
509 if(stage2_dst_surf != NULL) {
510 proc_ctx->surface_render_output_object = stage2_dst_surf;
512 proc_st->current_render_target = out_surface_id2;
515 proc_ctx->pipeline_param = pipeline_param;
517 if(pipeline_param->num_filters == 0 || pipeline_param->filters == NULL ){
518 /* implicity surface format coversion and scaling */
520 status = gen75_vpp_fmt_cvt(ctx, profile, codec_state, hw_context);
521 if(status != VA_STATUS_SUCCESS)
523 }else if(pipeline_param->num_filters == 1) {
524 struct object_buffer * obj_buf = BUFFER((*filter_id) + 0);
526 assert(obj_buf && obj_buf->buffer_store && obj_buf->buffer_store->buffer);
529 !obj_buf->buffer_store ||
530 !obj_buf->buffer_store->buffer) {
531 status = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
535 VAProcFilterParameterBuffer* filter =
536 (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
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);
545 }else if (pipeline_param->num_filters >= 2) {
547 for (i = 0; i < pipeline_param->num_filters; i++){
548 struct object_buffer * obj_buf = BUFFER(pipeline_param->filters[i]);
551 !obj_buf->buffer_store ||
552 !obj_buf->buffer_store->buffer) {
553 status = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
557 VAProcFilterParameterBuffer* filter =
558 (VAProcFilterParameterBuffer*)obj_buf-> buffer_store->buffer;
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");
568 gen75_vpp_vebox(ctx, proc_ctx);
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;
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;
587 gen75_vpp_vebox(ctx, proc_ctx);
590 if (num_tmp_surfaces)
591 i965_DestroySurfaces(ctx,
595 return VA_STATUS_SUCCESS;
598 if (num_tmp_surfaces)
599 i965_DestroySurfaces(ctx,
607 gen75_proc_context_destroy(void *hw_context)
609 struct intel_video_process_context *proc_ctx =
610 (struct intel_video_process_context *)hw_context;
611 VADriverContextP ctx = (VADriverContextP)(proc_ctx->driver_context);
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;
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;
627 gen75_proc_context_init(VADriverContextP ctx,
628 struct object_config *obj_config)
630 struct intel_video_process_context *proc_context
631 = calloc(1, sizeof(struct intel_video_process_context));
633 assert(proc_context);
634 proc_context->base.destroy = gen75_proc_context_destroy;
635 proc_context->base.run = gen75_proc_picture;
637 proc_context->vpp_vebox_ctx = NULL;
638 proc_context->vpp_fmt_cvt_ctx = NULL;
640 proc_context->driver_context = ctx;
642 return (struct hw_context *)proc_context;