mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-31 04:50:48 +00:00
- moved the span and swtruecolor creation code into FSoftwareTexture.
This commit is contained in:
parent
32e245f2b9
commit
4c67785c40
15 changed files with 608 additions and 630 deletions
|
@ -681,6 +681,7 @@ file( GLOB HEADER_FILES
|
|||
sound/wildmidi/*.h
|
||||
xlat/*.h
|
||||
swrenderer/*.h
|
||||
swrenderer/textures/*.h
|
||||
swrenderer/drawers/*.h
|
||||
swrenderer/scene/*.h
|
||||
swrenderer/segments/*.h
|
||||
|
@ -1244,6 +1245,7 @@ set (PCH_SOURCES
|
|||
sound/wildmidi/reverb.cpp
|
||||
sound/wildmidi/wildmidi_lib.cpp
|
||||
sound/wildmidi/wm_error.cpp
|
||||
swrenderer/textures/r_swtexture.cpp
|
||||
events.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "../swrenderer/textures/r_swtexture.h"
|
||||
#include "poly_renderer.cpp"
|
||||
#include "poly_renderthread.cpp"
|
||||
#include "drawers/poly_buffer.cpp"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "textures/r_swtexture.h"
|
||||
#include "r_memory.cpp"
|
||||
#include "r_renderthread.cpp"
|
||||
#include "r_swrenderer.cpp"
|
||||
|
|
|
@ -84,7 +84,7 @@ void FSoftwareRenderer::PrecacheTexture(FTexture *ttex, int cache)
|
|||
{
|
||||
bool isbgra = V_IsTrueColor();
|
||||
|
||||
if (ttex != NULL)
|
||||
if (ttex != NULL && ttex->isValid())
|
||||
{
|
||||
FSoftwareTexture *tex = ttex->GetSoftwareTexture();
|
||||
if (cache & FTextureManager::HIT_Columnmode)
|
||||
|
|
453
src/swrenderer/textures/r_swtexture.cpp
Normal file
453
src/swrenderer/textures/r_swtexture.cpp
Normal file
|
@ -0,0 +1,453 @@
|
|||
/*
|
||||
** texture.cpp
|
||||
** The base texture class
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2004-2007 Randy Heit
|
||||
** Copyright 2006-2018 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
**
|
||||
*/
|
||||
|
||||
#include "r_swtexture.h"
|
||||
#include "bitmap.h"
|
||||
#include "m_alloc.h"
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const uint32_t *FSoftwareTexture::GetColumnBgra(unsigned int column, const FSoftwareTextureSpan **spans_out)
|
||||
{
|
||||
const uint32_t *pixels = GetPixelsBgra();
|
||||
if (pixels == nullptr) return nullptr;
|
||||
|
||||
column %= GetWidth();
|
||||
|
||||
if (spans_out != nullptr)
|
||||
GetColumn(DefaultRenderStyle(), column, spans_out); // This isn't the right way to create the spans.
|
||||
return pixels + column * GetHeight();
|
||||
}
|
||||
|
||||
const uint32_t *FSoftwareTexture::GetPixelsBgra()
|
||||
{
|
||||
if (PixelsBgra.empty() || mTexture->CheckModified(DefaultRenderStyle()))
|
||||
{
|
||||
if (!GetColumn(DefaultRenderStyle(), 0, nullptr))
|
||||
return nullptr;
|
||||
|
||||
FBitmap bitmap;
|
||||
bitmap.Create(GetWidth(), GetHeight());
|
||||
mTexture->CopyTrueColorPixels(&bitmap, 0, 0);
|
||||
GenerateBgraFromBitmap(bitmap);
|
||||
}
|
||||
return PixelsBgra.data();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FSoftwareTextureSpan **FSoftwareTexture::CreateSpans (const uint8_t *pixels)
|
||||
{
|
||||
FSoftwareTextureSpan **spans, *span;
|
||||
|
||||
if (!mTexture->isMasked())
|
||||
{ // Texture does not have holes, so it can use a simpler span structure
|
||||
spans = (FSoftwareTextureSpan **)M_Malloc (sizeof(FSoftwareTextureSpan*)*GetWidth() + sizeof(FSoftwareTextureSpan)*2);
|
||||
span = (FSoftwareTextureSpan *)&spans[GetWidth()];
|
||||
for (int x = 0; x < GetWidth(); ++x)
|
||||
{
|
||||
spans[x] = span;
|
||||
}
|
||||
span[0].Length = GetHeight();
|
||||
span[0].TopOffset = 0;
|
||||
span[1].Length = 0;
|
||||
span[1].TopOffset = 0;
|
||||
}
|
||||
else
|
||||
{ // Texture might have holes, so build a complete span structure
|
||||
int numcols = GetWidth();
|
||||
int numrows = GetHeight();
|
||||
int numspans = numcols; // One span to terminate each column
|
||||
const uint8_t *data_p;
|
||||
bool newspan;
|
||||
int x, y;
|
||||
|
||||
data_p = pixels;
|
||||
|
||||
// Count the number of spans in this texture
|
||||
for (x = numcols; x > 0; --x)
|
||||
{
|
||||
newspan = true;
|
||||
for (y = numrows; y > 0; --y)
|
||||
{
|
||||
|
||||
if (*data_p++ == 0)
|
||||
{
|
||||
if (!newspan)
|
||||
{
|
||||
newspan = true;
|
||||
}
|
||||
}
|
||||
else if (newspan)
|
||||
{
|
||||
newspan = false;
|
||||
numspans++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate space for the spans
|
||||
spans = (FSoftwareTextureSpan **)M_Malloc (sizeof(FSoftwareTextureSpan*)*numcols + sizeof(FSoftwareTextureSpan)*numspans);
|
||||
|
||||
// Fill in the spans
|
||||
for (x = 0, span = (FSoftwareTextureSpan *)&spans[numcols], data_p = pixels; x < numcols; ++x)
|
||||
{
|
||||
newspan = true;
|
||||
spans[x] = span;
|
||||
for (y = 0; y < numrows; ++y)
|
||||
{
|
||||
if (*data_p++ == 0)
|
||||
{
|
||||
if (!newspan)
|
||||
{
|
||||
newspan = true;
|
||||
span++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newspan)
|
||||
{
|
||||
newspan = false;
|
||||
span->TopOffset = y;
|
||||
span->Length = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
span->Length++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!newspan)
|
||||
{
|
||||
span++;
|
||||
}
|
||||
span->TopOffset = 0;
|
||||
span->Length = 0;
|
||||
span++;
|
||||
}
|
||||
}
|
||||
return spans;
|
||||
}
|
||||
|
||||
void FSoftwareTexture::FreeSpans (FSoftwareTextureSpan **spans)
|
||||
{
|
||||
M_Free (spans);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FSoftwareTexture::GenerateBgraFromBitmap(const FBitmap &bitmap)
|
||||
{
|
||||
CreatePixelsBgraWithMipmaps();
|
||||
|
||||
// Transpose
|
||||
const uint32_t *src = (const uint32_t *)bitmap.GetPixels();
|
||||
uint32_t *dest = PixelsBgra.data();
|
||||
for (int x = 0; x < GetWidth(); x++)
|
||||
{
|
||||
for (int y = 0; y < GetHeight(); y++)
|
||||
{
|
||||
dest[y + x * GetHeight()] = src[x + y * GetWidth()];
|
||||
}
|
||||
}
|
||||
|
||||
GenerateBgraMipmaps();
|
||||
}
|
||||
|
||||
void FSoftwareTexture::CreatePixelsBgraWithMipmaps()
|
||||
{
|
||||
int levels = MipmapLevels();
|
||||
int buffersize = 0;
|
||||
for (int i = 0; i < levels; i++)
|
||||
{
|
||||
int w = MAX(GetWidth() >> i, 1);
|
||||
int h = MAX(GetHeight() >> i, 1);
|
||||
buffersize += w * h;
|
||||
}
|
||||
PixelsBgra.resize(buffersize, 0xffff0000);
|
||||
}
|
||||
|
||||
int FSoftwareTexture::MipmapLevels()
|
||||
{
|
||||
int widthbits = 0;
|
||||
while ((GetWidth() >> widthbits) != 0) widthbits++;
|
||||
|
||||
int heightbits = 0;
|
||||
while ((GetHeight() >> heightbits) != 0) heightbits++;
|
||||
|
||||
return MAX(widthbits, heightbits);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FSoftwareTexture::GenerateBgraMipmaps()
|
||||
{
|
||||
struct Color4f
|
||||
{
|
||||
float a, r, g, b;
|
||||
Color4f operator*(const Color4f &v) const { return Color4f{ a * v.a, r * v.r, g * v.g, b * v.b }; }
|
||||
Color4f operator/(const Color4f &v) const { return Color4f{ a / v.a, r / v.r, g / v.g, b / v.b }; }
|
||||
Color4f operator+(const Color4f &v) const { return Color4f{ a + v.a, r + v.r, g + v.g, b + v.b }; }
|
||||
Color4f operator-(const Color4f &v) const { return Color4f{ a - v.a, r - v.r, g - v.g, b - v.b }; }
|
||||
Color4f operator*(float s) const { return Color4f{ a * s, r * s, g * s, b * s }; }
|
||||
Color4f operator/(float s) const { return Color4f{ a / s, r / s, g / s, b / s }; }
|
||||
Color4f operator+(float s) const { return Color4f{ a + s, r + s, g + s, b + s }; }
|
||||
Color4f operator-(float s) const { return Color4f{ a - s, r - s, g - s, b - s }; }
|
||||
};
|
||||
|
||||
int levels = MipmapLevels();
|
||||
std::vector<Color4f> image(PixelsBgra.size());
|
||||
|
||||
// Convert to normalized linear colorspace
|
||||
{
|
||||
for (int x = 0; x < GetWidth(); x++)
|
||||
{
|
||||
for (int y = 0; y < GetHeight(); y++)
|
||||
{
|
||||
uint32_t c8 = PixelsBgra[x * GetHeight() + y];
|
||||
Color4f c;
|
||||
c.a = powf(APART(c8) * (1.0f / 255.0f), 2.2f);
|
||||
c.r = powf(RPART(c8) * (1.0f / 255.0f), 2.2f);
|
||||
c.g = powf(GPART(c8) * (1.0f / 255.0f), 2.2f);
|
||||
c.b = powf(BPART(c8) * (1.0f / 255.0f), 2.2f);
|
||||
image[x * GetHeight() + y] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate mipmaps
|
||||
{
|
||||
std::vector<Color4f> smoothed(GetWidth() * GetHeight());
|
||||
Color4f *src = image.data();
|
||||
Color4f *dest = src + GetWidth() * GetHeight();
|
||||
for (int i = 1; i < levels; i++)
|
||||
{
|
||||
int srcw = MAX(GetWidth() >> (i - 1), 1);
|
||||
int srch = MAX(GetHeight() >> (i - 1), 1);
|
||||
int w = MAX(GetWidth() >> i, 1);
|
||||
int h = MAX(GetHeight() >> i, 1);
|
||||
|
||||
// Downscale
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
int sx0 = x * 2;
|
||||
int sx1 = MIN((x + 1) * 2, srcw - 1);
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
int sy0 = y * 2;
|
||||
int sy1 = MIN((y + 1) * 2, srch - 1);
|
||||
|
||||
Color4f src00 = src[sy0 + sx0 * srch];
|
||||
Color4f src01 = src[sy1 + sx0 * srch];
|
||||
Color4f src10 = src[sy0 + sx1 * srch];
|
||||
Color4f src11 = src[sy1 + sx1 * srch];
|
||||
Color4f c = (src00 + src01 + src10 + src11) * 0.25f;
|
||||
|
||||
dest[y + x * h] = c;
|
||||
}
|
||||
}
|
||||
|
||||
// Sharpen filter with a 3x3 kernel:
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
Color4f c = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
for (int kx = -1; kx < 2; kx++)
|
||||
{
|
||||
for (int ky = -1; ky < 2; ky++)
|
||||
{
|
||||
int a = y + ky;
|
||||
int b = x + kx;
|
||||
if (a < 0) a = h - 1;
|
||||
if (a == h) a = 0;
|
||||
if (b < 0) b = w - 1;
|
||||
if (b == w) b = 0;
|
||||
c = c + dest[a + b * h];
|
||||
}
|
||||
}
|
||||
c = c * (1.0f / 9.0f);
|
||||
smoothed[y + x * h] = c;
|
||||
}
|
||||
}
|
||||
float k = 0.08f;
|
||||
for (int j = 0; j < w * h; j++)
|
||||
dest[j] = dest[j] + (dest[j] - smoothed[j]) * k;
|
||||
|
||||
src = dest;
|
||||
dest += w * h;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to bgra8 sRGB colorspace
|
||||
{
|
||||
Color4f *src = image.data() + GetWidth() * GetHeight();
|
||||
uint32_t *dest = PixelsBgra.data() + GetWidth() * GetHeight();
|
||||
for (int i = 1; i < levels; i++)
|
||||
{
|
||||
int w = MAX(GetWidth() >> i, 1);
|
||||
int h = MAX(GetHeight() >> i, 1);
|
||||
for (int j = 0; j < w * h; j++)
|
||||
{
|
||||
uint32_t a = (uint32_t)clamp(powf(MAX(src[j].a, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||
uint32_t r = (uint32_t)clamp(powf(MAX(src[j].r, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||
uint32_t g = (uint32_t)clamp(powf(MAX(src[j].g, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||
uint32_t b = (uint32_t)clamp(powf(MAX(src[j].b, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||
dest[j] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
src += w * h;
|
||||
dest += w * h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FSoftwareTexture::GenerateBgraMipmapsFast()
|
||||
{
|
||||
uint32_t *src = PixelsBgra.data();
|
||||
uint32_t *dest = src + GetWidth() * GetHeight();
|
||||
int levels = MipmapLevels();
|
||||
for (int i = 1; i < levels; i++)
|
||||
{
|
||||
int srcw = MAX(GetWidth() >> (i - 1), 1);
|
||||
int srch = MAX(GetHeight() >> (i - 1), 1);
|
||||
int w = MAX(GetWidth() >> i, 1);
|
||||
int h = MAX(GetHeight() >> i, 1);
|
||||
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
int sx0 = x * 2;
|
||||
int sx1 = MIN((x + 1) * 2, srcw - 1);
|
||||
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
int sy0 = y * 2;
|
||||
int sy1 = MIN((y + 1) * 2, srch - 1);
|
||||
|
||||
uint32_t src00 = src[sy0 + sx0 * srch];
|
||||
uint32_t src01 = src[sy1 + sx0 * srch];
|
||||
uint32_t src10 = src[sy0 + sx1 * srch];
|
||||
uint32_t src11 = src[sy1 + sx1 * srch];
|
||||
|
||||
uint32_t alpha = (APART(src00) + APART(src01) + APART(src10) + APART(src11) + 2) / 4;
|
||||
uint32_t red = (RPART(src00) + RPART(src01) + RPART(src10) + RPART(src11) + 2) / 4;
|
||||
uint32_t green = (GPART(src00) + GPART(src01) + GPART(src10) + GPART(src11) + 2) / 4;
|
||||
uint32_t blue = (BPART(src00) + BPART(src01) + BPART(src10) + BPART(src11) + 2) / 4;
|
||||
|
||||
dest[y + x * h] = (alpha << 24) | (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
}
|
||||
|
||||
src = dest;
|
||||
dest += w * h;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const uint8_t *FSoftwareTexture::GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out)
|
||||
{
|
||||
int index = !!(style.Flags & STYLEF_RedIsAlpha);
|
||||
auto Pixeldata = GetPixels(style);
|
||||
if ((unsigned)column >= (unsigned)GetWidth())
|
||||
{
|
||||
if (mTexture->WidthMask + 1 == GetWidth())
|
||||
{
|
||||
column &= mTexture->WidthMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
column %= GetWidth();
|
||||
}
|
||||
}
|
||||
if (spans_out != nullptr)
|
||||
{
|
||||
if (Spandata[index] == nullptr)
|
||||
{
|
||||
Spandata[index] = CreateSpans (Pixeldata);
|
||||
}
|
||||
*spans_out = Spandata[index][column];
|
||||
}
|
||||
return Pixeldata + column*GetHeight();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FSoftwareTexture::FreeAllSpans()
|
||||
{
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
if (Spandata[i] != nullptr)
|
||||
{
|
||||
FreeSpans (Spandata[i]);
|
||||
Spandata[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
129
src/swrenderer/textures/r_swtexture.h
Normal file
129
src/swrenderer/textures/r_swtexture.h
Normal file
|
@ -0,0 +1,129 @@
|
|||
#pragma once
|
||||
#include "textures/textures.h"
|
||||
|
||||
|
||||
struct FSoftwareTextureSpan
|
||||
{
|
||||
uint16_t TopOffset;
|
||||
uint16_t Length; // A length of 0 terminates this column
|
||||
};
|
||||
|
||||
|
||||
// For now this is just a minimal wrapper around FTexture. Once the software renderer no longer accesses FTexture directly, it is time for cleaning up.
|
||||
class FSoftwareTexture
|
||||
{
|
||||
FTexture *mTexture;
|
||||
FTexture *mSource;
|
||||
std::vector<uint32_t> PixelsBgra;
|
||||
FSoftwareTextureSpan **Spandata[2] = { nullptr, nullptr };
|
||||
|
||||
|
||||
public:
|
||||
FSoftwareTexture(FTexture *tex)
|
||||
{
|
||||
mTexture = tex;
|
||||
mSource = tex;
|
||||
}
|
||||
|
||||
virtual ~FSoftwareTexture()
|
||||
{
|
||||
FreeAllSpans();
|
||||
}
|
||||
|
||||
FTexture *GetTexture() const
|
||||
{
|
||||
return mTexture;
|
||||
}
|
||||
|
||||
// The feature from hell... :(
|
||||
bool useWorldPanning() const
|
||||
{
|
||||
return mTexture->bWorldPanning;
|
||||
}
|
||||
|
||||
bool isMasked()
|
||||
{
|
||||
return mTexture->bMasked;
|
||||
}
|
||||
|
||||
bool UseBasePalette() const { return mTexture->UseBasePalette(); }
|
||||
int GetSkyOffset() const { return mTexture->GetSkyOffset(); }
|
||||
PalEntry GetSkyCapColor(bool bottom) const { return mTexture->GetSkyCapColor(bottom); }
|
||||
|
||||
int GetWidth () { return mTexture->GetWidth(); }
|
||||
int GetHeight () { return mTexture->GetHeight(); }
|
||||
int GetWidthBits() { return mTexture->WidthBits; }
|
||||
int GetHeightBits() { return mTexture->HeightBits; }
|
||||
bool Mipmapped() { return mTexture->Mipmapped(); }
|
||||
|
||||
int GetScaledWidth () { return mTexture->GetScaledWidth(); }
|
||||
int GetScaledHeight () { return mTexture->GetScaledHeight(); }
|
||||
double GetScaledWidthDouble () { return mTexture->GetScaledWidthDouble(); }
|
||||
double GetScaledHeightDouble () { return mTexture->GetScaledHeightDouble(); }
|
||||
double GetScaleY() const { return mTexture->GetScaleY(); }
|
||||
|
||||
// Now with improved offset adjustment.
|
||||
int GetLeftOffset(int adjusted) { return mTexture->GetLeftOffset(adjusted); }
|
||||
int GetTopOffset(int adjusted) { return mTexture->GetTopOffset(adjusted); }
|
||||
int GetScaledLeftOffset (int adjusted) { return mTexture->GetScaledLeftOffset(adjusted); }
|
||||
int GetScaledTopOffset (int adjusted) { return mTexture->GetScaledTopOffset(adjusted); }
|
||||
double GetScaledLeftOffsetDouble(int adjusted) { return mTexture->GetScaledLeftOffsetDouble(adjusted); }
|
||||
double GetScaledTopOffsetDouble(int adjusted) { return mTexture->GetScaledTopOffsetDouble(adjusted); }
|
||||
|
||||
// Interfaces for the different renderers. Everything that needs to check renderer-dependent offsets
|
||||
// should use these, so that if changes are needed, this is the only place to edit.
|
||||
|
||||
// For the original software renderer
|
||||
int GetLeftOffsetSW() { return GetLeftOffset(r_spriteadjustSW); }
|
||||
int GetTopOffsetSW() { return GetTopOffset(r_spriteadjustSW); }
|
||||
int GetScaledLeftOffsetSW() { return GetScaledLeftOffset(r_spriteadjustSW); }
|
||||
int GetScaledTopOffsetSW() { return GetScaledTopOffset(r_spriteadjustSW); }
|
||||
|
||||
// For the softpoly renderer, in case it wants adjustment
|
||||
int GetLeftOffsetPo() { return GetLeftOffset(r_spriteadjustSW); }
|
||||
int GetTopOffsetPo() { return GetTopOffset(r_spriteadjustSW); }
|
||||
int GetScaledLeftOffsetPo() { return GetScaledLeftOffset(r_spriteadjustSW); }
|
||||
int GetScaledTopOffsetPo() { return GetScaledTopOffset(r_spriteadjustSW); }
|
||||
|
||||
DVector2 GetScale() const { return mTexture->Scale; }
|
||||
|
||||
// Returns the whole texture, stored in column-major order
|
||||
const uint8_t *GetPixels(FRenderStyle style)
|
||||
{
|
||||
return mTexture->GetPixels(style);
|
||||
}
|
||||
|
||||
void Unload()
|
||||
{
|
||||
mTexture->Unload();
|
||||
PixelsBgra = std::vector<uint32_t>();
|
||||
}
|
||||
|
||||
void GenerateBgraFromBitmap(const FBitmap &bitmap);
|
||||
void CreatePixelsBgraWithMipmaps();
|
||||
void GenerateBgraMipmaps();
|
||||
void GenerateBgraMipmapsFast();
|
||||
int MipmapLevels();
|
||||
void FreeAllSpans();
|
||||
|
||||
FSoftwareTextureSpan **CreateSpans (const uint8_t *pixels);
|
||||
void FreeSpans (FSoftwareTextureSpan **spans);
|
||||
|
||||
// Returns a single column of the texture
|
||||
virtual const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out);
|
||||
|
||||
// Returns a single column of the texture, in BGRA8 format
|
||||
virtual const uint32_t *GetColumnBgra(unsigned int column, const FSoftwareTextureSpan **spans_out);
|
||||
|
||||
// Returns the whole texture, stored in column-major order, in BGRA8 format
|
||||
virtual const uint32_t *GetPixelsBgra();
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline FSoftwareTexture *FTexture::GetSoftwareTexture()
|
||||
{
|
||||
if (!SoftwareTexture) SoftwareTexture = new FSoftwareTexture(this);
|
||||
return SoftwareTexture;
|
||||
}
|
|
@ -44,10 +44,12 @@ FCanvasTexture::FCanvasTexture (const char *name, int width, int height)
|
|||
CalcBitSize ();
|
||||
|
||||
bMasked = false;
|
||||
/*
|
||||
DummySpans[0].TopOffset = 0;
|
||||
DummySpans[0].Length = height;
|
||||
DummySpans[1].TopOffset = 0;
|
||||
DummySpans[1].Length = 0;
|
||||
*/
|
||||
UseType = ETextureType::Wall;
|
||||
bNeedsUpdate = true;
|
||||
bDidUpdate = false;
|
||||
|
@ -61,6 +63,7 @@ FCanvasTexture::~FCanvasTexture ()
|
|||
Unload ();
|
||||
}
|
||||
|
||||
#if 0
|
||||
const uint8_t *FCanvasTexture::GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out)
|
||||
{
|
||||
bNeedsUpdate = true;
|
||||
|
@ -85,6 +88,7 @@ const uint8_t *FCanvasTexture::GetColumn(FRenderStyle style, unsigned int column
|
|||
}
|
||||
return Pixels + column*Height;
|
||||
}
|
||||
#endif
|
||||
|
||||
const uint8_t *FCanvasTexture::GetPixels (FRenderStyle style)
|
||||
{
|
||||
|
@ -96,6 +100,7 @@ const uint8_t *FCanvasTexture::GetPixels (FRenderStyle style)
|
|||
return Pixels;
|
||||
}
|
||||
|
||||
#if 0
|
||||
const uint32_t *FCanvasTexture::GetPixelsBgra()
|
||||
{
|
||||
bNeedsUpdate = true;
|
||||
|
@ -105,6 +110,7 @@ const uint32_t *FCanvasTexture::GetPixelsBgra()
|
|||
}
|
||||
return PixelsBgra;
|
||||
}
|
||||
#endif
|
||||
|
||||
void FCanvasTexture::MakeTexture (FRenderStyle) // This ignores the render style because making it work as alpha texture is impractical.
|
||||
{
|
||||
|
|
|
@ -164,7 +164,7 @@ public:
|
|||
|
||||
protected:
|
||||
uint8_t *Pixels;
|
||||
FSoftwareTextureSpan **Spans;
|
||||
//FSoftwareTextureSpan **Spans;
|
||||
int DefinitionLump;
|
||||
|
||||
struct TexPart
|
||||
|
@ -199,8 +199,6 @@ protected:
|
|||
|
||||
// The getters must optionally redirect if it's a simple one-patch texture.
|
||||
const uint8_t *GetPixels(FRenderStyle style) override { return bRedirect ? Parts->Texture->GetPixels(style) : FWorldTexture::GetPixels(style); }
|
||||
const uint8_t *GetColumn(FRenderStyle style, unsigned int col, const FSoftwareTextureSpan **out) override
|
||||
{ return bRedirect ? Parts->Texture->GetColumn(style, col, out) : FWorldTexture::GetColumn(style, col, out); }
|
||||
|
||||
|
||||
private:
|
||||
|
@ -215,7 +213,7 @@ private:
|
|||
//==========================================================================
|
||||
|
||||
FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflumpnum)
|
||||
: Pixels (0), Spans(0), Parts(nullptr), Inits(nullptr), bRedirect(false), bTranslucentPatches(false)
|
||||
: Pixels (0), Parts(nullptr), Inits(nullptr), bRedirect(false), bTranslucentPatches(false)
|
||||
{
|
||||
union
|
||||
{
|
||||
|
@ -1065,7 +1063,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, TexInit &init)
|
|||
//==========================================================================
|
||||
|
||||
FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, ETextureType usetype)
|
||||
: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false)
|
||||
: Pixels (0), Parts(0), bRedirect(false), bTranslucentPatches(false)
|
||||
{
|
||||
TArray<TexPart> parts;
|
||||
TArray<TexInit> inits;
|
||||
|
|
|
@ -59,7 +59,7 @@ void FWarpTexture::Unload ()
|
|||
{
|
||||
SourcePic->Unload ();
|
||||
FWorldTexture::Unload();
|
||||
FreeAllSpans();
|
||||
//FreeAllSpans();
|
||||
}
|
||||
|
||||
bool FWarpTexture::CheckModified (FRenderStyle style)
|
||||
|
@ -67,6 +67,7 @@ bool FWarpTexture::CheckModified (FRenderStyle style)
|
|||
return screen->FrameTime != GenTime[!!(style.Flags & STYLEF_RedIsAlpha)];
|
||||
}
|
||||
|
||||
/*
|
||||
const uint32_t *FWarpTexture::GetPixelsBgra()
|
||||
{
|
||||
auto Pixels = GetPixels(DefaultRenderStyle());
|
||||
|
@ -85,6 +86,7 @@ const uint32_t *FWarpTexture::GetPixelsBgra()
|
|||
}
|
||||
return PixelsBgra.data();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
uint8_t *FWarpTexture::MakeTexture(FRenderStyle style)
|
||||
|
@ -93,7 +95,7 @@ uint8_t *FWarpTexture::MakeTexture(FRenderStyle style)
|
|||
const uint8_t *otherpix = SourcePic->GetPixels(style);
|
||||
auto Pixels = new uint8_t[Width * Height];
|
||||
WarpBuffer(Pixels, otherpix, Width, Height, WidthOffsetMultiplier, HeightOffsetMultiplier, time, Speed, bWarped);
|
||||
FreeAllSpans();
|
||||
//FreeAllSpans();
|
||||
GenTime[!!(style.Flags & STYLEF_RedIsAlpha)] = time;
|
||||
return Pixels;
|
||||
}
|
||||
|
|
|
@ -56,25 +56,6 @@ FWorldTexture::FWorldTexture(const char *name, int lumpnum)
|
|||
FWorldTexture::~FWorldTexture()
|
||||
{
|
||||
Unload();
|
||||
FreeAllSpans();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FWorldTexture::FreeAllSpans()
|
||||
{
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
if (Spandata[i] != nullptr)
|
||||
{
|
||||
FreeSpans (Spandata[i]);
|
||||
Spandata[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -102,38 +83,6 @@ void FWorldTexture::Unload ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
const uint8_t *FWorldTexture::GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out)
|
||||
{
|
||||
int index = !!(style.Flags & STYLEF_RedIsAlpha);
|
||||
GetPixels(style);
|
||||
if ((unsigned)column >= (unsigned)Width)
|
||||
{
|
||||
if (WidthMask + 1 == Width)
|
||||
{
|
||||
column &= WidthMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
column %= Width;
|
||||
}
|
||||
}
|
||||
if (spans_out != nullptr)
|
||||
{
|
||||
if (Spandata[index] == nullptr)
|
||||
{
|
||||
Spandata[index] = CreateSpans (Pixeldata[index]);
|
||||
}
|
||||
*spans_out = Spandata[index][column];
|
||||
}
|
||||
return Pixeldata[index] + column*Height;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const uint8_t *FWorldTexture::GetPixels (FRenderStyle style)
|
||||
{
|
||||
if (CheckModified(style))
|
||||
|
|
|
@ -53,18 +53,6 @@ FSkyBox::~FSkyBox()
|
|||
// The faces are only referenced but not owned so don't delete them.
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// If something attempts to use this as a texture just pass the information of the first face.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const uint8_t *FSkyBox::GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out)
|
||||
{
|
||||
if (faces[0]) return faces[0]->GetColumn(style, column, spans_out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
|
|
|
@ -17,7 +17,7 @@ public:
|
|||
|
||||
FSkyBox(const char *name = nullptr);
|
||||
~FSkyBox();
|
||||
const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out);
|
||||
//const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out);
|
||||
const uint8_t *GetPixels (FRenderStyle style);
|
||||
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf);
|
||||
bool UseBasePalette();
|
||||
|
|
|
@ -231,40 +231,6 @@ FTexture::~FTexture ()
|
|||
|
||||
void FTexture::Unload()
|
||||
{
|
||||
PixelsBgra = std::vector<uint32_t>();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const uint32_t *FTexture::GetColumnBgra(unsigned int column, const FSoftwareTextureSpan **spans_out)
|
||||
{
|
||||
const uint32_t *pixels = GetPixelsBgra();
|
||||
if (pixels == nullptr) return nullptr;
|
||||
|
||||
column %= Width;
|
||||
|
||||
if (spans_out != nullptr)
|
||||
GetColumn(DefaultRenderStyle(), column, spans_out); // This isn't the right way to create the spans.
|
||||
return pixels + column * Height;
|
||||
}
|
||||
|
||||
const uint32_t *FTexture::GetPixelsBgra()
|
||||
{
|
||||
if (PixelsBgra.empty() || CheckModified(DefaultRenderStyle()))
|
||||
{
|
||||
if (!GetColumn(DefaultRenderStyle(), 0, nullptr))
|
||||
return nullptr;
|
||||
|
||||
FBitmap bitmap;
|
||||
bitmap.Create(GetWidth(), GetHeight());
|
||||
CopyTrueColorPixels(&bitmap, 0, 0);
|
||||
GenerateBgraFromBitmap(bitmap);
|
||||
}
|
||||
return PixelsBgra.data();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -327,333 +293,6 @@ void FTexture::CalcBitSize ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FSoftwareTextureSpan **FTexture::CreateSpans (const uint8_t *pixels) const
|
||||
{
|
||||
FSoftwareTextureSpan **spans, *span;
|
||||
|
||||
if (!bMasked)
|
||||
{ // Texture does not have holes, so it can use a simpler span structure
|
||||
spans = (FSoftwareTextureSpan **)M_Malloc (sizeof(FSoftwareTextureSpan*)*Width + sizeof(FSoftwareTextureSpan)*2);
|
||||
span = (FSoftwareTextureSpan *)&spans[Width];
|
||||
for (int x = 0; x < Width; ++x)
|
||||
{
|
||||
spans[x] = span;
|
||||
}
|
||||
span[0].Length = Height;
|
||||
span[0].TopOffset = 0;
|
||||
span[1].Length = 0;
|
||||
span[1].TopOffset = 0;
|
||||
}
|
||||
else
|
||||
{ // Texture might have holes, so build a complete span structure
|
||||
int numcols = Width;
|
||||
int numrows = Height;
|
||||
int numspans = numcols; // One span to terminate each column
|
||||
const uint8_t *data_p;
|
||||
bool newspan;
|
||||
int x, y;
|
||||
|
||||
data_p = pixels;
|
||||
|
||||
// Count the number of spans in this texture
|
||||
for (x = numcols; x > 0; --x)
|
||||
{
|
||||
newspan = true;
|
||||
for (y = numrows; y > 0; --y)
|
||||
{
|
||||
|
||||
if (*data_p++ == 0)
|
||||
{
|
||||
if (!newspan)
|
||||
{
|
||||
newspan = true;
|
||||
}
|
||||
}
|
||||
else if (newspan)
|
||||
{
|
||||
newspan = false;
|
||||
numspans++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate space for the spans
|
||||
spans = (FSoftwareTextureSpan **)M_Malloc (sizeof(FSoftwareTextureSpan*)*numcols + sizeof(FSoftwareTextureSpan)*numspans);
|
||||
|
||||
// Fill in the spans
|
||||
for (x = 0, span = (FSoftwareTextureSpan *)&spans[numcols], data_p = pixels; x < numcols; ++x)
|
||||
{
|
||||
newspan = true;
|
||||
spans[x] = span;
|
||||
for (y = 0; y < numrows; ++y)
|
||||
{
|
||||
if (*data_p++ == 0)
|
||||
{
|
||||
if (!newspan)
|
||||
{
|
||||
newspan = true;
|
||||
span++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newspan)
|
||||
{
|
||||
newspan = false;
|
||||
span->TopOffset = y;
|
||||
span->Length = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
span->Length++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!newspan)
|
||||
{
|
||||
span++;
|
||||
}
|
||||
span->TopOffset = 0;
|
||||
span->Length = 0;
|
||||
span++;
|
||||
}
|
||||
}
|
||||
return spans;
|
||||
}
|
||||
|
||||
void FTexture::FreeSpans (FSoftwareTextureSpan **spans) const
|
||||
{
|
||||
M_Free (spans);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FTexture::GenerateBgraFromBitmap(const FBitmap &bitmap)
|
||||
{
|
||||
CreatePixelsBgraWithMipmaps();
|
||||
|
||||
// Transpose
|
||||
const uint32_t *src = (const uint32_t *)bitmap.GetPixels();
|
||||
uint32_t *dest = PixelsBgra.data();
|
||||
for (int x = 0; x < Width; x++)
|
||||
{
|
||||
for (int y = 0; y < Height; y++)
|
||||
{
|
||||
dest[y + x * Height] = src[x + y * Width];
|
||||
}
|
||||
}
|
||||
|
||||
GenerateBgraMipmaps();
|
||||
}
|
||||
|
||||
void FTexture::CreatePixelsBgraWithMipmaps()
|
||||
{
|
||||
int levels = MipmapLevels();
|
||||
int buffersize = 0;
|
||||
for (int i = 0; i < levels; i++)
|
||||
{
|
||||
int w = MAX(Width >> i, 1);
|
||||
int h = MAX(Height >> i, 1);
|
||||
buffersize += w * h;
|
||||
}
|
||||
PixelsBgra.resize(buffersize, 0xffff0000);
|
||||
}
|
||||
|
||||
int FTexture::MipmapLevels() const
|
||||
{
|
||||
int widthbits = 0;
|
||||
while ((Width >> widthbits) != 0) widthbits++;
|
||||
|
||||
int heightbits = 0;
|
||||
while ((Height >> heightbits) != 0) heightbits++;
|
||||
|
||||
return MAX(widthbits, heightbits);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FTexture::GenerateBgraMipmaps()
|
||||
{
|
||||
struct Color4f
|
||||
{
|
||||
float a, r, g, b;
|
||||
Color4f operator*(const Color4f &v) const { return Color4f{ a * v.a, r * v.r, g * v.g, b * v.b }; }
|
||||
Color4f operator/(const Color4f &v) const { return Color4f{ a / v.a, r / v.r, g / v.g, b / v.b }; }
|
||||
Color4f operator+(const Color4f &v) const { return Color4f{ a + v.a, r + v.r, g + v.g, b + v.b }; }
|
||||
Color4f operator-(const Color4f &v) const { return Color4f{ a - v.a, r - v.r, g - v.g, b - v.b }; }
|
||||
Color4f operator*(float s) const { return Color4f{ a * s, r * s, g * s, b * s }; }
|
||||
Color4f operator/(float s) const { return Color4f{ a / s, r / s, g / s, b / s }; }
|
||||
Color4f operator+(float s) const { return Color4f{ a + s, r + s, g + s, b + s }; }
|
||||
Color4f operator-(float s) const { return Color4f{ a - s, r - s, g - s, b - s }; }
|
||||
};
|
||||
|
||||
int levels = MipmapLevels();
|
||||
std::vector<Color4f> image(PixelsBgra.size());
|
||||
|
||||
// Convert to normalized linear colorspace
|
||||
{
|
||||
for (int x = 0; x < Width; x++)
|
||||
{
|
||||
for (int y = 0; y < Height; y++)
|
||||
{
|
||||
uint32_t c8 = PixelsBgra[x * Height + y];
|
||||
Color4f c;
|
||||
c.a = powf(APART(c8) * (1.0f / 255.0f), 2.2f);
|
||||
c.r = powf(RPART(c8) * (1.0f / 255.0f), 2.2f);
|
||||
c.g = powf(GPART(c8) * (1.0f / 255.0f), 2.2f);
|
||||
c.b = powf(BPART(c8) * (1.0f / 255.0f), 2.2f);
|
||||
image[x * Height + y] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate mipmaps
|
||||
{
|
||||
std::vector<Color4f> smoothed(Width * Height);
|
||||
Color4f *src = image.data();
|
||||
Color4f *dest = src + Width * Height;
|
||||
for (int i = 1; i < levels; i++)
|
||||
{
|
||||
int srcw = MAX(Width >> (i - 1), 1);
|
||||
int srch = MAX(Height >> (i - 1), 1);
|
||||
int w = MAX(Width >> i, 1);
|
||||
int h = MAX(Height >> i, 1);
|
||||
|
||||
// Downscale
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
int sx0 = x * 2;
|
||||
int sx1 = MIN((x + 1) * 2, srcw - 1);
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
int sy0 = y * 2;
|
||||
int sy1 = MIN((y + 1) * 2, srch - 1);
|
||||
|
||||
Color4f src00 = src[sy0 + sx0 * srch];
|
||||
Color4f src01 = src[sy1 + sx0 * srch];
|
||||
Color4f src10 = src[sy0 + sx1 * srch];
|
||||
Color4f src11 = src[sy1 + sx1 * srch];
|
||||
Color4f c = (src00 + src01 + src10 + src11) * 0.25f;
|
||||
|
||||
dest[y + x * h] = c;
|
||||
}
|
||||
}
|
||||
|
||||
// Sharpen filter with a 3x3 kernel:
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
Color4f c = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
for (int kx = -1; kx < 2; kx++)
|
||||
{
|
||||
for (int ky = -1; ky < 2; ky++)
|
||||
{
|
||||
int a = y + ky;
|
||||
int b = x + kx;
|
||||
if (a < 0) a = h - 1;
|
||||
if (a == h) a = 0;
|
||||
if (b < 0) b = w - 1;
|
||||
if (b == w) b = 0;
|
||||
c = c + dest[a + b * h];
|
||||
}
|
||||
}
|
||||
c = c * (1.0f / 9.0f);
|
||||
smoothed[y + x * h] = c;
|
||||
}
|
||||
}
|
||||
float k = 0.08f;
|
||||
for (int j = 0; j < w * h; j++)
|
||||
dest[j] = dest[j] + (dest[j] - smoothed[j]) * k;
|
||||
|
||||
src = dest;
|
||||
dest += w * h;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to bgra8 sRGB colorspace
|
||||
{
|
||||
Color4f *src = image.data() + Width * Height;
|
||||
uint32_t *dest = PixelsBgra.data() + Width * Height;
|
||||
for (int i = 1; i < levels; i++)
|
||||
{
|
||||
int w = MAX(Width >> i, 1);
|
||||
int h = MAX(Height >> i, 1);
|
||||
for (int j = 0; j < w * h; j++)
|
||||
{
|
||||
uint32_t a = (uint32_t)clamp(powf(MAX(src[j].a, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||
uint32_t r = (uint32_t)clamp(powf(MAX(src[j].r, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||
uint32_t g = (uint32_t)clamp(powf(MAX(src[j].g, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||
uint32_t b = (uint32_t)clamp(powf(MAX(src[j].b, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||
dest[j] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
src += w * h;
|
||||
dest += w * h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FTexture::GenerateBgraMipmapsFast()
|
||||
{
|
||||
uint32_t *src = PixelsBgra.data();
|
||||
uint32_t *dest = src + Width * Height;
|
||||
int levels = MipmapLevels();
|
||||
for (int i = 1; i < levels; i++)
|
||||
{
|
||||
int srcw = MAX(Width >> (i - 1), 1);
|
||||
int srch = MAX(Height >> (i - 1), 1);
|
||||
int w = MAX(Width >> i, 1);
|
||||
int h = MAX(Height >> i, 1);
|
||||
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
int sx0 = x * 2;
|
||||
int sx1 = MIN((x + 1) * 2, srcw - 1);
|
||||
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
int sy0 = y * 2;
|
||||
int sy1 = MIN((y + 1) * 2, srch - 1);
|
||||
|
||||
uint32_t src00 = src[sy0 + sx0 * srch];
|
||||
uint32_t src01 = src[sy1 + sx0 * srch];
|
||||
uint32_t src10 = src[sy0 + sx1 * srch];
|
||||
uint32_t src11 = src[sy1 + sx1 * srch];
|
||||
|
||||
uint32_t alpha = (APART(src00) + APART(src01) + APART(src10) + APART(src11) + 2) / 4;
|
||||
uint32_t red = (RPART(src00) + RPART(src01) + RPART(src10) + RPART(src11) + 2) / 4;
|
||||
uint32_t green = (GPART(src00) + GPART(src01) + GPART(src10) + GPART(src11) + 2) / 4;
|
||||
uint32_t blue = (BPART(src00) + BPART(src01) + BPART(src10) + BPART(src11) + 2) / 4;
|
||||
|
||||
dest[y + x * h] = (alpha << 24) | (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
}
|
||||
|
||||
src = dest;
|
||||
dest += w * h;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FTexture::CopyToBlock (uint8_t *dest, int dwidth, int dheight, int xpos, int ypos, int rotate, const uint8_t *translation, FRenderStyle style)
|
||||
{
|
||||
const uint8_t *pixels = GetPixels(style);
|
||||
|
@ -1454,11 +1093,6 @@ void FTexture::SetSpriteAdjust()
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
const uint8_t *FTexture::GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const uint8_t *FTexture::GetPixels(FRenderStyle style)
|
||||
{
|
||||
return nullptr;
|
||||
|
|
|
@ -214,12 +214,6 @@ enum FTextureFormat : uint32_t
|
|||
class FSoftwareTexture;
|
||||
class FGLRenderState;
|
||||
|
||||
struct FSoftwareTextureSpan
|
||||
{
|
||||
uint16_t TopOffset;
|
||||
uint16_t Length; // A length of 0 terminates this column
|
||||
};
|
||||
|
||||
struct spriteframewithrotate;
|
||||
class FSerializer;
|
||||
namespace OpenGLRenderer
|
||||
|
@ -388,19 +382,9 @@ protected:
|
|||
int shaderindex = 0;
|
||||
|
||||
|
||||
|
||||
// Returns a single column of the texture
|
||||
virtual const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out);
|
||||
|
||||
// Returns a single column of the texture, in BGRA8 format
|
||||
virtual const uint32_t *GetColumnBgra(unsigned int column, const FSoftwareTextureSpan **spans_out);
|
||||
|
||||
// Returns the whole texture, stored in column-major order
|
||||
virtual const uint8_t *GetPixels(FRenderStyle style);
|
||||
|
||||
// Returns the whole texture, stored in column-major order, in BGRA8 format
|
||||
virtual const uint32_t *GetPixelsBgra();
|
||||
|
||||
// Returns true if GetPixelsBgra includes mipmaps
|
||||
virtual bool Mipmapped() { return true; }
|
||||
|
||||
|
@ -535,8 +519,6 @@ protected:
|
|||
|
||||
FTexture (const char *name = NULL, int lumpnum = -1);
|
||||
|
||||
FSoftwareTextureSpan **CreateSpans (const uint8_t *pixels) const;
|
||||
void FreeSpans (FSoftwareTextureSpan **spans) const;
|
||||
void CalcBitSize ();
|
||||
void CopyInfo(FTexture *other)
|
||||
{
|
||||
|
@ -545,13 +527,6 @@ protected:
|
|||
Rotations = other->Rotations;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> PixelsBgra;
|
||||
|
||||
void GenerateBgraFromBitmap(const FBitmap &bitmap);
|
||||
void CreatePixelsBgraWithMipmaps();
|
||||
void GenerateBgraMipmaps();
|
||||
void GenerateBgraMipmapsFast();
|
||||
int MipmapLevels() const;
|
||||
|
||||
|
||||
public:
|
||||
|
@ -577,112 +552,6 @@ public:
|
|||
friend class FTextureManager;
|
||||
};
|
||||
|
||||
// For now this is just a minimal wrapper around FTexture. Once the software renderer no longer accesses FTexture directly, it is time for cleaning up.
|
||||
class FSoftwareTexture
|
||||
{
|
||||
FTexture *mTexture;
|
||||
|
||||
|
||||
public:
|
||||
FSoftwareTexture(FTexture *tex)
|
||||
{
|
||||
mTexture = tex;
|
||||
}
|
||||
|
||||
FTexture *GetTexture() const
|
||||
{
|
||||
return mTexture;
|
||||
}
|
||||
|
||||
// The feature from hell... :(
|
||||
bool useWorldPanning() const
|
||||
{
|
||||
return mTexture->bWorldPanning;
|
||||
}
|
||||
|
||||
bool isMasked()
|
||||
{
|
||||
return mTexture->bMasked;
|
||||
}
|
||||
|
||||
bool UseBasePalette() const { return mTexture->UseBasePalette(); }
|
||||
int GetSkyOffset() const { return mTexture->GetSkyOffset(); }
|
||||
PalEntry GetSkyCapColor(bool bottom) const { return mTexture->GetSkyCapColor(bottom); }
|
||||
|
||||
int GetWidth () { return mTexture->GetWidth(); }
|
||||
int GetHeight () { return mTexture->GetHeight(); }
|
||||
int GetWidthBits() { return mTexture->WidthBits; }
|
||||
int GetHeightBits() { return mTexture->HeightBits; }
|
||||
bool Mipmapped() { return mTexture->Mipmapped(); }
|
||||
|
||||
int GetScaledWidth () { return mTexture->GetScaledWidth(); }
|
||||
int GetScaledHeight () { return mTexture->GetScaledHeight(); }
|
||||
double GetScaledWidthDouble () { return mTexture->GetScaledWidthDouble(); }
|
||||
double GetScaledHeightDouble () { return mTexture->GetScaledHeightDouble(); }
|
||||
double GetScaleY() const { return mTexture->GetScaleY(); }
|
||||
|
||||
// Now with improved offset adjustment.
|
||||
int GetLeftOffset(int adjusted) { return mTexture->GetLeftOffset(adjusted); }
|
||||
int GetTopOffset(int adjusted) { return mTexture->GetTopOffset(adjusted); }
|
||||
int GetScaledLeftOffset (int adjusted) { return mTexture->GetScaledLeftOffset(adjusted); }
|
||||
int GetScaledTopOffset (int adjusted) { return mTexture->GetScaledTopOffset(adjusted); }
|
||||
double GetScaledLeftOffsetDouble(int adjusted) { return mTexture->GetScaledLeftOffsetDouble(adjusted); }
|
||||
double GetScaledTopOffsetDouble(int adjusted) { return mTexture->GetScaledTopOffsetDouble(adjusted); }
|
||||
|
||||
// Interfaces for the different renderers. Everything that needs to check renderer-dependent offsets
|
||||
// should use these, so that if changes are needed, this is the only place to edit.
|
||||
|
||||
// For the original software renderer
|
||||
int GetLeftOffsetSW() { return GetLeftOffset(r_spriteadjustSW); }
|
||||
int GetTopOffsetSW() { return GetTopOffset(r_spriteadjustSW); }
|
||||
int GetScaledLeftOffsetSW() { return GetScaledLeftOffset(r_spriteadjustSW); }
|
||||
int GetScaledTopOffsetSW() { return GetScaledTopOffset(r_spriteadjustSW); }
|
||||
|
||||
// For the softpoly renderer, in case it wants adjustment
|
||||
int GetLeftOffsetPo() { return GetLeftOffset(r_spriteadjustSW); }
|
||||
int GetTopOffsetPo() { return GetTopOffset(r_spriteadjustSW); }
|
||||
int GetScaledLeftOffsetPo() { return GetScaledLeftOffset(r_spriteadjustSW); }
|
||||
int GetScaledTopOffsetPo() { return GetScaledTopOffset(r_spriteadjustSW); }
|
||||
|
||||
DVector2 GetScale() const { return mTexture->Scale; }
|
||||
|
||||
// Returns a single column of the texture
|
||||
const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out)
|
||||
{
|
||||
return mTexture->GetColumn(style, column, spans_out);
|
||||
}
|
||||
|
||||
// Returns a single column of the texture, in BGRA8 format
|
||||
const uint32_t *GetColumnBgra(unsigned int column, const FSoftwareTextureSpan **spans_out)
|
||||
{
|
||||
return mTexture->GetColumnBgra(column, spans_out);
|
||||
}
|
||||
|
||||
// Returns the whole texture, stored in column-major order
|
||||
const uint8_t *GetPixels(FRenderStyle style)
|
||||
{
|
||||
return mTexture->GetPixels(style);
|
||||
}
|
||||
|
||||
// Returns the whole texture, stored in column-major order, in BGRA8 format
|
||||
const uint32_t *GetPixelsBgra()
|
||||
{
|
||||
return mTexture->GetPixelsBgra();
|
||||
}
|
||||
|
||||
void Unload()
|
||||
{
|
||||
mTexture->Unload();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline FSoftwareTexture *FTexture::GetSoftwareTexture()
|
||||
{
|
||||
if (!SoftwareTexture) SoftwareTexture = new FSoftwareTexture(this);
|
||||
return SoftwareTexture;
|
||||
}
|
||||
|
||||
class FxAddSub;
|
||||
// Texture manager
|
||||
|
@ -883,17 +752,14 @@ class FWorldTexture : public FTexture
|
|||
{
|
||||
protected:
|
||||
uint8_t *Pixeldata[2] = { nullptr, nullptr };
|
||||
FSoftwareTextureSpan **Spandata[2] = { nullptr, nullptr };
|
||||
uint8_t PixelsAreStatic = 0; // can be set by subclasses which provide static pixel buffers.
|
||||
|
||||
FWorldTexture(const char *name = nullptr, int lumpnum = -1);
|
||||
~FWorldTexture();
|
||||
|
||||
const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out) override;
|
||||
const uint8_t *GetPixels(FRenderStyle style) override;
|
||||
void Unload() override;
|
||||
const uint8_t *GetPixels(FRenderStyle style) override;
|
||||
virtual uint8_t *MakeTexture(FRenderStyle style) = 0;
|
||||
void FreeAllSpans();
|
||||
};
|
||||
|
||||
// A texture that doesn't really exist
|
||||
|
@ -914,7 +780,7 @@ public:
|
|||
|
||||
virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL) override;
|
||||
virtual int CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, PalEntry *remap, FCopyInfo *inf = NULL) override;
|
||||
const uint32_t *GetPixelsBgra() override;
|
||||
//const uint32_t *GetPixelsBgra() override;
|
||||
bool CheckModified (FRenderStyle) override;
|
||||
|
||||
float GetSpeed() const { return Speed; }
|
||||
|
@ -943,9 +809,10 @@ public:
|
|||
FCanvasTexture (const char *name, int width, int height);
|
||||
~FCanvasTexture ();
|
||||
|
||||
const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out);
|
||||
//const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out);
|
||||
//const uint32_t *GetPixelsBgra() override;
|
||||
|
||||
const uint8_t *GetPixels (FRenderStyle style);
|
||||
const uint32_t *GetPixelsBgra() override;
|
||||
void Unload ();
|
||||
bool CheckModified (FRenderStyle) override;
|
||||
void NeedUpdate() { bNeedsUpdate=true; }
|
||||
|
@ -962,7 +829,7 @@ protected:
|
|||
DCanvas *CanvasBgra = nullptr;
|
||||
uint8_t *Pixels = nullptr;
|
||||
uint32_t *PixelsBgra = nullptr;
|
||||
FSoftwareTextureSpan DummySpans[2];
|
||||
//FSoftwareTextureSpan DummySpans[2];
|
||||
bool bNeedsUpdate = true;
|
||||
bool bDidUpdate = false;
|
||||
bool bPixelsAllocated = false;
|
||||
|
|
|
@ -171,7 +171,6 @@ class FFontChar1 : public FTexture
|
|||
{
|
||||
public:
|
||||
FFontChar1 (FTexture *sourcelump);
|
||||
const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out);
|
||||
const uint8_t *GetPixels (FRenderStyle style);
|
||||
void SetSourceRemap(const uint8_t *sourceremap);
|
||||
void Unload ();
|
||||
|
@ -192,7 +191,6 @@ public:
|
|||
FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs=0, int topofs=0);
|
||||
~FFontChar2 ();
|
||||
|
||||
const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out);
|
||||
const uint8_t *GetPixels (FRenderStyle style);
|
||||
void SetSourceRemap(const uint8_t *sourceremap);
|
||||
void Unload ();
|
||||
|
@ -201,7 +199,6 @@ protected:
|
|||
int SourceLump;
|
||||
int SourcePos;
|
||||
uint8_t *Pixels;
|
||||
FSoftwareTextureSpan **Spans;
|
||||
const uint8_t *SourceRemap;
|
||||
|
||||
void MakeTexture ();
|
||||
|
@ -1607,23 +1604,6 @@ void FFontChar1::MakeTexture ()
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FFontChar1 :: GetColumn
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const uint8_t *FFontChar1::GetColumn(FRenderStyle, unsigned int column, const FSoftwareTextureSpan **spans_out)
|
||||
{
|
||||
if (Pixels == NULL)
|
||||
{
|
||||
MakeTexture ();
|
||||
}
|
||||
|
||||
BaseTexture->GetColumn(DefaultRenderStyle(), column, spans_out);
|
||||
return Pixels + column*Height;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FFontChar1 :: SetSourceRemap
|
||||
|
@ -1672,7 +1652,7 @@ FFontChar1::~FFontChar1 ()
|
|||
//==========================================================================
|
||||
|
||||
FFontChar2::FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs, int topofs)
|
||||
: SourceLump (sourcelump), SourcePos (sourcepos), Pixels (0), Spans (0), SourceRemap(NULL)
|
||||
: SourceLump (sourcelump), SourcePos (sourcepos), Pixels (0), SourceRemap(NULL)
|
||||
{
|
||||
UseType = ETextureType::FontChar;
|
||||
Width = width;
|
||||
|
@ -1691,11 +1671,6 @@ FFontChar2::FFontChar2 (int sourcelump, int sourcepos, int width, int height, in
|
|||
FFontChar2::~FFontChar2 ()
|
||||
{
|
||||
Unload ();
|
||||
if (Spans != NULL)
|
||||
{
|
||||
FreeSpans (Spans);
|
||||
Spans = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1731,33 +1706,6 @@ const uint8_t *FFontChar2::GetPixels (FRenderStyle)
|
|||
return Pixels;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FFontChar2 :: GetColumn
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const uint8_t *FFontChar2::GetColumn(FRenderStyle, unsigned int column, const FSoftwareTextureSpan **spans_out)
|
||||
{
|
||||
if (Pixels == NULL)
|
||||
{
|
||||
MakeTexture ();
|
||||
}
|
||||
if (column >= Width)
|
||||
{
|
||||
column = WidthMask;
|
||||
}
|
||||
if (spans_out != NULL)
|
||||
{
|
||||
if (Spans == NULL)
|
||||
{
|
||||
Spans = CreateSpans (Pixels);
|
||||
}
|
||||
*spans_out = Spans[column];
|
||||
}
|
||||
return Pixels + column*Height;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FFontChar2 :: SetSourceRemap
|
||||
|
|
Loading…
Reference in a new issue