📄 wmesa.c
字号:
/*
* Windows (Win32) device driver for Mesa
*
*/
#include "wmesadef.h"
#include "colors.h"
#include <GL/wmesa.h>
#include "extensions.h"
#include "framebuffer.h"
#include "renderbuffer.h"
#include "drivers/common/driverfuncs.h"
#include "array_cache/acache.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "tnl/tnl.h"
#include "tnl/t_context.h"
#include "tnl/t_pipeline.h"
#define FLIP(Y) (Current->height-(Y)-1)
/* Static Data */
static PWMC Current = NULL;
/*
* Every driver should implement a GetString function in order to
* return a meaningful GL_RENDERER string.
*/
static const GLubyte *wmesa_get_string(GLcontext *ctx, GLenum name)
{
return (name == GL_RENDERER) ?
(GLubyte *) "Mesa Windows GDI Driver" : NULL;
}
/*
* Determine the pixel format based on the pixel size.
*/
static void wmSetPixelFormat(PWMC pwc, HDC hDC)
{
pwc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
// TEMP - only 16 and 32 bit targets are supported now
assert(pwc->cColorBits == 16 ||
pwc->cColorBits == 32);
switch(pwc->cColorBits){
case 8:
pwc->pixelformat = PF_INDEX8;
break;
case 16:
pwc->pixelformat = PF_5R6G5B;
break;
case 32:
pwc->pixelformat = PF_8R8G8B;
break;
default:
pwc->pixelformat = PF_BADFORMAT;
}
}
/*
* Create DIB for back buffer.
* We write into this memory with the span routines and then blit it
* to the window on a buffer swap.
*/
BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize)
{
HDC hdc = pwc->hDC;
LPBITMAPINFO pbmi = &(pwc->bmi);
HDC hic;
assert(pwc->db_flag == GL_TRUE);
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = lxSize;
pbmi->bmiHeader.biHeight= -lySize;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL);
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = 0;
pbmi->bmiHeader.biXPelsPerMeter = 0;
pbmi->bmiHeader.biYPelsPerMeter = 0;
pbmi->bmiHeader.biClrUsed = 0;
pbmi->bmiHeader.biClrImportant = 0;
pwc->cColorBits = pbmi->bmiHeader.biBitCount;
pwc->ScanWidth = (lxSize * (pwc->cColorBits / 8) + 3) & ~3;
hic = CreateIC("display", NULL, NULL, NULL);
pwc->dib.hDC = CreateCompatibleDC(hic);
pwc->hbmDIB = CreateDIBSection(hic,
&pwc->bmi,
DIB_RGB_COLORS,
(void **)&(pwc->pbPixels),
0,
0);
pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);
DeleteDC(hic);
wmSetPixelFormat(pwc, pwc->hDC);
return TRUE;
}
static void wmDeleteBackingStore(PWMC pwc)
{
if (pwc->hbmDIB) {
SelectObject(pwc->dib.hDC, pwc->hOldBitmap);
DeleteDC(pwc->dib.hDC);
DeleteObject(pwc->hbmDIB);
}
}
static void wmesa_get_buffer_size(GLframebuffer *buffer,
GLuint *width,
GLuint *height )
{
*width = Current->width;
*height = Current->height;
}
static void wmesa_flush(GLcontext* ctx)
{
if (Current->db_flag) {
BitBlt(Current->hDC, 0, 0, Current->width, Current->height,
Current->dib.hDC, 0, 0, SRCCOPY);
}
else {
/* Do nothing for single buffer */
}
}
/**********************************************************************/
/***** CLEAR Functions *****/
/**********************************************************************/
/* If we do not implement these, Mesa clears the buffers via the pixel
* span writing interface, which is very slow for a clear operation.
*/
/*
* Set the color index used to clear the color buffer.
*/
static void clear_index(GLcontext* ctx, GLuint index)
{
/* Note that indexed mode is not supported yet */
Current->clearColorRef = RGB(0,0,0);
}
/*
* Set the color used to clear the color buffer.
*/
static void clear_color(GLcontext* ctx, const GLfloat color[4])
{
GLubyte col[3];
UINT bytesPerPixel = Current->cColorBits / 8;
CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
Current->clearColorRef = RGB(col[0], col[1], col[2]);
DeleteObject(Current->clearPen);
DeleteObject(Current->clearBrush);
Current->clearPen = CreatePen(PS_SOLID, 1, Current->clearColorRef);
Current->clearBrush = CreateSolidBrush(Current->clearColorRef);
}
/*
* Clear the specified region of the color buffer using the clear color
* or index as specified by one of the two functions above.
*
* This procedure clears either the front and/or the back COLOR buffers.
* Only the "left" buffer is cleared since we are not stereo.
* Clearing of the other non-color buffers is left to the swrast.
*/
static void clear(GLcontext* ctx,
GLbitfield mask,
GLboolean all,
GLint x, GLint y,
GLint width, GLint height)
{
int done = 0;
/* Let swrast do all the work if the masks are not set to
* clear all channels. */
if (ctx->Color.ColorMask[0] != 0xff ||
ctx->Color.ColorMask[1] != 0xff ||
ctx->Color.ColorMask[2] != 0xff ||
ctx->Color.ColorMask[3] != 0xff) {
_swrast_Clear(ctx, mask, all, x, y, width, height);
return;
}
/* 'all' means clear the entire window */
if (all) {
x = y = 0;
width = Current->width;
height = Current->height;
}
/* Back buffer */
if (mask & BUFFER_BIT_BACK_LEFT) {
int i, rowSize;
UINT bytesPerPixel = Current->cColorBits / 8;
LPBYTE lpb, clearRow;
LPWORD lpw;
BYTE bColor;
WORD wColor;
BYTE r, g, b;
DWORD dwColor;
LPDWORD lpdw;
/* Try for a fast clear - clearing entire buffer with a single
* byte value. */
if (all) { /* entire buffer */
/* Now check for an easy clear value */
switch (bytesPerPixel) {
case 1:
bColor = BGR8(GetRValue(Current->clearColorRef),
GetGValue(Current->clearColorRef),
GetBValue(Current->clearColorRef));
memset(Current->pbPixels, bColor,
Current->ScanWidth * height);
done = 1;
break;
case 2:
wColor = BGR16(GetRValue(Current->clearColorRef),
GetGValue(Current->clearColorRef),
GetBValue(Current->clearColorRef));
if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
memset(Current->pbPixels, wColor & 0xff,
Current->ScanWidth * height);
done = 1;
}
break;
case 3:
/* fall through */
case 4:
if (GetRValue(Current->clearColorRef) ==
GetGValue(Current->clearColorRef) &&
GetRValue(Current->clearColorRef) ==
GetBValue(Current->clearColorRef)) {
memset(Current->pbPixels,
GetRValue(Current->clearColorRef),
Current->ScanWidth * height);
done = 1;
}
break;
default:
break;
}
} /* all */
if (!done) {
/* Need to clear a row at a time. Begin by setting the first
* row in the area to be cleared to the clear color. */
clearRow = Current->pbPixels +
Current->ScanWidth * FLIP(y) +
bytesPerPixel * x;
switch (bytesPerPixel) {
case 1:
lpb = clearRow;
bColor = BGR8(GetRValue(Current->clearColorRef),
GetGValue(Current->clearColorRef),
GetBValue(Current->clearColorRef));
memset(lpb, bColor, width);
break;
case 2:
lpw = (LPWORD)clearRow;
wColor = BGR16(GetRValue(Current->clearColorRef),
GetGValue(Current->clearColorRef),
GetBValue(Current->clearColorRef));
for (i=0; i<width; i++)
*lpw++ = wColor;
break;
case 3:
lpb = clearRow;
r = GetRValue(Current->clearColorRef);
g = GetGValue(Current->clearColorRef);
b = GetBValue(Current->clearColorRef);
for (i=0; i<width; i++) {
*lpb++ = b;
*lpb++ = g;
*lpb++ = r;
}
break;
case 4:
lpdw = (LPDWORD)clearRow;
dwColor = BGR32(GetRValue(Current->clearColorRef),
GetGValue(Current->clearColorRef),
GetBValue(Current->clearColorRef));
for (i=0; i<width; i++)
*lpdw++ = dwColor;
break;
default:
break;
} /* switch */
/* copy cleared row to other rows in buffer */
lpb = clearRow - Current->ScanWidth;
rowSize = width * bytesPerPixel;
for (i=1; i<height; i++) {
memcpy(lpb, clearRow, rowSize);
lpb -= Current->ScanWidth;
}
} /* not done */
mask &= ~BUFFER_BIT_BACK_LEFT;
} /* back buffer */
/* front buffer */
if (mask & BUFFER_BIT_FRONT_LEFT) {
HDC DC = Current->hDC;
HPEN Old_Pen = SelectObject(DC, Current->clearPen);
HBRUSH Old_Brush = SelectObject(DC, Current->clearBrush);
Rectangle(DC,
x,
FLIP(y),
x + width + 1,
FLIP(y) - height + 1);
SelectObject(DC, Old_Pen);
SelectObject(DC, Old_Brush);
mask &= ~BUFFER_BIT_FRONT_LEFT;
} /* front buffer */
/* Call swrast if there is anything left to clear (like DEPTH) */
if (mask)
_swrast_Clear(ctx, mask, all, x, y, width, height);
}
/**********************************************************************/
/***** PIXEL Functions *****/
/**********************************************************************/
/* SINGLE BUFFER */
/* These are slow, but work with all non-indexed visual types */
/* Write a horizontal span of RGBA color pixels with a boolean mask. */
static void write_rgba_span_single(const GLcontext* ctx,
struct gl_renderbuffer *rb,
GLuint n, GLint x, GLint y,
const GLubyte rgba[][4],
const GLubyte mask[] )
{
PWMC pwc = Current;
GLuint i;
(void) ctx;
y=FLIP(y);
if (mask) {
for (i=0; i<n; i++)
if (mask[i])
SetPixel(pwc->hDC, x+i, y, RGB(rgba[i][RCOMP], rgba[i][GCOMP],
rgba[i][BCOMP]));
}
else {
for (i=0; i<n; i++)
SetPixel(pwc->hDC, x+i, y, RGB(rgba[i][RCOMP], rgba[i][GCOMP],
rgba[i][BCOMP]));
}
}
/* Write a horizontal span of RGB color pixels with a boolean mask. */
static void write_rgb_span_single(const GLcontext* ctx,
struct gl_renderbuffer *rb,
GLuint n, GLint x, GLint y,
const GLubyte rgb[][3],
const GLubyte mask[] )
{
PWMC pwc = Current;
GLuint i;
(void) ctx;
y=FLIP(y);
if (mask) {
for (i=0; i<n; i++)
if (mask[i])
SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
rgb[i][BCOMP]));
}
else {
for (i=0; i<n; i++)
SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -