mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-22 20:11:44 +00:00
Fix some wayland bugs.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5633 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
dbc76288a5
commit
5626c20876
3 changed files with 155 additions and 109 deletions
|
@ -11349,6 +11349,93 @@ static void Image_ChangeFormatFlags(struct pendingtextureinfo *mips, unsigned in
|
|||
Image_ChangeFormat(mips, sh_config.texfmt, origfmt, imagename);
|
||||
}
|
||||
|
||||
//operates in place...
|
||||
void Image_Premultiply(struct pendingtextureinfo *mips)
|
||||
{
|
||||
//works for rgba or bgra
|
||||
int i;
|
||||
switch(mips->encoding)
|
||||
{
|
||||
case PTI_RGBA32F:
|
||||
{
|
||||
float *fte_restrict premul = (float*)mips->mip[0].data;
|
||||
for (i = 0; i < mips->mip[0].width*mips->mip[0].height; i++, premul+=4)
|
||||
{
|
||||
premul[0] = (premul[0] * premul[3]);
|
||||
premul[1] = (premul[1] * premul[3]);
|
||||
premul[2] = (premul[2] * premul[3]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PTI_RGBA16F:
|
||||
{
|
||||
unsigned short *fte_restrict premul = (unsigned short*)mips->mip[0].data;
|
||||
for (i = 0; i < mips->mip[0].width*mips->mip[0].height; i++, premul+=4)
|
||||
{
|
||||
float a = HalfToFloat(premul[3]);
|
||||
premul[0] = FloatToHalf(HalfToFloat(premul[0]) * a);
|
||||
premul[1] = FloatToHalf(HalfToFloat(premul[1]) * a);
|
||||
premul[2] = FloatToHalf(HalfToFloat(premul[2]) * a);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PTI_RGBA16:
|
||||
{
|
||||
unsigned short *fte_restrict premul = (unsigned short*)mips->mip[0].data;
|
||||
for (i = 0; i < mips->mip[0].width*mips->mip[0].height; i++, premul+=4)
|
||||
{
|
||||
premul[0] = (premul[0] * premul[3])>>16;
|
||||
premul[1] = (premul[1] * premul[3])>>16;
|
||||
premul[2] = (premul[2] * premul[3])>>16;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PTI_A2BGR10:
|
||||
{
|
||||
unsigned int *fte_restrict premul = (unsigned int*)mips->mip[0].data, r,g,b,a;
|
||||
for (i = 0; i < mips->mip[0].width*mips->mip[0].height; i++)
|
||||
{
|
||||
a = (*premul>>30)&0x3;
|
||||
b = (((*premul>>20)&0x3ff)*a)>>2;
|
||||
g = (((*premul>>10)&0x3ff)*a)>>2;
|
||||
r = (((*premul>> 0)&0x3ff)*a)>>2;
|
||||
*premul++ = (a<<30)|(b<<20)|(g<<20)|(r<<0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PTI_LLLX8: //FIXME: why the Xs?
|
||||
case PTI_LLLA8:
|
||||
case PTI_RGBA8:
|
||||
case PTI_RGBX8:
|
||||
case PTI_BGRA8:
|
||||
case PTI_BGRX8:
|
||||
case PTI_RGBA8_SRGB: //fixme: what's the correct multiplication for srgb?
|
||||
case PTI_RGBX8_SRGB:
|
||||
case PTI_BGRA8_SRGB:
|
||||
case PTI_BGRX8_SRGB:
|
||||
{
|
||||
qbyte *fte_restrict premul = (qbyte*)mips->mip[0].data;
|
||||
for (i = 0; i < mips->mip[0].width*mips->mip[0].height; i++, premul+=4)
|
||||
{
|
||||
premul[0] = (premul[0] * premul[3])>>8;
|
||||
premul[1] = (premul[1] * premul[3])>>8;
|
||||
premul[2] = (premul[2] * premul[3])>>8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PTI_L8A8:
|
||||
case PTI_L8A8_SRGB:
|
||||
{
|
||||
qbyte *fte_restrict premul = (qbyte*)mips->mip[0].data;
|
||||
for (i = 0; i < mips->mip[0].width*mips->mip[0].height; i++, premul+=2)
|
||||
premul[0] = (premul[0] * premul[1])>>8;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break; //format not known, so no idea how to premultiply it. bc2/3 might already be premultiplied or not...
|
||||
}
|
||||
}
|
||||
|
||||
//resamples and depalettes as required
|
||||
//ALWAYS frees rawdata, even on failure (but never mips).
|
||||
static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flags, void *rawdata, void *palettedata, int imgwidth, int imgheight, uploadfmt_t fmt, qboolean freedata)
|
||||
|
@ -12091,90 +12178,7 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag
|
|||
}
|
||||
|
||||
if (flags & IF_PREMULTIPLYALPHA)
|
||||
{
|
||||
//works for rgba or bgra
|
||||
int i;
|
||||
switch(mips->encoding)
|
||||
{
|
||||
case PTI_RGBA32F:
|
||||
{
|
||||
float *fte_restrict premul = (float*)mips->mip[0].data;
|
||||
for (i = 0; i < mips->mip[0].width*mips->mip[0].height; i++, premul+=4)
|
||||
{
|
||||
premul[0] = (premul[0] * premul[3]);
|
||||
premul[1] = (premul[1] * premul[3]);
|
||||
premul[2] = (premul[2] * premul[3]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PTI_RGBA16F:
|
||||
{
|
||||
unsigned short *fte_restrict premul = (unsigned short*)mips->mip[0].data;
|
||||
for (i = 0; i < mips->mip[0].width*mips->mip[0].height; i++, premul+=4)
|
||||
{
|
||||
float a = HalfToFloat(premul[3]);
|
||||
premul[0] = FloatToHalf(HalfToFloat(premul[0]) * a);
|
||||
premul[1] = FloatToHalf(HalfToFloat(premul[1]) * a);
|
||||
premul[2] = FloatToHalf(HalfToFloat(premul[2]) * a);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PTI_RGBA16:
|
||||
{
|
||||
unsigned short *fte_restrict premul = (unsigned short*)mips->mip[0].data;
|
||||
for (i = 0; i < mips->mip[0].width*mips->mip[0].height; i++, premul+=4)
|
||||
{
|
||||
premul[0] = (premul[0] * premul[3])>>16;
|
||||
premul[1] = (premul[1] * premul[3])>>16;
|
||||
premul[2] = (premul[2] * premul[3])>>16;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PTI_A2BGR10:
|
||||
{
|
||||
unsigned int *fte_restrict premul = (unsigned int*)mips->mip[0].data, r,g,b,a;
|
||||
for (i = 0; i < mips->mip[0].width*mips->mip[0].height; i++)
|
||||
{
|
||||
a = (*premul>>30)&0x3;
|
||||
b = (((*premul>>20)&0x3ff)*a)>>2;
|
||||
g = (((*premul>>10)&0x3ff)*a)>>2;
|
||||
r = (((*premul>> 0)&0x3ff)*a)>>2;
|
||||
*premul++ = (a<<30)|(b<<20)|(g<<20)|(r<<0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PTI_LLLX8: //FIXME: why the Xs?
|
||||
case PTI_LLLA8:
|
||||
case PTI_RGBA8:
|
||||
case PTI_RGBX8:
|
||||
case PTI_BGRA8:
|
||||
case PTI_BGRX8:
|
||||
case PTI_RGBA8_SRGB: //fixme: what's the correct multiplication for srgb?
|
||||
case PTI_RGBX8_SRGB:
|
||||
case PTI_BGRA8_SRGB:
|
||||
case PTI_BGRX8_SRGB:
|
||||
{
|
||||
qbyte *fte_restrict premul = (qbyte*)mips->mip[0].data;
|
||||
for (i = 0; i < mips->mip[0].width*mips->mip[0].height; i++, premul+=4)
|
||||
{
|
||||
premul[0] = (premul[0] * premul[3])>>8;
|
||||
premul[1] = (premul[1] * premul[3])>>8;
|
||||
premul[2] = (premul[2] * premul[3])>>8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PTI_L8A8:
|
||||
case PTI_L8A8_SRGB:
|
||||
{
|
||||
qbyte *fte_restrict premul = (qbyte*)mips->mip[0].data;
|
||||
for (i = 0; i < mips->mip[0].width*mips->mip[0].height; i++, premul+=2)
|
||||
premul[0] = (premul[0] * premul[1])>>8;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break; //format not known, so no idea how to premultiply it. bc2/3 might already be premultiplied or not...
|
||||
}
|
||||
}
|
||||
Image_Premultiply(mips);
|
||||
|
||||
mips->mip[0].needfree = freedata;
|
||||
return true;
|
||||
|
|
|
@ -479,6 +479,7 @@ qboolean Image_FormatHasAlpha(uploadfmt_t encoding);
|
|||
image_t *Image_LoadTexture (const char *identifier, int width, int height, uploadfmt_t fmt, void *data, unsigned int flags);
|
||||
struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char *iname, const char *fname, qbyte *filedata, int filesize);
|
||||
void Image_ChangeFormat(struct pendingtextureinfo *mips, qboolean *allowedformats, uploadfmt_t origfmt, const char *imagename);
|
||||
void Image_Premultiply(struct pendingtextureinfo *mips);
|
||||
void *Image_FlipImage(const void *inbuffer, void *outbuffer, int *inoutwidth, int *inoutheight, int pixelbytes, qboolean flipx, qboolean flipy, qboolean flipd);
|
||||
|
||||
#ifdef D3D8QUAKE
|
||||
|
|
|
@ -247,8 +247,10 @@ static struct wdisplay_s
|
|||
#endif
|
||||
|
||||
//stupid csd crap to work around shitty wayland servers
|
||||
int truewidth; //not really needed, but present for consistency
|
||||
int trueheight;
|
||||
int csdsize;
|
||||
char *csdcaption;
|
||||
qboolean hasssd; //probably false on gnome.
|
||||
int mousex,mousey;
|
||||
|
||||
|
@ -488,7 +490,7 @@ void xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *xdg_toplevel
|
|||
{
|
||||
if (!width || !height)
|
||||
{
|
||||
width = vid.pixelwidth;
|
||||
width = w.truewidth;
|
||||
height = w.trueheight;
|
||||
}
|
||||
|
||||
|
@ -497,8 +499,9 @@ void xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *xdg_toplevel
|
|||
pwl_egl_window_resize(w.enwindow, width, height, 0, 0);
|
||||
#endif
|
||||
|
||||
w.truewidth = width;
|
||||
w.trueheight = height;
|
||||
if (vid.pixelwidth != width || vid.pixelheight != w.trueheight-w.csdsize)
|
||||
if (vid.pixelwidth != width || vid.pixelheight != height-w.csdsize)
|
||||
{
|
||||
vid.pixelwidth = width;
|
||||
vid.pixelheight = w.trueheight-w.csdsize;
|
||||
|
@ -538,11 +541,12 @@ static void WL_shell_handle_configure(void *data, struct wl_shell_surface *shell
|
|||
pwl_egl_window_resize(w.enwindow, width, height, 0, 0);
|
||||
#endif
|
||||
|
||||
w.truewidth = width;
|
||||
w.trueheight = height;
|
||||
if (vid.pixelwidth != width || vid.pixelheight != w.trueheight-w.csdsize)
|
||||
if (vid.pixelwidth != width || vid.pixelheight != height-w.csdsize)
|
||||
{
|
||||
vid.pixelwidth = width;
|
||||
vid.pixelheight = w.trueheight-w.csdsize;
|
||||
vid.pixelheight = height-w.csdsize;
|
||||
Cvar_ForceCallback(&vid_conautoscale);
|
||||
}
|
||||
}
|
||||
|
@ -645,47 +649,70 @@ void *WL_CreateCursor(const qbyte *imagedata, int width, int height, uploadfmt_t
|
|||
const char *xdg_runtime_dir = getenv ("XDG_RUNTIME_DIR");
|
||||
int fd;
|
||||
struct cursorinfo_s *c;
|
||||
static qboolean allowfmts[PTI_MAX] = {[PTI_BGRX8]=true, [PTI_BGRA8]=true}; //FIXME: populate via wl_shm_add_listener instead of using formats that we THINK will work.
|
||||
struct pendingtextureinfo mips = {};
|
||||
|
||||
if (!w.shm)
|
||||
return NULL; //can't shm the image to the server
|
||||
|
||||
switch(format)
|
||||
mips.mipcount = 1;
|
||||
mips.type = PTI_2D;
|
||||
mips.encoding = format;
|
||||
mips.extrafree = NULL;
|
||||
|
||||
mips.mip[0].width = width*scale;
|
||||
mips.mip[0].height = height*scale;
|
||||
mips.mip[0].depth = 1;
|
||||
mips.mip[0].data = Image_ResampleTexture(format, imagedata, width, height, NULL, mips.mip[0].width, mips.mip[0].height);
|
||||
mips.mip[0].needfree = true;
|
||||
mips.mip[0].datasize = 0;
|
||||
if (!allowfmts[mips.encoding])
|
||||
Image_ChangeFormat(&mips, allowfmts, format, "cursor");
|
||||
if (!allowfmts[mips.encoding])
|
||||
return NULL; //failure...
|
||||
|
||||
switch(mips.encoding)
|
||||
{ //fte favours byte orders, while packed formats are ordered as hex numbers would be
|
||||
//wayland formats are as hex (explicitly little-endian, so byteswapped)
|
||||
case PTI_RGBA8: pbytes = 4; shmfmt = WL_SHM_FORMAT_ABGR8888; break;
|
||||
case PTI_RGBX8: pbytes = 4; shmfmt = WL_SHM_FORMAT_XBGR8888; break;
|
||||
case PTI_LLLA8: //just fall through
|
||||
case PTI_RGBA8: pbytes = 4; shmfmt = WL_SHM_FORMAT_ARGB8888; break;
|
||||
case PTI_RGBX8: pbytes = 4; shmfmt = WL_SHM_FORMAT_XRGB8888; break;
|
||||
case PTI_BGRA8: pbytes = 4; shmfmt = WL_SHM_FORMAT_ABGR8888; break;
|
||||
case PTI_BGRX8: pbytes = 4; shmfmt = WL_SHM_FORMAT_XBGR8888; break;
|
||||
case PTI_BGRA8: pbytes = 4; shmfmt = WL_SHM_FORMAT_ARGB8888; break;
|
||||
case PTI_LLLX8: //just fall through
|
||||
case PTI_BGRX8: pbytes = 4; shmfmt = WL_SHM_FORMAT_XRGB8888; break;
|
||||
case PTI_RGB8: pbytes = 3; shmfmt = WL_SHM_FORMAT_BGR888; break;
|
||||
case PTI_BGR8: pbytes = 3; shmfmt = WL_SHM_FORMAT_RGB888; break;
|
||||
|
||||
case PTI_RGB565:pbytes = 2; shmfmt = WL_SHM_FORMAT_RGB565; break;
|
||||
case PTI_A2BGR10:pbytes= 4; shmfmt = WL_SHM_FORMAT_ABGR2101010; break;
|
||||
case PTI_L8:
|
||||
default:
|
||||
Con_Printf("WL_CreateCursor: Unsupported format\n");
|
||||
return NULL; //failure
|
||||
Sys_Error("WL_CreateCursor: converted to unsupported pixel format %i", format);
|
||||
return NULL; //failure. can't convert from that format.
|
||||
}
|
||||
|
||||
Image_Premultiply(&mips);
|
||||
|
||||
fd = open (xdg_runtime_dir, __O_TMPFILE|O_RDWR|O_EXCL, 0600);
|
||||
size = width * height * pbytes;
|
||||
size = mips.mip[0].width * mips.mip[0].height * pbytes;
|
||||
if (fd >= 0)
|
||||
{
|
||||
ftruncate (fd, size);
|
||||
outdata = mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (outdata)
|
||||
{
|
||||
memcpy(outdata, imagedata, width*height*pbytes);
|
||||
memcpy(outdata, mips.mip[0].data, mips.mip[0].width*mips.mip[0].height*pbytes);
|
||||
pool = pwl_shm_create_pool (w.shm, fd, size);
|
||||
if (pool)
|
||||
{
|
||||
buffer = pwl_shm_pool_create_buffer (pool, 0, width, height, width*pbytes, shmfmt);
|
||||
buffer = pwl_shm_pool_create_buffer (pool, 0, mips.mip[0].width, mips.mip[0].height, mips.mip[0].width*pbytes, shmfmt);
|
||||
if (buffer)
|
||||
{
|
||||
surf = pwl_compositor_create_surface(w.compositor);
|
||||
if (surf)
|
||||
{ //yay! something worked for once!
|
||||
pwl_surface_attach(surf, buffer, 0, 0);
|
||||
pwl_surface_damage(surf, 0, 0, width, height);
|
||||
pwl_surface_damage(surf, 0, 0, mips.mip[0].width, mips.mip[0].height);
|
||||
pwl_surface_commit(surf);
|
||||
}
|
||||
//can't destroy the buffer too early
|
||||
|
@ -703,12 +730,16 @@ void *WL_CreateCursor(const qbyte *imagedata, int width, int height, uploadfmt_t
|
|||
c->buf = buffer;
|
||||
c->hot_x = hotx;
|
||||
c->hot_y = hoty;
|
||||
c->width = width;
|
||||
c->height = height;
|
||||
c->width = mips.mip[0].width;
|
||||
c->height = mips.mip[0].height;
|
||||
return c;
|
||||
}
|
||||
if (buffer)
|
||||
pwl_buffer_destroy(buffer); //don't need to track that any more
|
||||
|
||||
//free it conversions required it.
|
||||
if (mips.mip[0].needfree)
|
||||
Z_Free(mips.mip[0].data);
|
||||
return NULL;
|
||||
}
|
||||
qboolean WL_SetCursor(void *cursor)
|
||||
|
@ -1047,7 +1078,7 @@ static void WL_keyboard_handle_key(void *data, struct wl_keyboard *keyboard, uin
|
|||
ukey = 0;
|
||||
}
|
||||
|
||||
IN_KeyEvent(0, (state==WL_KEYBOARD_KEY_STATE_PRESSED)?1:0, qkey, 0);
|
||||
IN_KeyEvent(0, (state==WL_KEYBOARD_KEY_STATE_PRESSED)?1:0, qkey, ukey);
|
||||
}
|
||||
|
||||
static void WL_keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
|
||||
|
@ -1271,7 +1302,7 @@ static void WL_SwapBuffers(void)
|
|||
R2D_ImageColours(0.05, 0.05, 0.1, 1);
|
||||
R2D_FillBlock(0, 0, vid.pixelwidth, w.csdsize);
|
||||
R2D_ImageColours(1, 1, 1, 1);
|
||||
Draw_FunStringWidth(0, 4, "FTE QuakeWorld", vid.pixelwidth, 2, vid.activeapp);
|
||||
Draw_FunStringWidth(0, 4, w.csdcaption, vid.pixelwidth, 2, vid.activeapp);
|
||||
vid.width=vw;
|
||||
vid.height=vh;
|
||||
vid.rotpixelwidth=rw;
|
||||
|
@ -1307,7 +1338,10 @@ static void WL_SwapBuffers(void)
|
|||
break;
|
||||
}
|
||||
|
||||
w.absmouse = !vid.activeapp || Key_MouseShouldBeFree() || !w.relative_pointer || !in_windowed_mouse.value;
|
||||
//if the game wants absolute mouse positions...
|
||||
w.absmouse = !vid.activeapp || Key_MouseShouldBeFree() || !in_windowed_mouse.value;
|
||||
//and force it on if we're lacking one of the plethora of extensions that were needed to get the damn thing actually usable.
|
||||
w.absmouse |= !w.relative_pointer || !w.locked_pointer;
|
||||
if (!w.absmouse && !w.locked_pointer && w.pointer_constraints)
|
||||
{
|
||||
w.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(w.pointer_constraints, w.surface, w.pointer, NULL, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT);
|
||||
|
@ -1489,16 +1523,20 @@ static qboolean WL_Init (rendererstate_t *info, unsigned char *palette)
|
|||
pwl_shell_surface_set_toplevel(w.ssurface);
|
||||
}
|
||||
#endif
|
||||
|
||||
w.truewidth = info->width?info->width:640;
|
||||
w.trueheight = info->height?info->height:480;
|
||||
pwl_display_roundtrip(w.display);
|
||||
|
||||
{
|
||||
struct wl_region *region = pwl_compositor_create_region(w.compositor);
|
||||
pwl_region_add(region, 0, 0, info->width, info->height);
|
||||
pwl_region_add(region, 0, 0, w.truewidth, w.trueheight);
|
||||
pwl_surface_set_opaque_region(w.surface, region);
|
||||
//FIXME: leaks region?
|
||||
//FIXME: leaks region...
|
||||
//pwl_region_destroy(region);
|
||||
}
|
||||
pwl_display_roundtrip(w.display);
|
||||
vid.pixelwidth = info->width;
|
||||
w.trueheight = info->height;
|
||||
vid.pixelwidth = w.truewidth;
|
||||
vid.pixelheight = w.trueheight-w.csdsize;
|
||||
|
||||
vid.activeapp = true;
|
||||
|
@ -1525,7 +1563,7 @@ pwl_display_roundtrip(w.display);
|
|||
case QR_OPENGL:
|
||||
{
|
||||
EGLConfig cfg;
|
||||
w.enwindow = pwl_egl_window_create(w.surface, info->width, info->height);
|
||||
w.enwindow = pwl_egl_window_create(w.surface, w.truewidth, w.trueheight);
|
||||
if (!EGL_InitDisplay(info, EGL_PLATFORM_WAYLAND_KHR, w.display, (EGLNativeDisplayType)w.display, &cfg))
|
||||
{
|
||||
Con_Printf("couldn't find suitable EGL config\n");
|
||||
|
@ -1570,6 +1608,7 @@ static void WL_DeInit(void)
|
|||
pwl_display_roundtrip(w.display);
|
||||
pwl_display_disconnect(w.display);
|
||||
}
|
||||
Z_Free(w.csdcaption);
|
||||
memset(&w, 0, sizeof(w));
|
||||
}
|
||||
static qboolean WL_ApplyGammaRamps(unsigned int gammarampsize, unsigned short *ramps)
|
||||
|
@ -1587,6 +1626,8 @@ static void WL_SetCaption(const char *text)
|
|||
if (w.ssurface)
|
||||
pwl_shell_surface_set_title(w.ssurface, text);
|
||||
#endif
|
||||
|
||||
Z_StrDupPtr(&w.csdcaption, text);
|
||||
}
|
||||
|
||||
static int WL_GetPriority(void)
|
||||
|
|
Loading…
Reference in a new issue