[waffle] [PATCH 07/18] wgl: wire-up wgl_window and wgl_config hooks

Emil Velikov emil.l.velikov at gmail.com
Tue Jul 22 20:31:33 PDT 2014


WGL mandates that a window (device_context actually) must be
available before we choose the the config and create a context.
Create the window at wgl_config_choose() and hide it until
wgl_window_create() is executed.

Note that this will mandate 'only one window is allowed per config'
as such one should _never_ try to create two windows for a single
config with WGL.

To prevent issues, simply return NULL if we're trying to
create the second window.

Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com>
---
 src/waffle/wgl/wgl_config.c |  90 ++++++++++++++++++++++++++++++-
 src/waffle/wgl/wgl_config.h |   6 +++
 src/waffle/wgl/wgl_window.c | 125 ++++++++++++++++++++++++++++++++++++++++++--
 src/waffle/wgl/wgl_window.h |  12 +++++
 4 files changed, 226 insertions(+), 7 deletions(-)

diff --git a/src/waffle/wgl/wgl_config.c b/src/waffle/wgl/wgl_config.c
index 3bf8e33..5eaf36e 100644
--- a/src/waffle/wgl/wgl_config.c
+++ b/src/waffle/wgl/wgl_config.c
@@ -26,34 +26,100 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
+#include <windows.h>
 
 #include "wcore_config_attrs.h"
 #include "wcore_error.h"
 
 #include "wgl_config.h"
+#include "wgl_display.h"
 #include "wgl_error.h"
 #include "wgl_platform.h"
+#include "wgl_window.h"
 
 bool
 wgl_config_destroy(struct wcore_config *wc_self)
 {
     struct wgl_config *self = wgl_config(wc_self);
-    bool ok;
+    bool ok = true;
 
     if (!self)
         return true;
 
-    ok = wcore_config_teardown(wc_self);
+    if (self->window)
+        ok &= wgl_window_priv_destroy(&self->window->wcore);
+
+    ok &= wcore_config_teardown(wc_self);
     free(self);
     return ok;
 }
 
