From e230b5441c386cebe86d0bda8fe99421606c3a02 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 30 Sep 2025 00:52:43 +0000 Subject: [PATCH] xshm git-svn-id: http://svn2.nishi.boats/svn/milsko/trunk@69 b9cfdab3-6d41-4d17-bbe4-086880011989 --- GNUmakefile | 2 +- examples/example.c | 2 ++ include/Mw/GDI.h | 11 +++++--- include/Mw/LowLevel.h | 10 +++++-- include/Mw/MachDep.h | 2 ++ include/Mw/X11.h | 16 ++++++++--- src/frame.c | 20 +++++++++++++- src/gdi.c | 57 ++++++++++++++++++++++++++++++++++++++ src/x11.c | 64 +++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 172 insertions(+), 12 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 5041b2b..69ea856 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -33,7 +33,7 @@ endif ifeq ($(UNIX),1) L_CFLAGS += -DUSE_X11 L_OBJS += src/x11.o -L_LIBS += -lX11 -lGL +L_LIBS += -lX11 -lXrender -lXext -lGL GL = -lGL diff --git a/examples/example.c b/examples/example.c index f17ebfa..adb1dcb 100644 --- a/examples/example.c +++ b/examples/example.c @@ -64,6 +64,8 @@ int main() { MwNbackground, "#66f", NULL); + MwVaCreateWidget(MwFrameClass, "frame", window, 50, 50, 300, 300, NULL); + MwAddUserHandler(window, MwNresizeHandler, resize, NULL); MwAddUserHandler(button, MwNactivateHandler, handler, NULL); MwAddUserHandler(button2, MwNactivateHandler, handler, NULL); diff --git a/include/Mw/GDI.h b/include/Mw/GDI.h index 0e0a5a0..b8f134c 100644 --- a/include/Mw/GDI.h +++ b/include/Mw/GDI.h @@ -3,10 +3,6 @@ #define __MW_GDI_H__ #include - -typedef struct _MwLL * MwLL, MwLLRec; -typedef struct _MwLLColor *MwLLColor, MwLLColorRec; - #include #include @@ -28,4 +24,11 @@ struct _MwLLColor { int blue; }; +struct _MwLLPixmap { + int width; + int height; + + HBITMAP hBitmap; +}; + #endif diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index eed72a0..26dc8d2 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -6,11 +6,13 @@ typedef struct _MwLLHandler *MwLLHandler, MwLLHandlerRec; #ifdef _MILSKO -typedef struct _MwLL * MwLL, MwLLRec; -typedef struct _MwLLColor *MwLLColor, MwLLColorRec; +typedef struct _MwLL * MwLL, MwLLRec; +typedef struct _MwLLColor * MwLLColor, MwLLColorRec; +typedef struct _MwLLPixmap *MwLLPixmap, MwLLPixmapRec; #else typedef void* MwLL; typedef void* MwLLColor; +typedef void* MwLLPixmap; #endif #ifdef _MILSKO @@ -61,6 +63,10 @@ MWDECL int MwLLPending(MwLL handle); MWDECL void MwLLNextEvent(MwLL handle); MWDECL void MwLLSleep(int ms); +MWDECL MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int height); +MWDECL void MwLLDestroyPixmap(MwLLPixmap pixmap); +MWDECL void MwLLDrawPixmap(MwLL handle, MwRect* rect, MwLLPixmap pixmap); + #ifdef __cplusplus } #endif diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index 8da4094..5b05ddf 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -10,6 +10,8 @@ #include #else #include +#include +#include #endif #if defined(_MILSKO) && defined(_WIN32) diff --git a/include/Mw/X11.h b/include/Mw/X11.h index 3282b5d..1f0439f 100644 --- a/include/Mw/X11.h +++ b/include/Mw/X11.h @@ -3,15 +3,13 @@ #define __MW_X11_H__ #include - -typedef struct _MwLL * MwLL, MwLLRec; -typedef struct _MwLLColor *MwLLColor, MwLLColorRec; - #include #include #include #include +#include +#include struct _MwLL { Display* display; @@ -31,4 +29,14 @@ struct _MwLLColor { int blue; }; +struct _MwLLPixmap { + int width; + int height; + + int use_shm; + XShmSegmentInfo shm; + Display* display; + XImage* image; +}; + #endif diff --git a/src/frame.c b/src/frame.c index 0fc1889..e69863d 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1,8 +1,25 @@ /* $Id$ */ #include +MwLLPixmap pixmap; + static void create(MwWidget handle) { MwSetDefault(handle); + + int y, x; + unsigned char* dat = malloc(640 * 480 * 3); + for(y = 0; y < 480; y++) { + for(x = 0; x < 640; x++) { + unsigned char* px = &dat[(y * 640 + x) * 3]; + double c = (double)x / 640 * 255 / 2 + (double)y / 480 * 255 / 2; + + px[0] = c; + px[1] = 0; + px[2] = 0; + } + } + pixmap = MwLLCreatePixmap(handle->lowlevel, dat, 640, 480); + free(dat); } static void draw(MwWidget handle) { @@ -16,7 +33,8 @@ static void draw(MwWidget handle) { MwDrawFrameEx(handle, &r, base, 1, 1); MwDrawFrameEx(handle, &r, base, 0, 1); - MwDrawRect(handle, &r, base); + MwLLDrawPixmap(handle->lowlevel, &r, pixmap); + // MwDrawRect(handle, &r, base); MwLLFreeColor(base); } diff --git a/src/gdi.c b/src/gdi.c index 8fe46e1..1813f28 100644 --- a/src/gdi.c +++ b/src/gdi.c @@ -45,6 +45,7 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { } else if(msg == WM_SIZE) { MwLLDispatch(u->ll, resize); } else if(msg == WM_ERASEBKGND) { + return 1; } else if(msg == WM_NCHITTEST) { return HTCLIENT; } else if(msg == WM_DESTROY) { @@ -210,3 +211,59 @@ void MwLLNextEvent(MwLL handle) { void MwLLSleep(int ms) { Sleep(ms); } + +MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int height) { + MwLLPixmap r = malloc(sizeof(*r)); + HDC dc = GetDC(handle->hWnd); + BITMAPINFOHEADER bmih; + RGBQUAD* quad = NULL; + int y, x; + + r->width = width; + r->height = height; + + bmih.biSize = sizeof(bmih); + bmih.biWidth = width; + bmih.biHeight = -(LONG)height; + bmih.biPlanes = 1; + bmih.biBitCount = 32; + bmih.biCompression = BI_RGB; + bmih.biSizeImage = 0; + bmih.biXPelsPerMeter = 0; + bmih.biYPelsPerMeter = 0; + bmih.biClrUsed = 0; + bmih.biClrImportant = 0; + + r->hBitmap = CreateDIBSection(dc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, (void**)&quad, NULL, (DWORD)0); + + for(y = 0; y < height; y++) { + for(x = 0; x < width; x++) { + RGBQUAD* q = &quad[y * width + x]; + unsigned char* px = &data[(y * width + x) * 3]; + q->rgbRed = px[0]; + q->rgbGreen = px[1]; + q->rgbBlue = px[2]; + } + } + + ReleaseDC(handle->hWnd, dc); + + return r; +} + +void MwLLDestroyPixmap(MwLLPixmap pixmap) { + DeleteObject(pixmap->hBitmap); + + free(pixmap); +} + +void MwLLDrawPixmap(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { + HDC hmdc = CreateCompatibleDC(handle->hDC); + + SelectObject(hmdc, pixmap->hBitmap); + + SetStretchBltMode(handle->hDC, HALFTONE); + StretchBlt(handle->hDC, rect->x, rect->y, rect->width, rect->height, hmdc, 0, 0, pixmap->width, pixmap->height, SRCCOPY); + + DeleteDC(hmdc); +} diff --git a/src/x11.c b/src/x11.c index b520ff8..7f24e9d 100644 --- a/src/x11.c +++ b/src/x11.c @@ -25,6 +25,8 @@ MwLL MwLLCreate(MwLL parent, int x, int y, int width, int height) { r->gc = XCreateGC(r->display, r->window, 0, 0); + XSetGraphicsExposures(r->display, r->gc, False); + XSelectInput(r->display, r->window, mask); XMapWindow(r->display, r->window); @@ -137,3 +139,65 @@ void MwLLSleep(int ms) { void MwLLSetTitle(MwLL handle, const char* title) { XSetStandardProperties(handle->display, handle->window, title, "Mw Widget Toolkit", None, (char**)NULL, 0, NULL); } + +MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int height) { + MwLLPixmap r = malloc(sizeof(*r)); + char* d = malloc(4 * width * height); + int y, x; + + r->width = width; + r->height = height; + r->display = handle->display; + r->use_shm = XShmQueryExtension(handle->display) ? 1 : 0; + + if(r->use_shm) { + r->image = XShmCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), 24, ZPixmap, NULL, &r->shm, width, height); + free(d); + + r->shm.shmid = shmget(IPC_PRIVATE, r->image->bytes_per_line * height, IPC_CREAT | 0777); + r->shm.shmaddr = d = r->image->data = shmat(r->shm.shmid, 0, 0); + r->shm.readOnly = False; + XShmAttach(handle->display, &r->shm); + } else { + r->image = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), 24, ZPixmap, 0, d, width, height, 32, width * 4); + } + + for(y = 0; y < height; y++) { + for(x = 0; x < height; x++) { + unsigned char* px = &data[(y * width + x) * 3]; + unsigned long p = 0; + p <<= 8; + p |= px[0]; + p <<= 8; + p |= px[1]; + p <<= 8; + p |= px[2]; + XPutPixel(r->image, x, y, p); + } + } + + return r; +} + +void MwLLDestroyPixmap(MwLLPixmap pixmap) { + if(pixmap->use_shm) { + XShmDetach(pixmap->display, &pixmap->shm); + } + XDestroyImage(pixmap->image); + if(pixmap->use_shm) { + shmdt(pixmap->shm.shmaddr); + shmctl(pixmap->shm.shmid, IPC_RMID, 0); + } + + free(pixmap); +} + +void MwLLDrawPixmap(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { + if(pixmap->image != NULL) { + if(pixmap->use_shm) { + XShmPutImage(handle->display, handle->window, handle->gc, pixmap->image, 0, 0, rect->x, rect->y, rect->width, rect->height, False); + } else { + XPutImage(handle->display, handle->window, handle->gc, pixmap->image, 0, 0, rect->x, rect->y, rect->width, rect->height); + } + } +}