Descent3/2dlib/surface.cpp

777 lines
20 KiB
C++
Raw Normal View History

/*
* Descent 3
* Copyright (C) 2024 Parallax Software
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
--- HISTORICAL COMMENTS FOLLOW ---
2024-04-16 03:43:29 +00:00
* $Logfile: /DescentIII/Main/2dlib/surface.cpp $
* $Revision: 7 $
* $Date: 11/30/98 5:50p $
* $Author: Jason $
*
* Master Surface class
*
* $Log: /DescentIII/Main/2dlib/surface.cpp $
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 7 11/30/98 5:50p Jason
* added 4444 bitmap support
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 6 4/23/98 6:38p Jason
* made bitmaps use 1555 format
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 5 12/19/97 2:26p Jason
* more fixes for 2d/3d intergration
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 4 12/19/97 12:32p Samir
* lock now calls renderer functions.
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 3 11/11/97 1:24p Samir
* Fixed problem with clearing using the renderer.
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 2 10/15/97 5:20p Jason
* did a HUGE overhaul of the bitmap system
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 24 6/12/97 6:29p Samir
* DDGR v2.0 Changes in 2d system implemented.
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 23 6/06/97 12:18p Samir
* OpenGL HACKS to call renderer for some drawing functions. Must fix.
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 22 5/19/97 5:10p Jason
* changes for our new abstracted renderer code
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 21 4/30/97 3:15p Jason
* changes to support both 8bit and 16bit rendering in software
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 20 3/28/97 3:07p Samir
* Clear function now takes a color
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 19 3/27/97 11:11a Samir
* Moved code from ddgr library to 2dlib because it was ANSI compliant and
* should work on all systems
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 18 2/28/97 2:51p Samir
* took out __cdecl in atexit function.
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 17 2/17/97 2:19p Jason
* made blit function scale instead of clip
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 16 2/11/97 3:19p Jason
* added displaying of 8bit palettized graphics on 16bit surfaces
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 15 2/04/97 12:49p Samir
2024-04-16 18:56:40 +00:00
* Added lock(x,y) for those special cases.
*
2024-04-16 03:43:29 +00:00
* 14 2/03/97 3:01p Samir
* Used one memory surface global to grSurface for scratchpad blitting.
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 13 1/30/97 6:01p Samir
* The partition of memory and os surfaces as well as the change in
* ddgr_surface structure and all related changes.
*
* $NoKeywords: $
*/
2024-05-21 10:27:01 +00:00
#include <algorithm>
#include <cstdlib>
#include <cstring>
2024-05-21 10:27:01 +00:00
#include "bitmap.h"
2024-04-16 03:43:29 +00:00
#include "lib2d.h"
#include "pserror.h"
#include "renderer.h"
static inline unsigned XLAT_RGB_TO_16(ddgr_color c) {
2024-05-24 02:58:46 +00:00
uint8_t r, g, b;
r = (uint8_t)((c & 0x00ff0000) >> 16);
g = (uint8_t)((c & 0x0000ff00) >> 8);
b = (uint8_t)(c & 0x000000ff);
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
return (((r >> 3) << 10) + ((g >> 3) << 5) + (b >> 3));
2024-04-16 03:43:29 +00:00
}
ddgr_surface_node *grSurface::surf_list = nullptr; // the surface list
ddgr_surface_node *grSurface::surf_list_cur = nullptr; // current node on list.
ddgr_surface *grSurface::scratch_mem_surf = nullptr;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
void grSurface::init_system() {
// allocate our scratch memory surface used in uniblt
if (!grSurface::scratch_mem_surf) {
grSurface::scratch_mem_surf = new ddgr_surface;
memset(grSurface::scratch_mem_surf, 0, sizeof(ddgr_surface));
}
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
atexit(grSurface::close_system);
}
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
void grSurface::close_system() {
// cleanup our scratch memory surface for blt
if (grSurface::scratch_mem_surf) {
if (grSurface::scratch_mem_surf->obj != nullptr)
2024-04-16 18:56:40 +00:00
gr_mem_surf_Destroy(grSurface::scratch_mem_surf);
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
delete grSurface::scratch_mem_surf;
grSurface::scratch_mem_surf = nullptr;
2024-04-16 18:56:40 +00:00
}
}
2024-04-16 03:43:29 +00:00
// ---------------------------------------------------------------------------
// grSurface constructor and destructor
// ---------------------------------------------------------------------------
2024-04-16 18:56:40 +00:00
grSurface::grSurface() {
surf_Locked = 0;
m_SurfInit = 0;
memset(&ddsfObj, 0, sizeof(ddgr_surface));
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
grSurface::grSurface(int w, int h, int bpp, unsigned type, unsigned flags, const char *name) {
surf_Locked = 0;
m_SurfInit = 0;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
grSurface::create(w, h, bpp, type, flags, name);
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
grSurface::~grSurface() { grSurface::free(); }
void grSurface::create(int w, int h, int bpp, unsigned type, unsigned flags, const char *name) {
bool grerr;
if (m_SurfInit)
grSurface::free();
// create new surface: set up surface structure
memset(&ddsfObj, 0, sizeof(ddgr_surface));
ddsfObj.w = w;
ddsfObj.h = h;
ddsfObj.bpp = bpp;
ddsfObj.type = (uint16_t)type;
ddsfObj.flags = (uint16_t)flags;
2024-04-16 18:56:40 +00:00
if (name)
strncpy(ddsfObj.name, name, 15);
switch (type) {
case SURFTYPE_VIDEOSCREEN:
grerr = ddgr_surf_InitVideo(&ddsfObj);
break;
case SURFTYPE_GENERIC:
grerr = ddgr_surf_Create(&ddsfObj);
break;
case SURFTYPE_MEMORY:
grerr = (bool)gr_mem_surf_Create(&ddsfObj);
break;
default:
Int3(); // Invalid!!
}
if (!grerr)
Int3();
add_to_list(&ddsfObj);
m_SurfInit = 1;
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void grSurface::free() {
/* Freeing surface is same regardless of whether it was loaded from a bitmap handle or
created ourselves
*/
if (!m_SurfInit)
return;
ASSERT(!surf_Locked);
switch (ddsfObj.type) {
case SURFTYPE_VIDEOSCREEN:
ddgr_surf_CloseVideo(&ddsfObj);
break;
case SURFTYPE_GENERIC:
ddgr_surf_Destroy(&ddsfObj);
break;
case SURFTYPE_MEMORY:
gr_mem_surf_Destroy(&ddsfObj);
break;
default:
Int3(); // This really shouldn't happen. bad type!
}
remove_from_list(&ddsfObj);
m_SurfInit = 0;
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void grSurface::load(int handle) {
/* just load the bitmap from the handle info */
ASSERT(m_SurfInit);
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
grSurface::load((char *)bm_data(handle, 0), bm_w(handle, 0), bm_h(handle, 0), bm_bpp(handle), bm_format(handle));
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void grSurface::load(char *data, int w, int h, int bpp, int format) {
// copy defined bitmap given as arguments to this surface, with correct bpp translation.
int rowsize;
ASSERT(m_SurfInit);
/* perform lock, then copy data to this surface, then unlock */
grSurface::lock(&rowsize);
switch (ddsfObj.bpp) {
case BPP_16:
if (bpp == BPP_16)
xlat16_16(data, w, h, format);
if (bpp == BPP_24)
xlat24_16(data, w, h);
if (bpp == BPP_32)
xlat32_16(data, w, h);
break;
case BPP_24:
if (bpp == BPP_16)
xlat16_24(data, w, h);
break;
default:
Int3(); // NOT SUPPORTED YET
}
grSurface::unlock();
2024-04-16 03:43:29 +00:00
}
// loads 8bit palettized data onto this surface.
2024-04-16 18:56:40 +00:00
void grSurface::load(int handle, char *pal) {
ASSERT(m_SurfInit);
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
grSurface::load((char *)bm_data(handle, 0), bm_w(handle, 0), bm_h(handle, 0), pal);
2024-04-16 03:43:29 +00:00
}
// loads 8bit palettized data onto this surface.
2024-04-16 18:56:40 +00:00
void grSurface::load(char *data, int w, int h, char *pal) {
int rowsize;
ASSERT(m_SurfInit);
/* perform lock, then copy data to this surface, then unlock */
grSurface::lock(&rowsize);
switch (ddsfObj.bpp) {
case BPP_16:
2024-05-09 11:11:49 +00:00
// TODO: This is probably software renderer only?
xlat16_16(data, w, h);
2024-04-16 18:56:40 +00:00
default:
Int3(); // NOT SUPPORTED YET
}
grSurface::unlock();
2024-04-16 03:43:29 +00:00
}
// ---------------------------------------------------------------------------
// blt functions:: clear
// ---------------------------------------------------------------------------
2024-04-16 18:56:40 +00:00
void grSurface::clear(ddgr_color col) { grSurface::clear(0, 0, ddsfObj.w, ddsfObj.h, col); }
void grSurface::clear(int l, int t, int w, int h, ddgr_color col) {
ASSERT(m_SurfInit);
ASSERT(!surf_Locked);
switch (ddsfObj.type) {
case SURFTYPE_VIDEOSCREEN:
case SURFTYPE_GENERIC:
// HACK!!!!!!! I MUST CHANGE THIS
// ---------------------------------------------------------------------------
if (ddsfObj.flags & SURFFLAG_RENDERER) {
rend_FillRect(col, l, t, l + w, t + h);
return;
}
// ---------------------------------------------------------------------------
ddgr_surf_Clear(&ddsfObj, col, l, t, w, h);
break;
case SURFTYPE_MEMORY:
gr_mem_surf_Clear(&ddsfObj, col, l, t, w, h);
break;
default:
Int3();
}
2024-04-16 03:43:29 +00:00
}
// ---------------------------------------------------------------------------
// blt functions:
// these functions must support memory->os, os->memory, os->os, mem->mem blts.
// note that (os) blts and (video) blts use the os library.
// ---------------------------------------------------------------------------
2024-04-16 18:56:40 +00:00
void grSurface::uniblt(int dx, int dy, grSurface *ssf, int sx, int sy, int sw, int sh) {
int rowsize;
ASSERT(m_SurfInit);
// mode 11b = dd_to_dd, 01b = mem_to_dd, 10b = dd_to_mem, 00b = mem_to_mem
int mode = 0;
ddgr_surface *dsfs = &ddsfObj, *ssfs = &ssf->ddsfObj;
// setup blitting mode
if (ssfs->type == SURFTYPE_GENERIC || ssfs->type == SURFTYPE_VIDEOSCREEN)
mode = mode | 0x1;
if (dsfs->type == SURFTYPE_GENERIC || dsfs->type == SURFTYPE_VIDEOSCREEN)
mode = mode | 0x2;
/* case 1: os->os
just invoke os blitter
*/
if (mode == 0x3) {
ASSERT(!surf_Locked);
ddgr_surf_Blt(dsfs, dx, dy, ssfs, sx, sy, sw, sh);
2024-04-16 18:56:40 +00:00
return;
}
/* case 2: mem->mem
just lock both surfaces and do a memory blt.
*/
if (mode == 0) {
gr_mem_surf_Blt(dsfs, dx, dy, ssfs, sx, sy, sw, sh);
2024-04-16 18:56:40 +00:00
return;
}
/* case 3: os->mem
This requires locking both surfaces and performing a memory blt.
This also means tricking the memory blitter into thinking that the OS surface
is a memory surface
*/
if (mode == 0x1) {
char *data = ssf->lock(&rowsize);
grSurface::scratch_mem_surf->w = ssfs->w;
grSurface::scratch_mem_surf->h = ssfs->h;
grSurface::scratch_mem_surf->bpp = ssfs->bpp;
grSurface::scratch_mem_surf->type = SURFTYPE_MEMORY;
grSurface::scratch_mem_surf->flags = ssfs->flags;
gr_mem_surf_Init(grSurface::scratch_mem_surf, data, rowsize);
gr_mem_surf_Blt(dsfs, dx, dy, grSurface::scratch_mem_surf, sx, sy, sw, sh);
2024-04-16 18:56:40 +00:00
ssf->unlock();
return;
}
/* case 4: mem->os
This requires locking both surfaces and performing a memory blt.
This also means tricking the memory blitter into thinking that the OS surface
is a memory surface
*/
if (mode == 0x2) {
grSurface::lock(&rowsize);
grSurface::scratch_mem_surf->w = dsfs->w;
grSurface::scratch_mem_surf->h = dsfs->h;
grSurface::scratch_mem_surf->bpp = dsfs->bpp;
grSurface::scratch_mem_surf->type = SURFTYPE_MEMORY;
grSurface::scratch_mem_surf->flags = dsfs->flags;
gr_mem_surf_Init(grSurface::scratch_mem_surf, m_DataPtr, m_DataRowsize);
gr_mem_surf_Blt(grSurface::scratch_mem_surf, dx, dy, ssfs, sx, sy, sw, sh);
2024-04-16 18:56:40 +00:00
grSurface::unlock();
return;
}
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void grSurface::blt(int dx, int dy, grSurface *ssf) {
ASSERT(m_SurfInit);
grSurface::uniblt(dx, dy, ssf, 0, 0, ssf->width(), ssf->height());
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void grSurface::blt(int dx, int dy, grSurface *ssf, int sx, int sy, int sw, int sh) {
ASSERT(m_SurfInit);
grSurface::uniblt(dx, dy, ssf, sx, sy, sw, sh);
2024-04-16 03:43:29 +00:00
}
/* Helper functions
2024-04-16 18:56:40 +00:00
replace_color, simply replaces one color in the surface with another
2024-04-16 03:43:29 +00:00
*/
2024-04-16 18:56:40 +00:00
void grSurface::replace_color(ddgr_color sc, ddgr_color dc) {
int rowsize;
ASSERT(m_SurfInit);
grSurface::lock(&rowsize);
switch (ddsfObj.bpp) {
case BPP_16: {
uint16_t *data = (uint16_t *)m_DataPtr;
2024-04-16 18:56:40 +00:00
int rowsize_w = m_DataRowsize / 2;
uint16_t scc = XLAT_RGB_TO_16(sc), dcc = XLAT_RGB_TO_16(dc);
2024-04-16 18:56:40 +00:00
for (int y = 0; y < ddsfObj.h; y++) {
for (int x = 0; x < ddsfObj.w; x++)
if (data[x] == scc)
data[x] = dcc;
data += rowsize_w;
}
break;
}
case BPP_32:
default:
Int3();
}
grSurface::unlock();
}
2024-04-16 03:43:29 +00:00
// ---------------------------------------------------------------------------
// lock and unlock functions
// these handle memory and os locks
// ---------------------------------------------------------------------------
2024-04-16 18:56:40 +00:00
char *grSurface::lock(int *rowsize) {
bool grerr;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
ASSERT(m_SurfInit);
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
switch (ddsfObj.type) {
case SURFTYPE_VIDEOSCREEN:
case SURFTYPE_GENERIC:
grerr = ddgr_surf_Lock(&ddsfObj, (void **)&m_OrigDataPtr, &m_DataRowsize);
break;
case SURFTYPE_MEMORY:
grerr = gr_mem_surf_Lock(&ddsfObj, (void **)&m_OrigDataPtr, &m_DataRowsize);
break;
default:
Int3(); // invalid type!!
}
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
m_DataPtr = m_OrigDataPtr;
*rowsize = m_DataRowsize;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
if (!grerr)
return nullptr;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
surf_Locked++; // increment lock counter for this surface
2024-04-16 03:43:29 +00:00
2024-05-24 03:07:26 +00:00
rend_SetSoftwareParameters(ddgr_GetAspectRatio(), ddsfObj.w, ddsfObj.h, m_DataRowsize, (uint8_t *)m_OrigDataPtr);
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
return m_DataPtr;
2024-04-16 03:43:29 +00:00
}
/* do lock based off of x,y offsets */
2024-04-16 18:56:40 +00:00
char *grSurface::lock(int x, int y, int *rowsize) {
bool grerr = false;
2024-04-16 18:56:40 +00:00
ASSERT(m_SurfInit);
switch (ddsfObj.type) {
case SURFTYPE_VIDEOSCREEN:
case SURFTYPE_GENERIC:
grerr = ddgr_surf_Lock(&ddsfObj, (void **)&m_OrigDataPtr, &m_DataRowsize);
break;
case SURFTYPE_MEMORY:
grerr = gr_mem_surf_Lock(&ddsfObj, (void **)&m_OrigDataPtr, &m_DataRowsize);
break;
default:
Int3(); // invalid type!!
}
*rowsize = m_DataRowsize;
if (!grerr)
return nullptr;
2024-04-16 18:56:40 +00:00
/* calculate the adjusted data pointer based off of x,y,bpp */
char *data = m_OrigDataPtr;
data += (y * m_DataRowsize);
switch (ddsfObj.bpp) {
case BPP_16:
data += (x * 2);
break;
case BPP_32:
data += (x * 4);
break;
default:
Int3();
}
m_DataPtr = data;
surf_Locked++; // increment lock counter for this surface
2024-05-24 03:07:26 +00:00
rend_SetSoftwareParameters(ddgr_GetAspectRatio(), ddsfObj.w, ddsfObj.h, m_DataRowsize, (uint8_t *)m_OrigDataPtr);
2024-04-16 18:56:40 +00:00
return m_DataPtr;
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void grSurface::unlock() {
bool grerr;
ASSERT(m_SurfInit);
ASSERT(surf_Locked);
switch (ddsfObj.type) {
case SURFTYPE_VIDEOSCREEN:
case SURFTYPE_GENERIC:
grerr = ddgr_surf_Unlock(&ddsfObj, m_OrigDataPtr);
break;
case SURFTYPE_MEMORY:
grerr = gr_mem_surf_Unlock(&ddsfObj, m_OrigDataPtr);
break;
default:
Int3(); // invalid type!!
}
surf_Locked--;
}
2024-04-16 03:43:29 +00:00
// ---------------------------------------------------------------------------
// miscellaneous
// ---------------------------------------------------------------------------
2024-04-16 18:56:40 +00:00
void grSurface::attach_to_window(unsigned handle) {
ASSERT(m_SurfInit);
ddgr_surf_AttachHandle(&ddsfObj, handle);
2024-04-16 03:43:29 +00:00
}
// Private functions
// conversion_xlat
// ---------------------------------------------------------------------------
2024-04-16 18:56:40 +00:00
void grSurface::xlat8_16(char *data, int w, int h, char *pal) {
/* copy from 8bit source bitmap to destination surface just created and
locked
*/
uint16_t *dptr;
2024-04-16 18:56:40 +00:00
char *sptr;
int row, col;
int rowsize_w;
int height, width;
2024-05-24 03:07:26 +00:00
uint8_t *upal = (uint8_t *)pal;
2024-04-16 18:56:40 +00:00
dptr = (uint16_t *)m_DataPtr;
2024-04-16 18:56:40 +00:00
sptr = (char *)data;
rowsize_w = m_DataRowsize / 2;
2024-05-24 00:53:51 +00:00
height = std::min(h, ddsfObj.h);
width = std::min(w, ddsfObj.w);
2024-04-16 18:56:40 +00:00
for (row = 0; row < height; row++) {
for (col = 0; col < width; col++) {
2024-05-24 03:07:26 +00:00
uint8_t spix = sptr[col];
2024-04-16 18:56:40 +00:00
if (spix != 0) {
int r = upal[spix * 3] >> 3;
int g = upal[spix * 3 + 1] >> 2;
int b = upal[spix * 3 + 2] >> 3;
uint16_t destpix = (r << 11) | (g << 5) | b;
2024-04-16 18:56:40 +00:00
dptr[col] = destpix;
} else
dptr[col] = 0;
}
sptr += 256;
dptr += rowsize_w;
}
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void grSurface::xlat16_16(char *data, int w, int h, int format) {
/* 16-bit copy from source bitmap to destination surface just created and
locked
This function performs scaling if the source width and height don't match
that of the destinations - JL
*/
uint16_t *sptr, *dptr;
2024-04-16 18:56:40 +00:00
int row, col;
int rowsize_w;
int height, width;
fix xstep = IntToFix(w) / ddsfObj.w;
fix ystep = IntToFix(h) / ddsfObj.h;
fix fu = 0, fv = 0;
dptr = (uint16_t *)m_DataPtr;
sptr = (uint16_t *)data;
2024-04-16 18:56:40 +00:00
rowsize_w = m_DataRowsize / 2;
height = ddsfObj.h;
width = ddsfObj.w;
// height = SET_MIN(h, ddsfObj.h);
// width = SET_MIN(w, ddsfObj.w);
for (row = 0; row < height; row++, fv += ystep, fu = 0) {
for (col = 0; col < width; col++, fu += xstep) {
int newpix;
if (format == BITMAP_FORMAT_1555)
newpix = sptr[(FixToInt(fv) * w) + FixToInt(fu)];
else {
int temp_pix = sptr[(FixToInt(fv) * w) + FixToInt(fu)];
int r = (temp_pix >> 8) & 0xf;
int g = (temp_pix >> 4) & 0xf;
2024-04-16 20:59:11 +00:00
int b = (temp_pix) & 0xf;
2024-04-16 18:56:40 +00:00
r <<= 4;
g <<= 4;
b <<= 4;
newpix = OPAQUE_FLAG | GR_RGB16(r, g, b);
}
dptr[col] = newpix;
}
dptr += rowsize_w;
}
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void grSurface::xlat16_24(char *data, int w, int h) {
uint16_t *sptr;
2024-04-16 18:56:40 +00:00
char *dptr;
int scol, dcol, row;
int height, width;
dptr = (char *)m_DataPtr;
sptr = (uint16_t *)data;
2024-05-21 10:27:01 +00:00
height = std::min(h, ddsfObj.h);
width = std::min(w, ddsfObj.w);
2024-04-16 18:56:40 +00:00
for (row = 0; row < height; row++) {
dcol = 0;
for (scol = 0; scol < width; scol++) {
uint16_t pix;
2024-04-16 18:56:40 +00:00
ddgr_color new_color;
char r, g, b;
pix = sptr[scol];
new_color = GR_16_TO_COLOR(pix);
r = GR_COLOR_RED(new_color);
g = GR_COLOR_GREEN(new_color);
b = GR_COLOR_BLUE(new_color);
dptr[dcol++] = r;
dptr[dcol++] = g;
dptr[dcol++] = b;
}
sptr += w;
dptr += m_DataRowsize;
}
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void grSurface::xlat24_16(char *data, int w, int h) {
char *sptr;
uint16_t *dptr;
2024-04-16 18:56:40 +00:00
int scol, dcol, row;
int rowsize_w, height, width;
dptr = (uint16_t *)m_DataPtr;
2024-04-16 18:56:40 +00:00
sptr = (char *)data;
rowsize_w = m_DataRowsize / 2;
2024-05-24 00:53:51 +00:00
height = std::min(h, ddsfObj.h);
width = std::min(w, ddsfObj.w);
2024-04-16 18:56:40 +00:00
for (row = 0; row < height; row++) {
scol = 0;
for (dcol = 0; dcol < width; dcol++) {
uint16_t pix;
2024-04-16 18:56:40 +00:00
char r, g, b;
r = sptr[scol++];
g = sptr[scol++];
b = sptr[scol++];
pix = ((uint16_t)(r >> 3) << 11) + ((uint16_t)(g >> 2) << 5) + ((uint16_t)(b >> 3));
2024-04-16 18:56:40 +00:00
dptr[dcol] = pix;
}
sptr += (w * 3);
dptr += m_DataRowsize;
}
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void grSurface::xlat32_16(char *data, int w, int h) {
unsigned *sptr;
uint16_t *dptr;
2024-04-16 18:56:40 +00:00
int col, row;
int rowsize_w, height, width;
ASSERT((w % 4) == 0);
dptr = (uint16_t *)m_DataPtr;
2024-04-16 18:56:40 +00:00
sptr = (unsigned *)data;
rowsize_w = m_DataRowsize / 2;
2024-05-21 10:27:01 +00:00
height = std::min(h, ddsfObj.h);
width = std::min(w, ddsfObj.w);
2024-04-16 18:56:40 +00:00
for (row = 0; row < height; row++) {
for (col = 0; col < width; col++) {
unsigned pix;
uint16_t spix;
2024-04-16 18:56:40 +00:00
pix = sptr[col];
spix = (uint16_t)(pix & 0x000000f8) >> 3;
spix |= (uint16_t)(pix & 0x0000fc00) >> 5;
spix |= (uint16_t)(pix & 0x00f80000) >> 8;
2024-04-16 18:56:40 +00:00
dptr[col] = spix;
}
sptr += w;
dptr += rowsize_w;
}
2024-04-16 03:43:29 +00:00
}
//-----------------------------------------------------------------------------
// surface list functions
2024-04-16 18:56:40 +00:00
void grSurface::add_to_list(ddgr_surface *sf) {
ddgr_surface_node *node;
ASSERT(sf != nullptr);
2024-04-16 18:56:40 +00:00
if (!grSurface::surf_list_cur) {
// first surface on list
node = new ddgr_surface_node;
node->sf = sf;
node->prev = nullptr;
2024-04-16 18:56:40 +00:00
grSurface::surf_list = grSurface::surf_list_cur = node;
} else {
// next surface on list.
node = new ddgr_surface_node;
node->sf = sf;
node->prev = grSurface::surf_list_cur;
grSurface::surf_list_cur = node;
}
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void grSurface::remove_from_list(ddgr_surface *sf) {
ddgr_surface_node *node, *next_node;
ASSERT(grSurface::surf_list_cur);
ASSERT(sf != nullptr);
2024-04-16 18:56:40 +00:00
// node is current node. next node is node after it on the list. since we are
// going from end to beginning, this may confuse you.
node = grSurface::surf_list_cur;
next_node = nullptr; // grSurface::surf_list_cur should be at end of list, so no next node
2024-04-16 18:56:40 +00:00
while (node) {
if (node->sf == sf) {
if (next_node) { // delete from within list.
next_node->prev = node->prev;
} else { // delete from end of list. set list tail to deleted node prev.
grSurface::surf_list_cur = node->prev;
}
delete node;
node = nullptr; // break out of loop
2024-04-16 18:56:40 +00:00
} else {
// go down one node.
next_node = node;
node = node->prev;
}
}
2024-04-16 03:43:29 +00:00
}