Merge pull request #1025 from 0lvin/smallfixes

Cinematic JPG/PNG image support
This commit is contained in:
Yamagi 2023-07-16 09:38:56 +02:00 committed by GitHub
commit 146e5615af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 168 additions and 53 deletions

View File

@ -30,6 +30,20 @@
#include "header/client.h"
#include "input/header/input.h"
// don't need HDR stuff
#define STBI_NO_LINEAR
#define STBI_NO_HDR
// make sure STB_image uses standard malloc(), as we'll use standard free() to deallocate
#define STBI_MALLOC(sz) malloc(sz)
#define STBI_REALLOC(p,sz) realloc(p,sz)
#define STBI_FREE(p) free(p)
// Switch of the thread local stuff. Breaks mingw under Windows.
#define STBI_NO_THREAD_LOCALS
// include implementation part of stb_image into this file
#define STB_IMAGE_IMPLEMENTATION
#include "refresh/files/stb_image.h"
extern cvar_t *vid_renderer;
cvar_t *cin_force43;
@ -50,6 +64,7 @@ typedef struct
int width;
int height;
int color_bits;
byte *pic;
byte *pic_pending;
@ -598,6 +613,12 @@ SCR_DrawCinematic(void)
if (Q_stricmp(vid_renderer->string, "soft") == 0)
{
color = SCR_MinimalColor();
/* Soft render requires to reset palette before show RGBA image */
if (cin.color_bits == 32)
{
R_SetPalette(NULL);
}
}
else
{
@ -621,16 +642,51 @@ SCR_DrawCinematic(void)
Draw_Fill(x, y + h, w, viddef.height - (y + h), color);
}
Draw_StretchRaw(x, y, w, h, cin.width, cin.height, cin.pic);
Draw_StretchRaw(x, y, w, h, cin.width, cin.height, cin.pic, cin.color_bits);
return true;
}
byte *
SCR_LoadHiColor(const char* namewe, const char *ext, int *width, int *height)
{
char filename[256];
int bytesPerPixel;
byte *pic, *data = NULL;
void *rawdata;
size_t len;
Q_strlcpy(filename, namewe, sizeof(filename));
Q_strlcat(filename, ".", sizeof(filename));
Q_strlcat(filename, ext, sizeof(filename));
len = FS_LoadFile(filename, &rawdata);
if (!rawdata || len <=0)
{
return NULL;
}
data = stbi_load_from_memory(rawdata, len, width, height,
&bytesPerPixel, STBI_rgb_alpha);
if (data == NULL)
{
FS_FreeFile(rawdata);
return NULL;
}
pic = Z_Malloc(cin.height * cin.width * 4);
memcpy(pic, data, cin.height * cin.width * 4);
free(data);
return pic;
}
void
SCR_PlayCinematic(char *arg)
{
int width, height;
byte *palette;
byte *palette = NULL;
char name[MAX_OSPATH], *dot;
In_FlushQueue();
@ -645,11 +701,43 @@ SCR_PlayCinematic(char *arg)
/* static pcx image */
if (dot && !strcmp(dot, ".pcx"))
{
cvar_t *r_retexturing;
Com_sprintf(name, sizeof(name), "pics/%s", arg);
SCR_LoadPCX(name, &cin.pic, &palette, &cin.width, &cin.height);
r_retexturing = Cvar_Get("r_retexturing", "1", CVAR_ARCHIVE);
if (r_retexturing->value)
{
char namewe[256];
cin.color_bits = 32;
/* Remove the extension */
memset(namewe, 0, 256);
memcpy(namewe, name, strlen(name) - strlen(dot));
cin.pic = SCR_LoadHiColor(namewe, "tga", &cin.width, &cin.height);
if (!cin.pic)
{
cin.pic = SCR_LoadHiColor(namewe, "png", &cin.width, &cin.height);
}
if (!cin.pic)
{
cin.pic = SCR_LoadHiColor(namewe, "jpg", &cin.width, &cin.height);
}
}
if (!cin.pic)
{
SCR_LoadPCX(name, &cin.pic, &palette, &cin.width, &cin.height);
cin.color_bits = 8;
}
cl.cinematicframe = -1;
cl.cinematictime = 1;
SCR_EndLoadingPlaque();
cls.state = ca_active;
if (!cin.pic)
@ -657,7 +745,7 @@ SCR_PlayCinematic(char *arg)
Com_Printf("%s not found.\n", name);
cl.cinematictime = 0;
}
else
else if (palette)
{
memcpy(cl.cinematicpalette, palette, sizeof(cl.cinematicpalette));
Z_Free(palette);
@ -678,6 +766,7 @@ SCR_PlayCinematic(char *arg)
SCR_EndLoadingPlaque();
cin.color_bits = 8;
cls.state = ca_active;
FS_Read(&width, 4, cl.cinematic_file);

View File

@ -112,6 +112,14 @@ Mod_LoadMD2 (const char *mod_name, const void *buffer, int modfilelen,
return NULL;
}
if (pheader->num_skins > MAX_MD2SKINS)
{
R_Printf(PRINT_ALL, "%s has too many skins (%i > %i), "
"extra sprites will be ignored\n",
mod_name, pheader->num_skins, MAX_MD2SKINS);
pheader->num_skins = MAX_MD2SKINS;
}
//
// load base s and t vertices (not used in gl version)
//
@ -212,7 +220,7 @@ SPRITE MODELS
Mod_LoadSP2
support for .sp2 sprites
====
=================
*/
void *
Mod_LoadSP2 (const char *mod_name, const void *buffer, int modfilelen,
@ -239,9 +247,10 @@ Mod_LoadSP2 (const char *mod_name, const void *buffer, int modfilelen,
if (sprout->numframes > MAX_MD2SKINS)
{
R_Printf(PRINT_ALL, "%s has too many frames (%i > %i)",
R_Printf(PRINT_ALL, "%s has too many frames (%i > %i), "
"extra frames will be ignored\n",
mod_name, sprout->numframes, MAX_MD2SKINS);
return NULL;
sprout->numframes = MAX_MD2SKINS;
}
/* byte swap everything */
@ -278,8 +287,10 @@ Mod_ReLoadSkins(struct image_s **skins, findimage_t find_image, void *extradata,
int i;
sprout = (dsprite_t *)extradata;
for (i=0 ; i<sprout->numframes ; i++)
skins[i] = find_image (sprout->frames[i].name, it_sprite);
for (i=0; i < sprout->numframes; i++)
{
skins[i] = find_image(sprout->frames[i].name, it_sprite);
}
return sprout->numframes;
}
else if (type == mod_alias)
@ -288,8 +299,10 @@ Mod_ReLoadSkins(struct image_s **skins, findimage_t find_image, void *extradata,
int i;
pheader = (dmdl_t *)extradata;
for (i=0 ; i<pheader->num_skins ; i++)
for (i=0; i < pheader->num_skins; i++)
{
skins[i] = find_image ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
}
return pheader->num_frames;
}
/* Unknow format, no images associated with it */

View File

@ -330,10 +330,9 @@ RDraw_FadeScreen(void)
}
void
RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int bits)
{
GLfloat tex[8];
byte *source;
float hscale = 1.0f;
int frac, fracstep;
int i, j, trows;
@ -341,7 +340,7 @@ RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
R_Bind(0);
if(gl_config.npottextures || rows <= 256)
if(gl_config.npottextures || rows <= 256 || bits == 32)
{
// X, X
tex[0] = 0;
@ -389,7 +388,7 @@ RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
x, y + h
};
if (!gl_config.palettedtexture)
if (!gl_config.palettedtexture || bits == 32)
{
unsigned image32[320*240]; /* was 256 * 256, but we want a bit more space */
@ -398,7 +397,13 @@ RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
* pixels to fit into a 256x256 texture.
* This causes text in videos (which are 320x240) to not look broken anymore.
*/
if(gl_config.npottextures || rows <= 256)
if (bits == 32)
{
glTexImage2D(GL_TEXTURE_2D, 0, gl_tex_solid_format,
cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE,
data);
}
else if(gl_config.npottextures || rows <= 256)
{
unsigned* img = image32;
@ -435,6 +440,8 @@ RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
for (i = 0; i < trows; i++)
{
const byte *source;
row = (int)(i * hscale);
if (row > rows)
@ -466,6 +473,8 @@ RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
for (i = 0; i < trows; i++)
{
const byte *source;
row = (int)(i * hscale);
if (row > rows)

View File

@ -407,6 +407,6 @@ extern void RDraw_CharScaled(int x, int y, int num, float scale);
extern void RDraw_TileClear(int x, int y, int w, int h, char *pic);
extern void RDraw_Fill(int x, int y, int w, int h, int c);
extern void RDraw_FadeScreen(void);
extern void RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data);
extern void RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int bits);
#endif

View File

@ -350,7 +350,7 @@ GL3_Draw_FadeScreen(void)
}
void
GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int bits)
{
int i, j;
@ -360,20 +360,27 @@ GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
unsigned* img = image32;
if(cols*rows > 320*240)
if (bits == 32)
{
/* in case there is a bigger video after all,
* malloc enough space to hold the frame */
img = (unsigned*)malloc(cols*rows*4);
img = (unsigned *)data;
}
for(i=0; i<rows; ++i)
else
{
int rowOffset = i*cols;
for(j=0; j<cols; ++j)
if(cols*rows > 320*240)
{
byte palIdx = data[rowOffset+j];
img[rowOffset+j] = gl3_rawpalette[palIdx];
/* in case there is a bigger video after all,
* malloc enough space to hold the frame */
img = (unsigned*)malloc(cols*rows*4);
}
for(i=0; i<rows; ++i)
{
int rowOffset = i*cols;
for(j=0; j<cols; ++j)
{
byte palIdx = data[rowOffset+j];
img[rowOffset+j] = gl3_rawpalette[palIdx];
}
}
}
@ -387,7 +394,7 @@ GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
glTexImage2D(GL_TEXTURE_2D, 0, gl3_tex_solid_format,
cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);
if(img != image32)
if(img != image32 && img != (unsigned *)data)
{
free(img);
}

View File

@ -425,7 +425,7 @@ extern void GL3_DrawFrameBufferObject(int x, int y, int w, int h, GLuint fboText
extern void GL3_Draw_Fill(int x, int y, int w, int h, int c);
extern void GL3_Draw_FadeScreen(void);
extern void GL3_Draw_Flash(const float color[4], float x, float y, float w, float h);
extern void GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data);
extern void GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int bits);
// gl3_image.c

View File

@ -87,7 +87,6 @@ typedef enum
{
rserr_ok,
rserr_invalid_fullscreen,
rserr_invalid_mode,
rserr_unknown
@ -582,7 +581,7 @@ struct image_s *RE_Draw_FindPic (char *name);
void RE_Draw_GetPicSize (int *w, int *h, char *name);
void RE_Draw_PicScaled (int x, int y, char *name, float scale);
void RE_Draw_StretchPic (int x, int y, int w, int h, char *name);
void RE_Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data);
void RE_Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int bits);
void RE_Draw_CharScaled (int x, int y, int c, float scale);
void RE_Draw_TileClear (int x, int y, int w, int h, char *name);
void RE_Draw_Fill (int x, int y, int w, int h, int c);
@ -596,6 +595,7 @@ byte *Get_BestImageSize(const image_t *image, int *req_width, int *req_height);
void R_FreeUnusedImages(void);
qboolean R_ImageHasFreeSpace(void);
pixel_t R_ApplyLight(pixel_t pix, const light3_t light);
void R_Convert32To8bit(const unsigned char* pic_in, pixel_t* pic_out, size_t size, qboolean transparent);
void R_InitSkyBox(model_t *loadmodel);
void R_IMFlatShadedQuad( const vec3_t a, const vec3_t b, const vec3_t c, const vec3_t d, int color, float alpha );

View File

@ -321,7 +321,7 @@ RE_Draw_StretchRaw
=============
*/
void
RE_Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
RE_Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int bits)
{
image_t pic;
byte *image_scaled;
@ -329,7 +329,12 @@ RE_Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
// we have only one image size
pic.mip_levels = 1;
if (r_retexturing->value)
if (bits == 32)
{
image_scaled = malloc(cols * rows);
R_Convert32To8bit(data, image_scaled, cols * rows, false);
}
else if (r_retexturing->value)
{
if (cols < (w / 3) || rows < (h / 3))
{
@ -352,7 +357,7 @@ RE_Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
}
else
{
image_scaled = data;
image_scaled = (byte *)data;
}
pic.pixels[0] = image_scaled;

View File

@ -206,7 +206,7 @@ Get_BestImageSize(const image_t *image, int *req_width, int *req_height)
static byte *d_16to8table = NULL; // 16 to 8 bit conversion table
static void
void
R_Convert32To8bit(const unsigned char* pic_in, pixel_t* pic_out, size_t size,
qboolean transparent)
{

View File

@ -1516,8 +1516,7 @@ RE_SetMode(void)
vid.height = r_customheight->value;
/*
** if this returns rserr_invalid_fullscreen then it set the mode but not as a
** fullscreen mode, e.g. 320x200 on a system that doesn't support that res
** if this returns rserr_invalid_mode then it set previous resolution
*/
if ((err = SWimp_SetMode(&vid.width, &vid.height, r_mode->value, fullscreen)) == rserr_ok)
{
@ -1532,17 +1531,7 @@ RE_SetMode(void)
}
else
{
if (err == rserr_invalid_fullscreen)
{
ri.Cvar_SetValue("vid_fullscreen", 0);
R_Printf(PRINT_ALL, "%s() - fullscreen unavailable in this mode\n", __func__);
if (SWimp_SetMode(&vid.width, &vid.height, r_mode->value, 0) == rserr_ok)
{
return true;
}
}
else if (err == rserr_invalid_mode)
if (err == rserr_invalid_mode)
{
R_Printf(PRINT_ALL, "%s() - invalid mode\n", __func__);

View File

@ -197,8 +197,11 @@ typedef struct
void (EXPORT *DrawFill) (int x, int y, int w, int h, int c);
void (EXPORT *DrawFadeScreen) (void);
// Draw images for cinematic rendering (which can have a different palette). Note that calls
void (EXPORT *DrawStretchRaw) (int x, int y, int w, int h, int cols, int rows, byte *data);
/*
* Draw images for cinematic rendering (which can have a different palette if bits equals to 8).
* Note that calls
*/
void (EXPORT *DrawStretchRaw) (int x, int y, int w, int h, int cols, int rows, const byte *data, int bits);
/*
** video mode and refresh state management entry points
@ -278,7 +281,7 @@ void Draw_CharScaled(int x, int y, int num, float scale);
void Draw_TileClear(int x, int y, int w, int h, char *name);
void Draw_Fill(int x, int y, int w, int h, int c);
void Draw_FadeScreen(void);
void Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data);
void Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int bits);
//int R_Init(void *hinstance, void *hWnd);
//void R_Shutdown(void);
void R_SetPalette(const unsigned char *palette);

View File

@ -735,11 +735,11 @@ Draw_FadeScreen(void)
}
void
Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int bits)
{
if (ref_active)
{
re.DrawStretchRaw(x, y, w, h, cols, rows, data);
re.DrawStretchRaw(x, y, w, h, cols, rows, data, bits);
}
}