summaryrefslogtreecommitdiff
path: root/src/pnw_rotate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pnw_rotate.c')
-rw-r--r--src/pnw_rotate.c284
1 files changed, 284 insertions, 0 deletions
diff --git a/src/pnw_rotate.c b/src/pnw_rotate.c
new file mode 100644
index 0000000..082f811
--- /dev/null
+++ b/src/pnw_rotate.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Zeng Li <zeng.li@intel.com>
+ * Jason Hu <jason.hu@intel.com>
+ * Shengquan Yuan <shengquan.yuan@intel.com>
+ */
+
+#include <va/va.h>
+#include <va/va_backend.h>
+#include <va/va_backend_tpi.h>
+#include <va/va_backend_egl.h>
+#include <va/va_dricommon.h>
+
+#include "psb_drv_video.h"
+#include "psb_output.h"
+#include "vc1_defs.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <unistd.h>
+#include <wsbm/wsbm_pool.h>
+#include <wsbm/wsbm_manager.h>
+#include <wsbm/wsbm_util.h>
+#include <wsbm/wsbm_fencemgr.h>
+
+#define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData
+
+#define SET_SURFACE_INFO_rotate(psb_surface, rotate) psb_surface->extra_info[5] = (uint32_t) rotate;
+#define GET_SURFACE_INFO_rotate(psb_surface) ((int) psb_surface->extra_info[5])
+#define CHECK_SURFACE_REALLOC(psb_surface, msvdx_rotate, need) \
+do { \
+ int old_rotate = GET_SURFACE_INFO_rotate(psb_surface); \
+ switch (msvdx_rotate) { \
+ case 2: /* 180 */ \
+ if (old_rotate == 180) \
+ need = 0; \
+ else \
+ need = 1; \
+ break; \
+ case 1: /* 90 */ \
+ case 3: /* 270 */ \
+ if (old_rotate == 1 || old_rotate == 3) \
+ need = 0; \
+ else \
+ need = 1; \
+ break; \
+ } \
+} while (0)
+
+void psb_InitRotate(VADriverContextP ctx)
+{
+ char env_value[64];
+ INIT_DRIVER_DATA;
+
+ /* VA rotate from APP */
+ driver_data->va_rotate = VA_ROTATION_NONE;
+
+ /* window manager rotation from OS */
+ driver_data->mipi0_rotation = VA_ROTATION_NONE;
+ driver_data->mipi1_rotation = VA_ROTATION_NONE;
+ driver_data->hdmi_rotation = VA_ROTATION_NONE;
+
+ /* final rotation of VA rotate+WM rotate */
+ driver_data->local_rotation = VA_ROTATION_NONE;
+ driver_data->extend_rotation = VA_ROTATION_NONE;
+
+ /* MSVDX rotate */
+ driver_data->msvdx_rotate_want = ROTATE_VA2MSVDX(VA_ROTATION_NONE);
+
+ if (psb_parse_config("PSB_VIDEO_NOROTATE", &env_value[0]) == 0) {
+ psb__information_message("MSVDX: disable MSVDX rotation\n");
+ driver_data->disable_msvdx_rotate = 1;
+ }
+}
+
+void psb_RecalcRotate(VADriverContextP ctx)
+{
+ INIT_DRIVER_DATA;
+ int angle, new_rotate;
+ int old_rotate = driver_data->msvdx_rotate_want;
+
+ /* calc VA rotation and WM rotation, and assign to the final rotation degree */
+ angle = Rotation2Angle(driver_data->va_rotate) + Rotation2Angle(driver_data->mipi0_rotation);
+ driver_data->local_rotation = Angle2Rotation(angle);
+ angle = Rotation2Angle(driver_data->va_rotate) + Rotation2Angle(driver_data->hdmi_rotation);
+ driver_data->extend_rotation = Angle2Rotation(angle);
+
+ /* for any case that local and extened rotation are not same, fallback to GPU */
+ if ((driver_data->mipi1_rotation != VA_ROTATION_NONE) ||
+ ((driver_data->local_rotation != VA_ROTATION_NONE) &&
+ (driver_data->extend_rotation != VA_ROTATION_NONE) &&
+ (driver_data->local_rotation != driver_data->extend_rotation))) {
+ new_rotate = ROTATE_VA2MSVDX(driver_data->local_rotation);
+ if (driver_data->is_android == 0) /*fallback to texblit path*/
+ driver_data->output_method = PSB_PUTSURFACE_CTEXTURE;
+ } else {
+ if (driver_data->local_rotation == VA_ROTATION_NONE)
+ new_rotate = driver_data->extend_rotation;
+ else
+ new_rotate = driver_data->local_rotation;
+
+ if (driver_data->is_android == 0) {
+ if (driver_data->output_method != PSB_PUTSURFACE_FORCE_CTEXTURE)
+ driver_data->output_method = PSB_PUTSURFACE_COVERLAY;
+ }
+ }
+
+ if (old_rotate != new_rotate) {
+ psb__information_message("MSVDX: new rotation %d desired\n", new_rotate);
+ driver_data->msvdx_rotate_want = new_rotate;
+ }
+
+}
+
+
+void psb_CheckInterlaceRotate(object_context_p obj_context, unsigned char *pic_param_tmp)
+{
+ int interaced_stream;
+
+ switch (obj_context->profile) {
+ case VAProfileMPEG2Simple:
+ case VAProfileMPEG2Main:
+ break;
+ case VAProfileMPEG4Simple:
+ case VAProfileMPEG4AdvancedSimple:
+ case VAProfileMPEG4Main:
+ case VAProfileH263Baseline: {
+ VAPictureParameterBufferMPEG4 *pic_params = (VAPictureParameterBufferMPEG4 *)pic_param_tmp;
+
+ if (pic_params->vol_fields.bits.interlaced)
+ obj_context->interlaced_stream = 1; /* is it the right way to check? */
+ break;
+ }
+ case VAProfileH264Baseline:
+ case VAProfileH264Main:
+ case VAProfileH264High:
+ case VAProfileH264ConstrainedBaseline: {
+ VAPictureParameterBufferH264 *pic_params = (VAPictureParameterBufferH264 *)pic_param_tmp;
+ /* is it the right way to check? */
+ if (pic_params->pic_fields.bits.field_pic_flag || pic_params->seq_fields.bits.mb_adaptive_frame_field_flag)
+ obj_context->interlaced_stream = 1;
+
+ break;
+ }
+ case VAProfileVC1Simple:
+ case VAProfileVC1Main:
+ case VAProfileVC1Advanced: {
+ VAPictureParameterBufferVC1 *pic_params = (VAPictureParameterBufferVC1 *)pic_param_tmp;
+
+ /* is it the right way to check? */
+ if (pic_params->sequence_fields.bits.interlace && (pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FLDI))
+ obj_context->interlaced_stream = 1;
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (obj_context->interlaced_stream) {
+ object_surface_p obj_surface = obj_context->current_render_target;
+
+ psb__information_message("Intelaced stream, no MSVDX rotate\n");
+
+ SET_SURFACE_INFO_rotate(obj_surface->psb_surface, 0);
+ obj_context->msvdx_rotate = 0;
+ }
+}
+
+
+/*
+ * Detach a surface from obj_surface
+ */
+VAStatus psb_DestroyRotateSurface(
+ VADriverContextP ctx,
+ object_surface_p obj_surface,
+ int rotate
+)
+{
+ INIT_DRIVER_DATA;
+ psb_surface_p psb_surface = obj_surface->psb_surface_rotate;
+ VAStatus vaStatus = VA_STATUS_SUCCESS;
+
+ /* Allocate alternative output surface */
+ if (psb_surface) {
+ psb__information_message("Try to allocate surface for alternative rotate output\n");
+ psb_surface_destroy(obj_surface->psb_surface_rotate);
+ free(psb_surface);
+
+ obj_surface->psb_surface_rotate = NULL;
+ obj_surface->width_r = obj_surface->width;
+ obj_surface->height_r = obj_surface->height;
+ }
+
+ return vaStatus;
+}
+
+/*
+ * Create and attach a rotate surface to obj_surface
+ */
+VAStatus psb_CreateRotateSurface(
+ VADriverContextP ctx,
+ object_surface_p obj_surface,
+ int msvdx_rotate
+)
+{
+ int width, height;
+ psb_surface_p psb_surface;
+ VAStatus vaStatus = VA_STATUS_SUCCESS;
+ int need_realloc = 0, protected = 0;
+
+ INIT_DRIVER_DATA;
+
+ psb_surface = obj_surface->psb_surface_rotate;
+ if (psb_surface) {
+ CHECK_SURFACE_REALLOC(psb_surface, msvdx_rotate, need_realloc);
+ if (need_realloc == 0) {
+ SET_SURFACE_INFO_rotate(psb_surface, msvdx_rotate);
+ return VA_STATUS_SUCCESS;
+ } else { /* free the old rotate surface */
+ /*FIX ME: No sync mechanism to hold surface buffer b/w msvdx and display(overlay).
+ So Disable dynamic surface destroy/create for avoiding buffer corruption.
+ psb_surface_destroy(obj_surface->psb_surface_rotate);
+ memset(psb_surface, 0, sizeof(*psb_surface));*/
+ return VA_STATUS_SUCCESS;
+ }
+ } else
+ psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
+
+ psb__information_message("Try to allocate surface for alternative rotate output\n");
+
+ width = obj_surface->width;
+ height = obj_surface->height;
+
+ if (msvdx_rotate == 2 /* VA_ROTATION_180 */) {
+ vaStatus = psb_surface_create(driver_data, width, height, VA_FOURCC_NV12,
+ protected, psb_surface);
+ obj_surface->width_r = width;
+ obj_surface->height_r = height;
+ } else {
+ vaStatus = psb_surface_create(driver_data, obj_surface->height_origin, ((width + 0x1f) & ~0x1f), VA_FOURCC_NV12,
+ protected, psb_surface);
+ obj_surface->width_r = obj_surface->height_origin;
+ obj_surface->height_r = ((width + 0x1f) & ~0x1f);
+ }
+
+ if (VA_STATUS_SUCCESS != vaStatus) {
+ free(psb_surface);
+ obj_surface->psb_surface_rotate = NULL;
+ vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
+ DEBUG_FAILURE;
+ return vaStatus;
+ }
+
+ SET_SURFACE_INFO_rotate(psb_surface, msvdx_rotate);
+ obj_surface->psb_surface_rotate = psb_surface;
+
+ return vaStatus;
+}
+
+