diff options
author | José Fonseca <[email protected]> | 2012-02-08 16:23:06 +0000 |
---|---|---|
committer | José Fonseca <[email protected]> | 2012-02-10 16:23:27 +0000 |
commit | 9646762261d976d34bee8c8b1dcda9656cec655c (patch) | |
tree | 7433473c28a262191b0e06b87753df2d61435025 | |
parent | 90a95f4d2c50b63ffa4c114081a1cfa5cdfa05cb (diff) |
st/wgl: Properly support non-displayble pixel formats, and implement float pixelformats as as one.
WGL_ARB_pixel_format establishes the existence of pixel formats which
are invisible to GDI.
However we still need to pass a valid pixelformat to GDI, so that
context creation/binding works.
The actual WGL_TYPE_RGBA_FLOAT_ARB implementation is from Brian Paul.
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_context.c | 14 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_ext_pbuffer.c | 26 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_ext_pixelformat.c | 8 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_framebuffer.c | 21 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_framebuffer.h | 4 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_pixelformat.c | 52 |
6 files changed, 109 insertions, 16 deletions
diff --git a/src/gallium/state_trackers/wgl/stw_context.c b/src/gallium/state_trackers/wgl/stw_context.c index 1409f240ef5..7031af5bb3a 100644 --- a/src/gallium/state_trackers/wgl/stw_context.c +++ b/src/gallium/state_trackers/wgl/stw_context.c @@ -138,6 +138,7 @@ stw_create_context_attribs( int contextFlags, int profileMask) { int iPixelFormat; + struct stw_framebuffer *fb; const struct stw_pixelformat_info *pfi; struct st_context_attribs attribs; struct stw_context *ctx = NULL; @@ -154,6 +155,19 @@ stw_create_context_attribs( if(!iPixelFormat) return 0; + /* + * GDI only knows about displayable pixel formats, so determine the pixel format + * from the framebuffer. + * + * TODO: Remove the GetPixelFormat() above, and stop relying on GDI. + */ + fb = stw_framebuffer_from_hdc( hdc ); + if (fb) { + assert(iPixelFormat == fb->iDisplayablePixelFormat); + iPixelFormat = fb->iPixelFormat; + stw_framebuffer_release(fb); + } + pfi = stw_pixelformat_get_info( iPixelFormat ); if (hShareContext != 0) { diff --git a/src/gallium/state_trackers/wgl/stw_ext_pbuffer.c b/src/gallium/state_trackers/wgl/stw_ext_pbuffer.c index 282d8a3d424..2c3555d5dbf 100644 --- a/src/gallium/state_trackers/wgl/stw_ext_pbuffer.c +++ b/src/gallium/state_trackers/wgl/stw_ext_pbuffer.c @@ -65,7 +65,7 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) HPBUFFERARB WINAPI -wglCreatePbufferARB(HDC _hDC, +wglCreatePbufferARB(HDC hCurrentDC, int iPixelFormat, int iWidth, int iHeight, @@ -81,6 +81,9 @@ wglCreatePbufferARB(HDC _hDC, RECT rect; HWND hWnd; HDC hDC; + int iDisplayablePixelFormat; + PIXELFORMATDESCRIPTOR pfd; + BOOL bRet; info = stw_pixelformat_get_info(iPixelFormat); if (!info) { @@ -204,15 +207,28 @@ wglCreatePbufferARB(HDC _hDC, return 0; } - SetPixelFormat(hDC, iPixelFormat, &info->pfd); - + /* + * We can't pass non-displayable pixel formats to GDI, which is why we + * create the framebuffer object before calling SetPixelFormat(). + */ fb = stw_framebuffer_create(hDC, iPixelFormat); if (!fb) { SetLastError(ERROR_NO_SYSTEM_RESOURCES); - } else { - stw_framebuffer_release(fb); + return NULL; } + fb->bPbuffer = TRUE; + iDisplayablePixelFormat = fb->iDisplayablePixelFormat; + + stw_framebuffer_release(fb); + + /* + * We need to set a displayable pixel format on the hidden window DC + * so that wglCreateContext and wglMakeCurrent are not overruled by GDI. + */ + bRet = SetPixelFormat(hDC, iDisplayablePixelFormat, &pfd); + assert(bRet); + return (HPBUFFERARB)fb; } diff --git a/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c b/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c index 52253fc7d50..1856db384f8 100644 --- a/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c +++ b/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c @@ -42,6 +42,7 @@ #include <GL/wglext.h> #include "pipe/p_compiler.h" +#include "util/u_format.h" #include "util/u_memory.h" #include "stw_device.h" #include "stw_pixelformat.h" @@ -147,7 +148,12 @@ stw_query_attrib( case WGL_PIXEL_TYPE_ARB: switch (pfi->pfd.iPixelType) { case PFD_TYPE_RGBA: - *pvalue = WGL_TYPE_RGBA_ARB; + if (util_format_is_float(pfi->stvis.color_format)) { + *pvalue = WGL_TYPE_RGBA_FLOAT_ARB; + } + else { + *pvalue = WGL_TYPE_RGBA_ARB; + } break; case PFD_TYPE_COLORINDEX: *pvalue = WGL_TYPE_COLORINDEX_ARB; diff --git a/src/gallium/state_trackers/wgl/stw_framebuffer.c b/src/gallium/state_trackers/wgl/stw_framebuffer.c index 71b92f0d8f6..d0d5e9e0fe6 100644 --- a/src/gallium/state_trackers/wgl/stw_framebuffer.c +++ b/src/gallium/state_trackers/wgl/stw_framebuffer.c @@ -262,6 +262,12 @@ stw_framebuffer_create( fb->hWnd = hWnd; fb->iPixelFormat = iPixelFormat; + /* + * We often need a displayable pixel format to make GDI happy. Set it here (always 1, i.e., + * out first pixel format) where appropriat. + */ + fb->iDisplayablePixelFormat = iPixelFormat <= stw_dev->pixelformat_count ? iPixelFormat : 1; + fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat ); fb->stfb = stw_st_create_framebuffer( fb ); if (!fb->stfb) { @@ -445,15 +451,21 @@ DrvSetPixelFormat( return FALSE; index = (uint) iPixelFormat - 1; - count = stw_pixelformat_get_extended_count(); + count = stw_pixelformat_get_count(); if (index >= count) return FALSE; fb = stw_framebuffer_from_hdc_locked(hdc); if(fb) { - /* SetPixelFormat must be called only once */ + /* + * SetPixelFormat must be called only once. However ignore + * pbuffers, for which the framebuffer object is created first. + */ + boolean bPbuffer = fb->bPbuffer; + stw_framebuffer_release( fb ); - return FALSE; + + return bPbuffer; } fb = stw_framebuffer_create(hdc, iPixelFormat); @@ -467,7 +479,8 @@ DrvSetPixelFormat( * function instead of SetPixelFormat, so we call SetPixelFormat here to * avoid opengl32.dll's wglCreateContext to fail */ if (GetPixelFormat(hdc) == 0) { - SetPixelFormat(hdc, iPixelFormat, NULL); + BOOL bRet = SetPixelFormat(hdc, iPixelFormat, NULL); + assert(bRet); } return TRUE; diff --git a/src/gallium/state_trackers/wgl/stw_framebuffer.h b/src/gallium/state_trackers/wgl/stw_framebuffer.h index 6604e545cbc..439cf79b597 100644 --- a/src/gallium/state_trackers/wgl/stw_framebuffer.h +++ b/src/gallium/state_trackers/wgl/stw_framebuffer.h @@ -64,6 +64,10 @@ struct stw_framebuffer int iPixelFormat; const struct stw_pixelformat_info *pfi; + /* A pixel format that can be used by GDI */ + int iDisplayablePixelFormat; + boolean bPbuffer; + struct st_framebuffer_iface *stfb; /* diff --git a/src/gallium/state_trackers/wgl/stw_pixelformat.c b/src/gallium/state_trackers/wgl/stw_pixelformat.c index ffb7488cb1c..a9667a36981 100644 --- a/src/gallium/state_trackers/wgl/stw_pixelformat.c +++ b/src/gallium/state_trackers/wgl/stw_pixelformat.c @@ -85,6 +85,10 @@ stw_pf_color[] = { { PIPE_FORMAT_B4G4R4A4_UNORM, { 4, 4, 4, 4}, {16, 4, 0, 12} } }; +static const struct stw_pf_color_info +stw_pf_color_extended[] = { + { PIPE_FORMAT_R32G32B32A32_FLOAT, { 32, 32, 32, 32}, { 0, 32, 64, 96} } +}; static const struct stw_pf_depth_info stw_pf_depth_stencil[] = { @@ -116,13 +120,13 @@ stw_pf_multisample[] = { static void stw_pixelformat_add( struct stw_device *stw_dev, + boolean extended, const struct stw_pf_color_info *color, const struct stw_pf_depth_info *depth, unsigned accum, boolean doublebuffer, unsigned samples ) { - boolean extended = FALSE; struct stw_pixelformat_info *pfi; assert(stw_dev->pixelformat_extended_count < STW_MAX_PIXELFORMATS); @@ -146,7 +150,9 @@ stw_pixelformat_add( pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL; /* TODO: also support non-native pixel formats */ - pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW; + if (!extended) { + pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW; + } /* See http://www.opengl.org/pipeline/article/vol003_7/ */ pfi->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION; @@ -238,13 +244,47 @@ stw_pixelformat_init( void ) 0, PIPE_BIND_DEPTH_STENCIL)) continue; - stw_pixelformat_add( stw_dev, color, depth, 0, doublebuffer, samples ); - stw_pixelformat_add( stw_dev, color, depth, 16, doublebuffer, samples ); + stw_pixelformat_add( stw_dev, FALSE, color, depth, 0, doublebuffer, samples ); + stw_pixelformat_add( stw_dev, FALSE, color, depth, 16, doublebuffer, samples ); } } } } + /* + * Same as above, but for the extended color formats (e.g, float) and without PIPE_BIND_DISPLAY_TARGET bit. + */ + for(i = 0; i < Elements(stw_pf_multisample); ++i) { + unsigned samples = stw_pf_multisample[i]; + + /* FIXME: re-enabled MSAA when we can query it */ + if(samples) + continue; + + for(j = 0; j < Elements(stw_pf_color_extended); ++j) { + const struct stw_pf_color_info *color = &stw_pf_color_extended[j]; + + if(!screen->is_format_supported(screen, color->format, PIPE_TEXTURE_2D, + 0, PIPE_BIND_RENDER_TARGET)) + continue; + + for(k = 0; k < Elements(stw_pf_doublebuffer); ++k) { + unsigned doublebuffer = stw_pf_doublebuffer[k]; + + for(l = 0; l < Elements(stw_pf_depth_stencil); ++l) { + const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[l]; + + if(!screen->is_format_supported(screen, depth->format, PIPE_TEXTURE_2D, + 0, PIPE_BIND_DEPTH_STENCIL)) + continue; + + stw_pixelformat_add( stw_dev, TRUE, color, depth, 0, doublebuffer, samples ); + stw_pixelformat_add( stw_dev, TRUE, color, depth, 16, doublebuffer, samples ); + } + } + } + } + assert( stw_dev->pixelformat_count <= stw_dev->pixelformat_extended_count ); assert( stw_dev->pixelformat_extended_count <= STW_MAX_PIXELFORMATS ); } @@ -294,7 +334,7 @@ DrvDescribePixelFormat( if (!stw_dev) return 0; - count = stw_pixelformat_get_extended_count(); + count = stw_pixelformat_get_count(); if (ppfd == NULL) return count; @@ -370,7 +410,7 @@ int stw_pixelformat_choose( HDC hdc, (void) hdc; - count = stw_pixelformat_get_count(); + count = stw_pixelformat_get_extended_count(); bestindex = 0; bestdelta = ~0U; |