Mesa (master): st/wgl: Properly support non-displayble pixel formats, and implement float pixelformats as as one.

Jose Fonseca jrfonseca at kemper.freedesktop.org
Fri Feb 10 16:23:35 UTC 2012


Module: Mesa
Branch: master
Commit: 9646762261d976d34bee8c8b1dcda9656cec655c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=9646762261d976d34bee8c8b1dcda9656cec655c

Author: José Fonseca <jfonseca at vmware.com>
Date:   Wed Feb  8 16:23:06 2012 +0000

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.

---

 src/gallium/state_trackers/wgl/stw_context.c       |   14 +++++
 src/gallium/state_trackers/wgl/stw_ext_pbuffer.c   |   26 ++++++++--
 .../state_trackers/wgl/stw_ext_pixelformat.c       |    8 +++-
 src/gallium/state_trackers/wgl/stw_framebuffer.c   |   21 ++++++--
 src/gallium/state_trackers/wgl/stw_framebuffer.h   |    4 ++
 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 1409f24..7031af5 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 282d8a3..2c3555d 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 52253fc..1856db3 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 71b92f0..d0d5e9e 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 6604e54..439cf79 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 ffb7488..a9667a3 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;
 




More information about the mesa-commit mailing list