diff --git a/README.md b/README.md index f9b7f80..da03916 100644 --- a/README.md +++ b/README.md @@ -259,10 +259,8 @@ This list describes the amount of functions left from each standard to implement - [x] 4.6 (~4 total) # Limitations / Issues -- Frame glitches possible when running multiple clients -- Clients may reserve too much memory according to server's allocated memory -- Resizing is possible, no proper implementation -- New GLX FB configs may cause applications using `freeglut` or `glad` to no longer run +- New GLX FB configs may cause applications using `freeglut` or `glad` to no longer run (only tested on Linux clients). +- Incomplete framebuffers when using network feature # Troubleshooting diff --git a/inc/client/platform/icd.h b/inc/client/platform/icd.h new file mode 100644 index 0000000..94bf936 --- /dev/null +++ b/inc/client/platform/icd.h @@ -0,0 +1,23 @@ +#ifndef _ICD_H_ +#define _ICD_H_ + +#define ICD_SET_MAX_DIMENSIONS_DEFINITION(mw, mh, rw, rh) \ + void icd_set_max_dimensions(int width, int height) \ + { \ + mw = width; \ + mh = height; \ + rw = 16; \ + rh = 16; \ + } + +#define ICD_RESIZE_DEFINITION(rw, rh) \ + void icd_resize(int width, int height) \ + { \ + rw = width; \ + rh = height; \ + } \ + +void icd_set_max_dimensions(int width, int height); +void icd_resize(int width, int height); + +#endif \ No newline at end of file diff --git a/inc/network/packet.h b/inc/network/packet.h index 6f3f39e..eb9368c 100644 --- a/inc/network/packet.h +++ b/inc/network/packet.h @@ -30,6 +30,8 @@ struct PACKED sgl_packet_connect { uint64_t fifo_size; uint32_t gl_major; uint32_t gl_minor; + uint32_t max_width; + uint32_t max_height; }; struct PACKED sgl_packet_swapbuffers_request { diff --git a/inc/sharedgl.h b/inc/sharedgl.h index cd29edf..d2b5eeb 100644 --- a/inc/sharedgl.h +++ b/inc/sharedgl.h @@ -54,6 +54,10 @@ #define CEIL_DIV(num, den) ((num + den - 1) / den) +#define PACK(a, b) (((a) << 16) | ((b) & 0xFFFF)) +#define UNPACK_A(packed) (((packed) >> 16) & 0xFFFF) +#define UNPACK_B(packed) ((packed) & 0xFFFF) + inline bool is_value_likely_an_offset(const void *p) { uintptr_t v = (uintptr_t)p; @@ -65,7 +69,7 @@ inline bool is_value_likely_an_offset(const void *p) */ enum { SGL_CMD_INVALID, - SGL_CMD_FLIP, + SGL_CMD_FLIP, // USE SGL_CMD_REQUEST_FRAMEBUFFER INSTEAD SGL_CMD_SEND_DATA, SGL_CMD_GET_CONTEXT, SGL_CMD_SET_CONTEXT, @@ -75,7 +79,7 @@ enum { SGL_CMD_VP_UPLOAD_STAY, SGL_CMD_VP_DOWNLOAD, // UNLIKE VP_UPLOAD, WE USE BYTES INSTEAD OF INTS SGL_CMD_CREATE_CONTEXT, - SGL_CMD_REPORT_DIMS, + SGL_CMD_REPORT_DIMS, // NOT USED SGL_CMD_HELLO_WORLD, SGL_CMD_GOODBYE_WORLD, SGL_CMD_REQUEST_FRAMEBUFFER, diff --git a/src/client/glimpl.c b/src/client/glimpl.c index 60ff5ea..4b83d75 100644 --- a/src/client/glimpl.c +++ b/src/client/glimpl.c @@ -3,6 +3,8 @@ #include #include +#include + #include #include @@ -360,14 +362,6 @@ void glimpl_goodbye() #endif } -void glimpl_report(int width, int height) -{ - pb_push(SGL_CMD_REPORT_DIMS); - pb_push(width); - pb_push(height); - glimpl_submit(); -} - void glimpl_swap_buffers(int width, int height, int vflip, int format) { if (GLIMPL_USES_SHARED_MEMORY) { @@ -391,7 +385,7 @@ void glimpl_swap_buffers(int width, int height, int vflip, int format) net_send_udp(net_ctx, &packet, sizeof(packet), 0); - int expected = (width * height * 4) / SGL_SWAPBUFFERS_RESULT_SIZE + ((width * height * 4) % SGL_SWAPBUFFERS_RESULT_SIZE != 0); + int expected = CEIL_DIV((width * height * 4), SGL_SWAPBUFFERS_RESULT_SIZE); // wait for sync, timeout appears to disturb fifo upload struct sgl_packet_sync sync; @@ -479,6 +473,8 @@ void glimpl_init() }; pb_set_net(hooks, packet.fifo_size); + + icd_set_max_dimensions(packet.max_width, packet.max_height); } char *gl_version_override = getenv("GL_VERSION_OVERRIDE"); @@ -509,6 +505,9 @@ void glimpl_init() */ pb_push(SGL_CMD_CREATE_CONTEXT); glimpl_submit(); + + int packed_dims = pb_read(SGL_OFFSET_REGISTER_RETVAL); + icd_set_max_dimensions(UNPACK_A(packed_dims), UNPACK_B(packed_dims)); } } @@ -1724,6 +1723,7 @@ void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) pb_push(y); pb_push(width); pb_push(height); + icd_resize(width, height); } void glMultMatrixd(const GLdouble* m) diff --git a/src/client/platform/glx.c b/src/client/platform/glx.c index 0feb056..373c72c 100644 --- a/src/client/platform/glx.c +++ b/src/client/platform/glx.c @@ -1,5 +1,6 @@ #include +#include #include #include @@ -17,6 +18,11 @@ static int glx_major = 1; static int glx_minor = 4; static const char *glx_majmin_string = "1.4"; +static int max_width, max_height, real_width, real_height; + +ICD_SET_MAX_DIMENSIONS_DEFINITION(max_width, max_height, real_width, real_height); +ICD_RESIZE_DEFINITION(real_width, real_height); + struct glx_swap_data { XVisualInfo vinfo; XVisualInfo *visual_list; @@ -54,7 +60,7 @@ struct glx_fb_config { // to-do: add more like stereo }; -int n_valid_fb_configs; +static int n_valid_fb_configs; static struct glx_fb_config fb_configs[1729] = { 0 }; @@ -375,8 +381,6 @@ void glXSwapBuffers(Display* dpy, GLXDrawable drawable) XWindowAttributes attr; XGetWindowAttributes(dpy, drawable, &attr); - swap_data.width = attr.width; - swap_data.height = attr.height; swap_data.parent = XDefaultRootWindow(dpy); swap_data.nxvisuals = 0; swap_data.visual_template.screen = DefaultScreen(dpy); @@ -387,22 +391,17 @@ void glXSwapBuffers(Display* dpy, GLXDrawable drawable) /* * create an ximage whose pointer points to our framebuffer */ - swap_data.ximage = XCreateImage(dpy, swap_data.vinfo.visual, swap_data.vinfo.depth, ZPixmap, 0, glimpl_fb_address(), swap_data.width, swap_data.height, 8, swap_data.width*4); + swap_data.ximage = XCreateImage(dpy, swap_data.vinfo.visual, swap_data.vinfo.depth, ZPixmap, 0, glimpl_fb_address(), max_width, max_height, 8, max_width*4); swap_data.gcv.graphics_exposures = 0; swap_data.gc = XCreateGC(dpy, swap_data.parent, GCGraphicsExposures, &swap_data.gcv); - - /* - * report current window dimensions, initialization done - */ - glimpl_report(swap_data.width, swap_data.height); swap_data.initialized = true; } /* swap */ - glimpl_swap_buffers(swap_data.width, swap_data.height, 1, GL_BGRA); + glimpl_swap_buffers(real_width, real_height, 1, GL_BGRA); /* display */ - XPutImage(dpy, drawable, swap_data.gc, swap_data.ximage, 0, 0, 0, 0, swap_data.width, swap_data.height); + XPutImage(dpy, drawable, swap_data.gc, swap_data.ximage, 0, 0, 0, 0, real_width, real_height); /* sync */ XSync(dpy, False); diff --git a/src/client/platform/windrv.c b/src/client/platform/windrv.c index c0a7c9c..603fd6e 100644 --- a/src/client/platform/windrv.c +++ b/src/client/platform/windrv.c @@ -4,19 +4,25 @@ #include #include #include +#include #include static HWND capturedWindow; static HDC capturedHdc; -static int capturedWidth; -static int capturedHeight; +// static int capturedWidth; +// static int capturedHeight; static PIXELFORMATDESCRIPTOR pfdTable[64] = { 0 }; static int pfdCount = 0; static struct WGLCALLBACKS callbacks; +static int maxWidth, maxHeight, realWidth, realHeight; + +ICD_SET_MAX_DIMENSIONS_DEFINITION(maxWidth, maxHeight, realWidth, realHeight); +ICD_RESIZE_DEFINITION(realWidth, realHeight); + #define MIN_INTERNAL( A, B ) ( (A)<(B) ? (A) : (B) ) #define MAX_INTERNAL( A, B ) ( (A)>(B) ? (A) : (B) ) @@ -193,11 +199,11 @@ PGLCLTPROCTABLE APIENTRY DrvSetContext(HDC hdc, DHGLRC dhglrc, PFN_SETPROCTABLE capturedHdc = hdc; capturedWindow = WindowFromDC(capturedHdc); - RECT Rect; - if (GetClientRect(capturedWindow, &Rect)) { - capturedWidth = Rect.right - Rect.left; - capturedHeight = Rect.bottom - Rect.top; - } + // RECT Rect; + // if (GetClientRect(capturedWindow, &Rect)) { + // capturedWidth = Rect.right - Rect.left; + // capturedHeight = Rect.bottom - Rect.top; + // } return glimpl_GetProcTable(); } @@ -276,17 +282,15 @@ BOOL APIENTRY DrvSwapBuffers(HDC hdc) static void *Frame = NULL; if (!Init) { - bmi.bmiHeader.biWidth = capturedWidth; - bmi.bmiHeader.biHeight = -capturedHeight; - - glimpl_report(capturedWidth, capturedHeight); - Frame = glimpl_fb_address(); Init = 1; } - glimpl_swap_buffers(capturedWidth, capturedHeight, 1, GL_BGRA); /* to-do: fix overlay so vflip and -Height won't be needed */ - SetDIBitsToDevice(capturedHdc, 0, 0, capturedWidth, capturedHeight, 0, 0, 0, capturedHeight, Frame, &bmi, DIB_RGB_COLORS); + bmi.bmiHeader.biWidth = realWidth; + bmi.bmiHeader.biHeight = -realHeight; + + glimpl_swap_buffers(realWidth, realHeight, 1, GL_BGRA); /* to-do: fix overlay so vflip and -Height won't be needed */ + SetDIBitsToDevice(capturedHdc, 0, 0, realWidth, realHeight, 0, 0, 0, realHeight, Frame, &bmi, DIB_RGB_COLORS); // StretchDIBits(Hdc, 0, 0, Width, Height, 0, 0, Width, Height, Frame, &bmi, DIB_RGB_COLORS, SRCCOPY); return TRUE; diff --git a/src/server/context.c b/src/server/context.c index 03611f0..7e051e0 100644 --- a/src/server/context.c +++ b/src/server/context.c @@ -73,7 +73,6 @@ void sgl_context_destroy(struct sgl_host_context *ctx) free(ctx); } -#define SGL_DEBUG_EMIT_FRAMES #ifdef SGL_DEBUG_EMIT_FRAMES SDL_Window *window; #endif @@ -97,14 +96,14 @@ void *sgl_read_pixels(unsigned int width, unsigned int height, void *data, int v overlay_stage1(&overlay_ctx); - glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, data); // GL_BGRA + glReadPixels(0, 0, mw, height, format, GL_UNSIGNED_BYTE, data); // GL_BGRA int *pdata = data; if (vflip) { for (int y = 0; y < height / 2; y++) { - for (int x = 0; x < width; x++) { - int *ptop = &pdata[y * width + x]; - int *pbottom = &pdata[(height - y - 1) * width + x]; + for (int x = 0; x < mw; x++) { + int *ptop = &pdata[y * mw + x]; + int *pbottom = &pdata[(height - y - 1) * mw + x]; int vtop = *ptop; int vbottom = *pbottom; @@ -115,7 +114,7 @@ void *sgl_read_pixels(unsigned int width, unsigned int height, void *data, int v } } - overlay_stage2(&overlay_ctx, data, width, mem_usage); + overlay_stage2(&overlay_ctx, data, mw, mem_usage); #ifdef SGL_DEBUG_EMIT_FRAMES SDL_GL_SwapWindow(window); diff --git a/src/server/processor.c b/src/server/processor.c index 875b34e..0ce58ac 100644 --- a/src/server/processor.c +++ b/src/server/processor.c @@ -124,8 +124,6 @@ void sgl_cmd_processor_start(struct sgl_cmd_processor_args args) size_t fifo_size = args.memory_size - SGL_OFFSET_COMMAND_START - framebuffer_size; void *p = args.base_address; - int reported_width = -1; - int reported_height = -1; struct sgl_host_context *ctx; bool begun = false; @@ -240,7 +238,9 @@ void sgl_cmd_processor_start(struct sgl_cmd_processor_args args) /* framebuffer_size = */ framebuffer_size, /* fifo_size = */ fifo_size, /* gl_major = */ args.gl_major, - /* gl_minor = */ args.gl_minor + /* gl_minor = */ args.gl_minor, + /* max_width= */ width, + /* max_height= */ height }; net_send_tcp(net_ctx, socket, &packet, sizeof(packet)); @@ -361,6 +361,7 @@ void sgl_cmd_processor_start(struct sgl_cmd_processor_args args) * Internal Implementation */ case SGL_CMD_CREATE_CONTEXT: + *(int*)(p + SGL_OFFSET_REGISTER_RETVAL) = PACK(width, height); break; case SGL_CMD_GOODBYE_WORLD: { int id = *pb++;