diff options
Diffstat (limited to 'packages/mplayer/files/vo_w100.c')
-rw-r--r-- | packages/mplayer/files/vo_w100.c | 947 |
1 files changed, 947 insertions, 0 deletions
diff --git a/packages/mplayer/files/vo_w100.c b/packages/mplayer/files/vo_w100.c new file mode 100644 index 0000000000..702707c656 --- /dev/null +++ b/packages/mplayer/files/vo_w100.c @@ -0,0 +1,947 @@ +/* + * Video driver for ATI Imageon 100 (w100) + * by AGAWA Koji <i (AT) atty (DOT) jp> + * (C) 2004 + */ +/* English in this source code is written by machine translation. + Meaning also not leading, permitting. */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "config.h" +#include "video_out.h" +#include "video_out_internal.h" +#include "sub.h" +#include "aspect.h" +#include "mp_msg.h" +#include "subopt-helper.h" + +#include "vo_w100_api.h" +#include "vo_w100_fb.h" + +#define UNUSED(v) ((void)(v)) + +static vo_info_t info = { + "ATI Imageon 100", + "w100", + "AGAWA Koji <i (AT) atty (DOT) jp>", + "for Sharp Linux Zaurus SL-C700/750/760/860" +}; + +LIBVO_EXTERN(w100); + +// ---------------------------------------------------------------- +#define MAX_FRAMES 20 +typedef struct vidix_yuv_s +{ + unsigned y,u,v; +}vidix_yuv_t; + +typedef struct vidix_rect_s +{ + unsigned x,y,w,h; /* in pixels */ + vidix_yuv_t pitch; /* line-align in bytes */ +}vidix_rect_t; + +typedef struct w100_yuv_planes_s { + uint8_t *y; + uint8_t *u; + uint8_t *v; +} w100_yuv_planes_t; + +typedef struct w100_priv_s { + uint32_t format; + int src_width; + int src_height; + int nframes; /* total num of frames */ + int current_frame; /* current frame to display */ + int rotate; + int current_rotate; + + /* w100 info */ + int vram_size[2]; /* */ + void *vram_addr[2]; /* address */ + w100_yuv_planes_t frame_addrs[MAX_FRAMES]; + w100_yuv_planes_t frame_offsets[MAX_FRAMES]; + int is_graphic_window_enabled; + int eq_brightness; /* for mplayer */ + int display_brightness; /* for w100 */ + + /* overlay info */ + uint16_t overlay_handle; + ATI_OVERLAYPROP overlay_prop; + int overlay_pos_x; + int overlay_pos_y; + int overlay_expand_h; + int overlay_expand_v; + int overlay_pitch_y; + int overlay_pitch_u; + int overlay_pitch_v; + video_y_offset_u video_y_offset; + video_u_offset_u video_u_offset; + video_v_offset_u video_v_offset; +} w100_priv_t; + +static w100_priv_t st_w100_priv; +static vidix_yuv_t dstrides; + +static int test_rotate(int *arg) +{ + if ((*arg < -1) || (*arg > 3)) + return 0; + return 1; +} + +static opt_t subopts[] = { + { "rotate", OPT_ARG_INT, &st_w100_priv.rotate, (opt_test_f)test_rotate }, + { NULL } +}; + +static void draw_alpha(int x0,int y0, int w,int h, + unsigned char* src, unsigned char *srca, int stride) +{ + w100_priv_t *priv = &st_w100_priv; + uint8_t *psrc, *psrca, *pdst; + pdst = priv->frame_addrs[priv->current_frame].y; + pdst += (x0 * priv->overlay_prop.SrcPitch) + (priv->overlay_prop.SrcPitch - 1 - y0); + psrc = src; + psrca = srca; + while (h--) { + int j; + for (j = 0; j < w; ++j) { + if (psrca[j]) + pdst[j * priv->overlay_prop.SrcPitch] = + ((pdst[j * priv->overlay_prop.SrcPitch] * psrca[j]) >> 8) + psrc[j]; + } + psrc += stride; + psrca += stride; + pdst -= 1; + } +#if 0 + w100_priv_t *priv = &st_w100_priv; + uint32_t apitch, bespitch; + void *lvo_mem; + lvo_mem = priv->frame_addrs[priv->current_frame].y; + apitch = priv->overlay_pitch_y - 1; + switch (priv->format) { + case IMGFMT_YV12: + case IMGFMT_IYUV: + case IMGFMT_I420: + case IMGFMT_YVU9: + case IMGFMT_IF09: + case IMGFMT_Y8: + case IMGFMT_Y800: + bespitch = (priv->src_width + apitch) & (~apitch); + vo_draw_alpha_yv12(w,h,src,srca,stride,lvo_mem+bespitch*y0+x0,bespitch); + break; + case IMGFMT_YUY2: + bespitch = (priv->src_width*2 + apitch) & (~apitch); + vo_draw_alpha_yuy2(w,h,src,srca,stride,lvo_mem+bespitch*y0+2*x0,bespitch); + break; + case IMGFMT_UYVY: + bespitch = (priv->src_width*2 + apitch) & (~apitch); + vo_draw_alpha_yuy2(w,h,src,srca,stride,lvo_mem+bespitch*y0+2*x0+1,bespitch); + break; + case IMGFMT_RGB32: + case IMGFMT_BGR32: + bespitch = (priv->src_width*4 + apitch) & (~apitch); + vo_draw_alpha_rgb32(w,h,src,srca,stride,lvo_mem+y0*bespitch+4*x0,bespitch); + break; + case IMGFMT_RGB24: + case IMGFMT_BGR24: + bespitch = (priv->src_width*3 + apitch) & (~apitch); + vo_draw_alpha_rgb24(w,h,src,srca,stride,lvo_mem+y0*bespitch+3*x0,bespitch); + break; + case IMGFMT_RGB16: + case IMGFMT_BGR16: + bespitch = (priv->src_width*2 + apitch) & (~apitch); + vo_draw_alpha_rgb16(w,h,src,srca,stride,lvo_mem+y0*bespitch+2*x0,bespitch); + break; + case IMGFMT_RGB15: + case IMGFMT_BGR15: + bespitch = (priv->src_width*2 + apitch) & (~apitch); + vo_draw_alpha_rgb15(w,h,src,srca,stride,lvo_mem+y0*bespitch+2*x0,bespitch); + break; + default: + return; + } +#endif +} + +static uint32_t w100_draw_slice_420(uint8_t *image[], int stride[], + int w, int h, int x, int y) +{ + w100_priv_t *priv = &st_w100_priv; + uint8_t *src; + uint8_t *dest; + int i; + + /* Plane Y */ + dest = priv->frame_addrs[priv->current_frame].y; + dest += dstrides.y * y + x; + src = image[0]; + for (i = 0; i < h; ++i) { + memcpy(dest, src, w); + src += stride[0]; + dest += dstrides.y; + } + + /* Plane V */ + dest = priv->frame_addrs[priv->current_frame].u; + dest += dstrides.v * y / 4 + x; + src = image[1]; + for (i = 0; i < h / 2; ++i) { + memcpy(dest, src, w / 2); + src += stride[1]; + dest += dstrides.v / 2; + } + + /* Plane U */ + dest = priv->frame_addrs[priv->current_frame].v; + dest += dstrides.u * y / 4 + x; + src = image[2]; + for (i = 0; i < h / 2; ++i) { + memcpy(dest, src, w / 2); + src += stride[2]; + dest += dstrides.u / 2; + } + + return 0; +} + +/* + w must be multiple of 8 + */ +static uint32_t w100_draw_slice_420_rotate3(uint8_t *image[], int stride[], + int w, int h, int x, int y) +{ + w100_priv_t *priv = &st_w100_priv; + void *src, *dest; + int i, dpitch2, h_; + + h_ = h; + + for (i = 0; i < 3; ++i) { + src = image[i]; + switch (i) { + case 0: + dest = priv->frame_addrs[priv->current_frame].y; + dest += dstrides.y * x + dstrides.y - y; + dpitch2 = dstrides.y << 1; + break; + case 1: + dest = priv->frame_addrs[priv->current_frame].u; + dest += (dstrides.y >> 1) * (x >> 1) + (dstrides.y >> 1) - (y >> 1); + dpitch2 = dstrides.y; + h = h_ >> 1; + w >>= 1; + break; + case 2: + dest = priv->frame_addrs[priv->current_frame].v; + dest += (dstrides.y >> 1) * (x >> 1) + (dstrides.y >> 1) - (y >> 1); + h = h_ >> 1; + dpitch2 = dstrides.y; + break; + } + + __asm__ __volatile__ ( + "1: \n\t" + "mov r8, %[w] \n\t" + "sub %[dest], %[dest], #1 \n\t" + "mov r4, %[dest] \n\t" + "add r5, %[dest], %[dpitch2], lsr #1 \n\t" + + "2: \n\t" + "ldrb r0, [%[src]] \n\t" + "ldrb r1, [%[src], #1] \n\t" + "add %[src], %[src], #2 \n\t" + "strb r0, [r4] \n\t" + "strb r1, [r5] \n\t" + "add r4, r4, %[dpitch2] \n\t" + "add r5, r5, %[dpitch2] \n\t" + "ldrb r0, [%[src]] \n\t" + "ldrb r1, [%[src], #1] \n\t" + "add %[src], %[src], #2 \n\t" + "strb r0, [r4] \n\t" + "strb r1, [r5] \n\t" + "add r4, r4, %[dpitch2] \n\t" + "add r5, r5, %[dpitch2] \n\t" + "subs r8, r8, #4 \n\t" + "bne 2b \n\t" + + "add %[src], %[src], %[srcdiff] \n\t" + "subs %[h], %[h], #1 \n\t" + "bne 1b \n\t" + : [src]"+r"(src), [dest]"+r"(dest), [h]"+r"(h) + : [dpitch2]"r"(dpitch2), [w]"r"(w), [srcdiff]"r"(stride[i] - w) + : "memory", "r0", "r1", "r4", "r5", "r8"); + } +} + +static uint32_t w100_draw_slice_packed(uint8_t *image[], int stride[], + int w, int h, int x, int y) +{ +#if 0 + uint8_t *src; + uint8_t *dest; + int i; + + dest = st_w100_mem + vidix_play.offsets[st_next_frame] + vidix_play.offset.y; + dest += dstrides.y * y + x; + src = image[0]; + for (i = 0; i < h; ++i) { + memcpy(dest, src, w * st_image_bpp); + src += stride[0]; + dest += dstrides.y; + } +#endif + return 0; +} + +static uint32_t w100_get_image(mp_image_t *mpi) +{ +#if 0 + mp_msg(MSGT_VO, MSGL_V, "vo_w100: w100_get_image called.\n"); + + if (mpi->type == MP_IMGTYPE_STATIC && st_num_frames > 1) + return VO_FALSE; + if (mpi->flags & MP_IMGFLAG_READABLE) + return VO_FALSE; /* slow video ram */ + if (((mpi->stride[0] == dstrides.y && + (!(mpi->flags & MP_IMGFLAG_PLANAR) || + (mpi->stride[1] == dstrides.u && mpi->stride[2]==dstrides.v))) + || (mpi->flags & (MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_ACCEPT_WIDTH))) && + (!(vidix_play.flags & VID_PLAY_INTERLEAVED_UV))) { + if (mpi->flags & MP_IMGFLAG_ACCEPT_WIDTH) { + // check if only width is enough to represent strides: + if (mpi->flags & MP_IMGFLAG_PLANAR) { + if ((dstrides.y >> 1) != dstrides.v || dstrides.v != dstrides.u) + return VO_FALSE; + } else { + if (dstrides.y % (mpi->bpp / 8)) + return VO_FALSE; + } + } + mpi->planes[0] = st_w100_mem + vidix_play.offsets[st_next_frame] + + vidix_play.offset.y; + mpi->width = mpi->stride[0] = dstrides.y; + if (mpi->flags & MP_IMGFLAG_PLANAR) { + mpi->planes[1] = st_w100_mem + vidix_play.offsets[st_next_frame] + + vidix_play.offset.v; + mpi->stride[1] = dstrides.v >> mpi->chroma_x_shift; + mpi->planes[2] = st_w100_mem + vidix_play.offsets[st_next_frame] + + vidix_play.offset.u; + mpi->stride[2] = dstrides.u >> mpi->chroma_x_shift; + } else + mpi->width /= mpi->bpp / 8; + mpi->flags |= MP_IMGFLAG_DIRECT; + return VO_TRUE; + } +#endif + return VO_FALSE; +} + +static void w100_set_yuv_addrs(w100_priv_t *priv, w100_yuv_planes_t *offsets) +{ + uint32_t val; + + priv->video_y_offset.f.y_offset = GetRealMemAddr((uint32_t)offsets->y); + priv->video_u_offset.f.u_offset = GetRealMemAddr((uint32_t)offsets->u); + priv->video_v_offset.f.v_offset = GetRealMemAddr((uint32_t)offsets->v); + AtiCore_WriteReg(mmVIDEO_Y_OFFSET, (uint32_t *)&priv->video_y_offset); + AtiCore_WriteReg(mmVIDEO_U_OFFSET, (uint32_t *)&priv->video_u_offset); + AtiCore_WriteReg(mmVIDEO_V_OFFSET, (uint32_t *)&priv->video_v_offset); + + val = 0x7B; + AtiCore_WriteReg(mmDISP_DB_BUF_CNTL, &val); +} + +static void w100_set_overlay_expand(w100_priv_t *priv, int exp_h, int exp_v) +{ + video_ctrl_u video_ctrl; + + priv->overlay_expand_h = exp_h; + priv->overlay_expand_v = exp_v; + + AtiCore_ReadReg(mmVIDEO_CTRL, (uint32_t *)&video_ctrl); + video_ctrl.f.video_hor_exp = exp_h; + video_ctrl.f.video_ver_exp = exp_v; + AtiCore_WriteReg(mmVIDEO_CTRL, (uint32_t *)&video_ctrl); +} + +static int w100_setup(w100_priv_t *priv) +{ + if (!AtiCore_AllocOverlay(&priv->overlay_handle)) { + mp_msg(MSGT_VO, MSGL_FATAL, + "vo_w100: AtiCore_AllocOverlay failed.\n"); + return 0; + } + if (!AtiCore_SetupOverlay(priv->overlay_handle, &priv->overlay_prop)) { + mp_msg(MSGT_VO, MSGL_FATAL, + "vo_w100: AtiCore_SetupOverlay failed.\n"); + return 0; + } + AtiCore_SetOverlayPos(priv->overlay_handle, + priv->overlay_pos_x, priv->overlay_pos_y); + AtiCore_SetOverlayOnOff(priv->overlay_handle, 1); + w100_set_yuv_addrs(priv, &priv->frame_offsets[priv->current_frame]); + w100_set_overlay_expand(priv, priv->overlay_expand_h, priv->overlay_expand_v); + AtiCore_SetDisplayBrightness(priv->display_brightness); + AtiCore_SetGraphicWindowOnOff(priv->is_graphic_window_enabled); + +/* graphic_ctrl_t gc; */ +/* AtiCore_ReadReg(mmGRAPHIC_CTRL, &gc); */ +/* gc.low_power_on = 0; */ +/* AtiCore_WriteReg(mmGRAPHIC_CTRL, &gc); */ + + return 1; +} + +static void *w100_offset2addr(uint32_t offset) +{ + void *addr; + AtiCore_SetupMemoryTransfer((uint32_t)offset, &addr); + AtiCore_TerminateMemoryTransfer(); + return addr; +} + +// ---------------------------------------------------------------- interfaces +/* + * Preinitializes driver (real INITIALIZATION) + * arg - currently it's vo_subdevice + * returns: zero on successful initialization, non-zero on error. + */ +static int preinit(const char *vo_subdevice) +{ + w100_priv_t *priv = &st_w100_priv; + + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: preinit() was called\n"); + + if (!AtiCore_ProcessAttach()) + return -1; + + /* fill w100_priv_t information */ + memset(priv, 0, sizeof(*priv)); + priv->rotate = -1; + + if (subopt_parse(vo_subdevice, subopts) != 0) { + return -1; + } + + priv->is_graphic_window_enabled = 1; + priv->eq_brightness = 0; /* FIXME */ + + GetAvailableVideoMem(&priv->vram_size[INTERNAL_VRAM], + &priv->vram_size[EXTERNAL_VRAM]); + mp_msg(MSGT_VO, MSGL_V, "vo_w100: VRAM size %dKB/%dKB\n", + priv->vram_size[INTERNAL_VRAM] / 1024, + priv->vram_size[EXTERNAL_VRAM] / 1024); + + priv->vram_addr[INTERNAL_VRAM] = w100_offset2addr(VRAM_OFFSET_INTERNAL); + priv->vram_addr[EXTERNAL_VRAM] = w100_offset2addr(VRAM_OFFSET_EXTERNAL); + mp_msg(MSGT_VO, MSGL_V, "vo_w100: VRAM address 0x%08x/0x%08x\n", + priv->vram_addr[INTERNAL_VRAM], priv->vram_addr[EXTERNAL_VRAM]); + + lcd_background_color_u lbc; + lbc.f.lcd_bg_red = 0; + lbc.f.lcd_bg_green = 0; + lbc.f.lcd_bg_blue = 0; + AtiCore_WriteReg(mmLCD_BACKGROUND_COLOR, &lbc); + + return 0; +} + +/* + * Initialize (means CONFIGURE) the display driver. + * params: + * src_width,srcheight: image source size + * dst_width,dst_height: size of the requested window size, just a hint + * fullscreen: flag, 0=windowd 1=fullscreen, just a hint + * title: window title, if available + * format: fourcc of pixel format + * returns : zero on successful initialization, non-zero on error. + */ +static int config(uint32_t src_width, uint32_t src_height, + uint32_t dst_width, uint32_t dst_height, uint32_t flags, + char *title, uint32_t format) +{ + w100_priv_t *priv = &st_w100_priv; + int fs = flags & VOFLAG_FULLSCREEN; + int vm = flags & VOFLAG_MODESWITCHING; + int zoom = flags & VOFLAG_SWSCALE; + int y_pitch, uv_pitch; + int x_res = 480, y_res = 640; + uint32_t apitch; + int i; + uint32_t plane_flags = 0; + + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: config() was called\n"); + mp_msg(MSGT_VO, MSGL_V, "vo_w100: src_width:%d, src_height:%d, dst_width:%d, dst_height:%d\n", + src_width, src_height, dst_width, dst_height); + + if (!query_format(format)) { + printf("vo_w100: unsupported fourcc for this w100 driver: %x (%s)\n", + format, vo_format_name(format)); + return -1; + } + priv->format = format; + + // rotate + if (priv->rotate < 0) { + if (src_width > src_height) { + priv->current_rotate = 3; + } else { + priv->current_rotate = 0; + } + } else + priv->current_rotate = priv->rotate; + if (priv->current_rotate != 0 && priv->current_rotate != 3) { + mp_msg(MSGT_VO, MSGL_FATAL, "vo_w100: Rotate %d not supported\n", priv->current_rotate); + return -1; + } + + if (priv->current_rotate == 1 || priv->current_rotate == 3) { + i = src_width; + src_width = src_height; + src_height = i; + } + + dst_width = src_width; + dst_height = src_height; + + if (fs) { + int arg[] = { 0, 0, 1, 1, 2, 2, 2, 2, 3 }; + int arg2[] = { 1, 2, 4, 8 }; + int hor_exp = x_res / src_width; + int ver_exp = y_res / (src_height - 32); + int expand; + mp_msg(MSGT_VO, MSGL_V, "vo_w100: hor_exp:%d, ver_exp:%d\n", + hor_exp, ver_exp); + if ((hor_exp > 0 && hor_exp <= 8 && arg[hor_exp] >= 0) && + (ver_exp > 0 && ver_exp <= 8 && arg[ver_exp] >= 0)) { + if (arg[hor_exp] > arg[ver_exp]) + expand = arg[ver_exp]; + else + expand = arg[hor_exp]; + } + priv->overlay_expand_h = priv->overlay_expand_v = expand; + dst_width *= arg2[expand]; + dst_height *= arg2[expand]; + if (dst_height > y_res) + dst_height = y_res; + } + + // 表示領域をセンタリング + priv->overlay_pos_x = (x_res - dst_width) / 2; + priv->overlay_pos_y = (y_res - dst_height) / 2; + + // Hardware scaling + geometry(&priv->overlay_pos_x, &priv->overlay_pos_y, + &dst_width, &dst_height, x_res, y_res); + mp_msg(MSGT_VO, MSGL_V, "vo_w100: overlay pos(%d, %d)\n", + priv->overlay_pos_x, priv->overlay_pos_y); + mp_msg(MSGT_VO, MSGL_V, "vo_w100: src size(%dx%d), dst size(%dx%d)\n", + src_width, src_height, dst_width, dst_height); + + /* select first frame */ + priv->current_frame = 0; + + priv->src_width = src_width; + priv->src_height = src_height; + priv->overlay_pitch_y = 16; + priv->overlay_pitch_u = 16; + priv->overlay_pitch_v = 16; + + switch (format) { + case IMGFMT_YV12: + case IMGFMT_IYUV: + case IMGFMT_I420: + case IMGFMT_YVU9: + case IMGFMT_IF09: + case IMGFMT_Y8: + case IMGFMT_Y800: + y_pitch = (src_width + 15) & ~15; + uv_pitch = ((src_width / 2) + 7) & ~7; + break; + default: + return -1; + } + + /* サーフェイスが内蔵VRAMに収まらない場合は、V-Planeを外部VRAMに追い出す。 */ + if (y_pitch * src_height + uv_pitch * src_height > priv->vram_size[INTERNAL_VRAM]) + plane_flags = 4; + + if (vo_doublebuffering) { + if (y_pitch * src_height + uv_pitch * src_height * 2> priv->vram_size[INTERNAL_VRAM]) + plane_flags = 4; + } + + /* 外部VRAMにプレーンを置いた場合は、Graphic windowを切らないと画像が乱れる */ +/* priv->is_graphic_window_enabled = (plane_flags != 0) ? 0 : 1; */ + priv->is_graphic_window_enabled = 0; + + uint32_t p[2] = { + VRAM_OFFSET_INTERNAL, + VRAM_OFFSET_EXTERNAL + 640 * 480 * 2 + }; + i = 0; + while (i < MAX_FRAMES) { + int sel, j; + /* Y-plane */ + sel = plane_flags & 1 ? EXTERNAL_VRAM : INTERNAL_VRAM; + priv->frame_offsets[i].y = (void *)p[sel]; + priv->frame_addrs[i].y = w100_offset2addr(p[sel]); + p[sel] += y_pitch * src_height; + /* U-plane */ + sel = plane_flags & 2 ? EXTERNAL_VRAM : INTERNAL_VRAM; + priv->frame_offsets[i].u = (void *)p[sel]; + priv->frame_addrs[i].u = w100_offset2addr(p[sel]); + p[sel] += uv_pitch * (src_height / 2); + /* V-plane */ + sel = plane_flags & 4 ? EXTERNAL_VRAM : INTERNAL_VRAM; + priv->frame_offsets[i].v = (void *)p[sel]; + priv->frame_addrs[i].v = w100_offset2addr(p[sel]); + p[sel] += uv_pitch * (src_height / 2); + if ((p[INTERNAL_VRAM] - VRAM_OFFSET_INTERNAL >= priv->vram_size[INTERNAL_VRAM]) || + (p[EXTERNAL_VRAM] - VRAM_OFFSET_EXTERNAL >= priv->vram_size[EXTERNAL_VRAM])) + break; + mp_msg(MSGT_VO, MSGL_V, "vo_w100: frame_offsets[%d].y = 0x%08x\n", i, priv->frame_offsets[i].y); + mp_msg(MSGT_VO, MSGL_V, "vo_w100: frame_offsets[%d].u = 0x%08x\n", i, priv->frame_offsets[i].u); + mp_msg(MSGT_VO, MSGL_V, "vo_w100: frame_offsets[%d].v = 0x%08x\n", i, priv->frame_offsets[i].v); + ++i; + } + priv->nframes = i; + if (priv->nframes > MAX_FRAMES) + priv->nframes = MAX_FRAMES; + mp_msg(MSGT_VO, MSGL_V, "vo_w100: nframes = %d\n", priv->nframes); + + priv->overlay_prop.lpSrcBitmap = (void *)(priv->frame_offsets[0].y); + priv->overlay_prop.XCoord = 0; + priv->overlay_prop.YCoord = 0; + priv->overlay_prop.SrcPitch = y_pitch; + priv->overlay_prop.SrcHeight = src_height; + priv->overlay_prop.OverlayWidth = dst_width; + priv->overlay_prop.OverlayHeight = dst_height; + priv->overlay_prop.lpOverlayKey = 0; + priv->overlay_prop.OverlayFormat = OVLTYPE_YUV420; + + priv->display_brightness = 127; + + w100_set_yuv_addrs(priv, &priv->frame_offsets[0]); + + /* clear every frame */ + memset(priv->vram_addr[INTERNAL_VRAM], 0, priv->vram_size[INTERNAL_VRAM]); + memset(priv->vram_addr[EXTERNAL_VRAM] + 640 * 480 * 2, 0, + priv->vram_size[EXTERNAL_VRAM] - 640 * 480 * 2); + + switch (format) { + case IMGFMT_YV12: + case IMGFMT_I420: + case IMGFMT_IYUV: + case IMGFMT_YVU9: + case IMGFMT_IF09: + case IMGFMT_Y800: + case IMGFMT_Y8: + apitch = priv->overlay_pitch_y - 1; + dstrides.y = (src_width + apitch) & ~apitch; + apitch = priv->overlay_pitch_v - 1; + dstrides.v = (src_width + apitch) & ~apitch; + apitch = priv->overlay_pitch_u - 1; + dstrides.u = (src_width + apitch) & ~apitch; +/* st_image_bpp = 1; */ + break; + case IMGFMT_RGB32: + case IMGFMT_BGR32: + apitch = priv->overlay_pitch_y - 1; + dstrides.y = (src_width * 4 + apitch) & ~apitch; + dstrides.u = dstrides.v = 0; +/* st_image_bpp = 4; */ + break; + case IMGFMT_RGB24: + case IMGFMT_BGR24: + apitch = priv->overlay_pitch_y - 1; + dstrides.y = (src_width * 3 + apitch) & ~apitch; + dstrides.u = dstrides.v = 0; +/* st_image_bpp = 3; */ + break; + default: + apitch = priv->overlay_pitch_y - 1; + dstrides.y = (src_width * 2 + apitch) & ~apitch; + dstrides.u = dstrides.v = 0; +/* st_image_bpp = 2; */ + break; + } + + if (format == IMGFMT_YV12 || format == IMGFMT_I420 || format == IMGFMT_IYUV) { + switch (priv->current_rotate) { + case 0: + video_out_w100.draw_slice = w100_draw_slice_420; + break; + case 1: + break; + case 2: + break; + case 3: + video_out_w100.draw_slice = w100_draw_slice_420_rotate3; + break; + default: + video_out_w100.draw_slice = w100_draw_slice_420; + break; + } + } + /* else if (format == IMGFMT_YVU9 || format == IMGFMT_IF09) */ + /* vo_server->draw_slice = w100_draw_slice_410; */ + else + video_out_w100.draw_slice = w100_draw_slice_packed; + + if (!w100_setup(priv)) + return -1; + + return 0; +} + +/* + * Control interface + */ +static int control(uint32_t request, void *data, ...) +{ + w100_priv_t *priv = &st_w100_priv; + switch (request) { + case VOCTRL_GET_IMAGE: + return w100_get_image(data); + case VOCTRL_QUERY_FORMAT: + return query_format(*((uint32_t *)data)); + case VOCTRL_SET_EQUALIZER: + { + va_list ap; + int value; + + va_start(ap, data); + value = va_arg(ap, int); + va_end(ap); + + if (!strcasecmp(data, "brightness")) { + int br; + priv->eq_brightness = value * 10; + br = (priv->eq_brightness + 1000) * 127 / 2000; + if (br < 0) + br = 0; + if (br > 127) + br = 127; + if (br > 64) + br -= 64; + else + br += 64; + priv->display_brightness = br; + + mp_msg(MSGT_VO, MSGL_V, + "vo_w100: control(VOCTRL_SET_EQUALIZER) %d %d\n", + value, br); + + if (AtiCore_SetDisplayBrightness(priv->display_brightness)) + return VO_TRUE; + else + return VO_FALSE; + } + } + case VOCTRL_GET_EQUALIZER: + { + va_list ap; + int *value; + + va_start(ap, data); + value = va_arg(ap, int*); + va_end(ap); + + if (!strcasecmp(data, "brightness")) { + *value = priv->eq_brightness; + return VO_TRUE; + } else + return VO_FALSE; + } + } + + return VO_NOTIMPL; +} + +/* + * Display a new RGB/BGR frame of the video to the screen. + * params: + * src[0] - pointer to the image + */ +int draw_frame(uint8_t *src[]) +{ + mp_msg(MSGT_VO, MSGL_V, "vo_w100: dummy draw_frame() was called\n"); + return -1; +} + +/* + * Draw a planar YUV slice to the buffer: + * params: + * src[3] = source image planes (Y,U,V) + * stride[3] = source image planes line widths (in bytes) + * w,h = width*height of area to be copied (in Y pixels) + * x,y = position at the destination image (in Y pixels) + */ +int draw_slice(uint8_t *src[], int stride[], int w,int h, int x,int y) +{ + mp_msg(MSGT_VO, MSGL_V, "vo_w100: dummy draw_slice() was called\n"); + return -1; +} + + +/* + * Draws OSD to the screen buffer + */ +static void draw_osd(void) +{ + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: draw_osd() was called\n"); + vo_draw_text(st_w100_priv.src_height, st_w100_priv.src_width, draw_alpha); +} + +/* + * Blit/Flip buffer to the screen. Must be called after each frame! + */ +void flip_page(void) +{ + w100_priv_t *priv = &st_w100_priv; + + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: flip_page() was called\n"); + if (vo_doublebuffering) { + w100_set_yuv_addrs(priv, &priv->frame_offsets[priv->current_frame]); + priv->current_frame = (priv->current_frame + 1) % priv->nframes; + } +} + +/* + * This func is called after every frames to handle keyboard and + * other events. It's called in PAUSE mode too! + */ +extern int g_sigcont; +void check_events(void) +{ + w100_priv_t *priv = &st_w100_priv; + + if (g_sigcont) { + mp_msg(MSGT_VO, MSGL_INFO, "vo_w100: SIGCONT recived.\n"); + + /* Immediately after resuming, because kernel modifies the register, it + waits for that. */ + usleep(1000 * 1000); + + /* re-attach */ +#if 0 + /* Hmm... With respect to of context is necessary, but really it + fails. It does not release and also there is no problem. */ + if (!AtiCore_ReleaseOverlay(priv->overlay_handle)) { + mp_msg(MSGT_VO, MSGL_FATAL, + "vo_w100: AtiCore_ReleaseOverlay failed.\n"); + exit_player(NULL); + } +#endif + if (!AtiCore_ProcessDetach()) { + mp_msg(MSGT_VO, MSGL_FATAL, + "vo_w100: AtiCore_ProcessDetach failed.\n"); + exit_player(NULL); + } + if (!AtiCore_ProcessAttach()) { + mp_msg(MSGT_VO, MSGL_FATAL, + "vo_w100: AtiCore_ProcessAttach failed.\n"); + exit_player(NULL); + } + + /* re-setup */ + if (!w100_setup(priv)) + exit_player(NULL); + + g_sigcont = 0; + } +} + +/* + * Closes driver. Should restore the original state of the system. + */ +static void uninit(void) +{ + mp_msg(MSGT_VO, MSGL_V, "vo_w100: uninit() was called\n"); + + AtiCore_SetOverlayOnOff(st_w100_priv.overlay_handle, 0); + AtiCore_ReleaseOverlay(st_w100_priv.overlay_handle); + AtiCore_SetGraphicWindowOnOff(1); + AtiCore_ProcessDetach(); +} + + +// ---------------------------------------------------------------- +static int query_format(uint32_t format) +{ + mp_msg(MSGT_VO, MSGL_V, "vo_w100: query_format was called: %x (%s)\n", + format, vo_format_name(format)); + + if (IMGFMT_IS_RGB(format)) { + /* RGB/BGR Formats */ + // TODO + return 0; + + switch (IMGFMT_RGB_DEPTH(format)) { + case 16: + return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW + | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD | VFCAP_ACCEPT_STRIDE; + break; + } + } else { + /* Planar YUV Formats */ + switch (format) { + case IMGFMT_YV12: + case IMGFMT_IYUV: + case IMGFMT_I420: + case IMGFMT_YVU9: + case IMGFMT_IF09: + case IMGFMT_Y8: + case IMGFMT_Y800: + return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW + | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD | VFCAP_ACCEPT_STRIDE; + break; + } + } + + return 0; +} + +static void dump_vo_info(void) +{ + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: ================================\n"); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_flags:%x\n", vo_flags); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_depthonscreen:%d\n", vo_depthonscreen); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_screenwidth:%d\n", vo_screenwidth); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_screenheight:%d\n", vo_screenheight); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_dx:%d\n", vo_dx); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_dy:%d\n", vo_dy); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_dwidth:%d\n", vo_dwidth); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_dheight:%d\n", vo_dheight); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_dbpp:%d\n", vo_dbpp); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_grabpointer:%d\n", vo_grabpointer); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_doublebuffering:%d\n", vo_doublebuffering); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_directrendering:%d\n", vo_directrendering); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_vsync:%d\n", vo_vsync); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_fs:%d\n", vo_fs); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_fsmode:%d\n", vo_fsmode); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_panscan:%f\n", vo_panscan); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_adapter_num:%d\n", vo_adapter_num); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_refresh_rate:%d\n", vo_refresh_rate); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_gamma_brightness:%d\n", vo_gamma_brightness); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_gamma_saturation:%d\n", vo_gamma_saturation); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_gamma_contrast:%d\n", vo_gamma_contrast); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_gamma_hue:%d\n", vo_gamma_hue); +/* mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_gamma_red_intensity:%d\n", vo_gamma_red_intensity); */ +/* mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_gamma_green_intensity:%d\n", vo_gamma_green_intensity); */ +/* mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_gamma_blue_intensity:%d\n", vo_gamma_blue_intensity); */ +/* mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_mouse_timer_const:%d\n", vo_mouse_timer_const); */ + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_nomouse_input:%d\n", vo_nomouse_input); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_pts:%d\n", vo_pts); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_fps:%f\n", vo_fps); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: vo_colorkey:%d\n", vo_colorkey); + mp_msg(MSGT_VO, MSGL_DBG2, "vo_w100: ================================\n"); +} |