/* (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) (c) Copyright 2000-2004 Convergence (integrated media) GmbH All rights reserved. Written by Denis Oliver Kropp , Andreas Hundt , Sven Neumann , Ville Syrjälä and Claudio Ciccani . This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include "regs.h" #include "mmio.h" #include "mach64.h" #include "mach64_state.h" void mach64_set_destination( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; CoreSurface *destination = state->destination; unsigned int pitch = state->dst.pitch / DFB_BYTES_PER_PIXEL( destination->config.format ); mdev->pix_width &= ~DST_PIX_WIDTH; switch (destination->config.format) { case DSPF_RGB332: mdev->pix_width |= DST_PIX_WIDTH_8BPP; break; case DSPF_RGB555: case DSPF_ARGB1555: mdev->pix_width |= DST_PIX_WIDTH_15BPP; break; case DSPF_RGB16: mdev->pix_width |= DST_PIX_WIDTH_16BPP; break; case DSPF_RGB32: case DSPF_ARGB: mdev->pix_width |= DST_PIX_WIDTH_32BPP; break; default: D_BUG( "unexpected pixelformat!" ); return; } mach64_waitfifo( mdrv, mdev, 1 ); mach64_out32( mmio, DST_OFF_PITCH, (state->dst.offset/8) | ((pitch/8) << 22) ); } void mach64gt_set_destination( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; CoreSurface *destination = state->destination; unsigned int pitch = state->dst.pitch / DFB_BYTES_PER_PIXEL( destination->config.format ); mdev->pix_width &= ~DST_PIX_WIDTH; switch (destination->config.format) { case DSPF_RGB332: mdev->pix_width |= DST_PIX_WIDTH_RGB332; break; case DSPF_RGB555: case DSPF_ARGB1555: mdev->pix_width |= DST_PIX_WIDTH_ARGB1555; break; case DSPF_RGB444: case DSPF_ARGB4444: mdev->pix_width |= DST_PIX_WIDTH_ARGB4444; break; case DSPF_RGB16: mdev->pix_width |= DST_PIX_WIDTH_RGB565; break; case DSPF_RGB32: case DSPF_ARGB: mdev->pix_width |= DST_PIX_WIDTH_ARGB8888; break; default: D_BUG( "unexpected pixelformat!" ); return; } mdev->draw_blend &= ~DITHER_EN; mdev->blit_blend &= ~DITHER_EN; if (DFB_COLOR_BITS_PER_PIXEL( destination->config.format ) < 24) { mdev->draw_blend |= DITHER_EN; mdev->blit_blend |= DITHER_EN; } mach64_waitfifo( mdrv, mdev, 1 ); mach64_out32( mmio, DST_OFF_PITCH, (state->dst.offset/8) | ((pitch/8) << 22) ); } void mach64_set_source( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; CoreSurface *source = state->source; unsigned int pitch = state->src.pitch / DFB_BYTES_PER_PIXEL( source->config.format ); if (MACH64_IS_VALID( m_source )) return; mdev->pix_width &= ~SRC_PIX_WIDTH; switch (source->config.format) { case DSPF_RGB332: mdev->pix_width |= SRC_PIX_WIDTH_8BPP; break; case DSPF_RGB555: case DSPF_ARGB1555: mdev->pix_width |= SRC_PIX_WIDTH_15BPP; break; case DSPF_RGB16: mdev->pix_width |= SRC_PIX_WIDTH_16BPP; break; case DSPF_RGB32: case DSPF_ARGB: mdev->pix_width |= SRC_PIX_WIDTH_32BPP; break; default: D_BUG( "unexpected pixelformat!" ); return; } mach64_waitfifo( mdrv, mdev, 1 ); mach64_out32( mmio, SRC_OFF_PITCH, (state->src.offset/8) | ((pitch/8) << 22) ); MACH64_VALIDATE( m_source ); } void mach64gt_set_source( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; CoreSurface *source = state->source; unsigned int pitch = state->src.pitch / DFB_BYTES_PER_PIXEL( source->config.format ); if (MACH64_IS_VALID( m_source )) return; mdev->pix_width &= ~SRC_PIX_WIDTH; switch (source->config.format) { case DSPF_RGB332: mdev->pix_width |= SRC_PIX_WIDTH_RGB332; break; case DSPF_RGB555: case DSPF_ARGB1555: mdev->pix_width |= SRC_PIX_WIDTH_ARGB1555; break; case DSPF_RGB444: case DSPF_ARGB4444: mdev->pix_width |= SRC_PIX_WIDTH_ARGB4444; break; case DSPF_RGB16: mdev->pix_width |= SRC_PIX_WIDTH_RGB565; break; case DSPF_RGB32: case DSPF_ARGB: mdev->pix_width |= SRC_PIX_WIDTH_ARGB8888; break; default: D_BUG( "unexpected pixelformat!" ); return; } mach64_waitfifo( mdrv, mdev, 1 ); mach64_out32( mmio, SRC_OFF_PITCH, (state->src.offset/8) | ((pitch/8) << 22) ); MACH64_VALIDATE( m_source ); } void mach64gt_set_source_scale( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; CoreSurface *source = state->source; unsigned int offset = state->src.offset; unsigned int pitch = state->src.pitch; int height = source->config.size.h; if (MACH64_IS_VALID( m_source_scale )) return; mdev->pix_width &= ~SCALE_PIX_WIDTH; switch (source->config.format) { case DSPF_RGB332: mdev->pix_width |= SCALE_PIX_WIDTH_RGB332; break; case DSPF_RGB555: case DSPF_ARGB1555: mdev->pix_width |= SCALE_PIX_WIDTH_ARGB1555; break; case DSPF_RGB444: case DSPF_ARGB4444: mdev->pix_width |= SCALE_PIX_WIDTH_ARGB4444; break; case DSPF_RGB16: mdev->pix_width |= SCALE_PIX_WIDTH_RGB565; break; case DSPF_RGB32: case DSPF_ARGB: mdev->pix_width |= SCALE_PIX_WIDTH_ARGB8888; break; default: D_BUG( "unexpected pixelformat!" ); return; } mdev->blit_blend &= ~SCALE_PIX_EXPAND; if (DFB_COLOR_BITS_PER_PIXEL( source->config.format ) < 24) mdev->blit_blend |= SCALE_PIX_EXPAND; mdev->field = source->field; if (mdev->blit_deinterlace) { if (mdev->field) { if (source->config.caps & DSCAPS_SEPARATED) { offset += height/2 * pitch; } else { offset += pitch; pitch *= 2; } } height /= 2; } mdev->source = source; mdev->scale_offset = offset; mdev->scale_pitch = pitch; mdev->tex_offset = offset; mdev->tex_pitch = direct_log2( pitch / DFB_BYTES_PER_PIXEL( source->config.format ) ); mdev->tex_height = direct_log2( height ); mdev->tex_size = MAX( mdev->tex_pitch, mdev->tex_height ); mach64_waitfifo( mdrv, mdev, 1 ); mach64_out32( mmio, TEX_SIZE_PITCH, (mdev->tex_pitch << 0) | (mdev->tex_size << 4) | (mdev->tex_height << 8) ); if (mdev->chip >= CHIP_3D_RAGE_PRO) { mach64_waitfifo( mdrv, mdev, 1 ); mach64_out32( mmio, TEX_CNTL, TEX_CACHE_FLUSH ); } MACH64_VALIDATE( m_source_scale ); } void mach64_set_clip( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; mach64_waitfifo( mdrv, mdev, 2 ); mach64_out32( mmio, SC_LEFT_RIGHT, (S13( state->clip.x2 ) << 16) | S13( state->clip.x1 ) ); mach64_out32( mmio, SC_TOP_BOTTOM, (S14( state->clip.y2 ) << 16) | S14( state->clip.y1 ) ); } void mach64_set_color( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; DFBColor color = state->color; u32 clr; if (MACH64_IS_VALID( m_color )) return; if (state->drawingflags & DSDRAW_SRC_PREMULTIPLY) { color.r = (color.r * (color.a + 1)) >> 8; color.g = (color.g * (color.a + 1)) >> 8; color.b = (color.b * (color.a + 1)) >> 8; } switch (state->destination->config.format) { case DSPF_RGB332: clr = PIXEL_RGB332( color.r, color.g, color.b ); break; case DSPF_RGB555: clr = PIXEL_RGB555( color.r, color.g, color.b ); break; case DSPF_ARGB1555: clr = PIXEL_ARGB1555( color.a, color.r, color.g, color.b ); break; case DSPF_RGB444: clr = PIXEL_RGB444( color.r, color.g, color.b ); break; case DSPF_ARGB4444: clr = PIXEL_ARGB4444( color.a, color.r, color.g, color.b ); break; case DSPF_RGB16: clr = PIXEL_RGB16( color.r, color.g, color.b ); break; case DSPF_RGB32: clr = PIXEL_RGB32( color.r, color.g, color.b ); break; case DSPF_ARGB: clr = PIXEL_ARGB( color.a, color.r, color.g, color.b ); break; default: D_BUG( "unexpected pixelformat!" ); return; } mach64_waitfifo( mdrv, mdev, 1 ); mach64_out32( mmio, DP_FRGD_CLR, clr ); MACH64_VALIDATE( m_color ); } void mach64_set_color_3d( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; DFBColor color = state->color; if (MACH64_IS_VALID( m_color_3d )) return; if (state->drawingflags & DSDRAW_SRC_PREMULTIPLY) { color.r = (color.r * (color.a + 1)) >> 8; color.g = (color.g * (color.a + 1)) >> 8; color.b = (color.b * (color.a + 1)) >> 8; } /* Some 3D color registers scaler registers are shared. */ mach64_waitfifo( mdrv, mdev, 7 ); mach64_out32( mmio, RED_X_INC, 0 ); mach64_out32( mmio, RED_START, color.r << 16 ); mach64_out32( mmio, GREEN_X_INC, 0 ); mach64_out32( mmio, GREEN_START, color.g << 16 ); mach64_out32( mmio, BLUE_X_INC, 0 ); mach64_out32( mmio, BLUE_START, color.b << 16 ); mach64_out32( mmio, ALPHA_START, color.a << 16 ); MACH64_INVALIDATE( m_color_tex | m_blit_blend ); MACH64_VALIDATE( m_color_3d ); } void mach64_set_color_tex( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; DFBColor color = state->color; if (MACH64_IS_VALID( m_color_tex )) return; if (state->blittingflags & DSBLIT_SRC_PREMULTCOLOR) { if (state->blittingflags & DSBLIT_COLORIZE) { color.r = (color.r * (color.a + 1)) >> 8; color.g = (color.g * (color.a + 1)) >> 8; color.b = (color.b * (color.a + 1)) >> 8; } else { color.r = color.g = color.b = color.a; } } /* Some 3D color registers scaler registers are shared. */ mach64_waitfifo( mdrv, mdev, 7 ); mach64_out32( mmio, RED_X_INC, 0 ); mach64_out32( mmio, RED_START, color.r << 16 ); mach64_out32( mmio, GREEN_X_INC, 0 ); mach64_out32( mmio, GREEN_START, color.g << 16 ); mach64_out32( mmio, BLUE_X_INC, 0 ); mach64_out32( mmio, BLUE_START, color.b << 16 ); mach64_out32( mmio, ALPHA_START, color.a << 16 ); MACH64_INVALIDATE( m_color_3d | m_blit_blend ); MACH64_VALIDATE( m_color_tex ); } void mach64_set_src_colorkey( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; if (MACH64_IS_VALID( m_srckey )) return; mach64_waitfifo( mdrv, mdev, 3 ); mach64_out32( mmio, CLR_CMP_MSK, (1 << DFB_COLOR_BITS_PER_PIXEL( state->source->config.format )) - 1 ); mach64_out32( mmio, CLR_CMP_CLR, state->src_colorkey ); mach64_out32( mmio, CLR_CMP_CNTL, CLR_CMP_FN_EQUAL | CLR_CMP_SRC_2D ); MACH64_VALIDATE( m_srckey ); MACH64_INVALIDATE( m_srckey_scale | m_dstkey | m_disable_key ); } void mach64_set_src_colorkey_scale( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; u32 clr, msk; if (MACH64_IS_VALID( m_srckey_scale )) return; if (mdev->chip < CHIP_3D_RAGE_PRO) { switch (state->source->config.format) { case DSPF_RGB332: clr = ((state->src_colorkey & 0xE0) << 16) | ((state->src_colorkey & 0x1C) << 11) | ((state->src_colorkey & 0x03) << 6); msk = 0xE0E0C0; break; case DSPF_RGB444: case DSPF_ARGB4444: clr = ((state->src_colorkey & 0x0F00) << 12) | ((state->src_colorkey & 0x00F0) << 8) | ((state->src_colorkey & 0x000F) << 4); msk = 0xF0F0F0; break; case DSPF_RGB555: case DSPF_ARGB1555: clr = ((state->src_colorkey & 0x7C00) << 9) | ((state->src_colorkey & 0x03E0) << 6) | ((state->src_colorkey & 0x001F) << 3); msk = 0xF8F8F8; break; case DSPF_RGB16: clr = ((state->src_colorkey & 0xF800) << 8) | ((state->src_colorkey & 0x07E0) << 5) | ((state->src_colorkey & 0x001F) << 3); msk = 0xF8FCF8; break; case DSPF_RGB32: case DSPF_ARGB: clr = state->src_colorkey; msk = 0xFFFFFF; break; default: D_BUG( "unexpected pixelformat!" ); return; } } else { clr = state->src_colorkey; msk = (1 << DFB_COLOR_BITS_PER_PIXEL( state->source->config.format )) - 1; } mach64_waitfifo( mdrv, mdev, 3 ); mach64_out32( mmio, CLR_CMP_MSK, msk ); mach64_out32( mmio, CLR_CMP_CLR, clr ); mach64_out32( mmio, CLR_CMP_CNTL, CLR_CMP_FN_EQUAL | CLR_CMP_SRC_SCALE ); MACH64_VALIDATE( m_srckey_scale ); MACH64_INVALIDATE( m_srckey | m_dstkey | m_disable_key ); } void mach64_set_dst_colorkey( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; if (MACH64_IS_VALID( m_dstkey )) return; mach64_waitfifo( mdrv, mdev, 3 ); mach64_out32( mmio, CLR_CMP_MSK, (1 << DFB_COLOR_BITS_PER_PIXEL( state->destination->config.format )) - 1 ); mach64_out32( mmio, CLR_CMP_CLR, state->dst_colorkey ); mach64_out32( mmio, CLR_CMP_CNTL, CLR_CMP_FN_NOT_EQUAL | CLR_CMP_SRC_DEST ); MACH64_VALIDATE( m_dstkey ); MACH64_INVALIDATE( m_srckey | m_srckey_scale | m_disable_key ); } void mach64_disable_colorkey( Mach64DriverData *mdrv, Mach64DeviceData *mdev ) { volatile u8 *mmio = mdrv->mmio_base; if (MACH64_IS_VALID( m_disable_key )) return; mach64_waitfifo( mdrv, mdev, 1 ); mach64_out32( mmio, CLR_CMP_CNTL, CLR_CMP_FN_FALSE ); MACH64_VALIDATE( m_disable_key ); MACH64_INVALIDATE( m_srckey | m_srckey_scale | m_dstkey ); } static u32 mach64SourceBlend[] = { ALPHA_BLND_SRC_ZERO, ALPHA_BLND_SRC_ONE, 0, 0, ALPHA_BLND_SRC_SRCALPHA, ALPHA_BLND_SRC_INVSRCALPHA, ALPHA_BLND_SRC_DSTALPHA, ALPHA_BLND_SRC_INVDSTALPHA, ALPHA_BLND_SRC_DSTCOLOR, ALPHA_BLND_SRC_INVDSTCOLOR, ALPHA_BLND_SAT }; static u32 mach64DestBlend[] = { ALPHA_BLND_DST_ZERO, ALPHA_BLND_DST_ONE, ALPHA_BLND_DST_SRCCOLOR, ALPHA_BLND_DST_INVSRCCOLOR, ALPHA_BLND_DST_SRCALPHA, ALPHA_BLND_DST_INVSRCALPHA, ALPHA_BLND_DST_DSTALPHA, ALPHA_BLND_DST_INVDSTALPHA, 0, 0, 0 }; void mach64_set_draw_blend( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; if (MACH64_IS_VALID( m_draw_blend )) return; mdev->draw_blend &= DITHER_EN; mdev->draw_blend |= ALPHA_FOG_EN_ALPHA | mach64SourceBlend[state->src_blend - 1] | mach64DestBlend [state->dst_blend - 1]; if (mdev->chip >= CHIP_3D_RAGE_PRO) { /* FIXME: This is wrong. */ mach64_waitfifo( mdrv, mdev, 1 ); mach64_out32( mmio, ALPHA_TST_CNTL, ALPHA_DST_SEL_DSTALPHA ); } MACH64_VALIDATE( m_draw_blend ); } void mach64_set_blit_blend( Mach64DriverData *mdrv, Mach64DeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; if (MACH64_IS_VALID( m_blit_blend )) return; mdev->blit_blend &= SCALE_PIX_EXPAND | DITHER_EN; if (state->blittingflags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) { /* Disable dithering because it is applied even when * the source pixels are completely transparent. */ if (DFB_PIXELFORMAT_HAS_ALPHA( state->source->config.format )) mdev->blit_blend &= ~DITHER_EN; mdev->blit_blend |= ALPHA_FOG_EN_ALPHA | mach64SourceBlend[state->src_blend - 1] | mach64DestBlend [state->dst_blend - 1]; if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL) { if (DFB_PIXELFORMAT_HAS_ALPHA( state->source->config.format )) { mdev->blit_blend |= TEX_MAP_AEN; } else { mach64_waitfifo( mdrv, mdev, 1 ); mach64_out32( mmio, ALPHA_START, 0xFF << 16 ); MACH64_INVALIDATE( m_color_3d | m_color_tex ); } } if (mdev->chip >= CHIP_3D_RAGE_PRO) { /* FIXME: This is wrong. */ mach64_waitfifo( mdrv, mdev, 1 ); mach64_out32( mmio, ALPHA_TST_CNTL, ALPHA_DST_SEL_DSTALPHA ); } } else { /* This needs to be set even without alpha blending. * Otherwise alpha channel won't get copied. */ if (DFB_PIXELFORMAT_HAS_ALPHA( state->source->config.format )) mdev->blit_blend |= TEX_MAP_AEN; if (mdev->chip >= CHIP_3D_RAGE_PRO) { /* FIXME: This is wrong. */ mach64_waitfifo( mdrv, mdev, 1 ); mach64_out32( mmio, ALPHA_TST_CNTL, ALPHA_DST_SEL_SRCALPHA ); } } if (state->blittingflags & (DSBLIT_COLORIZE | DSBLIT_SRC_PREMULTCOLOR)) mdev->blit_blend |= TEX_LIGHT_FCN_MODULATE; MACH64_VALIDATE( m_blit_blend ); }