diff --git a/src/Backends/Rendering/Window/Software/X11.cpp b/src/Backends/Rendering/Window/Software/X11.cpp index e5f8f0dc..c2e1bb64 100644 --- a/src/Backends/Rendering/Window/Software/X11.cpp +++ b/src/Backends/Rendering/Window/Software/X11.cpp @@ -13,15 +13,22 @@ #include static Window window; + +// Framebuffer is the image that the game gets to write to static XImage* framebufferImage; -static unsigned char* framebufferPixels; +static char *framebufferPixels; +static XShmSegmentInfo framebufferSegInfo; +// Display is the one X gets to read from, we swap them every frame +static XImage* displayImage; +static char *displayPixels; +static XShmSegmentInfo displaySegInfo; + static int framebufferPitch; static char* xfriendlyFB; static GC gc; static int screenWidth; static int screenHeight; static bool useShmP = false; -static XShmSegmentInfo seginfo; extern Display* xDisplay; extern Visual* xVisual; @@ -45,22 +52,34 @@ void createFramebuffer() { int depth = DefaultDepth(xDisplay, DefaultScreen(xDisplay)); // Setting up the framebuffer - xfriendlyFB = NULL; + displayPixels = NULL; if(useShmP) { + displayImage = XShmCreateImage(xDisplay, xVisual, + depth, ZPixmap, NULL, + &displaySegInfo, screenWidth, screenHeight); + displaySegInfo.shmid = shmget(IPC_PRIVATE, + displayImage->bytes_per_line * displayImage->height, + IPC_CREAT | 0777); + displaySegInfo.shmaddr = displayPixels = displayImage->data = + (char*)shmat(displaySegInfo.shmid, NULL, 0); + XShmAttach(xDisplay, &displaySegInfo); + framebufferImage = XShmCreateImage(xDisplay, xVisual, depth, ZPixmap, NULL, - &seginfo, screenWidth, screenHeight); - seginfo.shmid = shmget(IPC_PRIVATE, - framebufferImage->bytes_per_line * framebufferImage->height, - IPC_CREAT | 0777); - seginfo.shmaddr = xfriendlyFB = framebufferImage->data = (char*)shmat(seginfo.shmid, NULL, 0); - XShmAttach(xDisplay, &seginfo); + &framebufferSegInfo, screenWidth, screenHeight); + framebufferSegInfo.shmid = shmget(IPC_PRIVATE, + framebufferImage->bytes_per_line * displayImage->height, + IPC_CREAT | 0777); + framebufferSegInfo.shmaddr = framebufferPixels = framebufferImage->data = + (char*)shmat(framebufferSegInfo.shmid, NULL, 0); + XShmAttach(xDisplay, &framebufferSegInfo); } else { - xfriendlyFB = (char*)malloc(screenWidth * screenHeight * 4); - framebufferImage = XCreateImage(xDisplay, xVisual, + displayPixels = (char*)malloc(screenWidth * screenHeight * 4); + framebufferPixels = displayPixels; + displayImage = XCreateImage(xDisplay, xVisual, depth, ZPixmap, 0, - (char*)xfriendlyFB, screenWidth, screenHeight, + (char*)displayPixels, screenWidth, screenHeight, 32, 0); } } @@ -91,12 +110,12 @@ bool WindowBackend_Software_CreateWindow(const char *window_title, size_t screen XSetWMProtocols(xDisplay, window, &WM_DELETE_WINDOW, 1); createFramebuffer(); - if(checkImageOK(framebufferImage) == false) { + if(checkImageOK(displayImage) == false) { Backend_PrintError("Something's off with the framebuffer.\n"); return false; } - if(framebufferImage == 0) { + if(displayImage == 0) { return false; } @@ -108,16 +127,24 @@ unsigned char* WindowBackend_Software_GetFramebuffer(size_t *pitch) { *pitch = framebufferPitch; - return (unsigned char*)xfriendlyFB; + return (unsigned char*)framebufferPixels; } void WindowBackend_Software_DestroyWindow(void) { if(useShmP) { - XShmDetach(xDisplay, &seginfo); + XShmDetach(xDisplay, &displaySegInfo); + XShmDetach(xDisplay, &framebufferSegInfo); + + XDestroyImage(displayImage); XDestroyImage(framebufferImage); - shmdt(seginfo.shmaddr); - shmctl(seginfo.shmid, IPC_RMID, 0); + + shmdt(displaySegInfo.shmaddr); + shmctl(displaySegInfo.shmid, IPC_RMID, 0); + + shmdt(framebufferSegInfo.shmaddr); + shmctl(framebufferSegInfo.shmid, IPC_RMID, 0); } + XDestroyWindow(xDisplay, window); } @@ -129,22 +156,19 @@ void WindowBackend_Software_HandleWindowResize(size_t width, size_t height) { } void WindowBackend_Software_Display(void) { - // Convert Cave Story's framebuffer format to the Sun's - // This is the exact reverse of how it is on modern - // computers. Yup, it's endianess. - // int srci = 0; - // for(int i = 0; i < screenWidth * screenHeight * 4; i += 4) { - // int src; - // xfriendlyFB[i + 3] = 0; // UNUSED - // xfriendlyFB[i + 2] = framebufferPixels[srci + 0]; // BLUE - // xfriendlyFB[i + 1] = framebufferPixels[srci + 1]; // GREEN - // xfriendlyFB[i + 0] = framebufferPixels[srci + 2]; // RED - // srci += 4; - // } - //memcpy(xfriendlyFB, framebufferPixels, screenWidth * screenHeight * 4); if(useShmP) { - XShmPutImage(xDisplay, window, gc, framebufferImage, 0, 0, 0, 0, screenWidth, screenHeight, 0); + XShmPutImage(xDisplay, window, gc, displayImage, 0, 0, 0, 0, screenWidth, screenHeight, 0); + + // Swap images + XImage* tempI = displayImage; + displayImage = framebufferImage; + framebufferImage = tempI; + + // Swap pixel pointers + char* tempP = displayPixels; + displayPixels = framebufferPixels; + framebufferPixels = tempP; } else { - XPutImage(xDisplay, window, gc, framebufferImage, 0, 0, 0, 0, screenWidth, screenHeight); + XPutImage(xDisplay, window, gc, displayImage, 0, 0, 0, 0, screenWidth, screenHeight); } }