-src = $(wildcard src/*.c) test.c
+src = $(wildcard src/*.c)
obj = $(src:.c=.o)
dep = $(obj:.o=.d)
bin = test
CFLAGS = -pedantic -Wall -g -MMD -Isrc
LDFLAGS = -lvulkan -lm
+sys ?= $(shell uname -s | sed 's/MINGW.*/mingw/')
+
+ifeq ($(sys), mingw)
+ src += test_win.c
+ CFLAGS += -DBUILD_WIN32
+else
+ src += test_x11.c
+ CFLAGS += -DBUILD_X11
+ LDFLAGS += -lX11
+endif
+
$(bin): $(obj)
$(CC) -o $@ $(obj) $(LDFLAGS)
VkApplicationInfo appinf = {0};
VkLayerProperties *lprop = 0;
VkExtensionProperties *iext;
- uint32_t i, j, num_inst_layers, num_inst_ext, lprop_count, iext_count;
+ uint32_t i, j, num_inst_layers, num_inst_ext, lprop_count, iext_count, pdev_count;
char **inst_layers = 0, **inst_ext = 0;
+ VkPhysicalDevice *pdev;
+ VkPhysicalDeviceProperties pdevp;
static const char *debug_layers[] = {
"VK_LAYER_LUNARG_device_limits",
static const char *extensions[] = {
"VK_KHR_surface",
"VK_KHR_xlib_surface",
+ "VK_KHR_win32_surface",
0
};
return -1;
}
+ if(vkEnumeratePhysicalDevices(vk, &pdev_count, 0) != 0 || !pdev_count) {
+ fprintf(stderr, "ggfx_init: failed to enumerate physical devices\n");
+ return -1;
+ }
+ if(!(pdev = malloc(pdev_count * sizeof *pdev))) {
+ perror("ggfx_init: failed to allocate memory for physical devices");
+ return -1;
+ }
+ vkEnumeratePhysicalDevices(vk, &pdev_count, pdev);
+
+ printf("Found %d physical devices\n", pdev_count);
+ for(i=0; i<pdev_count; i++) {
+ vkGetPhysicalDeviceProperties(pdev[i], &pdevp);
+ printf(" - %s\n", pdevp.deviceName);
+ }
+
return 0;
}
+++ /dev/null
-#include "gphgfx.h"
-
-int main(int argc, char **argv)
-{
- if(ggfx_init("test", GGFX_INIT_DEBUG) == -1) {
- return 1;
- }
-
- ggfx_shutdown();
- return 0;
-}
--- /dev/null
+#include <stdio.h>
+#include <windows.h>
+#include "gphgfx.h"
+
+static void redraw(void);
+static void reshape(int x, int y);
+static void keydown(int key, int x, int y);
+static void keyup(int key, int x, int y);
+static void button(int bn, int st, int x, int y);
+static void motion(int x, int y);
+
+static int create_window(const char *title, int width, int height);
+static HRESULT CALLBACK handle_message(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam);
+static int translate_vkey(int vkey);
+static void handle_mbutton(int bn, int st, WPARAM wparam, LPARAM lparam);
+
+static HWND win;
+static HINSTANCE hinst;
+static HDC dc;
+static int win_width, win_height;
+
+
+int WINAPI WinMain(HINSTANCE hinst_, HINSTANCE hprev, char *cmdline, int showcmd)
+{
+ WNDCLASSEX wc = {0};
+ MSG msg;
+
+ hinst = hinst_;
+
+ wc.cbSize = sizeof wc;
+ wc.hbrBackground = GetStockObject(BLACK_BRUSH);
+ wc.hCursor = LoadCursor(0, IDC_ARROW);
+ wc.hIcon = wc.hIconSm = LoadIcon(0, IDI_APPLICATION);
+ wc.hInstance = hinst;
+ wc.lpfnWndProc = handle_message;
+ wc.lpszClassName = "gphgfxtest";
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ if(!RegisterClassEx(&wc)) {
+ fprintf(stderr, "failed to register window class\n");
+ return 1;
+ }
+
+ if(create_window("gph-gfx test", 800, 600) == -1) {
+ UnregisterClass("gphgfxtest", hinst);
+ return 1;
+ }
+
+ for(;;) {
+ while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ if(quit) goto end;
+ }
+ redraw();
+ }
+end:
+
+ ggfx_shutdown();
+ ReleaseDC(dc);
+ DestroyWindow(win);
+ UnregisterClass("gphgfxtest", hinst);
+ return 0;
+}
+
+static int create_window(const char *title, int width, int height)
+{
+ if(!(win = CreateWindow("gphgfxtest", title, WS_OVERLAPPEDWINDOW, 0, 0, width,
+ height, 0, 0, hinst, 0))) {
+ fprintf(stderr, "failed to create window\n");
+ return -1;
+ }
+ dc = GetDC(win);
+
+ ShowWindow(win, 1);
+ return 0;
+}
+
+static HRESULT CALLBACK handle_message(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam)
+{
+ static int mouse_x, mouse_y;
+ int x, y, key;
+
+ switch(msg) {
+ case WM_CLOSE:
+ quit = 1;
+ PostQuitMessage(0);
+ break;
+
+ case WM_PAINT:
+ /*upd_pending = 1;*/
+ ValidateRect(win, 0);
+ break;
+
+ case WM_SIZE:
+ x = lparam & 0xffff;
+ y = lparam >> 16;
+ if(x != win_width && y != win_height) {
+ win_width = x;
+ win_height = y;
+ reshape(win_width, win_height);
+ }
+ break;
+
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ key = translate_vkey(wparam);
+ keydown(key, mouse_x, mouse_y);
+ break;
+
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ key = translate_vkey(wparam);
+ keyup(key, mouse_x, mouse_y);
+ break;
+
+ case WM_LBUTTONDOWN:
+ handle_mbutton(0, 1, wparam, lparam);
+ break;
+ case WM_MBUTTONDOWN:
+ handle_mbutton(1, 1, wparam, lparam);
+ break;
+ case WM_RBUTTONDOWN:
+ handle_mbutton(2, 1, wparam, lparam);
+ break;
+ case WM_LBUTTONUP:
+ handle_mbutton(0, 0, wparam, lparam);
+ break;
+ case WM_MBUTTONUP:
+ handle_mbutton(1, 0, wparam, lparam);
+ break;
+ case WM_RBUTTONUP:
+ handle_mbutton(2, 0, wparam, lparam);
+ break;
+
+ case WM_MOUSEMOVE:
+ motion(lparam & 0xffff, lparam >> 16);
+ break;
+
+ case WM_SYSCOMMAND:
+ wparam &= 0xfff0;
+ if(wparam == SC_KEYMENU || wparam == SC_SCREENSAVE || wparam == SC_MONITORPOWER) {
+ return 0;
+ }
+ default:
+ return DefWindowProc(win, msg, wparam, lparam);
+ }
+
+ return 0;
+}
+
+
+static int translate_vkey(int vkey)
+{
+ if(vkey >= 'A' && vkey <= 'Z') {
+ vkey += 32;
+ }
+
+ return vkey;
+}
+
+static void handle_mbutton(int bn, int st, WPARAM wparam, LPARAM lparam)
+{
+ int x = lparam & 0xffff;
+ int y = lparam >> 16;
+ mouse(bn, st, x, y);
+}
--- /dev/null
+#include <stdio.h>
+#include <unistd.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include "gphgfx.h"
+
+static void redraw(void);
+static void reshape(int x, int y);
+static void keydown(int key, int x, int y);
+static void keyup(int key, int x, int y);
+static void button(int bn, int st, int x, int y);
+static void motion(int x, int y);
+
+static int create_window(const char *title, int width, int height);
+static void handle_event(XEvent *ev);
+static KeySym translate_keysym(KeySym sym);
+static void set_window_title(const char *title);
+
+static Display *dpy;
+static int scr;
+static Window win, root;
+static Atom xa_wm_proto, xa_wm_del_win;
+static int quit, mapped, win_width, win_height, modstate;
+static GC gc;
+
+int main(int argc, char **argv)
+{
+ if(!(dpy = XOpenDisplay(0))) {
+ fprintf(stderr, "failed to connect to the X server\n");
+ return 1;
+ }
+ xa_wm_proto = XInternAtom(dpy, "WM_PROTOCOLS", False);
+ xa_wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+
+ scr = DefaultScreen(dpy);
+ root = RootWindow(dpy, scr);
+
+ if(create_window("gph-gfx test", 800, 600) == -1) {
+ return 1;
+ }
+
+ if(ggfx_init("test", GGFX_INIT_DEBUG) == -1) {
+ return 1;
+ }
+
+ for(;;) {
+ while(XPending(dpy)) {
+ XEvent ev;
+ XNextEvent(dpy, &ev);
+ handle_event(&ev);
+ if(quit) goto end;
+ }
+ redraw();
+ }
+end:
+
+ ggfx_shutdown();
+ XFreeGC(dpy, gc);
+ XCloseDisplay(dpy);
+ return 0;
+}
+
+
+static void redraw(void)
+{
+ XSetForeground(dpy, gc, 0xff00);
+ XClearWindow(dpy, win);
+ usleep(10000);
+}
+
+static void reshape(int x, int y)
+{
+ printf("reshape %dx%d\n", x, y);
+}
+
+static void keydown(int key, int x, int y)
+{
+ switch(key) {
+ case 27:
+ quit = 1;
+ break;
+ }
+}
+
+static void keyup(int key, int x, int y)
+{
+}
+
+static void button(int bn, int st, int x, int y)
+{
+}
+
+static void motion(int x, int y)
+{
+}
+
+static int create_window(const char *title, int width, int height)
+{
+ XSetWindowAttributes xattr = {0};
+ XVisualInfo vinf;
+ unsigned int xattr_mask;
+
+ if(!XMatchVisualInfo(dpy, scr, 24, TrueColor, &vinf)) {
+ fprintf(stderr, "failed to find appropriate visual\n");
+ return -1;
+ }
+
+ xattr.background_pixel = BlackPixel(dpy, scr);
+ xattr.colormap = XCreateColormap(dpy, root, vinf.visual, AllocNone);
+ xattr_mask = CWBackPixel | CWColormap | CWBackPixmap | CWBorderPixel;
+ if(!(win = XCreateWindow(dpy, root, 0, 0, width, height, 0, vinf.depth,
+ InputOutput, vinf.visual, xattr_mask, &xattr))) {
+ fprintf(stderr, "Failed to create window\n");
+ return -1;
+ }
+
+ XSelectInput(dpy, win, ExposureMask | StructureNotifyMask | KeyPressMask |
+ KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask);
+
+ set_window_title(title);
+ XSetWMProtocols(dpy, win, &xa_wm_del_win, 1);
+ XMapWindow(dpy, win);
+
+ gc = XCreateGC(dpy, win, 0, 0);
+ return 0;
+}
+
+
+static KeySym translate_keysym(KeySym sym)
+{
+ switch(sym) {
+ case XK_Escape:
+ return 27;
+ case XK_BackSpace:
+ return '\b';
+ case XK_Linefeed:
+ return '\r';
+ case XK_Return:
+ return '\n';
+ case XK_Delete:
+ return 127;
+ case XK_Tab:
+ return '\t';
+ default:
+ break;
+ }
+ return sym;
+}
+
+static void handle_event(XEvent *ev)
+{
+ KeySym sym;
+
+ switch(ev->type) {
+ case MapNotify:
+ mapped = 1;
+ break;
+ case UnmapNotify:
+ mapped = 0;
+ break;
+ case ConfigureNotify:
+ if(ev->xconfigure.width != win_width || ev->xconfigure.height != win_height) {
+ win_width = ev->xconfigure.width;
+ win_height = ev->xconfigure.height;
+ reshape(ev->xconfigure.width, ev->xconfigure.height);
+ }
+ break;
+
+ case ClientMessage:
+ if(ev->xclient.message_type == xa_wm_proto) {
+ if(ev->xclient.data.l[0] == xa_wm_del_win) {
+ quit = 1;
+ }
+ }
+ break;
+
+ case Expose:
+ /*upd_pending = 1;*/
+ break;
+
+ case KeyPress:
+ case KeyRelease:
+ modstate = ev->xkey.state & (ShiftMask | ControlMask | Mod1Mask);
+ if(!(sym = XLookupKeysym(&ev->xkey, 0))) {
+ break;
+ }
+ sym = translate_keysym(sym);
+ if(ev->type == KeyPress) {
+ keydown(sym, ev->xkey.x, ev->xkey.y);
+ } else {
+ keyup(sym, ev->xkey.x, ev->xkey.y);
+ }
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ modstate = ev->xbutton.state & (ShiftMask | ControlMask | Mod1Mask);
+ button(ev->xbutton.button - Button1, ev->type == ButtonPress,
+ ev->xbutton.x, ev->xbutton.y);
+ break;
+
+ case MotionNotify:
+ motion(ev->xmotion.x, ev->xmotion.y);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void set_window_title(const char *title)
+{
+ XTextProperty tprop;
+ if(!XStringListToTextProperty((char**)&title, 1, &tprop)) {
+ return;
+ }
+ XSetWMName(dpy, win, &tprop);
+ XFree(tprop.value);
+}