📄 mgmesa.c
字号:
/* * MiniGUI device driver for Mesa * * Copyright (C) 2006 Feynman Software (http://www.fmsoft.cn) * */#include <GL/mgmesa.h>#include "mgmesadef.h"#include "colors.h"#include "context.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"/* linked list of our Framebuffers (windows) */static mgMesaFramebuffer FirstFramebuffer = NULL;/** * Create a new mgMesaFramebuffer object which will correspond to the * given HDC (Window handle). */mgMesaFramebuffermgmesa_new_framebuffer (HDC hdc, GLvisual *visual){ mgMesaFramebuffer pwfb = (mgMesaFramebuffer) malloc(sizeof(struct mgmesa_framebuffer)); if (pwfb) { _mesa_initialize_framebuffer(&pwfb->Base, visual); pwfb->dc = hdc; /* insert at head of list */ pwfb->next = FirstFramebuffer; FirstFramebuffer = pwfb; } return pwfb;}/** * Given an hdc, free the corresponding mgMesaFramebuffer */voidmgmesa_free_framebuffer (HDC hdc){ mgMesaFramebuffer pwfb, prev; for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) { if (pwfb->dc == 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 mgMesaFramebuffer */mgMesaFramebuffermgmesa_lookup_framebuffer (HDC hdc){ mgMesaFramebuffer pwfb; for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) { if (pwfb->dc == hdc) return pwfb; } return NULL;}/** * Given a GLframebuffer, return the corresponding mgMesaFramebuffer. */static mgMesaFramebuffer mgmesa_framebuffer (GLframebuffer *fb){ return (mgMesaFramebuffer) fb;}/** * Given a GLcontext, return the corresponding mgMesaContext. */static mgMesaContext mgmesa_context (const GLcontext *ctx){ return (mgMesaContext) ctx;}/* * Every driver should implement a GetString function in order to * return a meaningful GL_RENDERER string. */static const GLubyte *mgmesa_get_string (GLcontext *ctx, GLenum name){ return (name == GL_RENDERER) ? (GLubyte *) "Mesa MiniGUI Driver" : NULL;}/* * Determine the pixel format based on the pixel size. */static void mgSetPixelFormat (mgMesaFramebuffer pwfb, HDC dc){ pwfb->color_bits = GetGDCapability (dc, GDCAP_BITSPP); /* Only 16 and 32 bit targets are supported now */ assert (pwfb->color_bits == 0 || pwfb->color_bits == 16 || pwfb->color_bits == 32); switch(pwfb->color_bits){ case 8: pwfb->pixelformat = PF_INDEX8; break; case 16: pwfb->pixelformat = PF_5R6G5B; break; 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 mgCreateBackingStore (mgMesaFramebuffer pwfb, long lxSize, long lySize){ RECT rc = {0, 0, 1, 1}; pwfb->memdc = CreateCompatibleDCEx (pwfb->dc, lxSize, lySize); pwfb->color_bits = GetGDCapability (pwfb->dc, GDCAP_BITSPP); pwfb->pixels = LockDC (pwfb->memdc, &rc, NULL, NULL, &pwfb->pitch); UnlockDC (pwfb->memdc); mgSetPixelFormat (pwfb, pwfb->dc); return TRUE;}static mgDeleteBackingStore (mgMesaFramebuffer pwfb){ if (pwfb->memdc) { DeleteMemDC (pwfb->memdc); }}/** * 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 = GetGDCapability (hdc, GDCAP_HPIXEL); *height = GetGDCapability (hdc, GDCAP_VPIXEL); }}static voidmgmesa_get_buffer_size (GLframebuffer *buffer, GLuint *width, GLuint *height){ mgMesaFramebuffer pwfb = mgmesa_framebuffer (buffer); get_window_size (pwfb->dc, width, height);}static void mgmesa_flush (GLcontext *ctx){ mgMesaContext pwc = mgmesa_context (ctx); mgMesaFramebuffer pwfb = mgmesa_framebuffer(ctx->WinSysDrawBuffer); if (ctx->Visual.doubleBufferMode == 1 && pwfb->memdc) { BitBlt (pwfb->memdc, 0, 0, pwfb->Base.Width, pwfb->Base.Height, pwfb->dc, 0, 0, 0); } 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){ mgMesaContext pwc = mgmesa_context (ctx); /* Note that indexed mode is not supported yet */ pwc->clear_color.r = 0; pwc->clear_color.g = 0; pwc->clear_color.b = 0;}/* * Set the color used to clear the color buffer. */static void clear_color (GLcontext *ctx, const GLfloat color[4]){ mgMesaContext pwc = mgmesa_context(ctx); mgMesaFramebuffer pwfb = mgmesa_framebuffer(ctx->DrawBuffer); GLubyte col[3]; UINT bytesPerPixel = pwfb->color_bits / 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->clear_color.r = col[0]; pwc->clear_color.g = col[1]; pwc->clear_color.b = col[2];}/* * 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) {#define FLIP(Y) (ctx->DrawBuffer->Height - (Y) - 1) mgMesaContext pwc = mgmesa_context(ctx); mgMesaFramebuffer pwfb = mgmesa_framebuffer(ctx->DrawBuffer); gal_pixel pixel; RECT rc = {x, FLIP(y) + 1, x + width + 1, FLIP(y) - height + 1}; /* 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; } NormalizeRect (&rc); /* Back buffer */ if (mask & BUFFER_BIT_BACK_LEFT) { #if 0 int done = 0; int i, rowSize; UINT bytesPerPixel = pwfb->color_bits / 8; BYTE* lpb, clearRow; WORD* lpw; BYTE bColor; WORD wColor; BYTE r, g, b; DWORD dwColor; DWORD* 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(pwc->clear_color.r, pwc->clear_color.g, pwc->clear_color.b); memset (pwfb->pixels, bColor, pwfb->pitch * height); done = 1; break; case 2: wColor = BGR16(pwc->clear_color.r, pwc->clear_color.g, pwc->clear_color.b); if (((wColor >> 8) & 0xff) == (wColor & 0xff)) { memset (pwfb->pixels, wColor & 0xff, pwfb->pitch * height); done = 1; } break; case 3: /* fall through */ case 4: if (pwc->clear_color.r == pwc->clear_color.g && pwc->clear_color.r == pwc->clear_color.b) { memset (pwfb->pixels, pwc->clear_color.r, pwfb->pitch * 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->pixels + pwfb->pitch * FLIP(y) + bytesPerPixel * x; switch (bytesPerPixel) { case 1: lpb = clearRow; bColor = BGR8(pwc->clear_color.r, pwc->clear_color.g, pwc->clear_color.b); memset (lpb, bColor, width); break; case 2: lpw = (WORD*)clearRow; wColor = BGR16(pwc->clear_color.r, pwc->clear_color.g, pwc->clear_color.b); for (i=0; i<width; i++) *lpw++ = wColor; break; case 3: lpb = clearRow; r = pwc->clear_color.r; g = pwc->clear_color.g; b = pwc->clear_color.b; for (i=0; i<width; i++) { *lpb++ = b; *lpb++ = g; *lpb++ = r; } break; case 4: lpdw = (DWORD*)clearRow; dwColor = BGR32(pwc->clear_color.r, pwc->clear_color.g, pwc->clear_color.b); for (i=0; i<width; i++) *lpdw++ = dwColor; break; default: break; } /* switch */ /* copy cleared row to other rows in buffer */ lpb = clearRow - pwfb->pitch; rowSize = width * bytesPerPixel; for (i=1; i<height; i++) { memcpy (lpb, clearRow, rowSize); lpb -= pwfb->pitch; } } /* not done */#else SetBrushType (pwfb->memdc, BT_SOLID); SetBrushColor (pwfb->memdc, RGB2Pixel (pwfb->memdc, pwc->clear_color.r, pwc->clear_color.g, pwc->clear_color.b)); FillBox (pwfb->memdc, rc.left, rc.top, RECTW (rc), RECTH (rc));#endif mask &= ~BUFFER_BIT_BACK_LEFT; } /* back buffer */ /* front buffer */ if (mask & BUFFER_BIT_FRONT_LEFT) { SetBrushType (pwc->dc, BT_SOLID); SetBrushColor (pwc->dc, RGB2Pixel (pwc->dc, pwc->clear_color.r, pwc->clear_color.g, pwc->clear_color.b)); FillBox (pwfb->dc, rc.left, rc.top, RECTW (rc), RECTH (rc)); 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); #undef FLIP} /**********************************************************************//***** PIXEL Functions *****//**********************************************************************/#define FLIP(Y) (rb->Height - (Y) - 1)/** ** Front Buffer reading/writing ** 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_front(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] ){ mgMesaContext pwc = mgmesa_context(ctx); GLuint i; (void) ctx; y = FLIP (y); if (mask) { for (i=0; i<n; i++) if (mask[i]) SetPixelRGB (pwc->dc, x+i, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -