VGA software cursor

svn path=/trunk/; revision=1918
This commit is contained in:
Jason Filby 2001-05-26 08:21:03 +00:00
parent 02e9af8bda
commit a91a0d77da
3 changed files with 165 additions and 42 deletions

View file

@ -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)) {

View file

@ -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; j<ppdev->pPointerAttributes->Height; j++)
{
cx = ppdev->xyCursor.x;
for (i=0; i<ppdev->pPointerAttributes->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;
}

View file

@ -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 <ddk/ntddk.h>
#include <ddk/ntddvid.h>
#include <ddk/winddi.h>
@ -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++;
}
}