windows-nt/Source/XPSP1/NT/multimedia/opengl/server/pixel/px_fast.c
2020-09-26 16:20:57 +08:00

1461 lines
41 KiB
C

/******************************Module*Header*******************************\
* Module Name: px_fast.c *
* *
* Fast special case code for the pixel routines *
* *
* Created: 10-Oct-1995 *
* Author: Drew Bliss [drewb] *
* *
* Copyright (c) 1995 Microsoft Corporation *
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include <gencx.h>
#include <devlock.h>
#include "px_fast.h"
#ifdef NT
// Color rescaling table for [0,255] -> [0,7]
// Generated by (i*14+255)/510, which matches the OpenGL conversion of
// i*7.0/255.0+0.5
static GLubyte ab255to7[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
};
// Similar table for [0,255] -> [0,3]
static GLubyte ab255to3[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
};
// Color rescaling table for [0,7] -> [0,255]
// Computed as i*255/7
static GLubyte ab7to255[8] =
{
0, 36, 72, 109, 145, 182, 218, 255
};
// Similar table for [0,3] -> [0,255]
static GLubyte ab3to255[4] =
{
0, 85, 170, 255
};
/******************************Public*Routine******************************\
*
* DrawRgbPixels
*
* Special case of glDrawPixels for GL_RGB with straight data copy
*
* History:
* Tue Oct 10 18:43:04 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
GLboolean DrawRgbPixels(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
{
HDC hdc = NULL;
HBITMAP hbm = NULL;
__GLcolorBuffer *cfb;
BYTE abBitmapInfo[sizeof(BITMAPINFO)+2*sizeof(RGBQUAD)];
BITMAPINFO *pbmi = NULL;
BITMAPINFOHEADER *pbmih;
BYTE *pbBits, *pbSrc, *pbDst;
int x, y, xDst, yDst;
GLboolean bFail = GL_TRUE;
int cbSrcLine, cbSrcExtra, cbDstExtra, cbSrcElement, cbDstElement;
int cbSrcWidth, cbDstWidth;
int cBits;
__GLGENcontext *gengc;
HPALETTE hpal;
#if 0
DbgPrint("DrawRgbPixels\n");
#endif
gengc = (__GLGENcontext *)gc;
cBits = gengc->gsurf.pfd.cColorBits;
// Don't bother with 4bpp because of problems with color reduction
// The same problems occur in 8bpp but there is special case code
// to handle it.
if (cBits < 8)
{
return GL_FALSE;
}
// If there is no lock, we must have failed to reacquire the lock
// from some previous call. This is an error condition
// and we should not continue.
if (gengc->fsLocks == 0)
{
WARNING("DrawRgbPixels: No lock\n");
return GL_FALSE;
}
// We need to synchronize with GDI so that the surface state is
// stable before we begin making GDI calls
glsrvSynchronizeWithGdi(gengc, gengc->pwndLocked, COLOR_LOCK_FLAGS);
cfb = gc->drawBuffer;
// Determine buffer coordinates
xDst = __GL_UNBIAS_X(gc, spanInfo->startCol);
yDst = __GL_UNBIAS_Y(gc, spanInfo->startRow)-spanInfo->height+1;
if (cBits == 8)
{
pbmi = (BITMAPINFO *)gcTempAlloc(gc, sizeof(BITMAPINFO)+
255*sizeof(RGBQUAD));
if (pbmi == NULL)
{
goto EH_Fail;
}
}
else
{
pbmi = (BITMAPINFO *)abBitmapInfo;
}
pbmih = &pbmi->bmiHeader;
pbmih->biSize = sizeof(BITMAPINFOHEADER);
// Start out setting the width to the line length to describe
// the actual data coming in
pbmih->biWidth = spanInfo->srcLineLength;
pbmih->biHeight = spanInfo->height;
pbmih->biPlanes = 1;
if (cBits == 8)
{
int i;
RGBQUAD rqTmp;
// If the destination is 8bpp then we do the color
// reduction ourselves. In this case we want to create
// an 8bpp DIB whose color table matches the destination
pbmih->biBitCount = 8;
pbmih->biCompression = BI_RGB;
hpal = GetCurrentObject(CURRENT_DC, OBJ_PAL);
if (hpal == NULL)
{
goto EH_Fail;
}
if (GetPaletteEntries(hpal, 0, 256,
(LPPALETTEENTRY)pbmi->bmiColors) != 256)
{
goto EH_Fail;
}
for (i = 0; i < 256; i++)
{
rqTmp = pbmi->bmiColors[i];
pbmi->bmiColors[i].rgbRed = rqTmp.rgbBlue;
pbmi->bmiColors[i].rgbBlue = rqTmp.rgbRed;
pbmi->bmiColors[i].rgbReserved = 0;
}
cbDstElement = 1;
}
else
{
if (spanInfo->srcFormat == GL_BGRA_EXT)
{
pbmih->biBitCount = 32;
pbmih->biCompression = BI_BITFIELDS;
*((DWORD *)pbmi->bmiColors+0) = 0xff0000;
*((DWORD *)pbmi->bmiColors+1) = 0xff00;
*((DWORD *)pbmi->bmiColors+2) = 0xff;
cbDstElement = 4;
}
else
{
pbmih->biBitCount = 24;
pbmih->biCompression = BI_RGB;
cbDstElement = 3;
}
}
pbmih->biSizeImage = 0;
pbmih->biXPelsPerMeter = 0;
pbmih->biYPelsPerMeter = 0;
pbmih->biClrUsed = 0;
pbmih->biClrImportant = 0;
// For GL_BGR_EXT and GL_BGRA_EXT we can use the data directly if
// it is laid out in memory like a DIB. The key thing to check
// is that scanlines are DWORD aligned.
// If we can't use the data directly, fall back on the DIB section
// method which works for anything
if (cBits > 8 &&
(spanInfo->srcFormat == GL_BGR_EXT ||
spanInfo->srcFormat == GL_BGRA_EXT) &&
spanInfo->srcAlignment == 4)
{
if (SetDIBitsToDevice(CURRENT_DC, xDst, yDst,
spanInfo->width, spanInfo->height,
spanInfo->srcSkipPixels, spanInfo->srcSkipLines,
0, spanInfo->height, spanInfo->srcImage,
pbmi, DIB_RGB_COLORS) == 0)
{
goto EH_Fail;
}
bFail = GL_FALSE;
goto EH_Fail;
}
// Create a DIB section of the appropriate height and width
// We originally set the BITMAPINFO width to the width of the
// incoming data, but we only need to create a DIB section
// as large as the data we're going to copy so reset the
// width
pbmih->biWidth = spanInfo->width;
hdc = CreateCompatibleDC(CURRENT_DC);
if (hdc == NULL)
{
goto EH_Fail;
}
hbm = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS,
&pbBits, NULL, 0);
if (hbm == NULL)
{
goto EH_Fail;
}
if (SelectObject(hdc, hbm) == NULL)
{
goto EH_Fail;
}
// Copy the input data to the DIB's contents, possibly swapping R and B,
// plus skipping any appropriate data, fixing up alignment and
// obeying the line length
if (spanInfo->srcFormat == GL_BGRA_EXT)
{
cbSrcElement = 4;
}
else
{
cbSrcElement = 3;
}
cbSrcLine = spanInfo->srcLineLength*cbSrcElement;
cbSrcExtra = cbSrcLine % spanInfo->srcAlignment;
if (cbSrcExtra != 0)
{
cbSrcExtra = spanInfo->srcAlignment-cbSrcExtra;
cbSrcLine += cbSrcExtra;
}
cbSrcWidth = spanInfo->width * cbSrcElement;
cbSrcExtra = cbSrcLine - cbSrcWidth;
cbDstWidth = spanInfo->width * cbDstElement;
cbDstExtra = cbDstWidth & 3;
if (cbDstExtra != 0)
{
cbDstExtra = 4-cbDstExtra;
}
pbSrc = (BYTE *)spanInfo->srcImage+
spanInfo->srcSkipPixels*cbSrcElement+
spanInfo->srcSkipLines*cbSrcLine;
pbDst = pbBits;
if (cBits == 8)
{
// For 8bpp destinations we need to perform the color reduction
// ourselves because GDI's reduction doesn't match OpenGL's.
// GDI does a closest-match-in-palette for each pixel, while
// OpenGL does a rescaling of the color range plus rounding
switch(spanInfo->srcFormat)
{
case GL_RGB:
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*pbDst++ =
(ab255to3[*(pbSrc+2)] << cfb->blueShift) |
(ab255to7[*(pbSrc+1)] << cfb->greenShift) |
(ab255to7[*(pbSrc+0)] << cfb->redShift);
pbSrc += 3;
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
break;
case GL_BGR_EXT:
case GL_BGRA_EXT:
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*pbDst++ =
(ab255to3[*(pbSrc+0)] << cfb->blueShift) |
(ab255to7[*(pbSrc+1)] << cfb->greenShift) |
(ab255to7[*(pbSrc+2)] << cfb->redShift);
pbSrc += cbSrcElement;
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
break;
}
}
else
{
switch(spanInfo->srcFormat)
{
case GL_RGB:
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*pbDst++ = *(pbSrc+2);
*pbDst++ = *(pbSrc+1);
*pbDst++ = *pbSrc;
pbSrc += 3;
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
break;
case GL_BGR_EXT:
case GL_BGRA_EXT:
if (cbSrcExtra == 0 && cbDstExtra == 0)
{
CopyMemory(pbDst, pbSrc, cbSrcWidth*spanInfo->height);
}
else
{
cbDstWidth += cbDstExtra;
for (y = 0; y < spanInfo->height; y++)
{
CopyMemory(pbDst, pbSrc, cbSrcWidth);
pbSrc += cbSrcLine;
pbDst += cbDstWidth;
}
}
break;
}
}
// Copy the DIB to the buffer
bFail = !BitBlt(CURRENT_DC, xDst, yDst, spanInfo->width, spanInfo->height,
hdc, 0, 0, SRCCOPY);
EH_Fail:
if (hdc != NULL)
{
DeleteDC(hdc);
}
if (hbm != NULL)
{
DeleteObject(hbm);
}
if (pbmi != NULL && pbmi != (BITMAPINFO *)abBitmapInfo)
{
gcTempFree(gc, pbmi);
}
// No more need for GDI operations
glsrvDecoupleFromGdi(gengc, gengc->pwndLocked, COLOR_LOCK_FLAGS);
return !bFail;
}
/******************************Public*Routine******************************\
*
* StoreZPixels
*
* Special case of glDrawPixels for GL_DEPTH_COMPONENTs going directly
* into the Z buffer with no color buffer modification.
*
* History:
* Tue Oct 10 18:43:36 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
GLboolean StoreZPixels(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
{
__GLdepthBuffer *fb;
BYTE *pbBits, *pbSrc, *pbDst;
int x, y;
int cbElement, cbSrcLine, cbSrcExtra, cbDstExtra;
#if 0
DbgPrint("StoreZPixels\n");
#endif
fb = &gc->depthBuffer;
// Copy the input data to the depth buffer,
// skipping any appropriate data, fixing up alignment and
// obeying the line length
switch(spanInfo->srcType)
{
case GL_UNSIGNED_SHORT:
cbElement = 2;
break;
case GL_UNSIGNED_INT:
cbElement = 4;
break;
default:
ASSERTOPENGL(0, "StoreZPixels: Unknown srcType\n");
break;
}
cbSrcLine = spanInfo->srcLineLength*cbElement;
cbSrcExtra = cbSrcLine % spanInfo->srcAlignment;
if (cbSrcExtra != 0)
{
cbSrcExtra = spanInfo->srcAlignment-cbSrcExtra;
cbSrcLine += cbSrcExtra;
}
pbSrc = (BYTE *)spanInfo->srcImage+
spanInfo->srcSkipPixels*cbElement+
spanInfo->srcSkipLines*cbSrcLine;
// Determine buffer coordinates
x = spanInfo->startCol;
y = spanInfo->startRow;
if (fb->buf.elementSize == sizeof(__GLzValue))
{
pbDst = (BYTE *)__GL_DEPTH_ADDR(fb, (__GLzValue*), x, y);
cbDstExtra = -(fb->buf.outerWidth+spanInfo->width)*sizeof(__GLzValue);
}
else
{
pbDst = (BYTE *)__GL_DEPTH_ADDR(fb, (__GLz16Value*), x, y);
cbDstExtra = -(fb->buf.outerWidth+spanInfo->width)*
sizeof(__GLz16Value);
}
switch(spanInfo->srcType)
{
case GL_UNSIGNED_SHORT:
if (fb->buf.elementSize == sizeof(__GLzValue))
{
ASSERTOPENGL(fb->scale == 0x7fffffff,
"Depth buffer scale invalid\n");
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*(__GLzValue *)pbDst =
(__GLzValue)(*(GLushort *)pbSrc) << (Z16_SHIFT-1);
pbDst += sizeof(__GLzValue);
pbSrc += cbElement;
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
}
else
{
ASSERTOPENGL(fb->scale == 0x7fff,
"Depth buffer scale invalid\n");
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*(__GLz16Value *)pbDst =
(*(GLushort *)pbSrc) >> 1;
pbDst += sizeof(__GLz16Value);
pbSrc += cbElement;
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
}
break;
case GL_UNSIGNED_INT:
if (fb->buf.elementSize == sizeof(__GLzValue))
{
ASSERTOPENGL(fb->scale == 0x7fffffff,
"Depth buffer scale invalid\n");
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*(__GLzValue *)pbDst =
(*(GLuint *)pbSrc) >> 1;
pbDst += sizeof(__GLzValue);
pbSrc += cbElement;
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
}
else
{
ASSERTOPENGL(fb->scale == 0x7fff,
"Depth buffer scale invalid\n");
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*(__GLz16Value *)pbDst =
(__GLz16Value)((*(GLuint *)pbSrc) >> (Z16_SHIFT+1));
pbDst += sizeof(__GLz16Value);
pbSrc += cbElement;
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
}
break;
}
return GL_TRUE;
}
/******************************Public*Routine******************************\
*
* ReadRgbPixels
*
* Special case of glReadPixels for GL_RGB with straight data copy
*
* History:
* Tue Oct 10 18:43:04 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
GLboolean ReadRgbPixels(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
{
HDC hdc = NULL;
HBITMAP hbm = NULL;
__GLcolorBuffer *cfb;
BYTE abBitmapInfo[sizeof(BITMAPINFO)+2*sizeof(RGBQUAD)];
BITMAPINFO *pbmi = NULL;
BITMAPINFOHEADER *pbmih;
BYTE *pbBits, *pbDst, *pbSrc;
DWORD *pdwDst;
int x, y;
GLboolean bFail = GL_TRUE;
int cbDstLine, cbDstExtra, cbSrcExtra, cbSrcElement, cbDstElement;
int cbSrcWidth, cbDstWidth;
int cBits;
HPALETTE hpal;
__GLGENcontext *gengc;
#if 0
DbgPrint("ReadRgbPixels\n");
#endif
gengc = (__GLGENcontext *)gc;
cBits = gengc->gsurf.pfd.cColorBits;
// Don't bother with 4bpp surfaces
if (cBits < 8)
{
return GL_FALSE;
}
// If there is no lock, we must have failed to reacquire the lock
// from some previous call. This is an error condition
// and we should not continue.
if (gengc->fsLocks == 0)
{
WARNING("ReadRgbPixels: No lock\n");
return GL_FALSE;
}
// We need to synchronize with GDI so that the surface state is
// stable before we begin making GDI calls
glsrvSynchronizeWithGdi(gengc, gengc->pwndLocked, COLOR_LOCK_FLAGS);
cfb = gc->readBuffer;
if (cBits == 8)
{
pbmi = (BITMAPINFO *)gcTempAlloc(gc, sizeof(BITMAPINFO)+
255*sizeof(RGBQUAD));
if (pbmi == NULL)
{
goto EH_Fail;
}
}
else
{
pbmi = (BITMAPINFO *)abBitmapInfo;
}
pbmih = &pbmi->bmiHeader;
pbmih->biSize = sizeof(BITMAPINFOHEADER);
// Start out setting the width to the line length to describe
// the actual data coming in
pbmih->biWidth = spanInfo->width;
pbmih->biHeight = spanInfo->height;
pbmih->biPlanes = 1;
if (cBits == 8)
{
int i;
RGBQUAD rqTmp;
// If the destination is 8bpp then we do the color
// expansion ourselves. In this case we want to create
// an 8bpp DIB whose color table matches the source
pbmih->biBitCount = 8;
pbmih->biCompression = BI_RGB;
hpal = GetCurrentObject(CURRENT_DC, OBJ_PAL);
if (hpal == NULL)
{
goto EH_Fail;
}
if (GetPaletteEntries(hpal, 0, 256,
(LPPALETTEENTRY)pbmi->bmiColors) != 256)
{
goto EH_Fail;
}
for (i = 0; i < 256; i++)
{
rqTmp = pbmi->bmiColors[i];
pbmi->bmiColors[i].rgbRed = rqTmp.rgbBlue;
pbmi->bmiColors[i].rgbBlue = rqTmp.rgbRed;
pbmi->bmiColors[i].rgbReserved = 0;
}
cbSrcElement = 1;
}
else
{
if (spanInfo->dstFormat == GL_BGRA_EXT)
{
pbmih->biBitCount = 32;
pbmih->biCompression = BI_BITFIELDS;
*((DWORD *)pbmi->bmiColors+0) = 0xff0000;
*((DWORD *)pbmi->bmiColors+1) = 0xff00;
*((DWORD *)pbmi->bmiColors+2) = 0xff;
cbSrcElement = 4;
}
else
{
pbmih->biBitCount = 24;
pbmih->biCompression = BI_RGB;
cbSrcElement = 3;
}
}
pbmih->biSizeImage = 0;
pbmih->biXPelsPerMeter = 0;
pbmih->biYPelsPerMeter = 0;
pbmih->biClrUsed = 0;
pbmih->biClrImportant = 0;
// Create a DIB section of the appropriate height and width
// We originally set the BITMAPINFO width to the width of the
// incoming data, but we only need to create a DIB section
// as large as the data we're going to copy so reset the
// width
pbmih->biWidth = spanInfo->width;
hdc = CreateCompatibleDC(CURRENT_DC);
if (hdc == NULL)
{
goto EH_Fail;
}
hbm = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS,
&pbBits, NULL, 0);
if (hbm == NULL)
{
goto EH_Fail;
}
if (SelectObject(hdc, hbm) == NULL)
{
goto EH_Fail;
}
if (cBits <= 8)
{
hpal = GetCurrentObject(CURRENT_DC, OBJ_PAL);
if (hpal != NULL)
{
if (SelectPalette(hdc, hpal, FALSE) == NULL)
{
goto EH_Fail;
}
if (RealizePalette(hdc) == GDI_ERROR)
{
goto EH_Fail;
}
}
}
// Determine buffer coordinates
x = __GL_UNBIAS_X(gc, (GLint)spanInfo->readX);
y = __GL_UNBIAS_Y(gc, (GLint)spanInfo->readY)-spanInfo->height+1;
// Copy the buffer's contents to the DIB
if (!BitBlt(hdc, 0, 0, spanInfo->width, spanInfo->height,
CURRENT_DC, x, y, SRCCOPY))
{
goto EH_Fail;
}
GdiFlush();
// Copy the DIB's contents to the output buffer, swapping R and B,
// plus skipping any appropriate data, fixing up alignment and
// obeying the line length
if (spanInfo->dstFormat == GL_BGRA_EXT)
{
cbDstElement = 4;
}
else
{
cbDstElement = 3;
}
cbDstLine = spanInfo->dstLineLength*cbDstElement;
cbDstExtra = cbDstLine % spanInfo->dstAlignment;
if (cbDstExtra != 0)
{
cbDstExtra = spanInfo->dstAlignment-cbDstExtra;
cbDstLine += cbDstExtra;
}
cbDstWidth = spanInfo->width * cbDstElement;
cbDstExtra = cbDstLine - cbDstWidth;
cbSrcWidth = spanInfo->width * cbSrcElement;
cbSrcExtra = cbSrcWidth & 3;
if (cbSrcExtra != 0)
{
cbSrcExtra = 4-cbSrcExtra;
}
pbSrc = pbBits;
pbDst = (BYTE *)spanInfo->dstImage+
spanInfo->dstSkipPixels*cbDstElement+
spanInfo->dstSkipLines*cbDstLine;
if (cBits == 8)
{
BYTE b;
// For 8bpp sources we need to do the color expansion ourselves
// because the 8bpp palette is only an approximation of a 3-3-2
// palette since the system colors are forced into it. Also,
// GL does a rescaling of the color range.
switch(spanInfo->dstFormat)
{
case GL_RGB:
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
b = *pbSrc++;
*pbDst++ =
ab7to255[(b & gc->modes.redMask) >> cfb->redShift];
*pbDst++ =
ab7to255[(b & gc->modes.greenMask) >> cfb->greenShift];
*pbDst++ =
ab3to255[(b & gc->modes.blueMask) >> cfb->blueShift];
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
break;
case GL_BGR_EXT:
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
b = *pbSrc++;
*pbDst++ =
ab3to255[(b & gc->modes.blueMask) >> cfb->blueShift];
*pbDst++ =
ab7to255[(b & gc->modes.greenMask) >> cfb->greenShift];
*pbDst++ =
ab7to255[(b & gc->modes.redMask) >> cfb->redShift];
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
break;
case GL_BGRA_EXT:
pdwDst = (DWORD *)pbDst;
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
b = *pbSrc++;
*pdwDst++ =
0xff000000 |
((DWORD)ab7to255[(b & gc->modes.redMask) >>
cfb->redShift] << 16) |
((DWORD)ab7to255[(b & gc->modes.greenMask) >>
cfb->greenShift] << 8) |
((DWORD)ab3to255[(b & gc->modes.blueMask) >>
cfb->blueShift]);
}
pbSrc += cbSrcExtra;
pdwDst = (DWORD *)(((BYTE *)pdwDst) + cbDstExtra);
}
break;
}
}
else
{
switch(spanInfo->dstFormat)
{
case GL_RGB:
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*pbDst++ = *(pbSrc+2);
*pbDst++ = *(pbSrc+1);
*pbDst++ = *pbSrc;
pbSrc += 3;
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
break;
case GL_BGR_EXT:
if (cbSrcExtra == 0 && cbDstExtra == 0)
{
CopyMemory(pbDst, pbSrc, cbDstWidth*spanInfo->height);
}
else
{
cbSrcWidth += cbSrcExtra;
for (y = 0; y < spanInfo->height; y++)
{
CopyMemory(pbDst, pbSrc, cbDstWidth);
pbSrc += cbSrcWidth;
pbDst += cbDstLine;
}
}
break;
case GL_BGRA_EXT:
{
DWORD *pdwSrc = (DWORD *)pbSrc;
pdwDst = (DWORD *)pbDst;
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*pdwDst++ = 0xff000000 | (*pdwSrc++);
}
pdwSrc = (DWORD *)(((BYTE *)pdwSrc) + cbSrcExtra);
pdwDst = (DWORD *)(((BYTE *)pdwDst) + cbDstExtra);
}
}
}
}
bFail = GL_FALSE;
EH_Fail:
if (hdc != NULL)
{
DeleteDC(hdc);
}
if (hbm != NULL)
{
DeleteObject(hbm);
}
if (pbmi != NULL && pbmi != (BITMAPINFO *)abBitmapInfo)
{
gcTempFree(gc, pbmi);
}
// No more need for GDI operations
glsrvDecoupleFromGdi(gengc, gengc->pwndLocked, COLOR_LOCK_FLAGS);
return !bFail;
}
/******************************Public*Routine******************************\
*
* ReadZPixels
*
* Special case of glReadPixels for GL_DEPTH_COMPONENTs with
* unsigned types that require minimal transformation
*
* History:
* Tue Oct 10 18:43:36 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
GLboolean ReadZPixels(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
{
__GLdepthBuffer *fb;
BYTE *pbBits, *pbSrc, *pbDst;
int x, y;
int cbElement, cbDstLine, cbSrcExtra, cbDstExtra;
#if 0
DbgPrint("ReadZPixels\n");
#endif
fb = &gc->depthBuffer;
// Copy the depth buffer data to the output
// skipping any appropriate data, fixing up alignment and
// obeying the line length
switch(spanInfo->dstType)
{
case GL_UNSIGNED_SHORT:
cbElement = 2;
break;
case GL_UNSIGNED_INT:
cbElement = 4;
break;
default:
ASSERTOPENGL(0, "ReadZPixels: Unknown dstType\n");
break;
}
cbDstLine = spanInfo->dstLineLength*cbElement;
cbDstExtra = cbDstLine % spanInfo->dstAlignment;
if (cbDstExtra != 0)
{
cbDstExtra = spanInfo->dstAlignment-cbDstExtra;
cbDstLine += cbDstExtra;
}
pbDst = (BYTE *)spanInfo->dstImage+
spanInfo->dstSkipPixels*cbElement+
spanInfo->dstSkipLines*cbDstLine;
// Determine buffer coordinates
x = (GLint)spanInfo->readX;
y = (GLint)spanInfo->readY;
if (fb->buf.elementSize == sizeof(__GLzValue))
{
pbSrc = (BYTE *)__GL_DEPTH_ADDR(fb, (__GLzValue*), x, y);
cbSrcExtra = -(fb->buf.outerWidth+spanInfo->width)*sizeof(__GLzValue);
}
else
{
pbSrc = (BYTE *)__GL_DEPTH_ADDR(fb, (__GLz16Value*), x, y);
cbSrcExtra = -(fb->buf.outerWidth+spanInfo->width)*
sizeof(__GLz16Value);
}
switch(spanInfo->dstType)
{
case GL_UNSIGNED_SHORT:
if (fb->buf.elementSize == sizeof(__GLzValue))
{
ASSERTOPENGL(fb->scale == 0x7fffffff,
"Depth buffer scale invalid\n");
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*(GLushort *)pbDst =
(GLushort)(*(__GLzValue *)pbSrc) >> (Z16_SHIFT-1);
pbSrc += sizeof(__GLzValue);
pbDst += cbElement;
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
}
else
{
ASSERTOPENGL(fb->scale == 0x7fff,
"Depth buffer scale invalid\n");
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*(GLushort *)pbDst =
(*(__GLz16Value *)pbSrc) << 1;
pbSrc += sizeof(__GLz16Value);
pbDst += cbElement;
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
}
break;
case GL_UNSIGNED_INT:
if (fb->buf.elementSize == sizeof(__GLzValue))
{
ASSERTOPENGL(fb->scale == 0x7fffffff,
"Depth buffer scale invalid\n");
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*(GLuint *)pbDst =
(*(__GLzValue *)pbSrc) << 1;
pbSrc += sizeof(__GLzValue);
pbDst += cbElement;
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
}
else
{
ASSERTOPENGL(fb->scale == 0x7fff,
"Depth buffer scale invalid\n");
for (y = 0; y < spanInfo->height; y++)
{
for (x = 0; x < spanInfo->width; x++)
{
*(GLuint *)pbDst =
(GLuint)((*(__GLz16Value *)pbSrc) << (Z16_SHIFT+1));
pbSrc += sizeof(__GLz16Value);
pbDst += cbElement;
}
pbSrc += cbSrcExtra;
pbDst += cbDstExtra;
}
}
break;
}
return GL_TRUE;
}
/******************************Public*Routine******************************\
*
* CopyRgbPixels
*
* Special case of glCopyPixels for straight data copy
*
* Currently we only have to deal with normal color buffers
* If we start supporting aux buffers it may no longer be possible
* to accelerate this function in all cases
*
* History:
* Tue Oct 10 18:43:04 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
GLboolean CopyRgbPixels(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
{
__GLcolorBuffer *cfbSrc, *cfbDst;
int xSrc, ySrc, xDst, yDst;
GLboolean bFail;
__GLGENcontext *gengc;
#if 0
DbgPrint("CopyRgbPixels\n");
#endif
gengc = (__GLGENcontext *)gc;
// If there is no lock, we must have failed to reacquire the lock
// from some previous call. This is an error condition
// and we should not continue.
if (gengc->fsLocks == 0)
{
WARNING("CopyRgbPixels: No lock\n");
return GL_FALSE;
}
// We need to synchronize with GDI so that the surface state is
// stable before we begin making GDI calls
glsrvSynchronizeWithGdi(gengc, gengc->pwndLocked, COLOR_LOCK_FLAGS);
cfbSrc = gc->readBuffer;
cfbDst = gc->drawBuffer;
// Determine buffer coordinates
xSrc = __GL_UNBIAS_X(gc, (GLint)spanInfo->readX);
ySrc = __GL_UNBIAS_Y(gc, (GLint)spanInfo->readY)-spanInfo->height+1;
xDst = __GL_UNBIAS_X(gc, (GLint)spanInfo->x);
yDst = __GL_UNBIAS_Y(gc, (GLint)spanInfo->y)-spanInfo->height+1;
// Copy the data between the buffers
bFail = (GLboolean)BitBlt(CURRENT_DC_CFB(cfbDst), xDst, yDst,
spanInfo->width, spanInfo->height,
CURRENT_DC_CFB(cfbSrc), xSrc, ySrc, SRCCOPY);
// No more need for GDI operations
glsrvDecoupleFromGdi(gengc, gengc->pwndLocked, COLOR_LOCK_FLAGS);
return bFail;
}
/******************************Public*Routine******************************\
*
* CopyZPixels
*
* Special case of glCopyPixels for GL_DEPTH where there is no
* destination color buffer and the Z function is GL_ALWAYS
*
* History:
* Tue Oct 10 18:43:36 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
GLboolean CopyZPixels(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
{
__GLdepthBuffer *fb;
BYTE *pbSrc, *pbDst;
int y, xSrc, ySrc, xDst, yDst;
int cbLine, cbWidth;
#if 0
DbgPrint("CopyZPixels\n");
#endif
fb = &gc->depthBuffer;
// Determine buffer coordinates
xSrc = (GLint)spanInfo->readX;
ySrc = (GLint)spanInfo->readY;
xDst = (GLint)spanInfo->x;
yDst = (GLint)spanInfo->y;
if (fb->buf.elementSize == sizeof(__GLzValue))
{
pbSrc = (BYTE *)__GL_DEPTH_ADDR(fb, (__GLzValue*), xSrc, ySrc);
pbDst = (BYTE *)__GL_DEPTH_ADDR(fb, (__GLzValue*), xDst, yDst);
cbLine = -fb->buf.outerWidth*sizeof(__GLzValue);
cbWidth = spanInfo->width*sizeof(__GLzValue);
}
else
{
pbSrc = (BYTE *)__GL_DEPTH_ADDR(fb, (__GLz16Value*), xSrc, ySrc);
pbDst = (BYTE *)__GL_DEPTH_ADDR(fb, (__GLz16Value*), xDst, yDst);
cbLine = -fb->buf.outerWidth*sizeof(__GLz16Value);
cbWidth = spanInfo->width*sizeof(__GLz16Value);
}
if (cbLine == cbWidth)
{
MoveMemory(pbDst, pbSrc, cbWidth*spanInfo->height);
}
else
{
// Adjust copy direction to handle overlap cases
if (ySrc > yDst)
{
pbSrc += cbLine*spanInfo->height;
pbDst += cbLine*spanInfo->height;
for (y = 0; y < spanInfo->height; y++)
{
pbSrc -= cbLine;
pbDst -= cbLine;
CopyMemory(pbDst, pbSrc, cbWidth);
}
}
else if (ySrc < yDst)
{
for (y = 0; y < spanInfo->height; y++)
{
CopyMemory(pbDst, pbSrc, cbWidth);
pbSrc += cbLine;
pbDst += cbLine;
}
}
else
{
for (y = 0; y < spanInfo->height; y++)
{
MoveMemory(pbDst, pbSrc, cbWidth);
pbSrc += cbLine;
pbDst += cbLine;
}
}
}
return GL_TRUE;
}
/******************************Public*Routine******************************\
*
* CopyAlignedImage
*
* Copies data between memory images where straight data copy is applicable
*
* This routine doesn't handle overlap
* The old code doesn't seem to either, so perhaps this isn't a problem
*
* History:
* Tue Nov 07 14:27:06 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
GLboolean CopyAlignedImage(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
{
int cbLine;
int y;
GLubyte *src, *dst;
ASSERTOPENGL(spanInfo->srcGroupIncrement == spanInfo->dstGroupIncrement,
"CopyAlignedImage: Group size mismatch\n");
cbLine = spanInfo->width*spanInfo->dstGroupIncrement;
if (spanInfo->srcRowIncrement == spanInfo->dstRowIncrement &&
cbLine == spanInfo->srcRowIncrement)
{
// Source and destination rows are the same size and the copy
// is copying all of the row so we can do everything with a
// single copy
CopyMemory(spanInfo->dstCurrent, spanInfo->srcCurrent,
cbLine*spanInfo->height);
}
else
{
// Either the rows aren't the same size or we're not copying
// all of each row, so we have to go row by row
src = spanInfo->srcCurrent;
dst = spanInfo->dstCurrent;
for (y = spanInfo->height; y > 0; y--)
{
CopyMemory(dst, src, cbLine);
src += spanInfo->srcRowIncrement;
dst += spanInfo->dstRowIncrement;
}
}
return GL_TRUE;
}
/******************************Public*Routine******************************\
*
* CopyRgbToBgraImage
*
* Special case for 24-bit RGB to 32-bit BGRA
*
* History:
* Tue Nov 07 15:09:47 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
GLboolean CopyRgbToBgraImage(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
{
int x, y;
GLubyte *src;
GLuint *dst;
int srcStep, dstStep;
src = spanInfo->srcCurrent;
dst = spanInfo->dstCurrent;
srcStep = spanInfo->srcRowIncrement-
spanInfo->width*spanInfo->srcGroupIncrement;
dstStep = spanInfo->dstRowIncrement-
spanInfo->width*spanInfo->dstGroupIncrement;
ASSERTOPENGL((dstStep & 3) == 0, "Non-dword step\n");
dstStep >>= 2;
for (y = spanInfo->height; y > 0; y--)
{
for (x = spanInfo->width; x > 0; x--)
{
*dst++ =
0xff000000 |
((GLuint)src[0] << 16) |
((GLuint)src[1] << 8) |
((GLuint)src[2] << 0);
src += 3;
}
src += srcStep;
dst += dstStep;
}
return GL_TRUE;
}
/******************************Public*Routine******************************\
*
* CopyRgbaToBgraImage
*
* Special case for 32-bit RGBA to 32-bit BGRA
*
* History:
* Tue Nov 07 15:09:47 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
GLboolean CopyRgbaToBgraImage(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
{
int x, y;
GLubyte *src;
GLuint *dst;
int srcStep, dstStep;
src = spanInfo->srcCurrent;
dst = spanInfo->dstCurrent;
srcStep = spanInfo->srcRowIncrement-
spanInfo->width*spanInfo->srcGroupIncrement;
dstStep = spanInfo->dstRowIncrement-
spanInfo->width*spanInfo->dstGroupIncrement;
ASSERTOPENGL((dstStep & 3) == 0, "Non-dword step\n");
dstStep >>= 2;
for (y = spanInfo->height; y > 0; y--)
{
for (x = spanInfo->width; x > 0; x--)
{
*dst++ =
((GLuint)src[0] << 16) |
((GLuint)src[1] << 8) |
((GLuint)src[2] << 0) |
((GLuint)src[3] << 24);
src += 4;
}
src += srcStep;
dst += dstStep;
}
return GL_TRUE;
}
/******************************Public*Routine******************************\
*
* CopyBgrToBgraImage
*
* Special case for 24-bit BGR to 32-bit BGRA
*
* History:
* Tue Nov 07 15:09:47 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
GLboolean CopyBgrToBgraImage(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
{
int x, y;
GLubyte *src;
GLuint *dst;
int srcStep, dstStep;
src = spanInfo->srcCurrent;
dst = spanInfo->dstCurrent;
srcStep = spanInfo->srcRowIncrement-
spanInfo->width*spanInfo->srcGroupIncrement;
dstStep = spanInfo->dstRowIncrement-
spanInfo->width*spanInfo->dstGroupIncrement;
ASSERTOPENGL((dstStep & 3) == 0, "Non-dword step\n");
dstStep >>= 2;
for (y = spanInfo->height; y > 0; y--)
{
for (x = spanInfo->width; x > 0; x--)
{
*dst++ =
0xff000000 |
((GLuint)src[0] << 0) |
((GLuint)src[1] << 8) |
((GLuint)src[2] << 16);
src += 3;
}
src += srcStep;
dst += dstStep;
}
return GL_TRUE;
}
#endif