From a91a0d77dac36e7d3694b217204e1bbdf5aa40fb Mon Sep 17 00:00:00 2001 From: Jason Filby Date: Sat, 26 May 2001 08:21:03 +0000 Subject: [PATCH] VGA software cursor svn path=/trunk/; revision=1918 --- reactos/drivers/dd/vga/display/main/enable.c | 5 +- .../drivers/dd/vga/display/objects/pointer.c | 66 +++++---- .../dd/vga/display/vgavideo/vgavideo.c | 136 ++++++++++++++++-- 3 files changed, 165 insertions(+), 42 deletions(-) diff --git a/reactos/drivers/dd/vga/display/main/enable.c b/reactos/drivers/dd/vga/display/main/enable.c index 50c3dc54749..776aec7e223 100644 --- a/reactos/drivers/dd/vga/display/main/enable.c +++ b/reactos/drivers/dd/vga/display/main/enable.c @@ -1,9 +1,9 @@ /* * entry.c * - * $Revision: 1.12 $ + * $Revision: 1.13 $ * $Author: jfilby $ - * $Date: 2001/05/02 12:29:07 $ + * $Date: 2001/05/26 08:21:02 $ * */ @@ -370,6 +370,7 @@ HSURF VGADDIEnableSurface(IN DHPDEV PDev) pdsurf->Scan0 = ppdev->fbScreen; pdsurf->BitmapStart = ppdev->fbScreen; pdsurf->StartBmp = ppdev->fbScreen; + /* pdsurf->Conv = &ConvertBuffer[0]; */ if (!InitPointer(ppdev)) { diff --git a/reactos/drivers/dd/vga/display/objects/pointer.c b/reactos/drivers/dd/vga/display/objects/pointer.c index 5e7fc4cc706..bea9ce2da9d 100644 --- a/reactos/drivers/dd/vga/display/objects/pointer.c +++ b/reactos/drivers/dd/vga/display/objects/pointer.c @@ -14,13 +14,15 @@ BOOL InitPointer(PPDEV ppdev) ppdev->PointerAttributes = sizeof(VIDEO_POINTER_ATTRIBUTES) + (CursorWidth * CursorHeight) * 2; // space for two cursors (data and mask); we assume 4bpp.. but use 8bpp for speed + ppdev->pPointerAttributes = EngAllocMem(0, 512, ALLOC_TAG); + // Allocate memory for pointer attributes ppdev->pPointerAttributes = EngAllocMem(0, ppdev->PointerAttributes, ALLOC_TAG); ppdev->pPointerAttributes->Flags = 0; // FIXME: Do this right ppdev->pPointerAttributes->Width = CursorWidth; ppdev->pPointerAttributes->Height = CursorHeight; - ppdev->pPointerAttributes->WidthInBytes = CursorWidth; + ppdev->pPointerAttributes->WidthInBytes = CursorWidth / 2; ppdev->pPointerAttributes->Enable = 0; ppdev->pPointerAttributes->Column = 0; ppdev->pPointerAttributes->Row = 0; @@ -56,19 +58,35 @@ ULONG VGADDISetPointerShape(PSURFOBJ pso, PSURFOBJ psoMask, PSURFOBJ psoColor, P PRECTL prcl, ULONG fl) { PPDEV ppdev = (PPDEV)pso->dhpdev; - ULONG cursorBytes = ppdev->pPointerAttributes->WidthInBytes * ppdev->pPointerAttributes->Height; + PCHAR DFBTmp; + ULONG DFBAllocSize; // Hide the cursor (if it's there -- FIXME?) if(ppdev->pPointerAttributes->Enable != 0) vgaHideCursor(ppdev); // Copy the mask and color bitmaps into the PPDEV - RtlCopyMemory(ppdev->pPointerAttributes->Pixels, psoMask->pvBits, cursorBytes); - if(psoColor != NULL) RtlCopyMemory(ppdev->pPointerAttributes->Pixels + cursorBytes, psoColor->pvBits, cursorBytes); + RtlCopyMemory(ppdev->pPointerAttributes->Pixels, psoMask->pvBits, psoMask->cjBits); + if(psoColor != NULL) RtlCopyMemory(ppdev->pPointerAttributes->Pixels + 256, psoColor->pvBits, psoColor->cjBits); + ppdev->pPointerAttributes->WidthInBytes = psoMask->lDelta; + + EngFreeMem(behindCursor); + behindCursor = EngAllocMem(0, ppdev->pPointerAttributes->WidthInBytes * ppdev->pPointerAttributes->Height, ALLOC_TAG); // Set the new cursor position ppdev->xyCursor.x = x; ppdev->xyCursor.y = y; + // Convert the cursor DIB into a DFB + DFBAllocSize = psoMask->cjBits; + DFBTmp = EngAllocMem(0, DFBAllocSize, ALLOC_TAG); + DIB_BltToDFB(0, 0, + ppdev->pPointerAttributes->Width, + ppdev->pPointerAttributes->Height, + DFBTmp, ppdev->pPointerAttributes->WidthInBytes, + ppdev->pPointerAttributes->Pixels, ppdev->pPointerAttributes->WidthInBytes); + RtlCopyMemory(ppdev->pPointerAttributes->Pixels, DFBTmp, psoMask->cjBits); + EngFreeMem(DFBTmp); + // Show the cursor vgaShowCursor(ppdev); } @@ -77,11 +95,15 @@ void vgaHideCursor(PPDEV ppdev) { ULONG i, j, cx, cy, bitpos; + // Clip so as not to hide where we are just going to be repainting (if called from vgaShowCursor) + + // Display what was behind cursor - DFB_BltToVGA(oldx, oldx, oldy, - ppdev->pPointerAttributes->Width-1, - ppdev->pPointerAttributes->Height-1, - behindCursor); + DFB_BltToVGA(oldx, oldy, + ppdev->pPointerAttributes->Width, + ppdev->pPointerAttributes->Height, + behindCursor, + ppdev->pPointerAttributes->WidthInBytes); oldx = ppdev->xyCursor.x; oldy = ppdev->xyCursor.y; @@ -91,31 +113,25 @@ void vgaHideCursor(PPDEV ppdev) void vgaShowCursor(PPDEV ppdev) { - ULONG i, j, cx, cy, bitpos; + ULONG i, j, cx, cy; if(ppdev->pPointerAttributes->Enable != 0) vgaHideCursor(ppdev); // Capture pixels behind the cursor cx = ppdev->xyCursor.x; cy = ppdev->xyCursor.y; - bitpos = 0; - for (j=0; jpPointerAttributes->Height; j++) - { - cx = ppdev->xyCursor.x; - for (i=0; ipPointerAttributes->Width; i++) - { - behindCursor[bitpos] = vgaGetPixel(cx, cy); - bitpos++; - cx++; - } - cy++; - } + + // repaint background + DFB_BltFromVGA(ppdev->xyCursor.x, ppdev->xyCursor.y, + ppdev->pPointerAttributes->Width, ppdev->pPointerAttributes->Height, + behindCursor, ppdev->pPointerAttributes->WidthInBytes); // Display the cursor - DIB_BltToVGA(ppdev->xyCursor.x, ppdev->xyCursor.x, ppdev->xyCursor.y, - ppdev->pPointerAttributes->Width-1, - ppdev->pPointerAttributes->Height-1, - ppdev->pPointerAttributes->Pixels); + DFB_BltToVGA_Transparent(ppdev->xyCursor.x, ppdev->xyCursor.y, + ppdev->pPointerAttributes->Width, + ppdev->pPointerAttributes->Height, + ppdev->pPointerAttributes->Pixels, + ppdev->pPointerAttributes->WidthInBytes); ppdev->pPointerAttributes->Enable = 1; } diff --git a/reactos/drivers/dd/vga/display/vgavideo/vgavideo.c b/reactos/drivers/dd/vga/display/vgavideo/vgavideo.c index 3a69bf0922a..08342607ce2 100644 --- a/reactos/drivers/dd/vga/display/vgavideo/vgavideo.c +++ b/reactos/drivers/dd/vga/display/vgavideo/vgavideo.c @@ -1,15 +1,3 @@ -// -// The current VGA bitblt routines work just fine. However, they put the 4bpp data into 1 byte each. -// To solve the problem, whenever assigning to or retrieving data from the buffer, it must pass through -// a macro which packs it appropriately. -// -// Possible future enhancements: -// * Use putByte function for middlepix when bitbltting to the VGA -// - -// PROCESS 1: Use 4bpp bitblt instead of 8bpp-bitmap/4bpp-display -// - #include #include #include @@ -451,8 +439,8 @@ void DIB_BltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta) pb++; } - opb += Source_lDelta; // new test code - pb = opb; // new test code + opb += Source_lDelta; + pb = opb; } } @@ -494,7 +482,7 @@ void DIB_TransparentBltToVGA(int x, int y, int w, int h, void *b, int Source_lDe pb++; } - opb += Source_lDelta; // new test code + opb += Source_lDelta; pb = opb; // new test code } @@ -636,3 +624,121 @@ void DFB_BltToVGA(int x, int y, int w, int h, void *b, int bw) WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); WRITE_PORT_UCHAR((PUCHAR)GRA_D, saved_GC_mode); } + +void DFB_BltToVGA_Transparent(int x, int y, int w, int h, void *b, int bw) + +// This algorithm goes from goes from left to right, and inside that loop, top to bottom. +// It also stores each 4BPP pixel in an entire byte. +{ + unsigned char *bp, *bpX; + unsigned char *vp, *vpX; + unsigned char mask; + volatile unsigned char dummy; + int byte_per_line; + int i, j; + + bpX = b; + ASSIGNVP4(x, y, vpX) + ASSIGNMK4(x, y, mask) + byte_per_line = SCREEN_X >> 3; + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 + saved_GC_mode = READ_PORT_UCHAR((PUCHAR)GRA_D); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace + saved_GC_fun = READ_PORT_UCHAR((PUCHAR)GRA_D); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask + saved_GC_mask = READ_PORT_UCHAR((PUCHAR)GRA_D); + + for (i=w; i>0; i--) { + WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask); + bp = bpX; + vp = vpX; + for (j=h; j>0; j--) { + if (*bp != 0) + { + dummy = *vp; + *vp = *bp; + } + bp += bw; + vp += byte_per_line; + } + bpX++; + if ((mask >>= 1) == 0) { + vpX++; + mask = 0x80; + } + } + + // reset GC register + WRITE_PORT_UCHAR((PUCHAR)GRA_D, saved_GC_mask); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, saved_GC_fun); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, saved_GC_mode); +} + +void DFB_BltToDIB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw) + +// This algorithm converts a DFB into a DIB +// WARNING: This algorithm is buggy +{ + unsigned char *bp, *bpX, *dib, *dibTmp; + int i, j, dib_shift; + + bpX = b; + dib = bdib + y * dibw + (x / 2); + + for (i=w; i>0; i--) { + + // determine the bit shift for the DIB pixel + dib_shift = mod(w-i, 2); + if(dib_shift > 0) dib_shift = 4; + dibTmp = dib; + + bp = bpX; + for (j=h; j>0; j--) { + *dibTmp = *bp << dib_shift | *(bp + 1); + dibTmp += dibw; + bp += bw; + } + bpX++; + if(dib_shift == 0) dib++; + } +} + +void DIB_BltToDFB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw) + +// This algorithm converts a DIB into a DFB +{ + unsigned char *bp, *bpX, *dib, *dibTmp; + int i, j, dib_shift, dib_and; + + bpX = b; + dib = bdib + y * dibw + (x / 2); + + for (i=w; i>0; i--) { + + // determine the bit shift for the DIB pixel + dib_shift = mod(w-i, 2); + if(dib_shift > 0) { + dib_shift = 0; + dib_and = 0x0f; + } else { + dib_shift = 4; + dib_and = 0xf0; + } + + dibTmp = dib; + bp = bpX; + + for (j=h; j>0; j--) { + *bp = (*dibTmp & dib_and) >> dib_shift; + dibTmp += dibw; + bp += bw; + } + + bpX++; + if(dib_shift == 0) dib++; + } +}