/* (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 "matrox.h" #include "matrox_state.h" #define MGA_KEYMASK(format) ((1 << DFB_COLOR_BITS_PER_PIXEL(format)) - 1) static void matrox_calc_offsets( MatroxDeviceData *mdev, CoreSurface *surface, CoreSurfaceBufferLock *lock, bool unit_pixel, int offset[2][3] ) { int bytes_per_pixel = DFB_BYTES_PER_PIXEL( surface->config.format ); int pitch; if (unit_pixel) { offset[0][0] = lock->offset / bytes_per_pixel; pitch = lock->pitch / bytes_per_pixel; } else { offset[0][0] = mdev->fb.offset + lock->offset; pitch = lock->pitch; } switch (surface->config.format) { case DSPF_NV12: case DSPF_NV21: offset[0][1] = offset[0][0] + surface->config.size.h * pitch; offset[0][2] = 0; break; case DSPF_I420: offset[0][1] = offset[0][0] + surface->config.size.h * pitch; offset[0][2] = offset[0][1] + surface->config.size.h/2 * pitch/2; break; case DSPF_YV12: offset[0][2] = offset[0][0] + surface->config.size.h * pitch; offset[0][1] = offset[0][2] + surface->config.size.h/2 * pitch/2; break; default: offset[0][1] = 0; offset[0][2] = 0; } D_ASSERT( offset[0][0] % 64 == 0 ); D_ASSERT( offset[0][1] % 64 == 0 ); D_ASSERT( offset[0][2] % 64 == 0 ); if (mdev->blit_fields || mdev->blit_deinterlace) { if (surface->config.caps & DSCAPS_SEPARATED) { offset[1][0] = offset[0][0] + surface->config.size.h/2 * pitch; switch (surface->config.format) { case DSPF_NV12: case DSPF_NV21: offset[1][1] = offset[0][1] + surface->config.size.h/4 * pitch; offset[1][2] = 0; break; case DSPF_I420: case DSPF_YV12: offset[1][1] = offset[0][1] + surface->config.size.h/4 * pitch/2; offset[1][2] = offset[0][2] + surface->config.size.h/4 * pitch/2; break; default: offset[1][1] = 0; offset[1][2] = 0; } } else { offset[1][0] = offset[0][0] + pitch; switch (surface->config.format) { case DSPF_NV12: case DSPF_NV21: offset[1][1] = offset[0][1] + pitch; offset[1][2] = 0; break; case DSPF_I420: case DSPF_YV12: offset[1][1] = offset[0][1] + pitch/2; offset[1][2] = offset[0][2] + pitch/2; break; default: offset[1][1] = 0; offset[1][2] = 0; } } D_ASSERT( offset[1][0] % 64 == 0 ); D_ASSERT( offset[1][1] % 64 == 0 ); D_ASSERT( offset[1][2] % 64 == 0 ); } } void matrox_validate_destination( MatroxDriverData *mdrv, MatroxDeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; CoreSurface *destination = state->destination; CoreSurfaceBuffer *depth_buffer = NULL;//destination->depth_buffer; int bytes_per_pixel = DFB_BYTES_PER_PIXEL( destination->config.format ); if (MGA_IS_VALID( m_destination )) return; mdev->dst_pitch = state->dst.pitch / bytes_per_pixel; mdev->depth_buffer = depth_buffer != NULL; if (destination->config.format == DSPF_YUY2 || destination->config.format == DSPF_UYVY) mdev->dst_pitch /= 2; if (mdev->blit_fields && !(destination->config.caps & DSCAPS_SEPARATED)) mdev->dst_pitch *= 2; D_ASSERT( mdev->dst_pitch % 32 == 0 ); matrox_calc_offsets( mdev, destination, &state->dst, mdev->old_matrox, mdev->dst_offset ); mga_waitfifo( mdrv, mdev, depth_buffer ? 4 : 3 ); mga_out32( mmio, mdev->dst_offset[0][0], mdev->old_matrox ? YDSTORG : DSTORG ); mga_out32( mmio, mdev->dst_pitch, PITCH ); #if 0 if (depth_buffer) mga_out32( mmio, depth_buffer->video.offset, ZORG ); #endif switch (destination->config.format) { case DSPF_A8: case DSPF_ALUT44: case DSPF_LUT8: case DSPF_RGB332: mga_out32( mmio, PW8, MACCESS ); break; case DSPF_RGB555: case DSPF_ARGB1555: mga_out32( mmio, PW16 | DIT555, MACCESS ); break; case DSPF_RGB444: case DSPF_ARGB4444: case DSPF_RGB16: mga_out32( mmio, PW16, MACCESS ); break; case DSPF_RGB24: mga_out32( mmio, PW24, MACCESS ); break; case DSPF_RGB32: case DSPF_ARGB: mga_out32( mmio, PW32, MACCESS ); break; case DSPF_I420: case DSPF_YV12: case DSPF_NV12: case DSPF_NV21: mga_out32( mmio, PW8 | BYPASS332 | NODITHER, MACCESS ); break; case DSPF_YUY2: case DSPF_UYVY: mga_out32( mmio, PW32 | NODITHER, MACCESS ); break; default: D_BUG( "unexpected pixelformat!" ); break; } MGA_VALIDATE( m_destination ); } void matrox_set_clip( MatroxDriverData *mdrv, MatroxDeviceData *mdev, DFBRegion *clip ) { volatile u8 *mmio = mdrv->mmio_base; mga_waitfifo( mdrv, mdev, 3 ); if (mdev->old_matrox) { mga_out32( mmio, (mdev->dst_offset[0][0] + mdev->dst_pitch * clip->y1) & 0xFFFFFF, YTOP ); mga_out32( mmio, (mdev->dst_offset[0][0] + mdev->dst_pitch * clip->y2) & 0xFFFFFF, YBOT ); } else { mga_out32( mmio, (mdev->dst_pitch * clip->y1) & 0xFFFFFF, YTOP ); mga_out32( mmio, (mdev->dst_pitch * clip->y2) & 0xFFFFFF, YBOT ); } mga_out32( mmio, ((clip->x2 & 0x0FFF) << 16) | (clip->x1 & 0x0FFF), CXBNDRY ); } void matrox_validate_drawColor( MatroxDriverData *mdrv, MatroxDeviceData *mdev, CardState *state ) { DFBColor color = state->color; volatile u8 *mmio = mdrv->mmio_base; if (MGA_IS_VALID( m_drawColor )) 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; } mga_waitfifo( mdrv, mdev, 4 ); mga_out32( mmio, U8_TO_F0915(color.a), ALPHASTART ); mga_out32( mmio, U8_TO_F0915(color.r), DR4 ); mga_out32( mmio, U8_TO_F0915(color.g), DR8 ); mga_out32( mmio, U8_TO_F0915(color.b), DR12 ); MGA_VALIDATE( m_drawColor ); MGA_INVALIDATE( m_blitColor ); MGA_INVALIDATE( m_blitBlend ); } void matrox_validate_blitColor( MatroxDriverData *mdrv, MatroxDeviceData *mdev, CardState *state ) { DFBColor color = state->color; volatile u8 *mmio = mdrv->mmio_base; if (MGA_IS_VALID( m_blitColor )) return; if (state->blittingflags & DSBLIT_COLORIZE) { if (state->blittingflags & DSBLIT_SRC_PREMULTCOLOR) { 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 { if (state->blittingflags & DSBLIT_SRC_PREMULTCOLOR) color.r = color.g = color.b = color.a; else color.r = color.g = color.b = 0xff; } mga_waitfifo( mdrv, mdev, 4 ); mga_out32( mmio, U8_TO_F0915(color.a), ALPHASTART ); mga_out32( mmio, U8_TO_F0915(color.r), DR4 ); mga_out32( mmio, U8_TO_F0915(color.g), DR8 ); mga_out32( mmio, U8_TO_F0915(color.b), DR12 ); MGA_VALIDATE( m_blitColor ); MGA_INVALIDATE( m_drawColor ); MGA_INVALIDATE( m_blitBlend ); } void matrox_validate_color( MatroxDriverData *mdrv, MatroxDeviceData *mdev, CardState *state ) { DFBColor color = state->color; volatile u8 *mmio = mdrv->mmio_base; u32 fcol; u8 cb, cr; if (MGA_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_ALUT44: fcol = (color.a & 0xF0) | state->color_index; fcol |= fcol << 8; fcol |= fcol << 16; break; case DSPF_LUT8: fcol = state->color_index; fcol |= fcol << 8; fcol |= fcol << 16; break; case DSPF_RGB332: fcol = PIXEL_RGB332( color.r, color.g, color.b ); fcol |= fcol << 8; fcol |= fcol << 16; break; case DSPF_RGB444: fcol = PIXEL_RGB444( color.r, color.g, color.b ); fcol |= fcol << 16; break; case DSPF_ARGB4444: fcol = PIXEL_ARGB4444( color.a, color.r, color.g, color.b ); fcol |= fcol << 16; break; case DSPF_RGB555: fcol = PIXEL_RGB555( color.r, color.g, color.b ); fcol |= fcol << 16; break; case DSPF_ARGB1555: fcol = PIXEL_ARGB1555( color.a, color.r, color.g, color.b ); fcol |= fcol << 16; break; case DSPF_RGB16: fcol = PIXEL_RGB16( color.r, color.g, color.b ); fcol |= fcol << 16; break; case DSPF_RGB24: fcol = PIXEL_RGB32( color.r, color.g, color.b ); fcol |= fcol << 24; break; case DSPF_RGB32: fcol = PIXEL_RGB32( color.r, color.g, color.b ); break; case DSPF_ARGB: fcol = PIXEL_ARGB( color.a, color.r, color.g, color.b ); break; case DSPF_A8: fcol = color.a; fcol |= fcol << 8; fcol |= fcol << 16; break; case DSPF_I420: case DSPF_YV12: RGB_TO_YCBCR( color.r, color.g, color.b, fcol, cb, cr ); fcol |= fcol << 8; fcol |= fcol << 16; mdev->color[0] = fcol; mdev->color[1] = (cb << 24) | (cb << 16) | (cb << 8) | cb; mdev->color[2] = (cr << 24) | (cr << 16) | (cr << 8) | cr; break; case DSPF_NV12: RGB_TO_YCBCR( color.r, color.g, color.b, fcol, cb, cr ); fcol |= fcol << 8; fcol |= fcol << 16; mdev->color[0] = fcol; mdev->color[1] = (cr << 24) | (cb << 16) | (cr << 8) | cb; break; case DSPF_NV21: RGB_TO_YCBCR( color.r, color.g, color.b, fcol, cb, cr ); fcol |= fcol << 8; fcol |= fcol << 16; mdev->color[0] = fcol; mdev->color[1] = (cb << 24) | (cr << 16) | (cb << 8) | cr; break; case DSPF_YUY2: RGB_TO_YCBCR( color.r, color.g, color.b, fcol, cb, cr ); fcol = PIXEL_YUY2( fcol, cb, cr ); break; case DSPF_UYVY: RGB_TO_YCBCR( color.r, color.g, color.b, fcol, cb, cr ); fcol = PIXEL_UYVY( fcol, cb, cr ); break; default: D_BUG( "unexpected pixelformat!" ); return; } mga_waitfifo( mdrv, mdev, 1 ); mga_out32( mmio, fcol, FCOL ); MGA_VALIDATE( m_color ); MGA_INVALIDATE( m_srckey ); } static u32 matroxSourceBlend[] = { SRC_ZERO, /* DSBF_ZERO */ SRC_ONE, /* DSBF_ONE */ 0, /* DSBF_SRCCOLOR */ 0, /* DSBF_INVSRCCOLOR */ SRC_ALPHA, /* DSBF_SRCALPHA */ SRC_ONE_MINUS_SRC_ALPHA, /* DSBF_INVSRCALPHA */ SRC_DST_ALPHA, /* DSBF_DESTALPHA */ SRC_ONE_MINUS_DST_ALPHA, /* DSBF_INVDESTALPHA */ SRC_DST_COLOR, /* DSBF_DESTCOLOR */ SRC_ONE_MINUS_DST_COLOR, /* DSBF_INVDESTCOLOR */ SRC_SRC_ALPHA_SATURATE /* DSBF_SRCALPHASAT */ }; static u32 matroxDestBlend[] = { DST_ZERO, /* DSBF_ZERO */ DST_ONE, /* DSBF_ONE */ DST_SRC_COLOR, /* DSBF_SRCCOLOR */ DST_ONE_MINUS_SRC_COLOR, /* DSBF_INVSRCCOLOR */ DST_SRC_ALPHA, /* DSBF_SRCALPHA */ DST_ONE_MINUS_SRC_ALPHA, /* DSBF_INVSRCALPHA */ DST_DST_ALPHA, /* DSBF_DESTALPHA */ DST_ONE_MINUS_DST_ALPHA, /* DSBF_INVDESTALPHA */ 0, /* DSBF_DESTCOLOR */ 0, /* DSBF_INVDESTCOLOR */ 0 /* DSBF_SRCALPHASAT */ }; void matrox_validate_drawBlend( MatroxDriverData *mdrv, MatroxDeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; u32 alphactrl; if (MGA_IS_VALID( m_drawBlend )) return; alphactrl = matroxSourceBlend[state->src_blend - 1] | matroxDestBlend [state->dst_blend - 1] | ALPHACHANNEL | DIFFUSEDALPHA; mga_waitfifo( mdrv, mdev, 1 ); mga_out32( mmio, alphactrl, ALPHACTRL ); MGA_VALIDATE( m_drawBlend ); MGA_INVALIDATE( m_blitBlend ); } static u32 matroxAlphaSelect[] = { 0, 0, DIFFUSEDALPHA, MODULATEDALPHA }; void matrox_validate_blitBlend( MatroxDriverData *mdrv, MatroxDeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; u32 alphactrl; if (MGA_IS_VALID( m_blitBlend )) return; if (state->blittingflags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) { if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY) /* src_blend == ONE and dst_blend == INVSRCALPHA/INVSRCCOLOR */ alphactrl = matroxSourceBlend[DSBF_SRCALPHA - 1] | matroxDestBlend [state->dst_blend - 1] | VIDEOALPHA; else alphactrl = matroxSourceBlend[state->src_blend - 1] | matroxDestBlend [state->dst_blend - 1] | ALPHACHANNEL; if (state->source->config.format == DSPF_RGB32) { alphactrl |= DIFFUSEDALPHA; if (! (state->blittingflags & DSBLIT_BLEND_COLORALPHA)) { mga_out32( mmio, U8_TO_F0915(0xff), ALPHASTART ); MGA_INVALIDATE( m_drawColor | m_blitColor ); } } else alphactrl |= matroxAlphaSelect [state->blittingflags & 3]; } else { alphactrl = SRC_ONE | DST_ZERO | ALPHACHANNEL; if (state->source->config.format == DSPF_RGB32) { alphactrl |= DIFFUSEDALPHA; mga_out32( mmio, U8_TO_F0915(0xff), ALPHASTART ); MGA_INVALIDATE( m_drawColor | m_blitColor ); } } mga_waitfifo( mdrv, mdev, 1 ); mga_out32( mmio, alphactrl, ALPHACTRL ); MGA_VALIDATE( m_blitBlend ); MGA_INVALIDATE( m_drawBlend ); } static void matrox_tlutload( MatroxDriverData *mdrv, MatroxDeviceData *mdev, CorePalette *palette ) { volatile u8 *mmio = mdrv->mmio_base; volatile u16 *dst = dfb_gfxcard_memory_virtual( NULL, mdev->tlut_offset ); unsigned int i; for (i = 0; i < palette->num_entries; i++) *dst++ = PIXEL_RGB16( palette->entries[i].r, palette->entries[i].g, palette->entries[i].b ); mga_waitfifo( mdrv, mdev, mdev->old_matrox ? 8 : 9 ); mga_out32( mmio, BLTMOD_BU32RGB | BOP_COPY | SHFTZERO | SGNZERO | LINEAR | ATYPE_RSTR | OP_BITBLT, DWGCTL ); mga_out32( mmio, 1024, PITCH ); if (mdev->old_matrox) { mga_out32( mmio, mdev->tlut_offset / 2, AR3 ); mga_out32( mmio, palette->num_entries, AR0 ); mga_out32( mmio, 0, YDSTORG ); } else { mga_out32( mmio, 0, AR3 ); mga_out32( mmio, palette->num_entries, AR0 ); mga_out32( mmio, mdev->fb.offset + mdev->tlut_offset, SRCORG ); mga_out32( mmio, 0, DSTORG ); MGA_INVALIDATE( m_source ); } mga_out32( mmio, 0, FXBNDRY ); mga_out32( mmio, PW16 | TLUTLOAD, MACCESS ); mga_out32( mmio, palette->num_entries, YDSTLEN | EXECUTE ); MGA_INVALIDATE( m_destination ); } void matrox_validate_Source( MatroxDriverData *mdrv, MatroxDeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; CoreSurface *surface = state->source; int bytes_per_pixel = DFB_BYTES_PER_PIXEL(surface->config.format); u32 texctl = 0, texctl2 = 0; if (MGA_IS_VALID( m_Source )) return; mdev->src_pitch = state->src.pitch / bytes_per_pixel; mdev->field = surface->field; mdev->w = surface->config.size.w; mdev->h = surface->config.size.h; if (state->destination->config.format == DSPF_YUY2 || state->destination->config.format == DSPF_UYVY) { mdev->w /= 2; mdev->src_pitch /= 2; } if (mdev->blit_deinterlace || mdev->blit_fields) { mdev->h /= 2; if (!(surface->config.caps & DSCAPS_SEPARATED)) mdev->src_pitch *= 2; } D_ASSERT( mdev->src_pitch % 32 == 0 ); matrox_calc_offsets( mdev, surface, &state->src, false, mdev->src_offset ); if (mdev->blit_deinterlace && mdev->field) { mdev->src_offset[0][0] = mdev->src_offset[1][0]; mdev->src_offset[0][1] = mdev->src_offset[1][1]; mdev->src_offset[0][2] = mdev->src_offset[1][2]; } mdev->w2 = mga_log2( mdev->w ); mdev->h2 = mga_log2( mdev->h ); if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL) texctl = TAMASK; else texctl = TAKEY; switch (surface->config.format) { case DSPF_YUY2: texctl |= (state->destination->config.format == DSPF_YUY2) ? TW32 : TW422; break; case DSPF_UYVY: texctl |= (state->destination->config.format == DSPF_UYVY) ? TW32 : TW422UYVY; break; case DSPF_I420: case DSPF_YV12: case DSPF_NV12: case DSPF_NV21: case DSPF_A8: texctl |= TW8A; break; case DSPF_RGB444: case DSPF_ARGB4444: texctl |= TW12; break; case DSPF_RGB555: case DSPF_ARGB1555: texctl |= TW15; break; case DSPF_RGB16: texctl |= TW16; break; case DSPF_RGB32: case DSPF_ARGB: texctl |= TW32; break; case DSPF_LUT8: matrox_tlutload( mdrv, mdev, surface->palette ); texctl |= TW8; break; case DSPF_RGB332: matrox_tlutload( mdrv, mdev, mdev->rgb332_palette ); texctl |= TW8; break; default: D_BUG( "unexpected pixelformat!" ); break; } texctl |= ((mdev->src_pitch << 9) & TPITCHEXT) | TPITCHLIN; if (1 << mdev->w2 != mdev->w || 1 << mdev->h2 != mdev->h) texctl |= CLAMPUV; if (state->blittingflags & (DSBLIT_COLORIZE | DSBLIT_SRC_PREMULTCOLOR)) texctl |= TMODULATE; else texctl2 |= DECALDIS; if (state->blittingflags & DSBLIT_SRC_COLORKEY) texctl |= DECALCKEY | STRANS; else texctl2 |= CKSTRANSDIS; if (surface->config.format == DSPF_A8) texctl2 |= IDECAL | DECALDIS; mdev->texctl = texctl; mga_waitfifo( mdrv, mdev, 5 ); mga_out32( mmio, texctl, TEXCTL ); mga_out32( mmio, texctl2, TEXCTL2 ); mga_out32( mmio, ( (((u32)(mdev->w - 1) & 0x7ff) << 18) | (((u32)(4 - mdev->w2) & 0x3f) << 9) | (((u32)(mdev->w2 + 4) & 0x3f) ) ), TEXWIDTH ); mga_out32( mmio, ( (((u32)(mdev->h - 1) & 0x7ff) << 18) | (((u32)(4 - mdev->h2) & 0x3f) << 9) | (((u32)(mdev->h2 + 4) & 0x3f) ) ), TEXHEIGHT ); mga_out32( mmio, mdev->src_offset[0][0], TEXORG ); MGA_VALIDATE( m_Source ); } void matrox_validate_source( MatroxDriverData *mdrv, MatroxDeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; CoreSurface *surface = state->source; int bytes_per_pixel = DFB_BYTES_PER_PIXEL(surface->config.format); if (MGA_IS_VALID( m_source )) return; mdev->src_pitch = state->src.pitch / bytes_per_pixel; if (state->destination->config.format == DSPF_YUY2 || state->destination->config.format == DSPF_UYVY) mdev->src_pitch /= 2; if (mdev->blit_fields && !(surface->config.caps & DSCAPS_SEPARATED)) mdev->src_pitch *= 2; D_ASSERT( mdev->src_pitch % 32 == 0 ); matrox_calc_offsets( mdev, surface, &state->src, mdev->old_matrox, mdev->src_offset ); if (!mdev->old_matrox) { mga_waitfifo( mdrv, mdev, 1 ); mga_out32( mmio, mdev->src_offset[0][0], SRCORG ); } MGA_VALIDATE( m_source ); } void matrox_validate_SrcKey( MatroxDriverData *mdrv, MatroxDeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; CoreSurface *surface = state->source; u32 key; u32 mask; if (MGA_IS_VALID( m_SrcKey )) return; if (state->blittingflags & DSBLIT_SRC_COLORKEY) { mask = MGA_KEYMASK(surface->config.format); key = state->src_colorkey & mask; } else { mask = 0; key = 0xFFFF; } mga_waitfifo( mdrv, mdev, 2); mga_out32( mmio, ((mask & 0xFFFF) << 16) | (key & 0xFFFF), TEXTRANS ); mga_out32( mmio, (mask & 0xFFFF0000) | (key >> 16), TEXTRANSHIGH ); MGA_VALIDATE( m_SrcKey ); } void matrox_validate_srckey( MatroxDriverData *mdrv, MatroxDeviceData *mdev, CardState *state ) { volatile u8 *mmio = mdrv->mmio_base; CoreSurface *surface = state->source; u32 key; u32 mask; if (MGA_IS_VALID( m_srckey )) return; mask = MGA_KEYMASK(surface->config.format); key = state->src_colorkey & mask; switch (DFB_BYTES_PER_PIXEL(state->source->config.format)) { case 1: mask |= mask << 8; key |= key << 8; case 2: mask |= mask << 16; key |= key << 16; } mga_waitfifo( mdrv, mdev, 2); mga_out32( mmio, mask, BCOL ); mga_out32( mmio, key, FCOL ); MGA_VALIDATE( m_srckey ); MGA_INVALIDATE( m_color ); }