+static void
+wgl_config_set_pixeldescriptor(struct wgl_config *config,
+                               const struct wcore_config_attrs *attrs)
+{
+    PIXELFORMATDESCRIPTOR *pfd = &config->pfd;
+
+    pfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
+    pfd->nVersion = 1;
+
+    pfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+    if (attrs->double_buffered)
+        pfd->dwFlags |= PFD_DOUBLEBUFFER;
+
+    pfd->iPixelType = PFD_TYPE_RGBA;
+
+    pfd->cColorBits        = attrs->rgba_size;
+    pfd->cRedBits          = attrs->red_size;
+    pfd->cGreenBits        = attrs->green_size;
+    pfd->cBlueBits         = attrs->blue_size;
+    pfd->cAlphaBits        = attrs->alpha_size;
+
+    pfd->cDepthBits        = attrs->depth_size;
+    pfd->cStencilBits      = attrs->stencil_size;
+
+    // XXX: Double check these
+    pfd->cAccumRedBits     = attrs->accum_buffer;
+    pfd->cAccumGreenBits   = attrs->accum_buffer;
+    pfd->cAccumBlueBits    = attrs->accum_buffer;
+    pfd->cAccumAlphaBits   = attrs->accum_buffer;
+    pfd->cAccumBits        = pfd->cAccumRedBits +
+                             pfd->cAccumGreenBits +
+                             pfd->cAccumBlueBits +
+                             pfd->cAccumAlphaBits;
+
+    pfd->iLayerType = PFD_MAIN_PLANE;
+}
+
+static bool
+wgl_config_choose_native(struct wgl_config *config,
+                         struct wgl_display *dpy,
+                         const struct wcore_config_attrs *attrs)
+{
+    if (0 /* dpy->ARB_pixel_format */) {
+        // XXX: FINISHME
+    }
+    else {
+        config->pixel_format = ChoosePixelFormat(dpy->hDC, &config->pfd);
+        if (!config->pixel_format) {
+            wcore_errorf(WAFFLE_ERROR_UNKNOWN,
+                         "ChoosePixelFormat failed to find a matching format");
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
 struct wcore_config*
 wgl_config_choose(struct wcore_platform *wc_plat,
                   struct wcore_display *wc_dpy,
                   const struct wcore_config_attrs *attrs)
 {
     struct wgl_config *self;
+    struct wgl_display *dpy = wgl_display(wc_dpy);
+    struct wcore_window *wc_window;
     bool ok;
 
     self = wcore_calloc(sizeof(*self));
@@ -64,6 +130,26 @@ wgl_config_choose(struct wcore_platform *wc_plat,
     if (!ok)
         goto error;
 
+    wgl_config_set_pixeldescriptor(self, attrs);
+
+    ok = wgl_config_choose_native(self, dpy, attrs);
+    if (!ok)
+        goto error;
+
+    // Hurray, we've got the pixel format.
+
+    wc_window = wgl_window_priv_create(wc_plat, &self->wcore, 10, 10);
+    if (!wc_window)
+        goto error;
+
+    self->window = wgl_window(wc_window);
+
+    // Now let's pray that the root window's hDC is compatible with the
+    // new window hDC.
+    ok = SetPixelFormat(self->window->hDC, self->pixel_format, &self->pfd);
+    if (!ok)
+        goto error;
+
     return &self->wcore;
 
 error:
diff --git a/src/waffle/wgl/wgl_config.h b/src/waffle/wgl/wgl_config.h
index 5b58b42..822cc85 100644
--- a/src/waffle/wgl/wgl_config.h
+++ b/src/waffle/wgl/wgl_config.h
@@ -33,9 +33,15 @@
 
 struct wcore_config_attrs;
 struct wcore_platform;
+struct wgl_window;
 
 struct wgl_config {
     struct wcore_config wcore;
+    PIXELFORMATDESCRIPTOR pfd;
+    int pixel_format;
+
+    // XXX: Currently we manage only one window per config.
+    struct wgl_window *window;
 };
 
 DEFINE_CONTAINER_CAST_FUNC(wgl_config,
diff --git a/src/waffle/wgl/wgl_window.c b/src/waffle/wgl/wgl_window.c
index 922b835..43a49a4 100644
--- a/src/waffle/wgl/wgl_window.c
+++ b/src/waffle/wgl/wgl_window.c
@@ -23,21 +23,44 @@
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include <windows.h>
+
 #include "wcore_error.h"
 
 #include "wgl_config.h"
+#include "wgl_platform.h"
 #include "wgl_window.h"
 
 bool
 wgl_window_destroy(struct wcore_window *wc_self)
 {
     struct wgl_window *self = wgl_window(wc_self);
-    bool ok;
+
+    assert(self);
+    assert(self->hWnd);
+
+    self->created = false;
+    ShowWindow(self->hWnd, SW_HIDE);
+    return true;
+}
+
+bool
+wgl_window_priv_destroy(struct wcore_window *wc_self)
+{
+    struct wgl_window *self = wgl_window(wc_self);
+    bool ok = true;
 
     if (!self)
         return true;
 
-    ok = wcore_window_teardown(wc_self);
+    if (self->hWnd) {
+        if (self->hDC) {
+            ok &= ReleaseDC(self->hWnd, self->hDC);
+        }
+        ok &= DestroyWindow(self->hWnd);
+    }
+
+    ok &= wcore_window_teardown(wc_self);
     free(self);
     return ok;
 }
@@ -48,8 +71,37 @@ wgl_window_create(struct wcore_platform *wc_plat,
                   int width,
                   int height)
 {
+    struct wgl_config *config = wgl_config(wc_config);
+    bool ok;
+
+    assert(config->window);
+
+    // Currently we do not allow multiple windows per config.
+    // Neither piglit nor the waffle examples do that yet, so just
+    // return NULL in case that ever changes.
+    assert(!config->window->created);
+    if (config->window->created)
+        return NULL;
+
+    config->window->created = true;
+
+    ok = wgl_window_resize(&config->window->wcore, width, height);
+    if (!ok)
+        return NULL;
+
+    return &config->window->wcore;
+}
+
+struct wcore_window*
+wgl_window_priv_create(struct wcore_platform *wc_plat,
+                       struct wcore_config *wc_config,
+                       int width,
+                       int height)
+{
+    struct wgl_platform *plat = wgl_platform(wc_plat);
     struct wgl_window *self;
     bool ok;
+    RECT rect;
 
     self = wcore_calloc(sizeof(*self));
     if (!self)
@@ -59,6 +111,26 @@ wgl_window_create(struct wcore_platform *wc_plat,
     if (!ok)
         goto error;
 
+    rect.left = 0;
+    rect.top = 0;
+    rect.right = rect.left + width;
+    rect.bottom = rect.top + height;
+
+    ok = AdjustWindowRect(&rect, WS_POPUPWINDOW, FALSE);
+    if (!ok)
+        goto error;
+
+    self->hWnd = CreateWindow(plat->class_name, NULL, WS_POPUPWINDOW,
+                              0, 0,
+                              rect.right - rect.left, rect.bottom - rect.top,
+                              NULL, NULL, NULL, NULL);
+    if (!self->hWnd)
+        goto error;
+
+    self->hDC = GetDC(self->hWnd);
+    if (!self->hDC)
+        goto error;
+
     return &self->wcore;
 
 error:
@@ -69,19 +141,62 @@ error:
 bool
 wgl_window_show(struct wcore_window *wc_self)
 {
-    return false;
+    struct wgl_window *self = wgl_window(wc_self);
+
+    assert(self);
+    assert(self->hWnd);
+
+    // If the window was previously hidden the function returns zero,
+    // and non-zero otherwise.
+    // XXX: Use SW_SHOW or SW_SHOWDEFAULT, SW_SHOWNORMAL ?
+    ShowWindow(self->hWnd, SW_SHOW);
+    return true;
 }
 
 bool
 wgl_window_resize(struct wcore_window *wc_self,
                   int32_t width, int32_t height)
 {
-    return false;
+    struct wgl_window *self = wgl_window(wc_self);
+    RECT rect;
+    bool ok;
+
+    assert(self);
+    assert(self->hWnd);
+
+    rect.left = 0;
+    rect.top = 0;
+    rect.right = rect.left + width;
+    rect.bottom = rect.top + height;
+
+    ok = AdjustWindowRect(&rect, WS_POPUPWINDOW, FALSE);
+    if (!ok)
+        return false;
+
+    ok = SetWindowPos(self->hWnd, 0, 0, 0,
+                      rect.right - rect.left,
+                      rect.bottom - rect.top,
+                      SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
+
+#ifdef DEBUG
+    // Verify the client area size matches the required size.
+
+    GetClientRect(self->hWnd, &rect);
+    assert(rect.left == 0);
+    assert(rect.top == 0);
+    assert(rect.right - rect.left == width);
+    assert(rect.bottom - rect.top == height);
+#endif
+    return ok;
 }
 
 bool
 wgl_window_swap_buffers(struct wcore_window *wc_self)
 {
-    return false;
+    struct wgl_window *self = wgl_window(wc_self);
+
+    assert(self);
+    assert(self->hDC);
 
+    return SwapBuffers(self->hDC);
 }
diff --git a/src/waffle/wgl/wgl_window.h b/src/waffle/wgl/wgl_window.h
index ff1dbf3..787054a 100644
--- a/src/waffle/wgl/wgl_window.h
+++ b/src/waffle/wgl/wgl_window.h
@@ -34,6 +34,9 @@ struct wcore_platform;
 
 struct wgl_window {
     struct wcore_window wcore;
+    HWND hWnd;
+    HDC hDC;
+    bool created;
 };
 
 DEFINE_CONTAINER_CAST_FUNC(wgl_window,
@@ -41,6 +44,15 @@ DEFINE_CONTAINER_CAST_FUNC(wgl_window,
                            struct wcore_window,
                            wcore)
 struct wcore_window*
+wgl_window_priv_create(struct wcore_platform *wc_plat,
+                       struct wcore_config *wc_config,
+                       int width,
+                       int height);
+
+bool
+wgl_window_priv_destroy(struct wcore_window *wc_self);
+
+struct wcore_window*
 wgl_window_create(struct wcore_platform *wc_plat,
                   struct wcore_config *wc_config,
                   int width,
-- 
2.0.2



More information about the waffle mailing list