diff --git a/src/polyrenderer/drawers/poly_draw_args.cpp b/src/polyrenderer/drawers/poly_draw_args.cpp index c249e2a7e..bb31c1515 100644 --- a/src/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/polyrenderer/drawers/poly_draw_args.cpp @@ -50,8 +50,8 @@ void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height) void PolyDrawArgs::SetTexture(FSoftwareTexture *texture, FRenderStyle style) { mTexture = texture; - mTextureWidth = texture->GetWidth(); - mTextureHeight = texture->GetHeight(); + mTextureWidth = texture->GetPhysicalWidth(); + mTextureHeight = texture->GetPhysicalHeight(); if (PolyTriangleDrawer::IsBgra()) mTexturePixels = (const uint8_t *)texture->GetPixelsBgra(); else @@ -73,8 +73,8 @@ void PolyDrawArgs::SetTexture(FSoftwareTexture *texture, uint32_t translationID, mTranslation = table->Remap; mTexture = texture; - mTextureWidth = texture->GetWidth(); - mTextureHeight = texture->GetHeight(); + mTextureWidth = texture->GetPhysicalWidth(); + mTextureHeight = texture->GetPhysicalHeight(); mTexturePixels = texture->GetPixels(style); return; } @@ -83,8 +83,8 @@ void PolyDrawArgs::SetTexture(FSoftwareTexture *texture, uint32_t translationID, if (style.Flags & STYLEF_RedIsAlpha) { mTexture = texture; - mTextureWidth = texture->GetWidth(); - mTextureHeight = texture->GetHeight(); + mTextureWidth = texture->GetPhysicalWidth(); + mTextureHeight = texture->GetPhysicalHeight(); mTexturePixels = texture->GetPixels(style); } else diff --git a/src/polyrenderer/scene/poly_decal.cpp b/src/polyrenderer/scene/poly_decal.cpp index 442c70de8..54ba76955 100644 --- a/src/polyrenderer/scene/poly_decal.cpp +++ b/src/polyrenderer/scene/poly_decal.cpp @@ -158,25 +158,25 @@ void RenderPolyDecal::Render(PolyRenderThread *thread, DBaseDecal *decal, const vertices[0].z = (float)ztop; vertices[0].w = 1.0f; vertices[0].u = (float)u_left; - vertices[0].v = (float)v_top; + vertices[0].v = 1.0f - (float)v_top; vertices[1].x = (float)decal_right.X; vertices[1].y = (float)decal_right.Y; vertices[1].z = (float)ztop; vertices[1].w = 1.0f; vertices[1].u = (float)u_right; - vertices[1].v = (float)v_top; + vertices[1].v = 1.0f - (float)v_top; vertices[2].x = (float)decal_right.X; vertices[2].y = (float)decal_right.Y; vertices[2].z = (float)zbottom; vertices[2].w = 1.0f; vertices[2].u = (float)u_right; - vertices[2].v = (float)v_bottom; + vertices[2].v = 1.0f - (float)v_bottom; vertices[3].x = (float)decal_left.X; vertices[3].y = (float)decal_left.Y; vertices[3].z = (float)zbottom; vertices[3].w = 1.0f; vertices[3].u = (float)u_left; - vertices[3].v = (float)v_bottom; + vertices[3].v = 1.0f - (float)v_bottom; // Light calculations diff --git a/src/swrenderer/line/r_walldraw.cpp b/src/swrenderer/line/r_walldraw.cpp index 0dce2236e..4b97bd869 100644 --- a/src/swrenderer/line/r_walldraw.cpp +++ b/src/swrenderer/line/r_walldraw.cpp @@ -57,10 +57,11 @@ namespace swrenderer WallSampler::WallSampler(RenderViewport *viewport, int y1, double texturemid, float swal, double yrepeat, fixed_t xoffset, double xmagnitude, FSoftwareTexture *texture) { xoffset += FLOAT2FIXED(xmagnitude * 0.5); + xoffset *= texture->GetPhysicalScale(); if (!viewport->RenderTarget->IsBgra()) { - height = texture->GetHeight(); + height = texture->GetPhysicalHeight(); int uv_fracbits = 32 - texture->GetHeightBits(); if (uv_fracbits != 32) @@ -70,13 +71,13 @@ namespace swrenderer // Find start uv in [0-base_height[ range. // Not using xs_ToFixed because it rounds the result and we need something that always rounds down to stay within the range. double uv_stepd = swal * yrepeat; - double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / height; + double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / texture->GetHeight(); v = v - floor(v); v *= height; v *= (1 << uv_fracbits); uv_pos = (uint32_t)(int64_t)v; - uv_step = xs_ToFixed(uv_fracbits, uv_stepd); + uv_step = xs_ToFixed(uv_fracbits, uv_stepd * texture->GetPhysicalScale()); if (uv_step == 0) // To prevent divide by zero elsewhere uv_step = 1; } @@ -92,7 +93,7 @@ namespace swrenderer // If the texture's width isn't a power of 2, then we need to make it a // positive offset for proper clamping. int width; - if (col < 0 && (width = texture->GetWidth()) != (1 << texture->GetWidthBits())) + if (col < 0 && (width = texture->GetPhysicalWidth()) != (1 << texture->GetWidthBits())) { col = width + (col % width); } @@ -129,8 +130,8 @@ namespace swrenderer bool magnifying = lod < 0.0f; int mipmap_offset = 0; - int mip_width = texture->GetWidth(); - int mip_height = texture->GetHeight(); + int mip_width = texture->GetPhysicalWidth(); + int mip_height = texture->GetPhysicalHeight(); if (r_mipmap && texture->Mipmapped() && mip_width > 1 && mip_height > 1) { uint32_t xpos = (uint32_t)((((uint64_t)xoffset) << FRACBITS) / mip_width); diff --git a/src/swrenderer/plane/r_flatplane.cpp b/src/swrenderer/plane/r_flatplane.cpp index d826dbc56..7d27fdaf4 100644 --- a/src/swrenderer/plane/r_flatplane.cpp +++ b/src/swrenderer/plane/r_flatplane.cpp @@ -67,6 +67,8 @@ namespace swrenderer return; } + tex = texture; + drawerargs.SetSolidColor(3); drawerargs.SetTexture(Thread, texture); @@ -181,11 +183,11 @@ namespace swrenderer float zbufferdepth = (float)(1.0 / fabs(planeheight / Thread->Viewport->ScreenToViewY(y, 1.0))); - drawerargs.SetTextureUStep(distance * xstepscale / drawerargs.TextureWidth()); - drawerargs.SetTextureUPos((distance * curxfrac + pviewx) / drawerargs.TextureWidth()); + drawerargs.SetTextureUStep(distance * xstepscale / tex->GetWidth()); + drawerargs.SetTextureUPos((distance * curxfrac + pviewx) / tex->GetWidth()); - drawerargs.SetTextureVStep(distance * ystepscale / drawerargs.TextureHeight()); - drawerargs.SetTextureVPos((distance * curyfrac + pviewy) / drawerargs.TextureHeight()); + drawerargs.SetTextureVStep(distance * ystepscale / tex->GetHeight()); + drawerargs.SetTextureVPos((distance * curyfrac + pviewy) / tex->GetHeight()); if (viewport->RenderTarget->IsBgra()) { diff --git a/src/swrenderer/plane/r_flatplane.h b/src/swrenderer/plane/r_flatplane.h index 9e01afb94..fad5bdf8f 100644 --- a/src/swrenderer/plane/r_flatplane.h +++ b/src/swrenderer/plane/r_flatplane.h @@ -51,6 +51,7 @@ namespace swrenderer double xstepscale, ystepscale; double basexfrac, baseyfrac; VisiblePlaneLight *light_list; + FSoftwareTexture *tex; SpanDrawerArgs drawerargs; }; diff --git a/src/swrenderer/plane/r_skyplane.cpp b/src/swrenderer/plane/r_skyplane.cpp index 4f444ece5..5b5c4894a 100644 --- a/src/swrenderer/plane/r_skyplane.cpp +++ b/src/swrenderer/plane/r_skyplane.cpp @@ -248,11 +248,9 @@ namespace swrenderer RenderPortal *renderportal = Thread->Portal.get(); auto viewport = Thread->Viewport.get(); - uint32_t height = frontskytex->GetHeight(); - double uv_stepd = skyiscale * yrepeat; - double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / height; - double v_step = uv_stepd / height; + double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / frontskytex->GetHeight(); + double v_step = uv_stepd / frontskytex->GetHeight(); uint32_t uv_pos = (uint32_t)(int32_t)(v * 0x01000000); uint32_t uv_step = (uint32_t)(int32_t)(v_step * 0x01000000); @@ -272,8 +270,8 @@ namespace swrenderer { ang = (skyangle + viewport->xtoviewangle[x]) ^ skyflip; } - angle1 = (uint32_t)((UMulScale16(ang, frontcyl) + frontpos) >> FRACBITS); - angle2 = (uint32_t)((UMulScale16(ang, backcyl) + backpos) >> FRACBITS); + angle1 = UMulScale16(ang, frontcyl) + frontpos; + angle2 = UMulScale16(ang, backcyl) + backpos; drawerargs.SetFrontTexture(Thread, frontskytex, angle1); drawerargs.SetBackTexture(Thread, backskytex, angle2); @@ -296,7 +294,7 @@ namespace swrenderer void RenderSkyPlane::DrawSkyColumn(int start_x, int y1, int y2) { - if (1 << frontskytex->GetHeightBits() == frontskytex->GetHeight()) + if (1 << frontskytex->GetHeightBits() == frontskytex->GetPhysicalHeight()) { double texturemid = skymid * frontskytex->GetScale().Y + frontskytex->GetHeight(); DrawSkyColumnStripe(start_x, y1, y2, frontskytex->GetScale().Y, texturemid, frontskytex->GetScale().Y); diff --git a/src/swrenderer/plane/r_slopeplane.cpp b/src/swrenderer/plane/r_slopeplane.cpp index fb20f107e..41a30db83 100644 --- a/src/swrenderer/plane/r_slopeplane.cpp +++ b/src/swrenderer/plane/r_slopeplane.cpp @@ -98,6 +98,9 @@ namespace swrenderer drawerargs.SetSolidColor(3); drawerargs.SetTexture(Thread, texture); + _xscale /= texture->GetPhysicalScale(); + _yscale /= texture->GetPhysicalScale(); + lxscale = _xscale * ifloatpow2[drawerargs.TextureWidthBits()]; lyscale = _yscale * ifloatpow2[drawerargs.TextureHeightBits()]; xscale = 64.f / lxscale; diff --git a/src/swrenderer/textures/r_swtexture.cpp b/src/swrenderer/textures/r_swtexture.cpp index 100825252..1b6192eee 100644 --- a/src/swrenderer/textures/r_swtexture.cpp +++ b/src/swrenderer/textures/r_swtexture.cpp @@ -37,6 +37,9 @@ #include "r_swtexture.h" #include "bitmap.h" #include "m_alloc.h" +#include "imagehelpers.h" + +EXTERN_CVAR(Bool, gl_texture_usehires) FSoftwareTexture *FTexture::GetSoftwareTexture() @@ -56,12 +59,31 @@ FSoftwareTexture *FTexture::GetSoftwareTexture() // //========================================================================== +FSoftwareTexture::FSoftwareTexture(FTexture *tex) +{ + mTexture = tex; + mSource = tex; + + mBufferFlags = (gl_texture_usehires && !tex->isScaled() && tex->GetImage() && !tex->isSprite() ) ? CTF_CheckHires|CTF_ProcessData : CTF_ProcessData; + auto info = tex->CreateTexBuffer(0, CTF_CheckOnly| mBufferFlags); + mPhysicalWidth = info.mWidth; + mPhysicalHeight = info.mHeight; + mPhysicalScale = mPhysicalWidth / tex->Width; + CalcBitSize(); +} + +//========================================================================== +// +// +// +//========================================================================== + void FSoftwareTexture::CalcBitSize () { // WidthBits is rounded down, and HeightBits is rounded up int i; - for (i = 0; (1 << i) < GetWidth(); ++i) + for (i = 0; (1 << i) < GetPhysicalWidth(); ++i) { } WidthBits = i; @@ -69,7 +91,7 @@ void FSoftwareTexture::CalcBitSize () // Having WidthBits that would allow for columns past the end of the // texture is not allowed, even if it means the entire texture is // not drawn. - if (GetWidth() < (1 << WidthBits)) + if (GetPhysicalWidth() < (1 << WidthBits)) { WidthBits--; } @@ -77,7 +99,7 @@ void FSoftwareTexture::CalcBitSize () //
The minimum height is 2, because we cannot shift right 32 bits. // Scratch that. Somebody actually made a 1x1 texture, so now we have to handle it. - for (i = 0; (1 << i) < GetHeight(); ++i) + for (i = 0; (1 << i) < GetPhysicalHeight(); ++i) { } HeightBits = i; @@ -93,7 +115,36 @@ const uint8_t *FSoftwareTexture::GetPixels(int style) { if (Pixels.Size() == 0 || CheckModified(style)) { - Pixels = mSource->Get8BitPixels(style); + if (mPhysicalScale == 1) + { + Pixels = mSource->Get8BitPixels(style); + } + else + { + auto tempbuffer = mTexture->CreateTexBuffer(0, mBufferFlags); + Pixels.Resize(GetPhysicalWidth()*GetPhysicalHeight()); + PalEntry *pe = (PalEntry*)tempbuffer.mBuffer; + if (!style) + { + for (int y = 0; y < GetPhysicalHeight(); y++) + { + for (int x = 0; x < GetPhysicalWidth(); x++) + { + Pixels[y + x * GetPhysicalHeight()] = ImageHelpers::RGBToPalette(false, pe[x + y * GetPhysicalWidth()], true); + } + } + } + else + { + for (int y = 0; y < GetPhysicalHeight(); y++) + { + for (int x = 0; x < GetPhysicalWidth(); x++) + { + Pixels[y + x * GetPhysicalHeight()] = pe[x + y * GetPhysicalWidth()].r; + } + } + } + } } return Pixels.Data(); } @@ -108,8 +159,25 @@ const uint32_t *FSoftwareTexture::GetPixelsBgra() { if (PixelsBgra.Size() == 0 || CheckModified(2)) { - FBitmap bitmap = mTexture->GetBgraBitmap(nullptr); - GenerateBgraFromBitmap(bitmap); + if (mPhysicalScale == 1) + { + FBitmap bitmap = mTexture->GetBgraBitmap(nullptr); + GenerateBgraFromBitmap(bitmap); + } + else + { + auto tempbuffer = mTexture->CreateTexBuffer(0, mBufferFlags); + CreatePixelsBgraWithMipmaps(); + PalEntry *pe = (PalEntry*)tempbuffer.mBuffer; + for (int y = 0; y < GetPhysicalHeight(); y++) + { + for (int x = 0; x < GetPhysicalWidth(); x++) + { + PixelsBgra[y + x * GetPhysicalHeight()] = pe[x + y * GetPhysicalWidth()]; + } + } + GenerateBgraMipmaps(); + } } return PixelsBgra.Data(); } @@ -123,15 +191,15 @@ const uint32_t *FSoftwareTexture::GetPixelsBgra() const uint8_t *FSoftwareTexture::GetColumn(int index, unsigned int column, const FSoftwareTextureSpan **spans_out) { auto Pixeldata = GetPixels(index); - if ((unsigned)column >= (unsigned)GetWidth()) + if ((unsigned)column >= (unsigned)GetPhysicalWidth()) { - if (WidthMask + 1 == GetWidth()) + if (WidthMask + 1 == GetPhysicalWidth()) { column &= WidthMask; } else { - column %= GetWidth(); + column %= GetPhysicalWidth(); } } if (spans_out != nullptr) @@ -142,7 +210,7 @@ const uint8_t *FSoftwareTexture::GetColumn(int index, unsigned int column, const } *spans_out = Spandata[index][column]; } - return Pixeldata + column * GetHeight(); + return Pixeldata + column * GetPhysicalHeight(); } //========================================================================== @@ -154,15 +222,15 @@ const uint8_t *FSoftwareTexture::GetColumn(int index, unsigned int column, const const uint32_t *FSoftwareTexture::GetColumnBgra(unsigned int column, const FSoftwareTextureSpan **spans_out) { auto Pixeldata = GetPixelsBgra(); - if ((unsigned)column >= (unsigned)GetWidth()) + if ((unsigned)column >= (unsigned)GetPhysicalWidth()) { - if (WidthMask + 1 == GetWidth()) + if (WidthMask + 1 == GetPhysicalWidth()) { column &= WidthMask; } else { - column %= GetWidth(); + column %= GetPhysicalWidth(); } } if (spans_out != nullptr) @@ -173,7 +241,7 @@ const uint32_t *FSoftwareTexture::GetColumnBgra(unsigned int column, const FSoft } *spans_out = Spandata[2][column]; } - return Pixeldata + column * GetHeight(); + return Pixeldata + column * GetPhysicalHeight(); } //========================================================================== @@ -199,21 +267,21 @@ FSoftwareTextureSpan **FSoftwareTexture::CreateSpans (const T *pixels) 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 = (FSoftwareTextureSpan **)M_Malloc (sizeof(FSoftwareTextureSpan*)*GetPhysicalWidth() + sizeof(FSoftwareTextureSpan)*2); + span = (FSoftwareTextureSpan *)&spans[GetPhysicalWidth()]; + for (int x = 0; x < GetPhysicalWidth(); ++x) { spans[x] = span; } - span[0].Length = GetHeight(); + span[0].Length = GetPhysicalHeight(); 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 numcols = GetPhysicalWidth(); + int numrows = GetPhysicalHeight(); int numspans = numcols; // One span to terminate each column const T *data_p; bool newspan; @@ -305,11 +373,11 @@ void FSoftwareTexture::GenerateBgraFromBitmap(const FBitmap &bitmap) // Transpose const uint32_t *src = (const uint32_t *)bitmap.GetPixels(); uint32_t *dest = PixelsBgra.Data(); - for (int x = 0; x < GetWidth(); x++) + for (int x = 0; x < GetPhysicalWidth(); x++) { - for (int y = 0; y < GetHeight(); y++) + for (int y = 0; y < GetPhysicalHeight(); y++) { - dest[y + x * GetHeight()] = src[x + y * GetWidth()]; + dest[y + x * GetPhysicalHeight()] = src[x + y * GetPhysicalWidth()]; } } @@ -322,8 +390,8 @@ void FSoftwareTexture::CreatePixelsBgraWithMipmaps() int buffersize = 0; for (int i = 0; i < levels; i++) { - int w = MAX(GetWidth() >> i, 1); - int h = MAX(GetHeight() >> i, 1); + int w = MAX(GetPhysicalWidth() >> i, 1); + int h = MAX(GetPhysicalHeight() >> i, 1); buffersize += w * h; } PixelsBgra.Resize(buffersize); @@ -332,10 +400,10 @@ void FSoftwareTexture::CreatePixelsBgraWithMipmaps() int FSoftwareTexture::MipmapLevels() { int widthbits = 0; - while ((GetWidth() >> widthbits) != 0) widthbits++; + while ((GetPhysicalWidth() >> widthbits) != 0) widthbits++; int heightbits = 0; - while ((GetHeight() >> heightbits) != 0) heightbits++; + while ((GetPhysicalHeight() >> heightbits) != 0) heightbits++; return MAX(widthbits, heightbits); } @@ -366,32 +434,32 @@ void FSoftwareTexture::GenerateBgraMipmaps() // Convert to normalized linear colorspace { - for (int x = 0; x < GetWidth(); x++) + for (int x = 0; x < GetPhysicalWidth(); x++) { - for (int y = 0; y < GetHeight(); y++) + for (int y = 0; y < GetPhysicalHeight(); y++) { - uint32_t c8 = PixelsBgra[x * GetHeight() + y]; + uint32_t c8 = PixelsBgra[x * GetPhysicalHeight() + 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; + image[x * GetPhysicalHeight() + y] = c; } } } // Generate mipmaps { - std::vector smoothed(GetWidth() * GetHeight()); + std::vector smoothed(GetPhysicalWidth() * GetPhysicalHeight()); Color4f *src = image.data(); - Color4f *dest = src + GetWidth() * GetHeight(); + Color4f *dest = src + GetPhysicalWidth() * GetPhysicalHeight(); 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); + int srcw = MAX(GetPhysicalWidth() >> (i - 1), 1); + int srch = MAX(GetPhysicalHeight() >> (i - 1), 1); + int w = MAX(GetPhysicalWidth() >> i, 1); + int h = MAX(GetPhysicalHeight() >> i, 1); // Downscale for (int x = 0; x < w; x++) @@ -447,12 +515,12 @@ void FSoftwareTexture::GenerateBgraMipmaps() // Convert to bgra8 sRGB colorspace { - Color4f *src = image.data() + GetWidth() * GetHeight(); - uint32_t *dest = PixelsBgra.Data() + GetWidth() * GetHeight(); + Color4f *src = image.data() + GetPhysicalWidth() * GetPhysicalHeight(); + uint32_t *dest = PixelsBgra.Data() + GetPhysicalWidth() * GetPhysicalHeight(); for (int i = 1; i < levels; i++) { - int w = MAX(GetWidth() >> i, 1); - int h = MAX(GetHeight() >> i, 1); + int w = MAX(GetPhysicalWidth() >> i, 1); + int h = MAX(GetPhysicalHeight() >> 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); @@ -476,14 +544,14 @@ void FSoftwareTexture::GenerateBgraMipmaps() void FSoftwareTexture::GenerateBgraMipmapsFast() { uint32_t *src = PixelsBgra.Data(); - uint32_t *dest = src + GetWidth() * GetHeight(); + uint32_t *dest = src + GetPhysicalWidth() * GetPhysicalHeight(); 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); + int srcw = MAX(GetPhysicalWidth() >> (i - 1), 1); + int srch = MAX(GetPhysicalHeight() >> (i - 1), 1); + int w = MAX(GetPhysicalWidth() >> i, 1); + int h = MAX(GetPhysicalHeight() >> i, 1); for (int x = 0; x < w; x++) { diff --git a/src/swrenderer/textures/r_swtexture.h b/src/swrenderer/textures/r_swtexture.h index f03f8c86a..f4baeb21b 100644 --- a/src/swrenderer/textures/r_swtexture.h +++ b/src/swrenderer/textures/r_swtexture.h @@ -22,19 +22,17 @@ protected: FSoftwareTextureSpan **Spandata[3] = { }; uint8_t WidthBits = 0, HeightBits = 0; uint16_t WidthMask = 0; - + int mPhysicalWidth, mPhysicalHeight; + int mPhysicalScale; + int mBufferFlags; + void FreeAllSpans(); template FSoftwareTextureSpan **CreateSpans(const T *pixels); void FreeSpans(FSoftwareTextureSpan **spans); void CalcBitSize(); public: - FSoftwareTexture(FTexture *tex) - { - mTexture = tex; - mSource = tex; - CalcBitSize(); - } + FSoftwareTexture(FTexture *tex); virtual ~FSoftwareTexture() { @@ -69,7 +67,6 @@ public: 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); } @@ -95,6 +92,9 @@ public: int GetScaledTopOffsetPo() { return GetScaledTopOffset(r_spriteadjustSW); } DVector2 GetScale() const { return mTexture->Scale; } + int GetPhysicalWidth() { return mPhysicalWidth; } + int GetPhysicalHeight() { return mPhysicalHeight; } + int GetPhysicalScale() const { return mPhysicalScale; } virtual void Unload() { diff --git a/src/swrenderer/viewport/r_skydrawer.cpp b/src/swrenderer/viewport/r_skydrawer.cpp index 2bbab5abf..2f75e30e2 100644 --- a/src/swrenderer/viewport/r_skydrawer.cpp +++ b/src/swrenderer/viewport/r_skydrawer.cpp @@ -47,21 +47,21 @@ namespace swrenderer dc_viewport = viewport; } - void SkyDrawerArgs::SetFrontTexture(RenderThread *thread, FSoftwareTexture *texture, uint32_t column) + void SkyDrawerArgs::SetFrontTexture(RenderThread *thread, FSoftwareTexture *texture, fixed_t column) { if (thread->Viewport->RenderTarget->IsBgra()) { - dc_source = (const uint8_t *)texture->GetColumnBgra(column, nullptr); - dc_sourceheight = texture->GetHeight(); + dc_source = (const uint8_t *)texture->GetColumnBgra((column * texture->GetPhysicalScale()) >> FRACBITS, nullptr); + dc_sourceheight = texture->GetPhysicalHeight(); } else { - dc_source = texture->GetColumn(DefaultRenderStyle(), column, nullptr); - dc_sourceheight = texture->GetHeight(); + dc_source = texture->GetColumn(DefaultRenderStyle(), (column * texture->GetPhysicalScale()) >> FRACBITS, nullptr); + dc_sourceheight = texture->GetPhysicalHeight(); } } - void SkyDrawerArgs::SetBackTexture(RenderThread *thread, FSoftwareTexture *texture, uint32_t column) + void SkyDrawerArgs::SetBackTexture(RenderThread *thread, FSoftwareTexture *texture, fixed_t column) { if (texture == nullptr) { @@ -70,13 +70,13 @@ namespace swrenderer } else if (thread->Viewport->RenderTarget->IsBgra()) { - dc_source2 = (const uint8_t *)texture->GetColumnBgra(column, nullptr); - dc_sourceheight2 = texture->GetHeight(); + dc_source2 = (const uint8_t *)texture->GetColumnBgra((column * texture->GetPhysicalScale()) >> FRACBITS, nullptr); + dc_sourceheight2 = texture->GetPhysicalHeight(); } else { - dc_source2 = texture->GetColumn(DefaultRenderStyle(), column, nullptr); - dc_sourceheight2 = texture->GetHeight(); + dc_source2 = texture->GetColumn(DefaultRenderStyle(), (column * texture->GetPhysicalScale()) >> FRACBITS, nullptr); + dc_sourceheight2 = texture->GetPhysicalHeight(); } } } diff --git a/src/swrenderer/viewport/r_skydrawer.h b/src/swrenderer/viewport/r_skydrawer.h index 69ff04d9b..2634c514f 100644 --- a/src/swrenderer/viewport/r_skydrawer.h +++ b/src/swrenderer/viewport/r_skydrawer.h @@ -15,8 +15,8 @@ namespace swrenderer public: void SetDest(RenderViewport *viewport, int x, int y); void SetCount(int count) { dc_count = count; } - void SetFrontTexture(RenderThread *thread, FSoftwareTexture *texture, uint32_t column); - void SetBackTexture(RenderThread *thread, FSoftwareTexture *texture, uint32_t column); + void SetFrontTexture(RenderThread *thread, FSoftwareTexture *texture, fixed_t column); + void SetBackTexture(RenderThread *thread, FSoftwareTexture *texture, fixed_t column); void SetTextureVPos(uint32_t texturefrac) { dc_texturefrac = texturefrac; } void SetTextureVStep(uint32_t iscale) { dc_iscale = iscale; } void SetSolidTop(uint32_t color) { solid_top = color; } diff --git a/src/swrenderer/viewport/r_spandrawer.cpp b/src/swrenderer/viewport/r_spandrawer.cpp index 8c4bb26a7..665d18e89 100644 --- a/src/swrenderer/viewport/r_spandrawer.cpp +++ b/src/swrenderer/viewport/r_spandrawer.cpp @@ -34,21 +34,21 @@ namespace swrenderer { thread->PrepareTexture(tex, DefaultRenderStyle()); - ds_texwidth = tex->GetWidth(); - ds_texheight = tex->GetHeight(); + ds_texwidth = tex->GetPhysicalWidth(); + ds_texheight = tex->GetPhysicalHeight(); ds_xbits = tex->GetWidthBits(); ds_ybits = tex->GetHeightBits(); - if ((1 << ds_xbits) > tex->GetWidth()) + if ((1 << ds_xbits) > tex->GetPhysicalWidth()) { ds_xbits--; } - if ((1 << ds_ybits) > tex->GetHeight()) + if ((1 << ds_ybits) > tex->GetPhysicalHeight()) { ds_ybits--; } ds_source = thread->Viewport->RenderTarget->IsBgra() ? (const uint8_t*)tex->GetPixelsBgra() : tex->GetPixels(DefaultRenderStyle()); // Get correct render style? Shaded won't get here. - ds_source_mipmapped = tex->Mipmapped() && tex->GetWidth() > 1 && tex->GetHeight() > 1; + ds_source_mipmapped = tex->Mipmapped() && tex->GetPhysicalWidth() > 1 && tex->GetPhysicalHeight() > 1; } void SpanDrawerArgs::SetStyle(bool masked, bool additive, fixed_t alpha) diff --git a/src/swrenderer/viewport/r_spritedrawer.cpp b/src/swrenderer/viewport/r_spritedrawer.cpp index f53fe70b2..f6d870912 100644 --- a/src/swrenderer/viewport/r_spritedrawer.cpp +++ b/src/swrenderer/viewport/r_spritedrawer.cpp @@ -48,6 +48,10 @@ namespace swrenderer if (x < thread->X1 || x >= thread->X2) return; + col *= tex->GetPhysicalScale(); + iscale *= tex->GetPhysicalScale(); + spryscale /= tex->GetPhysicalScale(); + auto viewport = thread->Viewport.get(); // Handle the linear filtered version in a different function to reduce chances of merge conflicts from zdoom. @@ -60,7 +64,7 @@ namespace swrenderer dc_viewport = viewport; dc_x = x; dc_iscale = iscale; - dc_textureheight = tex->GetHeight(); + dc_textureheight = tex->GetPhysicalHeight(); const FSoftwareTextureSpan *span; const uint8_t *column; @@ -74,7 +78,7 @@ namespace swrenderer { span = unmaskedSpan; unmaskedSpan[0].TopOffset = 0; - unmaskedSpan[0].Length = tex->GetHeight(); + unmaskedSpan[0].Length = tex->GetPhysicalHeight(); unmaskedSpan[1].TopOffset = 0; unmaskedSpan[1].Length = 0; } @@ -134,7 +138,7 @@ namespace swrenderer // Normalize to 0-1 range: double uv_stepd = FIXED2DBL(dc_iscale); - double v_step = uv_stepd / tex->GetHeight(); + double v_step = uv_stepd / tex->GetPhysicalHeight(); // Convert to uint32_t: dc_iscale = (uint32_t)(v_step * (1 << 30)); @@ -150,8 +154,8 @@ namespace swrenderer bool magnifying = lod < 0.0f; int mipmap_offset = 0; - int mip_width = tex->GetWidth(); - int mip_height = tex->GetHeight(); + int mip_width = tex->GetPhysicalWidth(); + int mip_height = tex->GetPhysicalHeight(); uint32_t xpos = (uint32_t)((((uint64_t)xoffset) << FRACBITS) / mip_width); if (r_mipmap && tex->Mipmapped() && mip_width > 1 && mip_height > 1) { @@ -199,7 +203,7 @@ namespace swrenderer { span = unmaskedSpan; unmaskedSpan[0].TopOffset = 0; - unmaskedSpan[0].Length = tex->GetHeight(); + unmaskedSpan[0].Length = tex->GetPhysicalHeight(); unmaskedSpan[1].TopOffset = 0; unmaskedSpan[1].Length = 0; } @@ -233,7 +237,7 @@ namespace swrenderer SetDest(dc_viewport, dc_x, dc_yl); dc_count = dc_yh - dc_yl + 1; - double v = ((dc_yl + 0.5 - sprtopscreen) / spryscale) / tex->GetHeight(); + double v = ((dc_yl + 0.5 - sprtopscreen) / spryscale) / tex->GetPhysicalHeight(); dc_texturefrac = (uint32_t)(v * (1 << 30)); (thread->Drawers(dc_viewport)->*colfunc)(*this); diff --git a/src/textures/hires/hqresize.cpp b/src/textures/hires/hqresize.cpp index e6acb4911..82a4d8817 100644 --- a/src/textures/hires/hqresize.cpp +++ b/src/textures/hires/hqresize.cpp @@ -387,69 +387,71 @@ void FTexture::CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasA break; } - if (texbuffer.mBuffer) + int type = gl_texture_hqresizemode; + int mult = gl_texture_hqresizemult; +#ifdef HAVE_MMX + // hqNx MMX does not preserve the alpha channel so fall back to C-version for such textures + if (hasAlpha && type == 3) { - int type = gl_texture_hqresizemode; - int mult = gl_texture_hqresizemult; -#ifdef HAVE_MMX - // hqNx MMX does not preserve the alpha channel so fall back to C-version for such textures - if (hasAlpha && type == 3) - { - type = 2; - } -#endif - // These checks are to ensure consistency of the content ID. - if (mult < 2 || mult > 6 || type < 1 || type > 6) return; - if (type < 4 && mult > 4) mult = 4; - - if (!checkonly) - { - if (type == 1) - { - if (mult == 2) - texbuffer.mBuffer = scaleNxHelper(&scale2x, 2, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (mult == 3) - texbuffer.mBuffer = scaleNxHelper(&scale3x, 3, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (mult == 4) - texbuffer.mBuffer = scaleNxHelper(&scale4x, 4, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else return; - } - else if (type == 2) - { - if (mult == 2) - texbuffer.mBuffer = hqNxHelper(&hq2x_32, 2, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (mult == 3) - texbuffer.mBuffer = hqNxHelper(&hq3x_32, 3, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (mult == 4) - texbuffer.mBuffer = hqNxHelper(&hq4x_32, 4, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else return; - } -#ifdef HAVE_MMX - else if (type == 3) - { - if (mult == 2) - texbuffer.mBuffer = hqNxAsmHelper(&HQnX_asm::hq2x_32, 2, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (mult == 3) - texbuffer.mBuffer = hqNxAsmHelper(&HQnX_asm::hq3x_32, 3, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (mult == 4) - texbuffer.mBuffer = hqNxAsmHelper(&HQnX_asm::hq4x_32, 4, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else return; - } -#endif - else if (type == 4) - texbuffer.mBuffer = xbrzHelper(xbrz::scale, mult, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (type == 5) - texbuffer.mBuffer = xbrzHelper(xbrzOldScale, mult, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (type == 6) - texbuffer.mBuffer = normalNxHelper(&normalNx, mult, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else - return; - } - // Encode the scaling method in the content ID. - FContentIdBuilder contentId; - contentId.id = texbuffer.mContentId; - contentId.scaler = type; - contentId.scalefactor = mult; - texbuffer.mContentId = contentId.id; + type = 2; } +#endif + // These checks are to ensure consistency of the content ID. + if (mult < 2 || mult > 6 || type < 1 || type > 6) return; + if (type < 4 && mult > 4) mult = 4; + + if (!checkonly) + { + if (type == 1) + { + if (mult == 2) + texbuffer.mBuffer = scaleNxHelper(&scale2x, 2, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (mult == 3) + texbuffer.mBuffer = scaleNxHelper(&scale3x, 3, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (mult == 4) + texbuffer.mBuffer = scaleNxHelper(&scale4x, 4, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else return; + } + else if (type == 2) + { + if (mult == 2) + texbuffer.mBuffer = hqNxHelper(&hq2x_32, 2, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (mult == 3) + texbuffer.mBuffer = hqNxHelper(&hq3x_32, 3, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (mult == 4) + texbuffer.mBuffer = hqNxHelper(&hq4x_32, 4, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else return; + } +#ifdef HAVE_MMX + else if (type == 3) + { + if (mult == 2) + texbuffer.mBuffer = hqNxAsmHelper(&HQnX_asm::hq2x_32, 2, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (mult == 3) + texbuffer.mBuffer = hqNxAsmHelper(&HQnX_asm::hq3x_32, 3, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (mult == 4) + texbuffer.mBuffer = hqNxAsmHelper(&HQnX_asm::hq4x_32, 4, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else return; + } +#endif + else if (type == 4) + texbuffer.mBuffer = xbrzHelper(xbrz::scale, mult, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (type == 5) + texbuffer.mBuffer = xbrzHelper(xbrzOldScale, mult, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (type == 6) + texbuffer.mBuffer = normalNxHelper(&normalNx, mult, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else + return; + } + else + { + texbuffer.mWidth *= mult; + texbuffer.mHeight *= mult; + } + // Encode the scaling method in the content ID. + FContentIdBuilder contentId; + contentId.id = texbuffer.mContentId; + contentId.scaler = type; + contentId.scalefactor = mult; + texbuffer.mContentId = contentId.id; } diff --git a/src/textures/textures.h b/src/textures/textures.h index e40b9fc0a..934fb122f 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -330,6 +330,7 @@ public: int isWarped() const { return bWarped; } int GetRotations() const { return Rotations; } void SetRotations(int rot) { Rotations = int16_t(rot); } + bool isSprite() const { return UseType == ETextureType::Sprite || UseType == ETextureType::SkinSprite || UseType == ETextureType::Decal; } const FString &GetName() const { return Name; } bool allowNoDecals() const { return bNoDecals; }