📄 wmesa.c
字号:
/* * Windows (Win32/Win64) device driver for Mesa * */#include "wmesadef.h"#include "colors.h"#include <GL/wmesa.h>#include <winuser.h>#include "context.h"#include "extensions.h"#include "framebuffer.h"#include "renderbuffer.h"#include "drivers/common/driverfuncs.h"#include "vbo/vbo.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"/* linked list of our Framebuffers (windows) */static WMesaFramebuffer FirstFramebuffer = NULL;/** * Create a new WMesaFramebuffer object which will correspond to the * given HDC (Window handle). */WMesaFramebufferwmesa_new_framebuffer(HDC hdc, GLvisual *visual){ WMesaFramebuffer pwfb = (WMesaFramebuffer) malloc(sizeof(struct wmesa_framebuffer)); if (pwfb) { _mesa_initialize_framebuffer(&pwfb->Base, visual); pwfb->hDC = hdc; /* insert at head of list */ pwfb->next = FirstFramebuffer; FirstFramebuffer = pwfb; } return pwfb;}/** * Given an hdc, free the corresponding WMesaFramebuffer */voidwmesa_free_framebuffer(HDC hdc){ WMesaFramebuffer pwfb, prev; for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) { if (pwfb->hDC == hdc) break; prev = pwfb; } if (pwfb) { if (pwfb == FirstFramebuffer) FirstFramebuffer = pwfb->next; else prev->next = pwfb->next; free(pwfb); }}/** * Given an hdc, return the corresponding WMesaFramebuffer */WMesaFramebufferwmesa_lookup_framebuffer(HDC hdc){ WMesaFramebuffer pwfb; for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) { if (pwfb->hDC == hdc) return pwfb; } return NULL;}/** * Given a GLframebuffer, return the corresponding WMesaFramebuffer. */static WMesaFramebuffer wmesa_framebuffer(GLframebuffer *fb){ return (WMesaFramebuffer) fb;}/** * Given a GLcontext, return the corresponding WMesaContext. */static WMesaContext wmesa_context(const GLcontext *ctx){ return (WMesaContext) ctx;}/* * 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(WMesaFramebuffer pwfb, HDC hDC){ pwfb->cColorBits = GetDeviceCaps(hDC, BITSPIXEL); /* Only 16 and 32 bit targets are supported now */ assert(pwfb->cColorBits == 0 || pwfb->cColorBits == 16 || pwfb->cColorBits == 24 || pwfb->cColorBits == 32); switch(pwfb->cColorBits){ case 8: pwfb->pixelformat = PF_INDEX8; break; case 16: pwfb->pixelformat = PF_5R6G5B; break; case 24: case 32: pwfb->pixelformat = PF_8R8G8B; break; default: pwfb->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(WMesaFramebuffer pwfb, long lxSize, long lySize){ HDC hdc = pwfb->hDC; LPBITMAPINFO pbmi = &(pwfb->bmi); HDC hic; pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = lxSize; pbmi->bmiHeader.biHeight= -lySize; pbmi->bmiHeader.biPlanes = 1; pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwfb->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; pwfb->cColorBits = pbmi->bmiHeader.biBitCount; pwfb->ScanWidth = (lxSize * (pwfb->cColorBits / 8) + 3) & ~3; hic = CreateIC("display", NULL, NULL, NULL); pwfb->dib_hDC = CreateCompatibleDC(hic); pwfb->hbmDIB = CreateDIBSection(hic, &pwfb->bmi, DIB_RGB_COLORS, (void **)&(pwfb->pbPixels), 0, 0); pwfb->hOldBitmap = SelectObject(pwfb->dib_hDC, pwfb->hbmDIB); DeleteDC(hic); wmSetPixelFormat(pwfb, pwfb->hDC); return TRUE;}static wmDeleteBackingStore(WMesaFramebuffer pwfb){ if (pwfb->hbmDIB) { SelectObject(pwfb->dib_hDC, pwfb->hOldBitmap); DeleteDC(pwfb->dib_hDC); DeleteObject(pwfb->hbmDIB); }}/** * Find the width and height of the window named by hdc. */static voidget_window_size(HDC hdc, GLuint *width, GLuint *height){ if (WindowFromDC(hdc)) { RECT rect; GetClientRect(WindowFromDC(hdc), &rect); *width = rect.right - rect.left; *height = rect.bottom - rect.top; } else { /* Memory context */ /* From contributed code - use the size of the desktop * for the size of a memory context (?) */ *width = GetDeviceCaps(hdc, HORZRES); *height = GetDeviceCaps(hdc, VERTRES); }}static voidwmesa_get_buffer_size(GLframebuffer *buffer, GLuint *width, GLuint *height){ WMesaFramebuffer pwfb = wmesa_framebuffer(buffer); get_window_size(pwfb->hDC, width, height);}static void wmesa_flush(GLcontext *ctx){ WMesaContext pwc = wmesa_context(ctx); WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->WinSysDrawBuffer); if (ctx->Visual.doubleBufferMode == 1) { BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height, pwfb->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){ WMesaContext pwc = wmesa_context(ctx); /* Note that indexed mode is not supported yet */ pwc->clearColorRef = RGB(0,0,0);}/* * Set the color used to clear the color buffer. */static void clear_color(GLcontext *ctx, const GLfloat color[4]){ WMesaContext pwc = wmesa_context(ctx); WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); GLubyte col[3]; UINT bytesPerPixel = pwfb->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]); pwc->clearColorRef = RGB(col[0], col[1], col[2]); DeleteObject(pwc->clearPen); DeleteObject(pwc->clearBrush); pwc->clearPen = CreatePen(PS_SOLID, 1, pwc->clearColorRef); pwc->clearBrush = CreateSolidBrush(pwc->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){#define FLIP(Y) (ctx->DrawBuffer->Height - (Y) - 1) const GLint x = ctx->DrawBuffer->_Xmin; const GLint y = ctx->DrawBuffer->_Ymin; const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; WMesaContext pwc = wmesa_context(ctx); WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 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); return; } /* Back buffer */ if (mask & BUFFER_BIT_BACK_LEFT) { int i, rowSize; UINT bytesPerPixel = pwfb->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 (width == ctx->DrawBuffer->Width && height == ctx->DrawBuffer->Height) { /* entire buffer */ /* Now check for an easy clear value */ switch (bytesPerPixel) { case 1: bColor = BGR8(GetRValue(pwc->clearColorRef), GetGValue(pwc->clearColorRef), GetBValue(pwc->clearColorRef)); memset(pwfb->pbPixels, bColor, pwfb->ScanWidth * height); done = 1; break; case 2: wColor = BGR16(GetRValue(pwc->clearColorRef), GetGValue(pwc->clearColorRef), GetBValue(pwc->clearColorRef)); if (((wColor >> 8) & 0xff) == (wColor & 0xff)) { memset(pwfb->pbPixels, wColor & 0xff, pwfb->ScanWidth * height); done = 1; } break; case 3: /* fall through */ case 4: if (GetRValue(pwc->clearColorRef) == GetGValue(pwc->clearColorRef) && GetRValue(pwc->clearColorRef) == GetBValue(pwc->clearColorRef)) { memset(pwfb->pbPixels, GetRValue(pwc->clearColorRef), pwfb->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 = pwfb->pbPixels + pwfb->ScanWidth * FLIP(y) + bytesPerPixel * x; switch (bytesPerPixel) { case 1: lpb = clearRow; bColor = BGR8(GetRValue(pwc->clearColorRef), GetGValue(pwc->clearColorRef), GetBValue(pwc->clearColorRef)); memset(lpb, bColor, width); break; case 2: lpw = (LPWORD)clearRow; wColor = BGR16(GetRValue(pwc->clearColorRef), GetGValue(pwc->clearColorRef), GetBValue(pwc->clearColorRef)); for (i=0; i<width; i++) *lpw++ = wColor; break; case 3: lpb = clearRow; r = GetRValue(pwc->clearColorRef); g = GetGValue(pwc->clearColorRef); b = GetBValue(pwc->clearColorRef); for (i=0; i<width; i++) { *lpb++ = b; *lpb++ = g; *lpb++ = r; } break; case 4: lpdw = (LPDWORD)clearRow; dwColor = BGR32(GetRValue(pwc->clearColorRef), GetGValue(pwc->clearColorRef), GetBValue(pwc->clearColorRef)); for (i=0; i<width; i++) *lpdw++ = dwColor; break; default: break; } /* switch */ /* copy cleared row to other rows in buffer */ lpb = clearRow - pwfb->ScanWidth; rowSize = width * bytesPerPixel; for (i=1; i<height; i++) { memcpy(lpb, clearRow, rowSize); lpb -= pwfb->ScanWidth; } } /* not done */ mask &= ~BUFFER_BIT_BACK_LEFT; } /* back buffer */ /* front buffer */ if (mask & BUFFER_BIT_FRONT_LEFT) { HDC DC = pwc->hDC; HPEN Old_Pen = SelectObject(DC, pwc->clearPen); HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush); Rectangle(DC, x, FLIP(y) + 1, 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -