diff options
Diffstat (limited to 'src/mesa/drivers/windows/gdi/wmesa.c')
-rw-r--r-- | src/mesa/drivers/windows/gdi/wmesa.c | 630 |
1 files changed, 375 insertions, 255 deletions
diff --git a/src/mesa/drivers/windows/gdi/wmesa.c b/src/mesa/drivers/windows/gdi/wmesa.c index 982366be42b..fd7e28817e3 100644 --- a/src/mesa/drivers/windows/gdi/wmesa.c +++ b/src/mesa/drivers/windows/gdi/wmesa.c @@ -6,6 +6,7 @@ #include "wmesadef.h" #include "colors.h" #include <GL/wmesa.h> +#include "context.h" #include "extensions.h" #include "framebuffer.h" #include "renderbuffer.h" @@ -17,11 +18,63 @@ #include "tnl/t_context.h" #include "tnl/t_pipeline.h" -#define FLIP(Y) (Current->height-(Y)-1) -/* Static Data */ +/* linked list of our Framebuffers (windows) */ +static WMesaFramebuffer FirstFramebuffer = NULL; + + +/** + * Create a new WMesaFramebuffer object which will correspond to the + * given HDC (Window handle). + */ +WMesaFramebuffer +wmesa_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, return the corresponding WMesaFramebuffer + */ +WMesaFramebuffer +wmesa_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; +} -static PWMC Current = NULL; /* * Every driver should implement a GetString function in order to @@ -33,15 +86,17 @@ static const GLubyte *wmesa_get_string(GLcontext *ctx, GLenum name) (GLubyte *) "Mesa Windows GDI Driver" : NULL; } + /* * Determine the pixel format based on the pixel size. */ -static void wmSetPixelFormat(PWMC pwc, HDC hDC) +static void wmSetPixelFormat(WMesaContext pwc, HDC hDC) { pwc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL); // Only 16 and 32 bit targets are supported now - assert(pwc->cColorBits == 16 || + assert(pwc->cColorBits == 0 || + pwc->cColorBits == 16 || pwc->cColorBits == 32); switch(pwc->cColorBits){ @@ -59,13 +114,15 @@ static void wmSetPixelFormat(PWMC pwc, HDC hDC) } } -/* + +/** * 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. + * + * XXX we should probably pass a WMesaFramebuffer ptr, not a WMesaContext! */ - -BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize) +BOOL wmCreateBackingStore(WMesaContext pwc, long lxSize, long lySize) { HDC hdc = pwc->hDC; LPBITMAPINFO pbmi = &(pwc->bmi); @@ -105,7 +162,10 @@ BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize) return TRUE; } -static wmDeleteBackingStore(PWMC pwc) + +/* XXX pass WMesaFramebuffer, not WMesaContext. + */ +static wmDeleteBackingStore(WMesaContext pwc) { if (pwc->hbmDIB) { SelectObject(pwc->dib.hDC, pwc->hOldBitmap); @@ -114,20 +174,48 @@ static wmDeleteBackingStore(PWMC pwc) } } -static void wmesa_get_buffer_size(GLframebuffer *buffer, - GLuint *width, - GLuint *height ) + +/** + * Find the width and height of the window named by hdc. + */ +static void +get_window_size(HDC hdc, GLuint *width, GLuint *height) { - *width = Current->width; - *height = Current->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 void wmesa_flush(GLcontext* ctx) +static void +wmesa_get_buffer_size(GLframebuffer *buffer, GLuint *width, GLuint *height) { - if (Current->db_flag) { - BitBlt(Current->hDC, 0, 0, Current->width, Current->height, - Current->dib.hDC, 0, 0, SRCCOPY); + 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); + + /* XXX I guess we're _always_ double buffered and render to the back + * buffer. So flushing involves copying the back color buffer to + * the front. + */ + if (pwc->db_flag) { + BitBlt(pwc->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height, + pwc->dib.hDC, 0, 0, SRCCOPY); } else { /* Do nothing for single buffer */ @@ -146,28 +234,30 @@ static void wmesa_flush(GLcontext* ctx) /* * Set the color index used to clear the color buffer. */ -static void clear_index(GLcontext* ctx, GLuint index) +static void clear_index(GLcontext *ctx, GLuint index) { + WMesaContext pwc = wmesa_context(ctx); /* Note that indexed mode is not supported yet */ - Current->clearColorRef = RGB(0,0,0); + 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]) +static void clear_color(GLcontext *ctx, const GLfloat color[4]) { + WMesaContext pwc = wmesa_context(ctx); GLubyte col[3]; - UINT bytesPerPixel = Current->cColorBits / 8; + UINT bytesPerPixel = pwc->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); + 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); } @@ -180,12 +270,15 @@ static void clear_color(GLcontext* ctx, const GLfloat color[4]) * Clearing of the other non-color buffers is left to the swrast. */ -static void clear(GLcontext* ctx, +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) + + WMesaContext pwc = wmesa_context(ctx); int done = 0; /* Let swrast do all the work if the masks are not set to @@ -198,18 +291,11 @@ static void clear(GLcontext* ctx, 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; + UINT bytesPerPixel = pwc->cColorBits / 8; LPBYTE lpb, clearRow; LPWORD lpw; BYTE bColor; @@ -224,33 +310,33 @@ static void clear(GLcontext* ctx, /* 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); + bColor = BGR8(GetRValue(pwc->clearColorRef), + GetGValue(pwc->clearColorRef), + GetBValue(pwc->clearColorRef)); + memset(pwc->pbPixels, bColor, + pwc->ScanWidth * height); done = 1; break; case 2: - wColor = BGR16(GetRValue(Current->clearColorRef), - GetGValue(Current->clearColorRef), - GetBValue(Current->clearColorRef)); + wColor = BGR16(GetRValue(pwc->clearColorRef), + GetGValue(pwc->clearColorRef), + GetBValue(pwc->clearColorRef)); if (((wColor >> 8) & 0xff) == (wColor & 0xff)) { - memset(Current->pbPixels, wColor & 0xff, - Current->ScanWidth * height); + memset(pwc->pbPixels, wColor & 0xff, + pwc->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); + if (GetRValue(pwc->clearColorRef) == + GetGValue(pwc->clearColorRef) && + GetRValue(pwc->clearColorRef) == + GetBValue(pwc->clearColorRef)) { + memset(pwc->pbPixels, + GetRValue(pwc->clearColorRef), + pwc->ScanWidth * height); done = 1; } break; @@ -263,30 +349,30 @@ static void clear(GLcontext* ctx, /* 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) + + clearRow = pwc->pbPixels + + pwc->ScanWidth * FLIP(y) + bytesPerPixel * x; switch (bytesPerPixel) { case 1: lpb = clearRow; - bColor = BGR8(GetRValue(Current->clearColorRef), - GetGValue(Current->clearColorRef), - GetBValue(Current->clearColorRef)); + bColor = BGR8(GetRValue(pwc->clearColorRef), + GetGValue(pwc->clearColorRef), + GetBValue(pwc->clearColorRef)); memset(lpb, bColor, width); break; case 2: lpw = (LPWORD)clearRow; - wColor = BGR16(GetRValue(Current->clearColorRef), - GetGValue(Current->clearColorRef), - GetBValue(Current->clearColorRef)); + 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(Current->clearColorRef); - g = GetGValue(Current->clearColorRef); - b = GetBValue(Current->clearColorRef); + r = GetRValue(pwc->clearColorRef); + g = GetGValue(pwc->clearColorRef); + b = GetBValue(pwc->clearColorRef); for (i=0; i<width; i++) { *lpb++ = b; *lpb++ = g; @@ -295,9 +381,9 @@ static void clear(GLcontext* ctx, break; case 4: lpdw = (LPDWORD)clearRow; - dwColor = BGR32(GetRValue(Current->clearColorRef), - GetGValue(Current->clearColorRef), - GetBValue(Current->clearColorRef)); + dwColor = BGR32(GetRValue(pwc->clearColorRef), + GetGValue(pwc->clearColorRef), + GetBValue(pwc->clearColorRef)); for (i=0; i<width; i++) *lpdw++ = dwColor; break; @@ -306,11 +392,11 @@ static void clear(GLcontext* ctx, } /* switch */ /* copy cleared row to other rows in buffer */ - lpb = clearRow - Current->ScanWidth; + lpb = clearRow - pwc->ScanWidth; rowSize = width * bytesPerPixel; for (i=1; i<height; i++) { memcpy(lpb, clearRow, rowSize); - lpb -= Current->ScanWidth; + lpb -= pwc->ScanWidth; } } /* not done */ mask &= ~BUFFER_BIT_BACK_LEFT; @@ -318,9 +404,9 @@ static void clear(GLcontext* ctx, /* 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); + HDC DC = pwc->hDC; + HPEN Old_Pen = SelectObject(DC, pwc->clearPen); + HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush); Rectangle(DC, x, FLIP(y) + 1, @@ -335,6 +421,7 @@ static void clear(GLcontext* ctx, if (mask) _swrast_Clear(ctx, mask, all, x, y, width, height); +#undef FLIP } @@ -342,18 +429,21 @@ static void clear(GLcontext* ctx, /***** PIXEL Functions *****/ /**********************************************************************/ +#define FLIP(Y) (rb->Height - (Y) - 1) + + /* 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, +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; + WMesaContext pwc = wmesa_context(ctx); GLuint i; (void) ctx; @@ -373,13 +463,13 @@ static void write_rgba_span_single(const GLcontext* ctx, } /* Write a horizontal span of RGB color pixels with a boolean mask. */ -static void write_rgb_span_single(const GLcontext* ctx, +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; + WMesaContext pwc = wmesa_context(ctx); GLuint i; (void) ctx; @@ -402,14 +492,14 @@ static void write_rgb_span_single(const GLcontext* ctx, * Write a horizontal span of pixels with a boolean mask. The current color * is used for all pixels. */ -static void write_mono_rgba_span_single(const GLcontext* ctx, +static void write_mono_rgba_span_single(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, const GLchan color[4], const GLubyte mask[]) { GLuint i; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); COLORREF colorref; (void) ctx; @@ -427,7 +517,7 @@ static void write_mono_rgba_span_single(const GLcontext* ctx, } /* Write an array of RGBA pixels with a boolean mask. */ -static void write_rgba_pixels_single(const GLcontext* ctx, +static void write_rgba_pixels_single(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, const GLint x[], const GLint y[], @@ -435,7 +525,7 @@ static void write_rgba_pixels_single(const GLcontext* ctx, const GLubyte mask[] ) { GLuint i; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); (void) ctx; for (i=0; i<n; i++) if (mask[i]) @@ -450,7 +540,7 @@ static void write_rgba_pixels_single(const GLcontext* ctx, * Write an array of pixels with a boolean mask. The current color * is used for all pixels. */ -static void write_mono_rgba_pixels_single(const GLcontext* ctx, +static void write_mono_rgba_pixels_single(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, const GLint x[], const GLint y[], @@ -458,7 +548,7 @@ static void write_mono_rgba_pixels_single(const GLcontext* ctx, const GLubyte mask[] ) { GLuint i; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); COLORREF colorref; (void) ctx; colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]); @@ -468,16 +558,17 @@ static void write_mono_rgba_pixels_single(const GLcontext* ctx, } /* Read a horizontal span of color pixels. */ -static void read_rgba_span_single(const GLcontext* ctx, +static void read_rgba_span_single(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, GLubyte rgba[][4] ) { + WMesaContext pwc = wmesa_context(ctx); GLuint i; COLORREF Color; y = FLIP(y); for (i=0; i<n; i++) { - Color = GetPixel(Current->hDC, x+i, y); + Color = GetPixel(pwc->hDC, x+i, y); rgba[i][RCOMP] = GetRValue(Color); rgba[i][GCOMP] = GetGValue(Color); rgba[i][BCOMP] = GetBValue(Color); @@ -487,21 +578,22 @@ static void read_rgba_span_single(const GLcontext* ctx, /* Read an array of color pixels. */ -static void read_rgba_pixels_single(const GLcontext* ctx, +static void read_rgba_pixels_single(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4]) { - GLuint i; - COLORREF Color; - for (i=0; i<n; i++) { - GLint y2 = FLIP(y[i]); - Color = GetPixel(Current->hDC, x[i], y2); - rgba[i][RCOMP] = GetRValue(Color); - rgba[i][GCOMP] = GetGValue(Color); - rgba[i][BCOMP] = GetBValue(Color); - rgba[i][ACOMP] = 255; - } + WMesaContext pwc = wmesa_context(ctx); + GLuint i; + COLORREF Color; + for (i=0; i<n; i++) { + GLint y2 = FLIP(y[i]); + Color = GetPixel(pwc->hDC, x[i], y2); + rgba[i][RCOMP] = GetRValue(Color); + rgba[i][GCOMP] = GetGValue(Color); + rgba[i][BCOMP] = GetBValue(Color); + rgba[i][ACOMP] = 255; + } } /*********************************************************************/ @@ -515,13 +607,13 @@ LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \ /* Write a horizontal span of RGBA color pixels with a boolean mask. */ -static void write_rgba_span_32(const GLcontext* ctx, +static void write_rgba_span_32(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] ) { - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); GLuint i; LPDWORD lpdw; @@ -544,13 +636,13 @@ static void write_rgba_span_32(const GLcontext* ctx, /* Write a horizontal span of RGB color pixels with a boolean mask. */ -static void write_rgb_span_32(const GLcontext* ctx, +static void write_rgb_span_32(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, - const GLubyte rgb[][4], + const GLubyte rgb[][3], const GLubyte mask[] ) { - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); GLuint i; LPDWORD lpdw; @@ -575,7 +667,7 @@ static void write_rgb_span_32(const GLcontext* ctx, * Write a horizontal span of pixels with a boolean mask. The current color * is used for all pixels. */ -static void write_mono_rgba_span_32(const GLcontext* ctx, +static void write_mono_rgba_span_32(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, const GLchan color[4], @@ -584,7 +676,7 @@ static void write_mono_rgba_span_32(const GLcontext* ctx, LPDWORD lpdw; DWORD pixel; GLuint i; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x; y=FLIP(y); pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]); @@ -600,14 +692,14 @@ static void write_mono_rgba_span_32(const GLcontext* ctx, } /* Write an array of RGBA pixels with a boolean mask. */ -static void write_rgba_pixels_32(const GLcontext* ctx, +static void write_rgba_pixels_32(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[]) { GLuint i; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx);; for (i=0; i<n; i++) if (mask[i]) WMSETPIXEL32(pwc, FLIP(y[i]), x[i], @@ -618,7 +710,7 @@ static void write_rgba_pixels_32(const GLcontext* ctx, * Write an array of pixels with a boolean mask. The current color * is used for all pixels. */ -static void write_mono_rgba_pixels_32(const GLcontext* ctx, +static void write_mono_rgba_pixels_32(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, const GLint x[], const GLint y[], @@ -626,7 +718,7 @@ static void write_mono_rgba_pixels_32(const GLcontext* ctx, const GLubyte mask[]) { GLuint i; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); for (i=0; i<n; i++) if (mask[i]) WMSETPIXEL32(pwc, FLIP(y[i]),x[i],color[RCOMP], @@ -634,7 +726,7 @@ static void write_mono_rgba_pixels_32(const GLcontext* ctx, } /* Read a horizontal span of color pixels. */ -static void read_rgba_span_32(const GLcontext* ctx, +static void read_rgba_span_32(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, GLubyte rgba[][4] ) @@ -642,7 +734,7 @@ static void read_rgba_span_32(const GLcontext* ctx, GLuint i; DWORD pixel; LPDWORD lpdw; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); y = FLIP(y); lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x; @@ -657,7 +749,7 @@ static void read_rgba_span_32(const GLcontext* ctx, /* Read an array of color pixels. */ -static void read_rgba_pixels_32(const GLcontext* ctx, +static void read_rgba_pixels_32(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4]) @@ -665,7 +757,7 @@ static void read_rgba_pixels_32(const GLcontext* ctx, GLuint i; DWORD pixel; LPDWORD lpdw; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); for (i=0; i<n; i++) { GLint y2 = FLIP(y[i]); @@ -690,13 +782,13 @@ LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \ /* Write a horizontal span of RGBA color pixels with a boolean mask. */ -static void write_rgba_span_16(const GLcontext* ctx, +static void write_rgba_span_16(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] ) { - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); GLuint i; LPWORD lpw; @@ -719,13 +811,13 @@ static void write_rgba_span_16(const GLcontext* ctx, /* Write a horizontal span of RGB color pixels with a boolean mask. */ -static void write_rgb_span_16(const GLcontext* ctx, +static void write_rgb_span_16(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, const GLubyte rgb[][4], const GLubyte mask[] ) { - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); GLuint i; LPWORD lpw; @@ -750,7 +842,7 @@ static void write_rgb_span_16(const GLcontext* ctx, * Write a horizontal span of pixels with a boolean mask. The current color * is used for all pixels. */ -static void write_mono_rgba_span_16(const GLcontext* ctx, +static void write_mono_rgba_span_16(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, const GLchan color[4], @@ -759,7 +851,7 @@ static void write_mono_rgba_span_16(const GLcontext* ctx, LPWORD lpw; WORD pixel; GLuint i; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); (void) ctx; lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x; y=FLIP(y); @@ -776,14 +868,14 @@ static void write_mono_rgba_span_16(const GLcontext* ctx, } /* Write an array of RGBA pixels with a boolean mask. */ -static void write_rgba_pixels_16(const GLcontext* ctx, +static void write_rgba_pixels_16(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[]) { GLuint i; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); (void) ctx; for (i=0; i<n; i++) if (mask[i]) @@ -795,7 +887,7 @@ static void write_rgba_pixels_16(const GLcontext* ctx, * Write an array of pixels with a boolean mask. The current color * is used for all pixels. */ -static void write_mono_rgba_pixels_16(const GLcontext* ctx, +static void write_mono_rgba_pixels_16(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, const GLint x[], const GLint y[], @@ -803,7 +895,7 @@ static void write_mono_rgba_pixels_16(const GLcontext* ctx, const GLubyte mask[]) { GLuint i; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); (void) ctx; for (i=0; i<n; i++) if (mask[i]) @@ -812,14 +904,14 @@ static void write_mono_rgba_pixels_16(const GLcontext* ctx, } /* Read a horizontal span of color pixels. */ -static void read_rgba_span_16(const GLcontext* ctx, +static void read_rgba_span_16(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, GLubyte rgba[][4] ) { GLuint i, pixel; LPWORD lpw; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); y = FLIP(y); lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x; @@ -835,14 +927,14 @@ static void read_rgba_span_16(const GLcontext* ctx, /* Read an array of color pixels. */ -static void read_rgba_pixels_16(const GLcontext* ctx, +static void read_rgba_pixels_16(const GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4]) { GLuint i, pixel; LPWORD lpw; - PWMC pwc = Current; + WMesaContext pwc = wmesa_context(ctx); for (i=0; i<n; i++) { GLint y2 = FLIP(y[i]); @@ -872,6 +964,11 @@ wmesa_delete_renderbuffer(struct gl_renderbuffer *rb) _mesa_free(rb); } + +/** + * This is called by Mesa whenever it determines that the window size + * has changed. Do whatever's needed to cope with that. + */ static GLboolean wmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, @@ -879,6 +976,8 @@ wmesa_renderbuffer_storage(GLcontext *ctx, GLuint width, GLuint height) { + rb->Width = width; + rb->Height = height; return GL_TRUE; } @@ -930,13 +1029,14 @@ static void wmesa_resize_buffers(GLcontext *ctx, GLframebuffer *buffer, GLuint width, GLuint height) { - if (Current->width != width || Current->height != height) { - Current->width = width; - Current->height = height; + WMesaContext pwc = wmesa_context(ctx); + WMesaFramebuffer pwfb = wmesa_framebuffer(buffer); + + if (pwfb->Base.Width != width || pwfb->Base.Height != height) { /* Realloc back buffer */ - if (Current->db_flag) { - wmDeleteBackingStore(Current); - wmCreateBackingStore(Current, width, height); + if (pwc->db_flag) { + wmDeleteBackingStore(pwc); + wmCreateBackingStore(pwc, width, height); } } _mesa_resize_framebuffer(ctx, buffer, width, height); @@ -950,15 +1050,25 @@ wmesa_resize_buffers(GLcontext *ctx, GLframebuffer *buffer, * Remember, we have no opportunity to respond to conventional * resize events since the driver has no event loop. * Thus, we poll. - * Note that this trick isn't fool-proof. If the application never calls - * glViewport, our notion of the current window size may be incorrect. + * MakeCurrent also ends up making a call here, so that ensures + * we get the viewport set correctly, even if the app does not call + * glViewport and relies on the defaults. */ static void wmesa_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height) { - if (Current->width != width || Current->height != height) { - wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, width, height); + WMesaContext pwc = wmesa_context(ctx); + GLuint new_width, new_height; + + wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height); + + if (new_width != width || new_height != height) { + /** + * Either the window was resized or the viewport changed - not sure which. + * So call resize buffers to resize them if the window size changed. + */ + wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height); ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ } } @@ -1014,6 +1124,8 @@ WMesaContext WMesaCreateContext(HDC hDC, WMesaContext c; struct dd_function_table functions; GLint red_bits, green_bits, blue_bits, alpha_bits; + GLcontext *ctx; + GLvisual *visual; (void) Pal; @@ -1065,19 +1177,19 @@ WMesaContext WMesaCreateContext(HDC hDC, break; } /* Create visual based on flags */ - c->gl_visual = _mesa_create_visual(rgb_flag, - db_flag, /* db_flag */ - GL_FALSE, /* stereo */ - red_bits, green_bits, blue_bits, /* color RGB */ - alpha_flag ? alpha_bits : 0, /* color A */ - 0, /* index bits */ - DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */ - 8, /* stencil_bits */ - 16,16,16, /* accum RGB */ - alpha_flag ? 16 : 0, /* accum A */ - 1); /* num samples */ + visual = _mesa_create_visual(rgb_flag, + db_flag, /* db_flag */ + GL_FALSE, /* stereo */ + red_bits, green_bits, blue_bits, /* color RGB */ + alpha_flag ? alpha_bits : 0, /* color A */ + 0, /* index bits */ + DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */ + 8, /* stencil_bits */ + 16,16,16, /* accum RGB */ + alpha_flag ? 16 : 0, /* accum A */ + 1); /* num samples */ - if (!c->gl_visual) { + if (!visual) { _mesa_free(c); return NULL; } @@ -1094,155 +1206,163 @@ WMesaContext WMesaCreateContext(HDC hDC, functions.ResizeBuffers = wmesa_resize_buffers; functions.Viewport = wmesa_viewport; - /* allocate a new Mesa context */ - c->gl_ctx = _mesa_create_context(c->gl_visual, NULL, - &functions, (void *)c); - if (!c->gl_ctx) { - _mesa_destroy_visual( c->gl_visual ); - _mesa_free(c); - return NULL; - } - - _mesa_enable_sw_extensions(c->gl_ctx); - _mesa_enable_1_3_extensions(c->gl_ctx); - _mesa_enable_1_4_extensions(c->gl_ctx); - _mesa_enable_1_5_extensions(c->gl_ctx); - _mesa_enable_2_0_extensions(c->gl_ctx); + /* initialize the Mesa context data */ + ctx = &c->gl_ctx; + _mesa_initialize_context(ctx, visual, NULL, &functions, (void *)c); + + _mesa_enable_sw_extensions(ctx); + _mesa_enable_1_3_extensions(ctx); + _mesa_enable_1_4_extensions(ctx); + _mesa_enable_1_5_extensions(ctx); + _mesa_enable_2_0_extensions(ctx); /* Initialize the software rasterizer and helper modules. */ - if (!_swrast_CreateContext(c->gl_ctx) || - !_ac_CreateContext(c->gl_ctx) || - !_tnl_CreateContext(c->gl_ctx) || - !_swsetup_CreateContext(c->gl_ctx)) { - _mesa_destroy_visual(c->gl_visual); - _mesa_destroy_framebuffer(c->gl_buffer); - _mesa_free_context_data(c->gl_ctx); + if (!_swrast_CreateContext(ctx) || + !_ac_CreateContext(ctx) || + !_tnl_CreateContext(ctx) || + !_swsetup_CreateContext(ctx)) { + _mesa_free_context_data(ctx); _mesa_free(c); return NULL; } - _swsetup_Wakeup(c->gl_ctx); - TNL_CONTEXT(c->gl_ctx)->Driver.RunPipeline = _tnl_run_pipeline; + _swsetup_Wakeup(ctx); + TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline; return c; } -void WMesaDestroyContext( void ) + +void WMesaDestroyContext( WMesaContext pwc ) { - WMesaContext c = Current; + GLcontext *ctx = &pwc->gl_ctx; + GET_CURRENT_CONTEXT(cur_ctx); - WMesaMakeCurrent(NULL); + if (cur_ctx == ctx) { + /* unbind current if deleting current context */ + WMesaMakeCurrent(NULL, NULL); + } /* Release for device, not memory contexts */ - if(WindowFromDC(c->hDC) != NULL) + if (WindowFromDC(pwc->hDC) != NULL) { - ReleaseDC(WindowFromDC(c->hDC), c->hDC); + ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC); } - DeleteObject(c->clearPen); - DeleteObject(c->clearBrush); + DeleteObject(pwc->clearPen); + DeleteObject(pwc->clearBrush); - if (c->db_flag) - wmDeleteBackingStore(c); + if (pwc->db_flag) + wmDeleteBackingStore(pwc); - _swsetup_DestroyContext(c->gl_ctx); - _tnl_DestroyContext(c->gl_ctx); - _ac_DestroyContext(c->gl_ctx); - _swrast_DestroyContext(c->gl_ctx); + _swsetup_DestroyContext(ctx); + _tnl_DestroyContext(ctx); + _ac_DestroyContext(ctx); + _swrast_DestroyContext(ctx); - _mesa_destroy_visual(c->gl_visual); - _mesa_destroy_framebuffer(c->gl_buffer); - _mesa_free_context_data(c->gl_ctx); - _mesa_free(c->gl_ctx); - _mesa_free(c); + _mesa_free_context_data(ctx); + _mesa_free(pwc); } -void WMesaMakeCurrent(WMesaContext c) +/** + * Create a new color renderbuffer. + */ +struct gl_renderbuffer * +wmesa_new_renderbuffer(void) { - /* return if already current */ - if (Current == c || c == NULL) - return; + struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); + if (!rb) + return NULL; + + _mesa_init_renderbuffer(rb, (GLuint)0); + + rb->_BaseFormat = GL_RGBA; + rb->InternalFormat = GL_RGBA; + rb->DataType = CHAN_TYPE; + rb->Delete = wmesa_delete_renderbuffer; + rb->AllocStorage = wmesa_renderbuffer_storage; + return rb; +} + + +void WMesaMakeCurrent(WMesaContext c, HDC hdc) +{ + WMesaFramebuffer pwfb; + + { + /* return if already current */ + GET_CURRENT_CONTEXT(ctx); + WMesaContext pwc = wmesa_context(ctx); + if (c == pwc && pwc->hDC == hdc) + return; + } - /* Lazy creation of buffers */ - if (!c->gl_buffer) { + pwfb = wmesa_lookup_framebuffer(hdc); + + /* Lazy creation of framebuffers */ + if (c && !pwfb) { struct gl_renderbuffer *rb; - RECT rect; - - /* Determine window size */ - if (WindowFromDC(c->hDC)) { - GetClientRect(WindowFromDC(c->hDC), &rect); - c->width = rect.right - rect.left; - c->height = rect.bottom - rect.top; - } - else { /* Memory context */ - /* From contributed code - use the size of the desktop - * for the size of a memory context (?) */ - c->width = GetDeviceCaps(c->hDC, HORZRES); - c->height = GetDeviceCaps(c->hDC, VERTRES); - } + GLvisual *visual = &c->gl_ctx.Visual; + GLuint width, height; + + get_window_size(hdc, &width, &height); + c->clearPen = CreatePen(PS_SOLID, 1, 0); c->clearBrush = CreateSolidBrush(0); /* Create back buffer if double buffered */ if (c->db_flag) { - wmCreateBackingStore(c, c->width, c->height); - + wmCreateBackingStore(c, width, height); } - c->gl_buffer = _mesa_create_framebuffer(c->gl_visual); - if (!c->gl_buffer) - return; - - rb = CALLOC_STRUCT(gl_renderbuffer); - - if (!rb) - return; - - _mesa_init_renderbuffer(rb, (GLuint)0); - - rb->_BaseFormat = GL_RGBA; - rb->InternalFormat = GL_RGBA; - rb->DataType = CHAN_TYPE; - rb->Delete = wmesa_delete_renderbuffer; - rb->AllocStorage = wmesa_renderbuffer_storage; - - if (c->db_flag) - _mesa_add_renderbuffer(c->gl_buffer, BUFFER_BACK_LEFT, rb); - else - _mesa_add_renderbuffer(c->gl_buffer, BUFFER_FRONT_LEFT, rb); - wmesa_set_renderbuffer_funcs(rb, c->pixelformat, c->db_flag); - - /* Let Mesa own the Depth, Stencil, and Accum buffers */ - _mesa_add_soft_renderbuffers(c->gl_buffer, - GL_FALSE, /* color */ - c->gl_visual->depthBits > 0, - c->gl_visual->stencilBits > 0, - c->gl_visual->accumRedBits > 0, - c->alpha_flag, - GL_FALSE); + pwfb = wmesa_new_framebuffer(hdc, visual); + + /* need a color renderbuffer */ + rb = wmesa_new_renderbuffer(); + if (c->db_flag) + _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb); + else + _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb); + wmesa_set_renderbuffer_funcs(rb, c->pixelformat, c->db_flag); + + /* Let Mesa own the Depth, Stencil, and Accum buffers */ + _mesa_add_soft_renderbuffers(&pwfb->Base, + GL_FALSE, /* color */ + visual->depthBits > 0, + visual->stencilBits > 0, + visual->accumRedBits > 0, + c->alpha_flag, + GL_FALSE); } - - - - if (Current = c) - _mesa_make_current(c->gl_ctx, c->gl_buffer, c->gl_buffer); + if (c && pwfb) + _mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base); + else + _mesa_make_current(NULL, NULL, NULL); } -void WMesaSwapBuffers( void ) +void WMesaSwapBuffers( HDC hdc ) { GET_CURRENT_CONTEXT(ctx); - + WMesaContext pwc = wmesa_context(ctx); + WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc); + + if (!pwfb) { + _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc"); + return; + } + /* If we're swapping the buffer associated with the current context * we have to flush any pending rendering commands first. */ - if (Current && Current->gl_ctx == ctx) + if (pwc->hDC == hdc) { _mesa_notifySwapBuffers(ctx); - - if (Current->db_flag) - wmesa_flush(ctx); -} -/**********************************************************************/ -/***** END *****/ -/**********************************************************************/ + BitBlt(pwc->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height, + pwc->dib.hDC, 0, 0, SRCCOPY); + } + else { + /* XXX for now only allow swapping current window */ + _mesa_problem(NULL, "wmesa: can't swap non-current window"); + } +} |