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 <[email protected]> --- 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 _______________________________________________ waffle mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/waffle

