summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers
diff options
context:
space:
mode:
authorJosé Fonseca <[email protected]>2012-02-08 16:23:06 +0000
committerJosé Fonseca <[email protected]>2012-02-10 16:23:27 +0000
commit9646762261d976d34bee8c8b1dcda9656cec655c (patch)
tree7433473c28a262191b0e06b87753df2d61435025 /src/gallium/state_trackers
parent90a95f4d2c50b63ffa4c114081a1cfa5cdfa05cb (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.
Diffstat (limited to 'src/gallium/state_trackers')
-rw-r--r--src/gallium/state_trackers/wgl/stw_context.c14
-rw-r--r--src/gallium/state_trackers/wgl/stw_ext_pbuffer.c26
-rw-r--r--src/gallium/state_trackers/wgl/stw_ext_pixelformat.c8
-rw-r--r--src/gallium/state_trackers/wgl/stw_framebuffer.c21
-rw-r--r--src/gallium/state_trackers/wgl/stw_framebuffer.h4
-rw-r--r--src/gallium/state_trackers/wgl/stw_pixelformat.c52
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;