feat(windows): Http.* over WinHTTP, and the splash and window icon through WIC
http_win.ll implements http.ll's hs_* contract over WinHTTP: the request is a record built on the game thread, the whole exchange runs on a worker thread, TLS uses the system's certificate checks, and headers are answered from the kept request handle. ludicc links it with winhttp instead of refusing Http.* on Windows. win32.ll decodes the splash and App.set_icon images with WIC (ole32): the splash is a topmost borderless window at the artwork's size in points times the display scale, composited over its background colour; the icon becomes an HICON set on the window now or when win_open makes one. Verified on the PC: examples/library/http.ludic prints its expected output, a real GET to https://git.workshopsoft.io/ returns 200 with its body and Content-Type, and the bundled Maroon Lake shows its splash centred at launch and its icon in the title bar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
55b0e2ebf6
commit
40d78cbd92
4 changed files with 988 additions and 12 deletions
|
|
@ -237,6 +237,7 @@ show:
|
|||
store ptr %hwnd, ptr @W_hwnd
|
||||
%hdc = call ptr @GetDC(ptr %hwnd)
|
||||
store ptr %hdc, ptr @W_hdc
|
||||
call void @w_apply_icon() ; an App.set_icon that ran before there was a window
|
||||
%s1 = call i32 @ShowWindow(ptr %hwnd, i32 5) ; SW_SHOW
|
||||
%s2 = call i32 @SetForegroundWindow(ptr %hwnd)
|
||||
; RAWINPUTDEVICE { usUsagePage 1, usUsage 2 (mouse), dwFlags 0, hwndTarget }: the raw
|
||||
|
|
@ -893,19 +894,452 @@ entry:
|
|||
ret void
|
||||
}
|
||||
|
||||
; ---- the splash and the icon ---------------------------------------------------
|
||||
; Not yet: both need an image decoder (WIC), and on Windows the icon a player sees on
|
||||
; the taskbar and in Explorer is the one linked into the .exe, which `ludic bundle`
|
||||
; will do. Until then these keep the contract - safe to call, change nothing.
|
||||
; ---- images: a PNG or JPEG decoded by WIC --------------------------------------
|
||||
;
|
||||
; The splash and the window icon arrive as file bytes (out of the pack), and WIC -
|
||||
; the codecs every Windows install carries - turns them into 32-bit BGRA, as NSImage
|
||||
; does on macOS. COM slots, from wincodec.h:
|
||||
; IWICImagingFactory 4 CreateDecoderFromStream 10 CreateFormatConverter 14 CreateStream
|
||||
; IWICStream 16 InitializeFromMemory
|
||||
; IWICBitmapDecoder 13 GetFrame
|
||||
; IWICBitmapFrameDecode 5 GetResolution
|
||||
; IWICFormatConverter 3 GetSize 7 CopyPixels 8 Initialize
|
||||
; and 2 Release on all of them.
|
||||
|
||||
declare i32 @CoInitializeEx(ptr, i32)
|
||||
declare i32 @CoCreateInstance(ptr, ptr, i32, ptr, ptr)
|
||||
declare ptr @CreateDIBSection(ptr, ptr, i32, ptr, ptr, i32)
|
||||
declare ptr @CreateBitmap(i32, i32, i32, i32, ptr)
|
||||
declare ptr @CreateIconIndirect(ptr)
|
||||
declare i32 @DeleteObject(ptr)
|
||||
declare i64 @SendMessageA(ptr, i32, i64, i64)
|
||||
declare i32 @DestroyWindow(ptr)
|
||||
declare i32 @UpdateWindow(ptr)
|
||||
declare ptr @BeginPaint(ptr, ptr)
|
||||
declare i32 @EndPaint(ptr, ptr)
|
||||
declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
|
||||
|
||||
; CLSID_WICImagingFactory {cacaf262-9370-4615-a13b-9f5539da4c0a},
|
||||
; IID_IWICImagingFactory {ec5ec8a9-c395-4314-9c77-54d7a935ff70},
|
||||
; GUID_WICPixelFormat32bppBGRA {6fddc324-4e03-4bfe-b185-3d77768dc90f} - in memory order
|
||||
@.wic_clsid = private unnamed_addr constant [16 x i8] c"\62\F2\CA\CA\70\93\15\46\A1\3B\9F\55\39\DA\4C\0A"
|
||||
@.wic_iid = private unnamed_addr constant [16 x i8] c"\A9\C8\5E\EC\95\C3\14\43\9C\77\54\D7\A9\35\FF\70"
|
||||
@.wic_bgra = private unnamed_addr constant [16 x i8] c"\24\C3\DD\6F\03\4E\FE\4B\B1\85\3D\77\76\8D\C9\0F"
|
||||
@.w_splash_class = private unnamed_addr constant [12 x i8] c"LudicSplash\00"
|
||||
@.w_empty = private unnamed_addr constant [1 x i8] c"\00"
|
||||
|
||||
define internal ptr @w_vt(ptr %obj, i64 %slot) {
|
||||
entry:
|
||||
%vt = load ptr, ptr %obj
|
||||
%p = getelementptr ptr, ptr %vt, i64 %slot
|
||||
%f = load ptr, ptr %p
|
||||
ret ptr %f
|
||||
}
|
||||
|
||||
define internal void @w_release(ptr %pp) {
|
||||
entry:
|
||||
%o = load ptr, ptr %pp
|
||||
%none = icmp eq ptr %o, null
|
||||
br i1 %none, label %out, label %go
|
||||
go:
|
||||
%rel = call ptr @w_vt(ptr %o, i64 2)
|
||||
%r = call i32 %rel(ptr %o)
|
||||
store ptr null, ptr %pp
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
||||
; bytes -> a malloc'd w x h BGRA buffer (straight alpha), its size, and the image's own
|
||||
; horizontal dpi (72 when it names none); null when WIC cannot read it
|
||||
define internal ptr @w_decode(ptr %bytes, i32 %len, ptr %wout, ptr %hout, ptr %dpiout) {
|
||||
entry:
|
||||
%fp = alloca ptr, align 8
|
||||
%sp = alloca ptr, align 8
|
||||
%dp = alloca ptr, align 8
|
||||
%frp = alloca ptr, align 8
|
||||
%cp = alloca ptr, align 8
|
||||
%wp = alloca i32, align 4
|
||||
%hp = alloca i32, align 4
|
||||
%dx = alloca double, align 8
|
||||
%dy = alloca double, align 8
|
||||
store ptr null, ptr %fp
|
||||
store ptr null, ptr %sp
|
||||
store ptr null, ptr %dp
|
||||
store ptr null, ptr %frp
|
||||
store ptr null, ptr %cp
|
||||
store double 0.000000e+00, ptr %dx
|
||||
%nob = icmp eq ptr %bytes, null
|
||||
%empty = icmp sle i32 %len, 0
|
||||
%skip = or i1 %nob, %empty
|
||||
br i1 %skip, label %fail, label %com
|
||||
com:
|
||||
; COINIT_APARTMENTTHREADED; a thread already initialised answers S_FALSE or RPC_E_CHANGED_MODE, both fine
|
||||
%ci = call i32 @CoInitializeEx(ptr null, i32 2)
|
||||
%hr0 = call i32 @CoCreateInstance(ptr @.wic_clsid, ptr null, i32 1, ptr @.wic_iid, ptr %fp) ; CLSCTX_INPROC_SERVER
|
||||
%b0 = icmp slt i32 %hr0, 0
|
||||
br i1 %b0, label %fail, label %stream
|
||||
stream:
|
||||
%f = load ptr, ptr %fp
|
||||
%cs = call ptr @w_vt(ptr %f, i64 14)
|
||||
%hr1 = call i32 %cs(ptr %f, ptr %sp)
|
||||
%b1 = icmp slt i32 %hr1, 0
|
||||
br i1 %b1, label %fail, label %meminit
|
||||
meminit:
|
||||
%s = load ptr, ptr %sp
|
||||
%im = call ptr @w_vt(ptr %s, i64 16)
|
||||
%hr2 = call i32 %im(ptr %s, ptr %bytes, i32 %len)
|
||||
%b2 = icmp slt i32 %hr2, 0
|
||||
br i1 %b2, label %fail, label %decoder
|
||||
decoder:
|
||||
%cdfs = call ptr @w_vt(ptr %f, i64 4)
|
||||
%hr3 = call i32 %cdfs(ptr %f, ptr %s, ptr null, i32 0, ptr %dp) ; WICDecodeMetadataCacheOnDemand
|
||||
%b3 = icmp slt i32 %hr3, 0
|
||||
br i1 %b3, label %fail, label %frame
|
||||
frame:
|
||||
%d = load ptr, ptr %dp
|
||||
%gf = call ptr @w_vt(ptr %d, i64 13)
|
||||
%hr4 = call i32 %gf(ptr %d, i32 0, ptr %frp)
|
||||
%b4 = icmp slt i32 %hr4, 0
|
||||
br i1 %b4, label %fail, label %resolution
|
||||
resolution:
|
||||
%fr = load ptr, ptr %frp
|
||||
%gr = call ptr @w_vt(ptr %fr, i64 5)
|
||||
%hr5 = call i32 %gr(ptr %fr, ptr %dx, ptr %dy)
|
||||
%conv = call ptr @w_vt(ptr %f, i64 10)
|
||||
%hr6 = call i32 %conv(ptr %f, ptr %cp)
|
||||
%b6 = icmp slt i32 %hr6, 0
|
||||
br i1 %b6, label %fail, label %convert
|
||||
convert:
|
||||
%c = load ptr, ptr %cp
|
||||
%ini = call ptr @w_vt(ptr %c, i64 8)
|
||||
; to 32bpp BGRA, no dither, no palette, alpha threshold 0, WICBitmapPaletteTypeCustom
|
||||
%hr7 = call i32 %ini(ptr %c, ptr %fr, ptr @.wic_bgra, i32 0, ptr null, double 0.000000e+00, i32 0)
|
||||
%b7 = icmp slt i32 %hr7, 0
|
||||
br i1 %b7, label %fail, label %size
|
||||
size:
|
||||
%gs = call ptr @w_vt(ptr %c, i64 3)
|
||||
%hr8 = call i32 %gs(ptr %c, ptr %wp, ptr %hp)
|
||||
%w = load i32, ptr %wp
|
||||
%h = load i32, ptr %hp
|
||||
%zw = icmp sle i32 %w, 0
|
||||
%zh = icmp sle i32 %h, 0
|
||||
%zero = or i1 %zw, %zh
|
||||
br i1 %zero, label %fail, label %pixels
|
||||
pixels:
|
||||
%w64 = sext i32 %w to i64
|
||||
%h64 = sext i32 %h to i64
|
||||
%px = mul i64 %w64, %h64
|
||||
%bytesz = mul i64 %px, 4
|
||||
%buf = call ptr @malloc(i64 %bytesz)
|
||||
%stride = mul i32 %w, 4
|
||||
%bsz32 = trunc i64 %bytesz to i32
|
||||
%cpx = call ptr @w_vt(ptr %c, i64 7)
|
||||
%hr9 = call i32 %cpx(ptr %c, ptr null, i32 %stride, i32 %bsz32, ptr %buf)
|
||||
%b9 = icmp slt i32 %hr9, 0
|
||||
br i1 %b9, label %freebuf, label %ok
|
||||
freebuf:
|
||||
call void @free(ptr %buf)
|
||||
br label %fail
|
||||
ok:
|
||||
store i32 %w, ptr %wout
|
||||
store i32 %h, ptr %hout
|
||||
%dpd = load double, ptr %dx
|
||||
%dpi0 = fptosi double %dpd to i32
|
||||
%nodpi = icmp slt i32 %dpi0, 1
|
||||
%dpi = select i1 %nodpi, i32 72, i32 %dpi0
|
||||
store i32 %dpi, ptr %dpiout
|
||||
call void @w_release(ptr %cp)
|
||||
call void @w_release(ptr %frp)
|
||||
call void @w_release(ptr %dp)
|
||||
call void @w_release(ptr %sp)
|
||||
call void @w_release(ptr %fp)
|
||||
ret ptr %buf
|
||||
fail:
|
||||
call void @w_release(ptr %cp)
|
||||
call void @w_release(ptr %frp)
|
||||
call void @w_release(ptr %dp)
|
||||
call void @w_release(ptr %sp)
|
||||
call void @w_release(ptr %fp)
|
||||
ret ptr null
|
||||
}
|
||||
|
||||
; ---- the boot splash ---------------------------------------------------------------
|
||||
;
|
||||
; cocoa.ll's splash, on Windows: a borderless, topmost window with the game's artwork,
|
||||
; shown from lp_pak_boot before main and taken down by App.splash_hide(). It takes the
|
||||
; artwork's own size in points (pixels x 72 / its dpi, as NSImage measures it) at the
|
||||
; display's whole-number scale, so a 1440 x 810 image saved at 144 dpi is 720 x 405
|
||||
; points on either platform. The image is composited over the background colour once,
|
||||
; and painted from that on every WM_PAINT.
|
||||
|
||||
@W_splash = internal global ptr null
|
||||
@W_splash_px = internal global ptr null
|
||||
@W_splash_w = internal global i32 0
|
||||
@W_splash_h = internal global i32 0
|
||||
@W_splash_dw = internal global i32 0
|
||||
@W_splash_dh = internal global i32 0
|
||||
|
||||
define internal i64 @w_splash_proc(ptr %hwnd, i32 %msg, i64 %wp, i64 %lp) {
|
||||
entry:
|
||||
%ps = alloca [72 x i8], align 8 ; PAINTSTRUCT
|
||||
%bmi = alloca [44 x i8], align 4
|
||||
switch i32 %msg, label %def [
|
||||
i32 15, label %paint ; WM_PAINT
|
||||
i32 20, label %erase ; WM_ERASEBKGND
|
||||
]
|
||||
erase:
|
||||
ret i64 1
|
||||
paint:
|
||||
%hdc = call ptr @BeginPaint(ptr %hwnd, ptr %ps)
|
||||
%px = load ptr, ptr @W_splash_px
|
||||
%nopx = icmp eq ptr %px, null
|
||||
br i1 %nopx, label %endp, label %blit
|
||||
blit:
|
||||
%w = load i32, ptr @W_splash_w
|
||||
%h = load i32, ptr @W_splash_h
|
||||
%dw = load i32, ptr @W_splash_dw
|
||||
%dh = load i32, ptr @W_splash_dh
|
||||
call void @llvm.memset.p0.i64(ptr %bmi, i8 0, i64 44, i1 false)
|
||||
store i32 40, ptr %bmi
|
||||
%bw = getelementptr i8, ptr %bmi, i64 4
|
||||
store i32 %w, ptr %bw
|
||||
%nh = sub i32 0, %h
|
||||
%bh = getelementptr i8, ptr %bmi, i64 8
|
||||
store i32 %nh, ptr %bh
|
||||
%bp = getelementptr i8, ptr %bmi, i64 12
|
||||
store i16 1, ptr %bp
|
||||
%bb = getelementptr i8, ptr %bmi, i64 14
|
||||
store i16 32, ptr %bb
|
||||
%r = call i32 @StretchDIBits(ptr %hdc, i32 0, i32 0, i32 %dw, i32 %dh, i32 0, i32 0, i32 %w, i32 %h, ptr %px, ptr %bmi, i32 0, i32 13369376)
|
||||
br label %endp
|
||||
endp:
|
||||
%e = call i32 @EndPaint(ptr %hwnd, ptr %ps)
|
||||
ret i64 0
|
||||
def:
|
||||
%d = call i64 @DefWindowProcA(ptr %hwnd, i32 %msg, i64 %wp, i64 %lp)
|
||||
ret i64 %d
|
||||
}
|
||||
|
||||
define void @splash_show(ptr %bytes, i32 %len, i32 %bg) {
|
||||
entry:
|
||||
%wp = alloca i32, align 4
|
||||
%hp = alloca i32, align 4
|
||||
%dpip = alloca i32, align 4
|
||||
%wc = alloca [80 x i8], align 8
|
||||
%had = load ptr, ptr @W_splash
|
||||
%again = icmp ne ptr %had, null
|
||||
br i1 %again, label %out, label %decode
|
||||
decode:
|
||||
%px = call ptr @w_decode(ptr %bytes, i32 %len, ptr %wp, ptr %hp, ptr %dpip)
|
||||
%nopx = icmp eq ptr %px, null
|
||||
br i1 %nopx, label %out, label %over
|
||||
over:
|
||||
%w = load i32, ptr %wp
|
||||
%h = load i32, ptr %hp
|
||||
; composite over the background colour, so transparent edges sit on the game's backdrop
|
||||
%bgb = and i32 %bg, 255
|
||||
%bgg0 = lshr i32 %bg, 8
|
||||
%bgg = and i32 %bgg0, 255
|
||||
%bgr0 = lshr i32 %bg, 16
|
||||
%bgr = and i32 %bgr0, 255
|
||||
%w64 = sext i32 %w to i64
|
||||
%h64 = sext i32 %h to i64
|
||||
%n = mul i64 %w64, %h64
|
||||
br label %mix
|
||||
mix:
|
||||
%i = phi i64 [ 0, %over ], [ %i1, %mixb ]
|
||||
%more = icmp slt i64 %i, %n
|
||||
br i1 %more, label %mixb, label %placed
|
||||
mixb:
|
||||
%o = mul i64 %i, 4
|
||||
%pb = getelementptr i8, ptr %px, i64 %o
|
||||
%o1 = add i64 %o, 1
|
||||
%pg = getelementptr i8, ptr %px, i64 %o1
|
||||
%o2 = add i64 %o, 2
|
||||
%pr = getelementptr i8, ptr %px, i64 %o2
|
||||
%o3 = add i64 %o, 3
|
||||
%pa = getelementptr i8, ptr %px, i64 %o3
|
||||
%a8 = load i8, ptr %pa
|
||||
%a = zext i8 %a8 to i32
|
||||
%ia = sub i32 255, %a
|
||||
%sb8 = load i8, ptr %pb
|
||||
%sb = zext i8 %sb8 to i32
|
||||
%mb0 = mul i32 %sb, %a
|
||||
%mb1 = mul i32 %bgb, %ia
|
||||
%mb2 = add i32 %mb0, %mb1
|
||||
%mb = udiv i32 %mb2, 255
|
||||
%tb = trunc i32 %mb to i8
|
||||
store i8 %tb, ptr %pb
|
||||
%sg8 = load i8, ptr %pg
|
||||
%sg = zext i8 %sg8 to i32
|
||||
%mg0 = mul i32 %sg, %a
|
||||
%mg1 = mul i32 %bgg, %ia
|
||||
%mg2 = add i32 %mg0, %mg1
|
||||
%mg = udiv i32 %mg2, 255
|
||||
%tg = trunc i32 %mg to i8
|
||||
store i8 %tg, ptr %pg
|
||||
%sr8 = load i8, ptr %pr
|
||||
%sr = zext i8 %sr8 to i32
|
||||
%mr0 = mul i32 %sr, %a
|
||||
%mr1 = mul i32 %bgr, %ia
|
||||
%mr2 = add i32 %mr0, %mr1
|
||||
%mr = udiv i32 %mr2, 255
|
||||
%tr = trunc i32 %mr to i8
|
||||
store i8 %tr, ptr %pr
|
||||
store i8 -1, ptr %pa
|
||||
%i1 = add i64 %i, 1
|
||||
br label %mix
|
||||
placed:
|
||||
store ptr %px, ptr @W_splash_px
|
||||
store i32 %w, ptr @W_splash_w
|
||||
store i32 %h, ptr @W_splash_h
|
||||
; points = pixels x 72 / dpi; pixels on screen = points x the display's scale
|
||||
%dpi = load i32, ptr %dpip
|
||||
%pw0 = mul i32 %w, 72
|
||||
%ptw = sdiv i32 %pw0, %dpi
|
||||
%ph0 = mul i32 %h, 72
|
||||
%pth = sdiv i32 %ph0, %dpi
|
||||
%d0 = call i32 @SetProcessDpiAwarenessContext(ptr inttoptr (i64 -4 to ptr))
|
||||
%sysdpi = call i32 @GetDpiForSystem()
|
||||
%ds = call i32 @w_fit_scale(i32 %sysdpi, i32 %ptw, i32 %pth)
|
||||
%dw = mul i32 %ptw, %ds
|
||||
%dh = mul i32 %pth, %ds
|
||||
store i32 %dw, ptr @W_splash_dw
|
||||
store i32 %dh, ptr @W_splash_dh
|
||||
%inst = call ptr @GetModuleHandleA(ptr null)
|
||||
call void @llvm.memset.p0.i64(ptr %wc, i8 0, i64 80, i1 false)
|
||||
store i32 80, ptr %wc
|
||||
%wwp = getelementptr i8, ptr %wc, i64 8
|
||||
store ptr @w_splash_proc, ptr %wwp
|
||||
%whi = getelementptr i8, ptr %wc, i64 24
|
||||
store ptr %inst, ptr %whi
|
||||
%arrow = call ptr @LoadCursorA(ptr null, ptr inttoptr (i64 32512 to ptr))
|
||||
%whc = getelementptr i8, ptr %wc, i64 40
|
||||
store ptr %arrow, ptr %whc
|
||||
%wcn = getelementptr i8, ptr %wc, i64 64
|
||||
store ptr @.w_splash_class, ptr %wcn
|
||||
%atom = call i16 @RegisterClassExA(ptr %wc)
|
||||
%sw = call i32 @GetSystemMetrics(i32 0)
|
||||
%sh = call i32 @GetSystemMetrics(i32 1)
|
||||
%xw = sub i32 %sw, %dw
|
||||
%x = sdiv i32 %xw, 2
|
||||
%yh = sub i32 %sh, %dh
|
||||
%y = sdiv i32 %yh, 2
|
||||
; WS_EX_TOPMOST | WS_EX_TOOLWINDOW (no taskbar button), WS_POPUP | WS_VISIBLE
|
||||
%win = call ptr @CreateWindowExA(i32 136, ptr @.w_splash_class, ptr @.w_empty, i32 -1879048192, i32 %x, i32 %y, i32 %dw, i32 %dh, ptr null, ptr null, ptr %inst, ptr null)
|
||||
%nowin = icmp eq ptr %win, null
|
||||
br i1 %nowin, label %out, label %show
|
||||
show:
|
||||
store ptr %win, ptr @W_splash
|
||||
; paint it now: the game is about to spend a while loading and pumps nothing meanwhile
|
||||
%u = call i32 @UpdateWindow(ptr %win)
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @splash_hide() {
|
||||
entry:
|
||||
%win = load ptr, ptr @W_splash
|
||||
%none = icmp eq ptr %win, null
|
||||
br i1 %none, label %out, label %go
|
||||
go:
|
||||
%d = call i32 @DestroyWindow(ptr %win)
|
||||
store ptr null, ptr @W_splash
|
||||
%px = load ptr, ptr @W_splash_px
|
||||
call void @free(ptr %px)
|
||||
store ptr null, ptr @W_splash_px
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
||||
; ---- the window icon ---------------------------------------------------------------
|
||||
;
|
||||
; App.set_icon(path): the title bar and the taskbar button of a build with no icon
|
||||
; resource - which is every `ludic build`; a bundled .exe carries its own. The image
|
||||
; becomes an HICON from a 32-bit DIB with its alpha, set on the window now, or as soon
|
||||
; as win_open makes one.
|
||||
|
||||
@W_icon = internal global ptr null
|
||||
|
||||
declare void @free(ptr)
|
||||
declare ptr @malloc(i64)
|
||||
|
||||
define internal void @w_apply_icon() {
|
||||
entry:
|
||||
%hwnd = load ptr, ptr @W_hwnd
|
||||
%icon = load ptr, ptr @W_icon
|
||||
%nw = icmp eq ptr %hwnd, null
|
||||
%ni = icmp eq ptr %icon, null
|
||||
%skip = or i1 %nw, %ni
|
||||
br i1 %skip, label %out, label %set
|
||||
set:
|
||||
%iv = ptrtoint ptr %icon to i64
|
||||
%r1 = call i64 @SendMessageA(ptr %hwnd, i32 128, i64 1, i64 %iv) ; WM_SETICON, ICON_BIG
|
||||
%r0 = call i64 @SendMessageA(ptr %hwnd, i32 128, i64 0, i64 %iv) ; ICON_SMALL
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @app_set_icon(ptr %bytes, i32 %len) {
|
||||
entry:
|
||||
%wp = alloca i32, align 4
|
||||
%hp = alloca i32, align 4
|
||||
%dpip = alloca i32, align 4
|
||||
%bmi = alloca [44 x i8], align 4
|
||||
%bitsp = alloca ptr, align 8
|
||||
%ii = alloca [32 x i8], align 8 ; ICONINFO: fIcon 0, hbmMask 16, hbmColor 24
|
||||
%px = call ptr @w_decode(ptr %bytes, i32 %len, ptr %wp, ptr %hp, ptr %dpip)
|
||||
%nopx = icmp eq ptr %px, null
|
||||
br i1 %nopx, label %out, label %dib
|
||||
dib:
|
||||
%w = load i32, ptr %wp
|
||||
%h = load i32, ptr %hp
|
||||
call void @llvm.memset.p0.i64(ptr %bmi, i8 0, i64 44, i1 false)
|
||||
store i32 40, ptr %bmi
|
||||
%bw = getelementptr i8, ptr %bmi, i64 4
|
||||
store i32 %w, ptr %bw
|
||||
%nh = sub i32 0, %h
|
||||
%bh = getelementptr i8, ptr %bmi, i64 8
|
||||
store i32 %nh, ptr %bh
|
||||
%bpl = getelementptr i8, ptr %bmi, i64 12
|
||||
store i16 1, ptr %bpl
|
||||
%bbc = getelementptr i8, ptr %bmi, i64 14
|
||||
store i16 32, ptr %bbc
|
||||
store ptr null, ptr %bitsp
|
||||
%color = call ptr @CreateDIBSection(ptr null, ptr %bmi, i32 0, ptr %bitsp, ptr null, i32 0)
|
||||
%nocolor = icmp eq ptr %color, null
|
||||
br i1 %nocolor, label %freepx, label %fill
|
||||
fill:
|
||||
%bits = load ptr, ptr %bitsp
|
||||
%w64 = sext i32 %w to i64
|
||||
%h64 = sext i32 %h to i64
|
||||
%n = mul i64 %w64, %h64
|
||||
%nb = mul i64 %n, 4
|
||||
call void @llvm.memcpy.p0.p0.i64(ptr %bits, ptr %px, i64 %nb, i1 false)
|
||||
; with an alpha channel in the colour bitmap, an all-zero mask leaves every pixel to it
|
||||
%mask = call ptr @CreateBitmap(i32 %w, i32 %h, i32 1, i32 1, ptr null)
|
||||
call void @llvm.memset.p0.i64(ptr %ii, i8 0, i64 32, i1 false)
|
||||
store i32 1, ptr %ii
|
||||
%mp = getelementptr i8, ptr %ii, i64 16
|
||||
store ptr %mask, ptr %mp
|
||||
%cp = getelementptr i8, ptr %ii, i64 24
|
||||
store ptr %color, ptr %cp
|
||||
%icon = call ptr @CreateIconIndirect(ptr %ii)
|
||||
%d1 = call i32 @DeleteObject(ptr %mask)
|
||||
%d2 = call i32 @DeleteObject(ptr %color)
|
||||
%noicon = icmp eq ptr %icon, null
|
||||
br i1 %noicon, label %freepx, label %keep
|
||||
keep:
|
||||
store ptr %icon, ptr @W_icon
|
||||
call void @w_apply_icon()
|
||||
br label %freepx
|
||||
freepx:
|
||||
call void @free(ptr %px)
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue