diff --git a/src/Launcher.c b/src/Launcher.c index 8e8a82bfb..5d5243b29 100644 --- a/src/Launcher.c +++ b/src/Launcher.c @@ -105,7 +105,8 @@ static void Launcher_OnResize(void* obj) { Launcher_Framebuffer.Width = Game.Width; Launcher_Framebuffer.Height = Game.Height; - Window_InitRaw(&Launcher_Framebuffer); + Window_FreeFramebuffer(&Launcher_Framebuffer); + Window_AllocFramebuffer(&Launcher_Framebuffer); if (Launcher_Screen) Launcher_Screen->Reposition(Launcher_Screen); Launcher_Redraw(); } @@ -158,7 +159,7 @@ static void Launcher_Display(void) { } Launcher_Screen->OnDisplay(Launcher_Screen); - Window_DrawRaw(Launcher_Dirty); + Window_DrawFramebuffer(Launcher_Dirty); Launcher_Dirty.X = 0; Launcher_Dirty.Width = 0; Launcher_Dirty.Y = 0; Launcher_Dirty.Height = 0; @@ -210,6 +211,7 @@ static void Launcher_Free(void) { Launcher_Screen->Free(Launcher_Screen); Launcher_Screen = NULL; + Window_FreeFramebuffer(&Launcher_Framebuffer); } void Launcher_Run(void) { @@ -229,7 +231,7 @@ void Launcher_Run(void) { Launcher_Framebuffer.Width = Game.Width; Launcher_Framebuffer.Height = Game.Height; - Window_InitRaw(&Launcher_Framebuffer); + Window_AllocFramebuffer(&Launcher_Framebuffer); Http_Component.Init(); Resources_CheckExistence(); diff --git a/src/Window.c b/src/Window.c index 4986d724f..7433b14c7 100644 --- a/src/Window.c +++ b/src/Window.c @@ -550,27 +550,29 @@ void Window_ShowDialog(const char* title, const char* msg) { static HDC draw_DC; static HBITMAP draw_DIB; -void Window_InitRaw(Bitmap* bmp) { +void Window_AllocFramebuffer(Bitmap* bmp) { BITMAPINFO hdr = { 0 }; - if (!draw_DC) draw_DC = CreateCompatibleDC(win_DC); - if (draw_DIB) DeleteObject(draw_DIB); hdr.bmiHeader.biSize = sizeof(BITMAPINFO); hdr.bmiHeader.biWidth = bmp->Width; hdr.bmiHeader.biHeight = -bmp->Height; hdr.bmiHeader.biBitCount = 32; - hdr.bmiHeader.biPlanes = 1; + hdr.bmiHeader.biPlanes = 1; - draw_DIB = CreateDIBSection(draw_DC, &hdr, 0, (void**)&bmp->Scan0, NULL, 0); + draw_DIB = CreateDIBSection(draw_DC, &hdr, DIB_RGB_COLORS, (void**)&bmp->Scan0, NULL, 0); } -void Window_DrawRaw(Rect2D r) { +void Window_DrawFramebuffer(Rect2D r) { HGDIOBJ oldSrc = SelectObject(draw_DC, draw_DIB); - BOOL success = BitBlt(win_DC, r.X, r.Y, r.Width, r.Height, draw_DC, r.X, r.Y, SRCCOPY); + BitBlt(win_DC, r.X, r.Y, r.Width, r.Height, draw_DC, r.X, r.Y, SRCCOPY); SelectObject(draw_DC, oldSrc); } +void Window_FreeFramebuffer(Bitmap* bmp) { + DeleteObject(draw_DIB); +} + static void Window_InitRawMouse(void) { RAWINPUTDEVICE rid; _registerRawInput = (FUNC_RegisterRawInput)DynamicLib_GetFrom("USER32.DLL", "RegisterRawInputDevices"); @@ -1406,25 +1408,27 @@ void Window_ShowDialog(const char* title, const char* msg) { X11Window_Free(&w); } -static GC win_gc; -static XImage* win_image; -void Window_InitRaw(Bitmap* bmp) { - if (!win_gc) win_gc = XCreateGC(win_display, win_handle, 0, NULL); - if (win_image) XFree(win_image); +static GC fb_gc; +static XImage* fb_image;\ +void Window_AllocFramebuffer(Bitmap* bmp) { + if (!fb_gc) fb_gc = XCreateGC(win_display, win_handle, 0, NULL); - Mem_Free(bmp->Scan0); bmp->Scan0 = (uint8_t*)Mem_Alloc(bmp->Width * bmp->Height, 4, "window pixels"); - - win_image = XCreateImage(win_display, win_visual.visual, + fb_image = XCreateImage(win_display, win_visual.visual, win_visual.depth, ZPixmap, 0, (char*)bmp->Scan0, bmp->Width, bmp->Height, 32, 0); } -void Window_DrawRaw(Rect2D r) { - XPutImage(win_display, win_handle, win_gc, win_image, +void Window_DrawFramebuffer(Rect2D r) { + XPutImage(win_display, win_handle, fb_gc, fb_image, r.X, r.Y, r.X, r.Y, r.Width, r.Height); } +void Window_FreeFramebuffer(Bitmap* bmp) { + XFree(fb_image); + Mem_Free(bmp->Scan0); +} + void Window_EnableRawMouse(void) { Window_DefaultEnableRawMouse(); } void Window_UpdateRawMouse(void) { Window_DefaultUpdateRawMouse(); } void Window_DisableRawMouse(void) { Window_DefaultDisableRawMouse(); } @@ -1931,95 +1935,57 @@ void Window_ShowDialog(const char* title, const char* msg) { RunStandardAlert(dialog, NULL, &itemHit); } - -/* TODO: WORK OUT WHY THIS IS BROKEN!!!! -static CGrafPtr win_winPort; -static CGImageRef win_image; - -void Window_InitRaw(Bitmap* bmp) { - CGColorSpaceRef colorSpace; - CGDataProviderRef provider; - - if (!win_winPort) win_winPort = GetWindowPort(win_handle); - Mem_Free(bmp->Scan0); - bmp->Scan0 = Mem_Alloc(bmp->Width * bmp->Height, 4, "window pixels"); - - colorSpace = CGColorSpaceCreateDeviceRGB(); - provider = CGDataProviderCreateWithData(NULL, bmp->Scan0, - Bitmap_DataSize(bmp->Width, bmp->Height), NULL); - - win_image = CGImageCreate(bmp->Width, bmp->Height, 8, 32, bmp->Width * 4, colorSpace, - kCGBitmapByteOrder32Little | kCGImageAlphaFirst, provider, NULL, 0, 0); - - CGColorSpaceRelease(colorSpace); - CGDataProviderRelease(provider); -} - -void Window_DrawRaw(Rect2D r) { - CGContextRef context = NULL; - CGRect rect; - OSStatus err; - - err = QDBeginCGContext(win_winPort, &context); - if (err) Logger_Abort2(err, "Begin draw"); - - // TODO: Only update changed bit.. - rect.origin.x = 0; rect.origin.y = 0; - rect.size.width = Window_Width; - rect.size.height = Window_Height; - - CGContextDrawImage(context, rect, win_image); - CGContextSynchronize(context); - err = QDEndCGContext(win_winPort, &context); - if (err) Logger_Abort2(err, "End draw"); -} -*/ - -static CGrafPtr win_winPort; -static CGImageRef win_image; -static Bitmap* bmp_; +static CGrafPtr fb_port; +static Bitmap fb_bmp; static CGColorSpaceRef colorSpace; -static CGDataProviderRef provider; -void Window_InitRaw(Bitmap* bmp) { - if (!win_winPort) win_winPort = GetWindowPort(win_handle); - Mem_Free(bmp->Scan0); +void Window_AllocFramebuffer(Bitmap* bmp) { + if (!fb_port) fb_port = GetWindowPort(win_handle); + bmp->Scan0 = Mem_Alloc(bmp->Width * bmp->Height, 4, "window pixels"); - colorSpace = CGColorSpaceCreateDeviceRGB(); - - bmp_ = bmp; - //CGColorSpaceRelease(colorSpace); + fb_bmp = *bmp; } -void Window_DrawRaw(Rect2D r) { +void Window_DrawFramebuffer(Rect2D r) { CGContextRef context = NULL; + CGDataProviderRef provider; + GImageRef image; CGRect rect; OSStatus err; - err = QDBeginCGContext(win_winPort, &context); - if (err) Logger_Abort2(err, "Begin draw"); - /* TODO: REPLACE THIS AWFUL HACK */ + /* Unfortunately CGImageRef is immutable, so changing the */ + /* underlying data doesn't change what shows when drawing. */ + /* TODO: Use QuickDraw alternative instead */ /* TODO: Only update changed bit.. */ rect.origin.x = 0; rect.origin.y = 0; rect.size.width = Window_Width; rect.size.height = Window_Height; - provider = CGDataProviderCreateWithData(NULL, bmp_->Scan0, - Bitmap_DataSize(bmp_->Width, bmp_->Height), NULL); - win_image = CGImageCreate(bmp_->Width, bmp_->Height, 8, 32, bmp_->Width * 4, colorSpace, + err = QDBeginCGContext(fb_port, &context); + if (err) Logger_Abort2(err, "Begin draw"); + /* TODO: REPLACE THIS AWFUL HACK */ + + provider = CGDataProviderCreateWithData(NULL, fb_bmp.Scan0, + Bitmap_DataSize(fb_bmp.Width, fb_bmp.Height), NULL); + image = CGImageCreate(fb_bmp.Width, fb_bmp.Height, 8, 32, fb_bmp.Width * 4, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaFirst, provider, NULL, 0, 0); - CGContextDrawImage(context, rect, win_image); + CGContextDrawImage(context, rect, image); CGContextSynchronize(context); - err = QDEndCGContext(win_winPort, &context); + err = QDEndCGContext(fb_port, &context); if (err) Logger_Abort2(err, "End draw"); - CGImageRelease(win_image); + CGImageRelease(image); CGDataProviderRelease(provider); } +void Window_FreeFramebuffer(Bitmap* bmp) { + Mem_Free(bmp->Scan0); + CGColorSpaceRelease(colorSpace); +} + void Window_EnableRawMouse(void) { Window_DefaultEnableRawMouse(); } void Window_UpdateRawMouse(void) { Window_DefaultUpdateRawMouse(); } void Window_DisableRawMouse(void) { Window_DefaultDisableRawMouse(); } @@ -2307,7 +2273,7 @@ void Window_ShowDialog(const char* title, const char* msg) { } static SDL_Surface* surface; -void Window_InitRaw(Bitmap* bmp) { +void Window_AllocFramebuffer(Bitmap* bmp) { surface = SDL_GetWindowSurface(win_handle); if (!surface) Window_SDLFail("getting window surface"); @@ -2318,13 +2284,19 @@ void Window_InitRaw(Bitmap* bmp) { bmp->Scan0 = surface->pixels; } -void Window_DrawRaw(Rect2D r) { +void Window_DrawFramebuffer(Rect2D r) { SDL_Rect rect; rect.x = r.X; rect.w = r.Width; rect.y = r.Y; rect.h = r.Height; SDL_UpdateWindowSurfaceRects(win_handle, &rect, 1); } +void Window_FreeFramebuffer(Bitmap* bmp) { + /* SDL docs explicitly say to NOT free the surface */ + /* https://wiki.libsdl.org/SDL_GetWindowSurface */ + /* TODO: Do we still need to unlock it though? */ +} + void Window_EnableRawMouse(void) { Window_RegrabMouse(); SDL_SetRelativeMouseMode(true); @@ -2754,8 +2726,9 @@ void Window_ShowDialog(const char* title, const char* msg) { EM_ASM_({ alert(UTF8ToString($0) + "\n\n" + UTF8ToString($1)); }, title, msg); } -void Window_InitRaw(Bitmap* bmp) { Logger_Abort("Unsupported"); } -void Window_DrawRaw(Rect2D r) { Logger_Abort("Unsupported"); } +void Window_AllocFramebuffer(Bitmap* bmp) { } +void Window_DrawFramebuffer(Rect2D r) { } +void Window_FreeFramebuffer(Bitmap* bmp) { } void Window_EnableRawMouse(void) { Window_RegrabMouse(); @@ -2957,14 +2930,14 @@ void Window_ShowDialog(const char* title, const char* msg) { (*env)->DeleteLocalRef(env, args[1].l); } -static Bitmap srcBmp; -void Window_InitRaw(Bitmap* bmp) { +static Bitmap fb_bmp; +void Window_AllocFramebuffer(Bitmap* bmp) { Mem_Free(bmp->Scan0); bmp->Scan0 = Mem_Alloc(bmp->Width * bmp->Height, 4, "window pixels"); - srcBmp = *bmp; + fb_bmp = *bmp; } -void Window_DrawRaw(Rect2D r) { +void Window_DrawFramebuffer(Rect2D r) { ANativeWindow_Buffer buffer; uint32_t* src; uint32_t* dst; @@ -2990,17 +2963,21 @@ void Window_DrawRaw(Rect2D r) { Platform_Log3("WIN SIZE: %i,%i %i", &width, &height, &format); Platform_Log4("BUF SIZE: %i,%i %i/%i", &buffer.width, &buffer.height, &buffer.format, &buffer.stride); - src = (uint32_t*)srcBmp.Scan0 + b.left; + src = (uint32_t*)fb_bmp.Scan0 + b.left; dst = (uint32_t*)buffer.bits + b.left; size = (b.right - b.left) * 4; for (y = b.top; y < b.bottom; y++) { - Mem_Copy(dst + y * buffer.stride, src + y * srcBmp.Width, size); + Mem_Copy(dst + y * buffer.stride, src + y * fb_bmp.Width, size); } res = ANativeWindow_unlockAndPost(win_handle); if (res) Logger_Abort2(res, "Unlocking window pixels"); } +void Window_FreeFramebuffer(Bitmap* bmp) { + Mem_Free(bmp->Scan0); +} + void Window_EnableRawMouse(void) { Window_DefaultEnableRawMouse(); win_rawMouse = true; diff --git a/src/Window.h b/src/Window.h index 43f9d1957..7394da8f3 100644 --- a/src/Window.h +++ b/src/Window.h @@ -101,13 +101,15 @@ void Cursor_SetVisible(bool visible); /* Shows a dialog box window. */ CC_API void Window_ShowDialog(const char* title, const char* msg); -/* Initialises the internal state for being able to set window's pixels. */ -/* NOTE: Do not manually free bmp->Scan0 - it may be allocated by system. */ -/* NOTE: This function must also be called whenever the window is resized. */ -void Window_InitRaw(Bitmap* bmp); -/* Updates the window's pixels using the bitmap from Window_InitRaw. */ +/* Allocates a framebuffer that can be drawn/transferred to the window. */ +/* NOTE: Do NOT free bmp->Scan0, use Window_FreeFramebuffer. */ +/* NOTE: This MUST be called whenever the window is resized. */ +void Window_AllocFramebuffer(Bitmap* bmp); +/* Transfers pixels from the allocated framebuffer to the on-screen window. */ /* r can be used to only update a small region of pixels (may be ignored) */ -void Window_DrawRaw(Rect2D r); +void Window_DrawFramebuffer(Rect2D r); +/* Frees the previously allocated framebuffer. */ +void Window_FreeFramebuffer(Bitmap* bmp); /* Begins listening for raw input and starts raising MouseEvents.RawMoved. */ /* NOTE: Some backends only raise it when Window_UpdateRawMouse is called. */