1461 lines
41 KiB
C
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
|