/* Programme the Alt output if there is a rotation*/ void vld_dec_setup_alternative_frame(object_context_p obj_context) { uint32_t cmd = 0; psb_cmdbuf_p cmdbuf = obj_context->cmdbuf; context_DEC_p ctx = (context_DEC_p) obj_context->format_data; psb_surface_p src_surface = obj_context->current_render_target->psb_surface; psb_surface_p out_loop_surface = obj_context->current_render_target->out_loop_surface; int ved_scaling = (CONTEXT_SCALING(obj_context) && !ctx->yuv_ctx); /* In VPP ctx, current_render_target is rotated surface */ if (ctx->yuv_ctx && (VAEntrypointVideoProc == obj_context->entry_point)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Setup second-pass rotation\n"); out_loop_surface = src_surface; src_surface = ctx->yuv_ctx->src_surface; } if (CONTEXT_ALTERNATIVE_OUTPUT(obj_context) || obj_context->entry_point == VAEntrypointVideoProc) { if (ved_scaling) { out_loop_surface = obj_context->current_render_target->scaling_surface; #ifndef BAYTRAIL tng_ved_write_scale_reg(obj_context); REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS,ALTERNATIVE_OUTPUT_PICTURE_ROTATION, SCALE_INPUT_SIZE_SEL, 1); REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS,ALTERNATIVE_OUTPUT_PICTURE_ROTATION, SCALE_ENABLE, 1); #endif } if (out_loop_surface == NULL) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "out-loop surface is NULL, abort msvdx alternative output\n"); return; } if (GET_SURFACE_INFO_rotate(out_loop_surface) != obj_context->msvdx_rotate && !ved_scaling) drv_debug_msg(VIDEO_DEBUG_WARNING, "Display rotate mode does not match surface rotate mode!\n"); /* CRendecBlock RendecBlk( mCtrlAlloc , RENDEC_REGISTER_OFFSET(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS) ); */ psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS)); psb_cmdbuf_rendec_write_address(cmdbuf, &out_loop_surface->buf, out_loop_surface->buf.buffer_ofs); psb_cmdbuf_rendec_write_address(cmdbuf, &out_loop_surface->buf, out_loop_surface->buf.buffer_ofs + out_loop_surface->chroma_offset); psb_cmdbuf_rendec_end(cmdbuf); REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ALT_PICTURE_ENABLE, 1); REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ROTATION_ROW_STRIDE, out_loop_surface->stride_mode); REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , RECON_WRITE_DISABLE, 0); /* FIXME Always generate Rec */ REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ROTATION_MODE, GET_SURFACE_INFO_rotate(out_loop_surface)); RELOC(*ctx->p_range_mapping_base0, out_loop_surface->buf.buffer_ofs, &out_loop_surface->buf); RELOC(*ctx->p_range_mapping_base1, out_loop_surface->buf.buffer_ofs + out_loop_surface->chroma_offset, &out_loop_surface->buf); } if (obj_context->profile == VAProfileVP8Version0_3 || obj_context->profile == VAProfileJPEGBaseline || ctx->yuv_ctx) { psb_cmdbuf_rendec_start(cmdbuf, (REG_MSVDX_CMD_OFFSET + MSVDX_CMDS_AUX_LINE_BUFFER_BASE_ADDRESS_OFFSET)); psb_cmdbuf_rendec_write_address(cmdbuf, &ctx->aux_line_buffer_vld, ctx->aux_line_buffer_vld.buffer_ofs); psb_cmdbuf_rendec_end(cmdbuf); REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, USE_AUX_LINE_BUF, 1); if (ctx->yuv_ctx) REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , RECON_WRITE_DISABLE, 1); } /* Set the rotation registers */ psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION)); psb_cmdbuf_rendec_write(cmdbuf, cmd); *ctx->alt_output_flags = cmd; cmd = 0; REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, EXTENDED_ROW_STRIDE, EXT_ROW_STRIDE, src_surface->stride / 64); psb_cmdbuf_rendec_write(cmdbuf, cmd); psb_cmdbuf_rendec_end(cmdbuf); }
/* * Create and attach a rotate surface to obj_surface */ VAStatus psb_CreateRotateSurface( object_context_p obj_context, object_surface_p obj_surface, int msvdx_rotate ) { int width, height; psb_surface_p rotate_surface = NULL; bool rotate_surfaceAlloc = false; VAStatus vaStatus = VA_STATUS_SUCCESS; int need_realloc = 0; unsigned int flags = 0; psb_surface_share_info_p share_info = obj_surface->share_info; psb_driver_data_p driver_data = obj_context->driver_data; int rotate_stride = 0, rotate_tiling = 0; object_config_p obj_config = CONFIG(obj_context->config_id); unsigned char * surface_data; CHECK_CONFIG(obj_config); rotate_surface = obj_surface->out_loop_surface; if (msvdx_rotate == 0 #ifdef OVERLAY_ENABLE_MIRROR /*Bypass 180 degree rotate when overlay enabling mirror*/ || msvdx_rotate == VA_ROTATION_180 #endif ) return vaStatus; if (rotate_surface) { CHECK_SURFACE_REALLOC(rotate_surface, msvdx_rotate, need_realloc); if (need_realloc == 0) { goto exit; } else { /* free the old rotate surface */ /*FIX ME: it is not safe to do that because surfaces may be in use for rendering.*/ psb_surface_destroy(obj_surface->out_loop_surface); memset(rotate_surface, 0, sizeof(*rotate_surface)); } } else { rotate_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); CHECK_ALLOCATION(rotate_surface); rotate_surfaceAlloc = true; } #ifdef PSBVIDEO_MSVDX_DEC_TILING SET_SURFACE_INFO_tiling(rotate_surface, GET_SURFACE_INFO_tiling(obj_surface->psb_surface)); #endif #ifdef PSBVIDEO_MRFL_VPP_ROTATE SET_SURFACE_INFO_rotate(rotate_surface, msvdx_rotate); #endif drv_debug_msg(VIDEO_DEBUG_GENERAL, "Try to allocate surface for alternative rotate output\n"); flags = IS_ROTATED; if (msvdx_rotate == 2 /* VA_ROTATION_180 */) { width = obj_surface->width; height = obj_surface->height; #ifdef PSBVIDEO_MRFL_VPP_ROTATE if (obj_config->entrypoint == VAEntrypointVideoProc && share_info && share_info->out_loop_khandle) { vaStatus = psb_surface_create_from_kbuf(driver_data, width, height, obj_surface->psb_surface->size, VA_FOURCC_NV12, share_info->out_loop_khandle, obj_surface->psb_surface->stride, obj_surface->psb_surface->stride, obj_surface->psb_surface->stride, 0, 0, 0, rotate_surface); } else #endif vaStatus = psb_surface_create(driver_data, width, height, VA_FOURCC_NV12, flags, rotate_surface); } else { width = obj_surface->height_origin; height = (obj_surface->width + 0x1f) & ~0x1f; #ifdef PSBVIDEO_MRFL_VPP_ROTATE if (obj_config->entrypoint == VAEntrypointVideoProc && share_info && share_info->out_loop_khandle != 0) { drv_debug_msg(VIDEO_DEBUG_GENERAL,"Create the surface from kbuf out_loop_khandle=%x!\n", share_info->out_loop_khandle); rotate_tiling = GET_SURFACE_INFO_tiling(rotate_surface); rotate_stride = get_surface_stride(width, rotate_tiling); vaStatus = psb_surface_create_from_kbuf(driver_data, width, height, (rotate_stride * height * 3) / 2, VA_FOURCC_NV12, share_info->out_loop_khandle, rotate_stride, rotate_stride, rotate_stride, 0, rotate_stride * height, rotate_stride * height, rotate_surface); } else #endif { drv_debug_msg(VIDEO_DEBUG_GENERAL,"Create rotated buffer. width=%d, height=%d\n", width, height); if (CONTEXT_SCALING(obj_context)) { width = obj_context->scaling_buffer_height; height = (obj_context->scaling_buffer_width+ 0x1f) & ~0x1f; } vaStatus = psb_surface_create(driver_data, width, height, VA_FOURCC_NV12, flags, rotate_surface); } } if (VA_STATUS_SUCCESS != vaStatus) { free(rotate_surface); obj_surface->out_loop_surface = NULL; vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; return vaStatus; } //clear rotation surface if (CONTEXT_SCALING(obj_context)) { if (psb_buffer_map(&rotate_surface->buf, &surface_data)) { drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to map rotation buffer before clear it"); } else { memset(surface_data, 0, rotate_surface->chroma_offset); memset(surface_data + rotate_surface->chroma_offset, 0x80, rotate_surface->size - rotate_surface->chroma_offset); psb_buffer_unmap(&rotate_surface->buf); } } obj_surface->width_r = width; obj_surface->height_r = height; #ifdef PSBVIDEO_MSVDX_DEC_TILING drv_debug_msg(VIDEO_DEBUG_GENERAL, "attempt to update tile context\n"); if (GET_SURFACE_INFO_tiling(rotate_surface) && obj_config->entrypoint != VAEntrypointVideoProc) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "update tile context\n"); object_context_p obj_context = CONTEXT(obj_surface->context_id); if (NULL == obj_context) { vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT; DEBUG_FAILURE; if (rotate_surface != NULL && rotate_surfaceAlloc) { free(rotate_surface); rotate_surface = NULL; } return vaStatus; } unsigned long msvdx_tile = psb__tile_stride_log2_256(obj_surface->width_r); obj_context->msvdx_tile &= 0xf; /* clear rotate tile */ obj_context->msvdx_tile |= (msvdx_tile << 4); obj_context->ctp_type &= (~PSB_CTX_TILING_MASK); /* clear tile context */ obj_context->ctp_type |= ((obj_context->msvdx_tile & 0xff) << 16); psb_update_context(driver_data, obj_context->ctp_type); } #endif exit: obj_surface->out_loop_surface = rotate_surface; SET_SURFACE_INFO_rotate(rotate_surface, msvdx_rotate); /* derive the protected flag from the primay surface */ SET_SURFACE_INFO_protect(rotate_surface, GET_SURFACE_INFO_protect(obj_surface->psb_surface)); /*notify hwc that rotated buffer is ready to use. * TODO: Do these in psb_SyncSurface() */ if (share_info != NULL) { share_info->width_r = rotate_surface->stride; share_info->height_r = obj_surface->height_r; share_info->out_loop_khandle = (uint32_t)(wsbmKBufHandle(wsbmKBuf(rotate_surface->buf.drm_buf))); share_info->metadata_rotate = VAROTATION2HAL(driver_data->va_rotate); share_info->surface_rotate = VAROTATION2HAL(msvdx_rotate); share_info->out_loop_luma_stride = rotate_surface->stride; share_info->out_loop_chroma_u_stride = rotate_surface->stride; share_info->out_loop_chroma_v_stride = rotate_surface->stride; } return vaStatus; }