/*******************************Module*Header*****************************\ * * Copyright (c) 1992-1999 Microsoft Corporation * Copyright (c) 1992 Digital Equipment Corporation * * Module Name: * * tiler.cxx * * Abstract: * * This module implements code to copy a pattern to a target surface. * * Author: * * David N. Cutler (davec) 4-May-1992 * * Rewritten in C by: * * Eric Rehm (rehm@zso.dec.com) 15-July-1992 * * Environment: * * Kernel mode only. * * N.B. The AMD64 platform does not enforce alignment checks in kernel * mode. Therefore, even though this function deals with data that * is unaligned, avoidance of unaligned operations is not required. * * Revision History: * \*************************************************************************/ #include "precomp.hxx" VOID CopyPattern( PULONG pulTrg, LONG culFill, LONG hiPat, LONG loPat); VOID MergePattern( PULONG pulTrg, LONG culFill, LONG hiPat, LONG loPat); /****************************Public*Routine******************************\ * * extern "C" VOID * vFetchAndCopy ( * IN PFETCHFRAME pff * ) * * Routine Description: * * This routine repeatedly tiles one scan line of an aligned pattern. * * Arguments: * * pff - Supplies a pointer to a fetch frame. * * Return Value: * * None. * \*************************************************************************/ extern "C" VOID vFetchAndCopy ( FETCHFRAME *pff ) { PULONG pulTrg; // target surface address PULONG pulTrgEnd; // ending targe surface address PULONG pulPat; // base pattern address PULONG pulPatCur; // current pattern address PULONG pulPatEnd; // ending pattern address ULONG xPat; // pattern offset ULONG cxPat; // pattern width in pixels ULONG culFill; // fill size in longwords ULONG loPat, hiPat; // low, hi part of 8-byte pattern // Make copies of some things pulTrg = (PULONG) pff->pvTrg; // starting target surface address (t0) pulPat = (PULONG) pff->pvPat; // base pattern address (t1) xPat = pff->xPat; // pattern offset in bytes (t2) cxPat = pff->cxPat; // pattern width in pixels (t3) culFill = pff->culFill; // Size of fill in longwords pulTrgEnd = pulTrg + culFill; // compute ending target address (t4) pulPatCur = (PULONG) ((PUCHAR) pulPat + xPat); // compute current pattern address (t5) if (cxPat == 8) // check if pattern is exactly 8 pels { loPat = *pulPatCur; // get low part of 8-byte pattern if (xPat == 0) { hiPat = *(pulPatCur + 1); // get hi part of 8-byte pattern } else { hiPat = *pulPat; // get hi part of 8-byte pattern } CopyPattern( pulTrg, culFill, hiPat, loPat); // do a 4 or 8-byte copy } else { // // The pattern is not 8 bytes in width // or cannot be moved 8 bytes at a time // pulPatEnd = (PULONG) ((PUCHAR) pulPat + cxPat); // ending pattern address while (pulTrg < pulTrgEnd) { *pulTrg = *pulPatCur; // set target to 4-byte pattern value pulTrg += 1; // advance the target ptr one longword pulPatCur += 1; // advance the pattern pixel offset if (pulPatCur == pulPatEnd) // Check if at end of pattern { pulPatCur = pulPat; // get starting pattern address } } } } // end vFetchAndCopy /****************************Public*Routine******************************\ * * extern "C" VOID * vFetchShiftAndCopy ( * IN PFETCHFRAME pff * ) * * Routine Description: * * This routine repeatedly tiles one scan line of an unaligned pattern * using rop (P). * * Arguments: * * pff - Supplies a pointer to a fetch frame. * * Return Value: * * None. * \*************************************************************************/ extern "C" VOID vFetchShiftAndCopy ( FETCHFRAME *pff ) { PULONG pulTrg; // target surface address PULONG pulTrgEnd; // ending targe surface address ULONG *pulPat; // base pattern address ULONG *pulPatCur; // current pattern address ULONG xPat; // pattern offset ULONG cxPat; // pattern width in pixels ULONG culFill; // fill size in longwords ULONG loPat, hiPat; // low, hi part of 8-byte pattern // Make copies of some things pulTrg = (PULONG) pff->pvTrg; // starting target surface address (t0) pulPat = (PULONG) pff->pvPat; // base pattern address (t1) xPat = pff->xPat; // pattern offset in bytes (t2) cxPat = pff->cxPat; // pattern width in pixels (t3) culFill = pff->culFill; // Size of fill in longwords pulTrgEnd = pulTrg + culFill; // compute ending target address (t4) pulPatCur = (ULONG *) ((PUCHAR) pulPat + xPat); // compute current pattern address (t5) if (cxPat == 8) // check if pattern is exactly 8 pels { loPat = *pulPatCur; // get low part of 8-byte pattern xPat +=4; // get hi part of 8-byte pattern if (xPat >= cxPat) { xPat -= cxPat; } hiPat = *((ULONG *) ((PUCHAR) pulPat + xPat)); CopyPattern( pulTrg, culFill, hiPat, loPat); // do a 4 or 8-byte copy } else { // // The pattern is not 8 bytes in width // or cannot be moved 8 bytes at a time // while (pulTrg < pulTrgEnd) { *pulTrg = *pulPatCur; // set target to 4-byte pattern value pulTrg += 1; // advance the target ptr one longword xPat += 4; if (xPat >= cxPat) { xPat -= cxPat; } pulPatCur = (ULONG *) ((PUCHAR) pulPat + xPat); } } } // end vFetchShiftAndCopy /****************************Public*Routine******************************\ * * extern "C" VOID * vFetchNotAndCopy ( * IN PFETCHFRAME pff * ) * * Routine Description: * * This routine repeatedly tiles one scan line of an aligned pattern * using rop (Pn). * * Arguments: * * pff - Supplies a pointer to a fetch frame. * * Return Value: * * None. * \*************************************************************************/ extern "C" VOID vFetchNotAndCopy ( FETCHFRAME *pff ) { PULONG pulTrg; // target surface address PULONG pulTrgEnd; // ending targe surface address PULONG pulPat; // base pattern address PULONG pulPatCur; // current pattern address PULONG pulPatEnd; // ending pattern address ULONG xPat; // pattern offset ULONG cxPat; // pattern width in pixels ULONG culFill; // fill size in longwords ULONG loPat, hiPat; // low, hi part of 8-byte pattern // Make copies of some things pulTrg = (PULONG) pff->pvTrg; // starting target surface address (t0) pulPat = (PULONG) pff->pvPat; // base pattern address (t1) xPat = pff->xPat; // pattern offset in bytes (t2) cxPat = pff->cxPat; // pattern width in pixels (t3) culFill = pff->culFill; // Size of fill in longwords pulTrgEnd = pulTrg + culFill; // compute ending target address (t4) pulPatCur = (PULONG) ((PUCHAR) pulPat + xPat); // compute current pattern address (t5) if (cxPat == 8) // check if pattern is exactly 8 pels { loPat = *pulPatCur; // get low part of 8-byte pattern if (xPat == 0) { hiPat = *(pulPatCur + 1); // get hi part of 8-byte pattern } else { hiPat = *pulPat; // get hi part of 8-byte pattern } loPat = ~loPat; // complement pattern hiPat = ~hiPat; CopyPattern( pulTrg, culFill, hiPat, loPat); // do a 4 or 8-byte copy } else { // // The pattern is not 8 bytes in width // or cannot be moved 8 bytes at a time // pulPatEnd = (PULONG) ((PUCHAR) pulPat + cxPat); // ending pattern address while (pulTrg < pulTrgEnd) { *pulTrg = ~(*pulPatCur); // set target to complement of 4-byte pattern value pulTrg += 1; // advance the target ptr one longword pulPatCur += 1; // advance the pattern pixel offset if (pulPatCur == pulPatEnd) // Check if at end of pattern { pulPatCur = pulPat; // get starting pattern address } } } } // end vFetchNotAndCopy /****************************Public*Routine******************************\ * * extern "C" VOID * vFetchShiftNotAndCopy ( * IN PFETCHFRAME pff * ) * * Routine Description: * * This routine repeatedly tiles one scan line of an unaligned pattern * using rop (Pn). * * Arguments: * * pff - Supplies a pointer to a fetch frame. * * Return Value: * * None. * \*************************************************************************/ extern "C" VOID vFetchShiftNotAndCopy ( FETCHFRAME *pff ) { PULONG pulTrg; // target surface address PULONG pulTrgEnd; // ending targe surface address ULONG *pulPat; // base pattern address ULONG *pulPatCur; // current pattern address ULONG xPat; // pattern offset ULONG cxPat; // pattern width in pixels ULONG culFill; // fill size in longwords ULONG loPat, hiPat; // low, hi part of 8-byte pattern // Make copies of some things pulTrg = (PULONG) pff->pvTrg; // starting target surface address (t0) pulPat = (PULONG) pff->pvPat; // base pattern address (t1) xPat = pff->xPat; // pattern offset in bytes (t2) cxPat = pff->cxPat; // pattern width in pixels (t3) culFill = pff->culFill; // Size of fill in longwords pulTrgEnd = pulTrg + culFill; // compute ending target address (t4) pulPatCur = (ULONG *) ((PUCHAR) pulPat + xPat); // compute current pattern address (t5) if (cxPat == 8) // check if pattern is exactly 8 pels { loPat = *pulPatCur; // get low part of 8-byte pattern xPat +=4; // get hi part of 8-byte pattern if (xPat >= cxPat) { xPat -= cxPat; } hiPat = *((ULONG *) ((PUCHAR) pulPat + xPat)); loPat = ~loPat; // complement pattern hiPat = ~hiPat; CopyPattern( pulTrg, culFill, hiPat, loPat); // do a 4 or 8-byte copy } else { // // The pattern is not 8 bytes in width // or cannot be moved 8 bytes at a time // while (pulTrg < pulTrgEnd) { *pulTrg = ~(*pulPatCur); // set target to complemented 4-byte pattern value pulTrg += 1; // advance the target ptr one longword xPat += 4; if (xPat >= cxPat) { xPat -= cxPat; } pulPatCur = (ULONG *) ((PUCHAR) pulPat + xPat); } } } // end vFetchShiftNotAndCopy /****************************Private*Routine******************************\ * * VOID CopyPattern( PULONG pulTrg, LONG culFill, LONG hiPat, LONG loPat) * * Routine Description: * * This routine contains common code for copying an 8-byte pattern to * a target surface. * * Arguments: * * culFill - Supplies the size of the fill in bytes. * loPat, hiPat - Supplies the 8-byte pattern to copy. * pulTrg - Supplies the starting target surface address. * * Return Value: * * None. * * \*************************************************************************/ VOID CopyPattern ( PULONG pulTrg, // Starting target surface address (t0) LONG culFill, // size of fill in longwords (a1) LONG hiPat, // hi part of pattern (v1) LONG loPat // lo part of pattern (v0) ) { PULONG pulTrgEnd; // ending target surface address ULONG temp; // temp for swap pulTrgEnd = pulTrg + culFill; // ending target surface address(t4) // // If the fill size is not an even multiple of 8 bytes, then move one // longword and swap the pattern value. // if ((culFill & 0x01) != 0) { *pulTrg = loPat; // store low 4 bytes of pattern pulTrg += 1; // advance target ptr one longword culFill -= 1; if (culFill == 0) // if no more to move then we're done { return; } else // otherwise, swap 8-byte pattern value { temp = loPat; loPat = hiPat; hiPat = temp; } } // // Move 8-byte pattern value to target 8 bytes at a time. // pulTrgEnd -= 2; // ending segement address if ((culFill & 0x02) != 0) // check if even multiple of 8 bytes { while (pulTrg <= pulTrgEnd) // if not, move 8 bytes at a time { *pulTrg = loPat; // store 8-byte pattern value *(pulTrg + 1) = hiPat; pulTrg += 2; // advance target address } return; } else // move 16 bytes at a time { pulTrgEnd -= 2; // ending segement address while (pulTrg <= pulTrgEnd) { *pulTrg = loPat; // store 8-byte pattern value *(pulTrg + 1) = hiPat; *(pulTrg + 2) = loPat; // store 8-byte pattern value *(pulTrg + 3) = hiPat; pulTrg += 4; // advance target address } } } /****************************Public*Routine******************************\ * * extern "C" VOID * vFetchAndMerge ( * IN PFETCHFRAME pff * ) * * Routine Description: * * This routine repeatedly tiles one scan line of an aligned pattern * using ropt (DPx). * * Arguments: * * pff - Supplies a pointer to a fetch frame. * * Return Value: * * None. * \*************************************************************************/ extern "C" VOID vFetchAndMerge ( FETCHFRAME *pff ) { PULONG pulTrg; // target surface address PULONG pulTrgEnd; // ending targe surface address PULONG pulPat; // base pattern address PULONG pulPatCur; // current pattern address PULONG pulPatEnd; // ending pattern address ULONG xPat; // pattern offset ULONG cxPat; // pattern width in pixels ULONG culFill; // fill size in longwords ULONG loPat, hiPat; // low, hi part of 8-byte pattern // Make copies of some things pulTrg = (PULONG) pff->pvTrg; // starting target surface address (t0) pulPat = (PULONG) pff->pvPat; // base pattern address (t1) xPat = pff->xPat; // pattern offset in bytes (t2) cxPat = pff->cxPat; // pattern width in pixels (t3) culFill = pff->culFill; // Size of fill in longwords pulTrgEnd = pulTrg + culFill; // compute ending target address (t4) pulPatCur = (PULONG) ((PUCHAR) pulPat + xPat); // compute current pattern address (t5) if (cxPat == 8) // check if pattern is exactly 8 pels { loPat = *pulPatCur; // get low part of 8-byte pattern if (xPat == 0) { hiPat = *(pulPatCur + 1); // get hi part of 8-byte pattern } else { hiPat = *pulPat; // get hi part of 8-byte pattern } MergePattern( pulTrg, culFill, hiPat, loPat); //do a 4 or 8-byte copy } else { // // The pattern is not 8 bytes in width // or cannot be moved 8 bytes at a time // pulPatEnd = (PULONG) ((PUCHAR) pulPat + cxPat); // ending pattern address while (pulTrg < pulTrgEnd) { *pulTrg = (*pulPatCur) ^ (*pulTrg); // XOR 4-byte target with 4-byte pattern value pulTrg += 1; // advance the target ptr one longword pulPatCur += 1; // advance the pattern pixel offset if (pulPatCur == pulPatEnd) // Check if at end of pattern { pulPatCur = pulPat; // get starting pattern address } } } } // end vFetchAndMerge /****************************Public*Routine******************************\ * * extern "C" VOID * vFetchShiftAndMerge ( * IN PFETCHFRAME pff * ) * * Routine Description: * * This routine repeatedly tiles one scan line of an unaligned pattern * using rop (P). * * Arguments: * * pff - Supplies a pointer to a fetch frame. * * Return Value: * * None. * \*************************************************************************/ extern "C" VOID vFetchShiftAndMerge ( FETCHFRAME *pff ) { PULONG pulTrg; // target surface address PULONG pulTrgEnd; // ending targe surface address ULONG *pulPat; // base pattern address ULONG *pulPatCur; // current pattern address ULONG xPat; // pattern offset ULONG cxPat; // pattern width in pixels ULONG culFill; // fill size in longwords ULONG loPat, hiPat; // low, hi part of 8-byte pattern // Make copies of some things pulTrg = (PULONG) pff->pvTrg; // starting target surface address (t0) pulPat = (PULONG) pff->pvPat; // base pattern address (t1) xPat = pff->xPat; // pattern offset in bytes (t2) cxPat = pff->cxPat; // pattern width in pixels (t3) culFill = pff->culFill; // Size of fill in longwords pulTrgEnd = pulTrg + culFill; // compute ending target address (t4) pulPatCur = (ULONG *) ((PUCHAR) pulPat + xPat); // compute current pattern address (t5) if (cxPat == 8) // check if pattern is exactly 8 pels { loPat = *pulPatCur; // get low part of 8-byte pattern xPat +=4; // get hi part of 8-byte pattern if (xPat >= cxPat) { xPat -= cxPat; } hiPat = *((ULONG *) ((PUCHAR) pulPat + xPat)); MergePattern( pulTrg, culFill, hiPat, loPat); //do a 4 or 8-byte copy } else { // // The pattern is not 8 bytes in width // or cannot be moved 8 bytes at a time // while (pulTrg < pulTrgEnd) { *pulTrg = (*pulPatCur) ^ (*pulTrg); // XOR 4-byte target with 4-byte pattern value pulTrg += 1; // advance the target ptr one longword xPat += 4; if (xPat >= cxPat) { xPat -= cxPat; } pulPatCur = (ULONG *) ((PUCHAR) pulPat + xPat); } } } // end vFetchShiftAndMerge /****************************Private*Routine******************************\ * * VOID MergePattern( PULONG pulTrg, LONG culFill, LONG hiPat, LONG loPat) * * Routine Description: * * This routine contains common code for merging an 8-byte pattern with * a target surface. * * Arguments: * * culFill - Supplies the size of the fill in bytes. * loPat, hiPat - Supplies the 8-byte pattern to merge. * pulTrg - Supplies the starting target surface address. * * Return Value: * * None. * * \*************************************************************************/ VOID MergePattern ( PULONG pulTrg, // Starting target surface address (t0) LONG culFill, // size of fill in longwords (a1) LONG hiPat, // hi part of pattern (v1) LONG loPat // lo part of pattern (v0) ) { PULONG pulTrgEnd; // ending target surface address ULONG temp; // temp for swap pulTrgEnd = pulTrg + culFill; // ending target surface address(t4) // // If the fill size is not an even multiple of 8 bytes, then move one // longword and swap the pattern value. // if ((culFill & 0x01) != 0) { *pulTrg = loPat ^ (*pulTrg); // XOR low 4 bytes of pattern w/ target pulTrg += 1; // advance target ptr one longword culFill -= 1; if (culFill == 0) // if no more to move then we're done { return; } else // otherwise, swap 8-byte pattern value { temp = loPat; loPat = hiPat; hiPat = temp; } } // // Move 8-byte pattern value to target 8 bytes at a time. // pulTrgEnd -= 2; // ending segement address while (pulTrg <= pulTrgEnd) // if not, move 8 bytes at a time { *pulTrg = loPat ^ (*pulTrg); // XOR 4-byte pattern value pulTrg++; // advance target address *pulTrg = hiPat ^ (*pulTrg); // XOR 4-byte pattern value pulTrg++; // advance target address } return; }