[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