From 4ebfdac887d5f5d8af1c21ba238841b07cc282ff Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 1 Nov 2009 01:27:33 +0000 Subject: [PATCH] - Changed all coordinates for DrawTexture() to floating point so that the player sprites will retain the same precision they had when they were rendered as part of the 3D view. (needed for propery alignment of flashes on top of weapon sprites) It worked just fine for D3D, but software rendering was another matter. I consequently did battle with imprecisions in the whole masked texture drawing routines that had previously been partially masked by only drawing on whole pixel boundaries. Particularly, the tops of posts are calculated by multiplying by spryscale, and the texture mapping coordinates are calculated by multiplying by dc_iscale (where dc_iscale = 1 / spryscale). Since these are both 16.16 fixed point values, there is a significant variance. For best results, the drawing routines should only use one of these values, but that would mean introducing division into the inner loop. If the division removed the necessity for the fudge code in R_DrawMaskedColumn(), would it be worth it? Or would the divide be slower than the fudging? Or would I be better off doing it like Build and using transparent pixel checks instead, not bothering with skipping transparent areas? For now, I chop off the fractional part of the top coordinate for software drawing, since it was the easiest thing to do (even if it wasn't the most correct thing to do). SVN r1955 (trunk) --- docs/rh-log.txt | 21 + src/g_shared/sbarinfo_display.cpp | 6 +- src/r_things.cpp | 6 +- src/textures/textures.h | 4 + src/v_draw.cpp | 323 +++++++------ src/v_video.h | 52 ++- src/vectors.h | 2 +- src/win32/fb_d3d9.cpp | 46 +- src/win32/win32iface.h | 2 +- zdoom.vcproj | 746 +++++++++++++++--------------- 10 files changed, 657 insertions(+), 551 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index e10bcb43d..33919afc8 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,24 @@ +October 31, 2009 +- Changed all coordinates for DrawTexture() to floating point so that the + player sprites will retain the same precision they had when they were + rendered as part of the 3D view. (needed for propery alignment of flashes + on top of weapon sprites) It worked just fine for D3D, but software + rendering was another matter. I consequently did battle with imprecisions + in the whole masked texture drawing routines that had previously been + partially masked by only drawing on whole pixel boundaries. Particularly, + the tops of posts are calculated by multiplying by spryscale, and the + texture mapping coordinates are calculated by multiplying by dc_iscale + (where dc_iscale = 1 / spryscale). Since these are both 16.16 fixed point + values, there is a significant variance. For best results, the drawing + routines should only use one of these values, but that would mean + introducing division into the inner loop. If the division removed the + necessity for the fudge code in R_DrawMaskedColumn(), would it be worth it? + Or would the divide be slower than the fudging? Or would I be better off + doing it like Build and using transparent pixel checks instead, not + bothering with skipping transparent areas? For now, I chop off the + fractional part of the top coordinate for software drawing, since it was + the easiest thing to do (even if it wasn't the most correct thing to do). + October 29, 2009 - Fixed: Sprites and decals that are drawn with addition must fade to black. - Make TranslateToStartSpot() set the new sector references for a polyobj's diff --git a/src/g_shared/sbarinfo_display.cpp b/src/g_shared/sbarinfo_display.cpp index 77c52c60f..0a986fbbb 100644 --- a/src/g_shared/sbarinfo_display.cpp +++ b/src/g_shared/sbarinfo_display.cpp @@ -960,7 +960,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a h = fg->GetScaledHeight() << FRACBITS; if (Scaled) { - screen->VirtualToRealCoords(x, y, w, h, 320, 200, true); + screen->VirtualToRealCoordsFixed(x, y, w, h, 320, 200, true); } x >>= FRACBITS; y >>= FRACBITS; @@ -1018,7 +1018,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a ch = (fg->GetScaledHeight() - fg->GetScaledTopOffset() - cmd.special3 * 2) << FRACBITS; if (Scaled) { - screen->VirtualToRealCoords(cx, cy, cw, ch, 320, 200, true); + screen->VirtualToRealCoordsFixed(cx, cy, cw, ch, 320, 200, true); } cx >>= FRACBITS; cy >>= FRACBITS; @@ -1480,7 +1480,7 @@ void DSBarInfo::DrawGraphic(FTexture* texture, SBarInfoCoordinate x, SBarInfoCoo fixed_t fw = texture->GetScaledWidth() << FRACBITS; fixed_t fh = texture->GetScaledHeight() << FRACBITS; if(Scaled) - screen->VirtualToRealCoords(fx, fy, fw, fh, 320, 200, true); + screen->VirtualToRealCoordsFixed(fx, fy, fw, fh, 320, 200, true); // Round to nearest w = (fw + (FRACUNIT>>1)) >> FRACBITS; h = (fh + (FRACUNIT>>1)) >> FRACBITS; diff --git a/src/r_things.cpp b/src/r_things.cpp index c03c162ba..ea4accfa3 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1848,9 +1848,9 @@ void R_DrawRemainingPlayerSprites() } screen->DrawTexture(vis->pic, viewwindowx + VisPSpritesX1[i], - viewwindowy + viewheight/2 - MulScale32(vis->texturemid, vis->yscale) - 1, - DTA_DestWidth, FixedMul(vis->pic->GetWidth(), vis->xscale), - DTA_DestHeight, FixedMul(vis->pic->GetHeight(), vis->yscale), + viewwindowy + viewheight/2 - (vis->texturemid / 65536.0) * (vis->yscale / 65536.0) - 1, + DTA_DestWidthF, FIXED2FLOAT(vis->pic->GetWidth() * vis->xscale), + DTA_DestHeightF, FIXED2FLOAT(vis->pic->GetHeight() * vis->yscale), DTA_Translation, TranslationToTable(vis->Translation), DTA_FlipX, flip, DTA_TopOffset, 0, diff --git a/src/textures/textures.h b/src/textures/textures.h index 0f595b5cb..b62da46d8 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -178,9 +178,13 @@ public: int GetScaledWidth () { int foo = (Width << 17) / xScale; return (foo >> 1) + (foo & 1); } int GetScaledHeight () { int foo = (Height << 17) / yScale; return (foo >> 1) + (foo & 1); } + double GetScaledWidthDouble () { return (Width * 65536.f) / xScale; } + double GetScaledHeightDouble () { return (Height * 65536.f) / yScale; } int GetScaledLeftOffset () { int foo = (LeftOffset << 17) / xScale; return (foo >> 1) + (foo & 1); } int GetScaledTopOffset () { int foo = (TopOffset << 17) / yScale; return (foo >> 1) + (foo & 1); } + double GetScaledLeftOffsetDouble() { return (LeftOffset * 65536.f) / xScale; } + double GetScaledTopOffsetDouble() { return (TopOffset * 65536.f) / yScale; } virtual void SetFrontSkyLayer(); diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 05cd73c5c..7c05d9042 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -89,14 +89,14 @@ static int PalFromRGB(uint32 rgb) return LastPal; } -void STACK_ARGS DCanvas::DrawTexture (FTexture *img, int x, int y, int tags_first, ...) +void STACK_ARGS DCanvas::DrawTexture (FTexture *img, double x, double y, int tags_first, ...) { va_list tags; va_start(tags, tags_first); DrawTextureV(img, x, y, tags_first, tags); } -void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, va_list tags) +void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, double x, double y, uint32 tag, va_list tags) { FTexture::Span unmaskedSpan[2]; const FTexture::Span **spanptr, *spans; @@ -154,8 +154,8 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v BYTE *destorgsave = dc_destorg; dc_destorg = screen->GetBuffer(); - fixed_t x0 = parms.x - Scale (parms.left, parms.destwidth, parms.texwidth); - fixed_t y0 = parms.y - Scale (parms.top, parms.destheight, parms.texheight); + double x0 = parms.x - parms.left * parms.destwidth / parms.texwidth; + double y0 = parms.y - parms.top * parms.destheight / parms.texheight; if (mode != DontDraw) { @@ -174,31 +174,43 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v fixed_t centeryback = centeryfrac; centeryfrac = 0; - sprtopscreen = y0; - spryscale = parms.destheight / img->GetHeight(); + sprtopscreen = FLOAT2FIXED(y0); + // There is not enough precision in the drawing routines to keep the full + // precision for y0. :( + sprtopscreen &= ~(FRACUNIT - 1); + double yscale = parms.destheight / img->GetHeight(); + double iyscale = 1 / yscale; + + spryscale = FLOAT2FIXED(yscale); + +#if 0 // Fix precision errors that are noticeable at some resolutions - if (((y0 + parms.destheight) >> FRACBITS) > ((y0 + spryscale * img->GetHeight()) >> FRACBITS)) + if ((y0 + parms.destheight) > (y0 + yscale * img->GetHeight())) { spryscale++; } +#endif sprflipvert = false; - dc_iscale = 0xffffffffu / (unsigned)spryscale; - dc_texturemid = FixedMul (-y0, dc_iscale); + //dc_iscale = FLOAT2FIXED(iyscale); + //dc_texturemid = FLOAT2FIXED((-y0) * iyscale); + //dc_iscale = 0xffffffffu / (unsigned)spryscale; + dc_iscale = DivScale32(1, spryscale); + dc_texturemid = FixedMul(-sprtopscreen, dc_iscale) + FixedMul(centeryfrac-FRACUNIT, dc_iscale); fixed_t frac = 0; - fixed_t xiscale = DivScale32 (img->GetWidth(), parms.destwidth); - int x2 = (x0 + parms.destwidth) >> FRACBITS; + double xiscale = parms.texwidth / parms.destwidth; + double x2 = x0 + parms.destwidth; if (bottomclipper[0] != parms.dclip) { - clearbufshort (bottomclipper, screen->GetWidth(), (short)parms.dclip); + clearbufshort(bottomclipper, screen->GetWidth(), (short)parms.dclip); } if (parms.uclip != 0) { if (topclipper[0] != parms.uclip) { - clearbufshort (topclipper, screen->GetWidth(), (short)parms.uclip); + clearbufshort(topclipper, screen->GetWidth(), (short)parms.uclip); } mceilingclip = topclipper; } @@ -214,48 +226,53 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v xiscale = -xiscale; } - dc_x = x0 >> FRACBITS; if (parms.windowleft > 0 || parms.windowright < parms.texwidth) { - fixed_t xscale = parms.destwidth / parms.texwidth; - dc_x += (parms.windowleft * xscale) >> FRACBITS; - frac += parms.windowleft << FRACBITS; - x2 -= ((parms.texwidth - parms.windowright) * xscale) >> FRACBITS; + double xscale = parms.destwidth / parms.texwidth; + x0 += parms.windowleft * xscale; + frac += FLOAT2FIXED(parms.windowleft); + x2 -= (parms.texwidth - parms.windowright) * xscale; } - if (dc_x < parms.lclip) + if (x0 < parms.lclip) { - frac += (parms.lclip - dc_x) * xiscale; - dc_x = parms.lclip; + frac += FLOAT2FIXED((parms.lclip - x0) * xiscale); + x0 = parms.lclip; } if (x2 > parms.rclip) { x2 = parms.rclip; } - if (parms.destheight < 32*FRACUNIT) + // Drawing short output ought to fit in the data cache well enough + // if we draw one column at a time, so do that, since it's simpler. + if (parms.destheight < 32 || (parms.dclip - parms.uclip) < 32) { mode = DoDraw0; } + dc_x = int(x0); + int x2_i = int(x2); + fixed_t xiscale_i = FLOAT2FIXED(xiscale); + if (mode == DoDraw0) { // One column at a time stop4 = dc_x; } - else // DoDraw1 + else // DoDraw1` { // Up to four columns at a time - stop4 = x2 & ~3; + stop4 = x2_i & ~3; } - if (dc_x < x2) + if (dc_x < x2_i) { while ((dc_x < stop4) && (dc_x & 3)) { - pixels = img->GetColumn (frac >> FRACBITS, spanptr); - R_DrawMaskedColumn (pixels, spans); + pixels = img->GetColumn(frac >> FRACBITS, spanptr); + R_DrawMaskedColumn(pixels, spans); dc_x++; - frac += xiscale; + frac += xiscale_i; } while (dc_x < stop4) @@ -263,20 +280,20 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v rt_initcols(); for (int zz = 4; zz; --zz) { - pixels = img->GetColumn (frac >> FRACBITS, spanptr); - R_DrawMaskedColumnHoriz (pixels, spans); + pixels = img->GetColumn(frac >> FRACBITS, spanptr); + R_DrawMaskedColumnHoriz(pixels, spans); dc_x++; - frac += xiscale; + frac += xiscale_i; } - rt_draw4cols (dc_x - 4); + rt_draw4cols(dc_x - 4); } - while (dc_x < x2) + while (dc_x < x2_i) { - pixels = img->GetColumn (frac >> FRACBITS, spanptr); - R_DrawMaskedColumn (pixels, spans); + pixels = img->GetColumn(frac >> FRACBITS, spanptr); + R_DrawMaskedColumn(pixels, spans); dc_x++; - frac += xiscale; + frac += xiscale_i; } } centeryfrac = centeryback; @@ -287,11 +304,11 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v if (ticdup != 0 && menuactive == MENU_Off) { - NetUpdate (); + NetUpdate(); } } -bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_list tags, DrawParms *parms, bool hw) const +bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag, va_list tags, DrawParms *parms, bool hw) const { INTBOOL boolval; int intval; @@ -313,8 +330,8 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l virtBottom = false; - parms->texwidth = img->GetScaledWidth(); - parms->texheight = img->GetScaledHeight(); + parms->texwidth = img->GetScaledWidthDouble(); + parms->texheight = img->GetScaledHeightDouble(); parms->windowleft = 0; parms->windowright = parms->texwidth; @@ -322,8 +339,8 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l parms->uclip = 0; parms->lclip = 0; parms->rclip = this->GetWidth(); - parms->destwidth = parms->windowright << FRACBITS; - parms->destheight = parms->texheight << FRACBITS; + parms->destwidth = parms->windowright; + parms->destheight = parms->texheight; parms->top = img->GetScaledTopOffset(); parms->left = img->GetScaledLeftOffset(); parms->alpha = FRACUNIT; @@ -344,10 +361,12 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l parms->specialcolormap = NULL; parms->colormapstyle = NULL; - parms->x = x << FRACBITS; - parms->y = y << FRACBITS; + parms->x = x; + parms->y = y; - // Parse the tag list for attributes + // Parse the tag list for attributes. (For floating point attributes, + // consider that the C ABI dictates that all floats be promoted to + // doubles when passed as function arguments.) while (tag != TAG_DONE) { va_list *more_p; @@ -357,11 +376,11 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l { case TAG_IGNORE: default: - data = va_arg (tags, DWORD); + data = va_arg(tags, DWORD); break; case TAG_MORE: - more_p = va_arg (tags, va_list *); + more_p = va_arg(tags, va_list *); va_end (tags); #ifndef NO_VA_COPY va_copy (tags, *more_p); @@ -371,35 +390,43 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_DestWidth: - parms->destwidth = va_arg (tags, int) << FRACBITS; + parms->destwidth = va_arg(tags, int); + break; + + case DTA_DestWidthF: + parms->destwidth = va_arg(tags, double); break; case DTA_DestHeight: - parms->destheight = va_arg (tags, int) << FRACBITS; + parms->destheight = va_arg(tags, int); + break; + + case DTA_DestHeightF: + parms->destheight = va_arg(tags, double); break; case DTA_Clean: - boolval = va_arg (tags, INTBOOL); + boolval = va_arg(tags, INTBOOL); if (boolval) { - parms->x = (parms->x - 160*FRACUNIT) * CleanXfac + (Width * (FRACUNIT/2)); - parms->y = (parms->y - 100*FRACUNIT) * CleanYfac + (Height * (FRACUNIT/2)); - parms->destwidth = parms->texwidth * CleanXfac * FRACUNIT; - parms->destheight = parms->texheight * CleanYfac * FRACUNIT; + parms->x = (parms->x - 160.0) * CleanXfac + (Width * 0.5); + parms->y = (parms->y - 100.0) * CleanYfac + (Height * 0.5); + parms->destwidth = parms->texwidth * CleanXfac; + parms->destheight = parms->texheight * CleanYfac; } break; case DTA_CleanNoMove: - boolval = va_arg (tags, INTBOOL); + boolval = va_arg(tags, INTBOOL); if (boolval) { - parms->destwidth = parms->texwidth * CleanXfac * FRACUNIT; - parms->destheight = parms->texheight * CleanYfac * FRACUNIT; + parms->destwidth = parms->texwidth * CleanXfac; + parms->destheight = parms->texheight * CleanYfac; } break; case DTA_320x200: - boolval = va_arg (tags, INTBOOL); + boolval = va_arg(tags, INTBOOL); if (boolval) { parms->virtWidth = 320; @@ -408,7 +435,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_Bottom320x200: - boolval = va_arg (tags, INTBOOL); + boolval = va_arg(tags, INTBOOL); if (boolval) { parms->virtWidth = 320; @@ -421,99 +448,123 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l { bool xright = parms->x < 0; bool ybot = parms->y < 0; - intval = va_arg (tags, int); + intval = va_arg(tags, int); if (hud_scale) { parms->x *= CleanXfac; if (intval == HUD_HorizCenter) - parms->x += Width * FRACUNIT / 2; + parms->x += Width * 0.5; else if (xright) - parms->x = Width * FRACUNIT + parms->x; + parms->x = Width + parms->x; parms->y *= CleanYfac; if (ybot) - parms->y = Height * FRACUNIT + parms->y; - parms->destwidth = parms->texwidth * CleanXfac * FRACUNIT; - parms->destheight = parms->texheight * CleanYfac * FRACUNIT; + parms->y = Height + parms->y; + parms->destwidth = parms->texwidth * CleanXfac; + parms->destheight = parms->texheight * CleanYfac; } else { if (intval == HUD_HorizCenter) - parms->x += Width * FRACUNIT / 2; + parms->x += Width * 0.5; else if (xright) - parms->x = Width * FRACUNIT + parms->x; + parms->x = Width + parms->x; if (ybot) - parms->y = Height * FRACUNIT + parms->y; + parms->y = Height + parms->y; } } break; case DTA_VirtualWidth: - parms->virtWidth = va_arg (tags, int); + parms->virtWidth = va_arg(tags, int); + break; + + case DTA_VirtualWidthF: + parms->virtWidth = va_arg(tags, double); break; case DTA_VirtualHeight: - parms->virtHeight = va_arg (tags, int); + parms->virtHeight = va_arg(tags, int); + break; + + case DTA_VirtualHeightF: + parms->virtHeight = va_arg(tags, double); break; case DTA_Alpha: - parms->alpha = MIN (FRACUNIT, va_arg (tags, fixed_t)); + parms->alpha = MIN(FRACUNIT, va_arg (tags, fixed_t)); break; case DTA_AlphaChannel: - parms->alphaChannel = va_arg (tags, INTBOOL); + parms->alphaChannel = va_arg(tags, INTBOOL); break; case DTA_FillColor: - parms->fillcolor = va_arg (tags, int); + parms->fillcolor = va_arg(tags, uint32); break; case DTA_Translation: - parms->remap = va_arg (tags, FRemapTable *); + parms->remap = va_arg(tags, FRemapTable *); break; case DTA_ColorOverlay: - parms->colorOverlay = va_arg (tags, DWORD); + parms->colorOverlay = va_arg(tags, DWORD); break; case DTA_FlipX: - parms->flipX = va_arg (tags, INTBOOL); + parms->flipX = va_arg(tags, INTBOOL); break; case DTA_TopOffset: - parms->top = va_arg (tags, int); + parms->top = va_arg(tags, int); + break; + + case DTA_TopOffsetF: + parms->top = va_arg(tags, double); break; case DTA_LeftOffset: - parms->left = va_arg (tags, int); + parms->left = va_arg(tags, int); + break; + + case DTA_LeftOffsetF: + parms->left = va_arg(tags, double); break; case DTA_CenterOffset: - if (va_arg (tags, int)) + if (va_arg(tags, int)) { - parms->left = parms->texwidth / 2; - parms->top = parms->texheight / 2; + parms->left = parms->texwidth * 0.5; + parms->top = parms->texheight * 0.5; } break; case DTA_CenterBottomOffset: - if (va_arg (tags, int)) + if (va_arg(tags, int)) { - parms->left = parms->texwidth / 2; + parms->left = parms->texwidth * 0.5; parms->top = parms->texheight; } break; case DTA_WindowLeft: - parms->windowleft = va_arg (tags, int); + parms->windowleft = va_arg(tags, int); + break; + + case DTA_WindowLeftF: + parms->windowleft = va_arg(tags, double); break; case DTA_WindowRight: - parms->windowright = va_arg (tags, int); + parms->windowright = va_arg(tags, int); + break; + + case DTA_WindowRightF: + parms->windowright = va_arg(tags, double); break; case DTA_ClipTop: - parms->uclip = va_arg (tags, int); + parms->uclip = va_arg(tags, int); if (parms->uclip < 0) { parms->uclip = 0; @@ -521,7 +572,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_ClipBottom: - parms->dclip = va_arg (tags, int); + parms->dclip = va_arg(tags, int); if (parms->dclip > this->GetHeight()) { parms->dclip = this->GetHeight(); @@ -529,7 +580,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_ClipLeft: - parms->lclip = va_arg (tags, int); + parms->lclip = va_arg(tags, int); if (parms->lclip < 0) { parms->lclip = 0; @@ -537,7 +588,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_ClipRight: - parms->rclip = va_arg (tags, int); + parms->rclip = va_arg(tags, int); if (parms->rclip > this->GetWidth()) { parms->rclip = this->GetWidth(); @@ -545,15 +596,15 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_ShadowAlpha: - parms->shadowAlpha = MIN (FRACUNIT, va_arg (tags, fixed_t)); + parms->shadowAlpha = MIN(FRACUNIT, va_arg (tags, fixed_t)); break; case DTA_ShadowColor: - parms->shadowColor = va_arg (tags, int); + parms->shadowColor = va_arg(tags, int); break; case DTA_Shadow: - boolval = va_arg (tags, INTBOOL); + boolval = va_arg(tags, INTBOOL); if (boolval) { parms->shadowAlpha = FRACUNIT/2; @@ -566,32 +617,32 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_Masked: - parms->masked = va_arg (tags, INTBOOL); + parms->masked = va_arg(tags, INTBOOL); break; case DTA_BilinearFilter: - parms->bilinear = va_arg (tags, INTBOOL); + parms->bilinear = va_arg(tags, INTBOOL); break; case DTA_KeepRatio: // I think this is a terribly misleading name, since it actually turns // *off* aspect ratio correction. - parms->keepratio = va_arg (tags, INTBOOL); + parms->keepratio = va_arg(tags, INTBOOL); break; case DTA_RenderStyle: - parms->style.AsDWORD = va_arg (tags, DWORD); + parms->style.AsDWORD = va_arg(tags, DWORD); break; case DTA_SpecialColormap: - parms->specialcolormap = va_arg (tags, FSpecialColormap *); + parms->specialcolormap = va_arg(tags, FSpecialColormap *); break; case DTA_ColormapStyle: - parms->colormapstyle = va_arg (tags, FColormapStyle *); + parms->colormapstyle = va_arg(tags, FColormapStyle *); break; } - tag = va_arg (tags, DWORD); + tag = va_arg(tags, DWORD); } va_end (tags); @@ -645,66 +696,72 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l return true; } -void DCanvas::VirtualToRealCoords(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, - int vwidth, int vheight, bool vbottom, bool handleaspect) const +void DCanvas::VirtualToRealCoords(double &x, double &y, double &w, double &h, + double vwidth, double vheight, bool vbottom, bool handleaspect) const { int myratio = handleaspect ? CheckRatio (Width, Height) : 0; - int right = x + w; - int bottom = y + h; + double right = x + w; + double bottom = y + h; if (myratio != 0 && myratio != 4) { // The target surface is either 16:9 or 16:10, so expand the // specified virtual size to avoid undesired stretching of the // image. Does not handle non-4:3 virtual sizes. I'll worry about // those if somebody expresses a desire to use them. - x = Scale(x - vwidth*FRACUNIT/2, - Width*960, - vwidth*BaseRatioSizes[myratio][0]) - + Width*FRACUNIT/2; - w = Scale(right - vwidth*FRACUNIT/2, - Width*960, - vwidth*BaseRatioSizes[myratio][0]) - + Width*FRACUNIT/2 - x; + x = (x - vwidth * 0.5) * Width * 960 / (vwidth * BaseRatioSizes[myratio][0]) + Width * 0.5; + w = (right - vwidth * 0.5) * Width * 960 / (vwidth * BaseRatioSizes[myratio][0]) + Width * 0.5 - x; } else { - x = Scale (x, Width, vwidth); - w = Scale (right, Width, vwidth) - x; + x = x * Width / vwidth; + w = right * Width / vwidth - x; } if (myratio == 4) { // The target surface is 5:4 - y = Scale(y - vheight*FRACUNIT/2, - Height*600, - vheight*BaseRatioSizes[myratio][1]) - + Height*FRACUNIT/2; - h = Scale(bottom - vheight*FRACUNIT/2, - Height*600, - vheight*BaseRatioSizes[myratio][1]) - + Height*FRACUNIT/2 - y; + y = (y - vheight * 0.5) * Height * 600 / (vheight * BaseRatioSizes[myratio][1]) + Height * 0.5; + h = (bottom - vheight * 0.5) * Height * 600 / (vheight * BaseRatioSizes[myratio][1]) + Height * 0.5 - y; if (vbottom) { - y += (Height - Height * BaseRatioSizes[myratio][3] / 48) << (FRACBITS - 1); + y += (Height - Height * BaseRatioSizes[myratio][3] / 48.0) * 0.5; } } else { - y = Scale (y, Height, vheight); - h = Scale (bottom, Height, vheight) - y; + y = y * Height / vheight; + h = bottom * Height / vheight - y; } } +void DCanvas::VirtualToRealCoordsFixed(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, + int vwidth, int vheight, bool vbottom, bool handleaspect) const +{ + double dx, dy, dw, dh; + + dx = FIXED2FLOAT(x); + dy = FIXED2FLOAT(y); + dw = FIXED2FLOAT(w); + dh = FIXED2FLOAT(h); + VirtualToRealCoords(dx, dy, dw, dh, vwidth, vheight, vbottom, handleaspect); + x = FLOAT2FIXED(dx); + y = FLOAT2FIXED(dy); + w = FLOAT2FIXED(dw); + h = FLOAT2FIXED(dh); +} + void DCanvas::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom, bool handleaspect) const { - x <<= FRACBITS; - y <<= FRACBITS; - w <<= FRACBITS; - h <<= FRACBITS; - VirtualToRealCoords(x, y, w, h, vwidth, vheight, vbottom, handleaspect); - x >>= FRACBITS; - y >>= FRACBITS; - w >>= FRACBITS; - h >>= FRACBITS; + double dx, dy, dw, dh; + + dx = x; + dy = y; + dw = w; + dh = h; + VirtualToRealCoords(dx, dy, dw, dh, vwidth, vheight, vbottom, handleaspect); + x = int(dx + 0.5); + y = int(dy + 0.5); + w = int(dx + dw + 0.5) - x; + h = int(dy + dh + 0.5) - y; } void DCanvas::FillBorder (FTexture *img) diff --git a/src/v_video.h b/src/v_video.h index 3109901bb..394ba319e 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -87,8 +87,8 @@ enum DTA_VirtualHeight, // pretend the canvas is this tall DTA_TopOffset, // override texture's top offset DTA_LeftOffset, // override texture's left offset - DTA_CenterOffset, // override texture's left and top offsets and set them for the texture's middle - DTA_CenterBottomOffset,// override texture's left and top offsets and set them for the texture's bottom middle + DTA_CenterOffset, // bool: override texture's left and top offsets and set them for the texture's middle + DTA_CenterBottomOffset,// bool: override texture's left and top offsets and set them for the texture's bottom middle DTA_WindowLeft, // don't draw anything left of this column (on source, not dest) DTA_WindowRight, // don't draw anything at or to the right of this column (on source, not dest) DTA_ClipTop, // don't draw anything above this row (on dest, not source) @@ -104,6 +104,16 @@ enum DTA_SpecialColormap,// pointer to FSpecialColormapParameters (likely to be forever hardware-only) DTA_ColormapStyle, // pointer to FColormapStyle (hardware-only) + // floating point duplicates of some of the above: + DTA_DestWidthF, + DTA_DestHeightF, + DTA_TopOffsetF, + DTA_LeftOffsetF, + DTA_VirtualWidthF, + DTA_VirtualHeightF, + DTA_WindowLeftF, + DTA_WindowRightF, + // For DrawText calls: DTA_TextLen, // stop after this many characters, even if \0 not hit DTA_CellX, // horizontal size of character cell @@ -188,9 +198,12 @@ public: // Text drawing functions ----------------------------------------------- // 2D Texture drawing - void STACK_ARGS DrawTexture (FTexture *img, int x, int y, int tags, ...); + void STACK_ARGS DrawTexture (FTexture *img, double x, double y, int tags, ...); void FillBorder (FTexture *img); // Fills the border around a 4:3 part of the screen on non-4:3 displays - void VirtualToRealCoords(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; + void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom=false, bool handleaspect=true) const; + + // Code that uses these (i.e. SBARINFO) should probably be evaluated for using doubles all around instead. + void VirtualToRealCoordsFixed(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; void VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; // 2D Text drawing @@ -199,21 +212,23 @@ public: struct DrawParms { - fixed_t x, y; - int texwidth; - int texheight; - int windowleft; - int windowright; + double x, y; + double texwidth; + double texheight; + double destwidth; + double destheight; + double virtWidth; + double virtHeight; + double windowleft; + double windowright; int dclip; int uclip; int lclip; int rclip; - fixed_t destwidth; - fixed_t destheight; - int top; - int left; + double top; + double left; fixed_t alpha; - int fillcolor; + uint32 fillcolor; FRemapTable *remap; const BYTE *translation; DWORD colorOverlay; @@ -221,8 +236,6 @@ public: INTBOOL flipX; fixed_t shadowAlpha; int shadowColor; - int virtWidth; - int virtHeight; INTBOOL keepratio; INTBOOL masked; INTBOOL bilinear; @@ -239,8 +252,8 @@ protected: int LockCount; bool ClipBox (int &left, int &top, int &width, int &height, const BYTE *&src, const int srcpitch) const; - virtual void STACK_ARGS DrawTextureV (FTexture *img, int x, int y, uint32 tag, va_list tags); - bool ParseDrawTextureTags (FTexture *img, int x, int y, uint32 tag, va_list tags, DrawParms *parms, bool hw) const; + virtual void STACK_ARGS DrawTextureV (FTexture *img, double x, double y, uint32 tag, va_list tags); + bool ParseDrawTextureTags (FTexture *img, double x, double y, uint32 tag, va_list tags, DrawParms *parms, bool hw) const; DCanvas() {} @@ -339,7 +352,7 @@ public: // Tells the device to recreate itself with the new setting from vid_refreshrate. virtual void NewRefreshRate (); - // Set the rect defining the area effected by blending. + // Set the rect defining the area affected by blending. virtual void SetBlendingRect (int x1, int y1, int x2, int y2); // render 3D view @@ -470,6 +483,7 @@ extern "C" void ASM_PatchPitch (void); #endif int CheckRatio (int width, int height); +static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); } extern const int BaseRatioSizes[5][4]; diff --git a/src/vectors.h b/src/vectors.h index f3b154aa2..ea11ab611 100644 --- a/src/vectors.h +++ b/src/vectors.h @@ -1231,6 +1231,6 @@ typedef TMatrix3x3 FMatrix3x3; typedef TAngle FAngle; #define FLOAT2FIXED(f) fixed_t((f) * float(65536)) -#define FIXED2FLOAT(f) (float(f) / float(65536)) +#define FIXED2FLOAT(f) ((f) / float(65536)) #endif diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index a776144ea..7e9197b0e 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -2734,7 +2734,7 @@ void D3DFB::DrawPixel(int x, int y, int palcolor, uint32 color) // //========================================================================== -void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_first, va_list tags) +void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, double x, double y, uint32 tags_first, va_list tags) { if (In2D < 2) { @@ -2759,17 +2759,17 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi CheckQuadBatch(); - float xscale = float(parms.destwidth) / parms.texwidth / 65536.f; - float yscale = float(parms.destheight) / parms.texheight / 65536.f; - float x0 = float(parms.x) / 65536.f - float(parms.left) * xscale; - float y0 = float(parms.y) / 65536.f - float(parms.top) * yscale; - float x1 = x0 + float(parms.destwidth) / 65536.f; - float y1 = y0 + float(parms.destheight) / 65536.f; + double xscale = parms.destwidth / parms.texwidth; + double yscale = parms.destheight / parms.texheight; + double x0 = parms.x - parms.left * xscale; + double y0 = parms.y - parms.top * yscale; + double x1 = x0 + parms.destwidth; + double y1 = y0 + parms.destheight; float u0 = tex->Box->Left; float v0 = tex->Box->Top; float u1 = tex->Box->Right; float v1 = tex->Box->Bottom; - float uscale = 1.f / tex->Box->Owner->Width; + double uscale = 1.f / tex->Box->Owner->Width; bool scissoring = false; if (parms.flipX) @@ -2779,9 +2779,9 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi if (parms.windowleft > 0 || parms.windowright < parms.texwidth) { x0 += parms.windowleft * xscale; - u0 += parms.windowleft * uscale; + u0 = float(u0 + parms.windowleft * uscale); x1 -= (parms.texwidth - parms.windowright) * xscale; - u1 -= (parms.texwidth - parms.windowright) * uscale; + u1 = float(u1 - (parms.texwidth - parms.windowright) * uscale); } #if 0 float vscale = 1.f / tex->Box->Owner->Height / yscale; @@ -2841,6 +2841,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi float yoffs = GatheringWipeScreen ? 0.5f : 0.5f - LBOffset; +#if 0 // Coordinates are truncated to integers, because that's effectively // what the software renderer does. The hardware will instead round // to nearest, it seems. @@ -2848,11 +2849,18 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi y0 = floorf(y0) - yoffs; x1 = floorf(x1) - 0.5f; y1 = floorf(y1) - yoffs; +#else + x0 = x0 - 0.5f; + y0 = y0 - yoffs; + x1 = x1 - 0.5f; + y1 = y1 - yoffs; +#endif FBVERTEX *vert = &VertexData[VertexPos]; - vert[0].x = x0; - vert[0].y = y0; + // Fill the vertex buffer. + vert[0].x = float(x0); + vert[0].y = float(y0); vert[0].z = 0; vert[0].rhw = 1; vert[0].color0 = color0; @@ -2860,8 +2868,8 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi vert[0].tu = u0; vert[0].tv = v0; - vert[1].x = x1; - vert[1].y = y0; + vert[1].x = float(x1); + vert[1].y = float(y0); vert[1].z = 0; vert[1].rhw = 1; vert[1].color0 = color0; @@ -2869,8 +2877,8 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi vert[1].tu = u1; vert[1].tv = v0; - vert[2].x = x1; - vert[2].y = y1; + vert[2].x = float(x1); + vert[2].y = float(y1); vert[2].z = 0; vert[2].rhw = 1; vert[2].color0 = color0; @@ -2878,8 +2886,8 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi vert[2].tu = u1; vert[2].tv = v1; - vert[3].x = x0; - vert[3].y = y1; + vert[3].x = float(x0); + vert[3].y = float(y1); vert[3].z = 0; vert[3].rhw = 1; vert[3].color0 = color0; @@ -2887,6 +2895,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi vert[3].tu = u0; vert[3].tv = v1; + // Fill the vertex index buffer. IndexData[IndexPos ] = VertexPos; IndexData[IndexPos + 1] = VertexPos + 1; IndexData[IndexPos + 2] = VertexPos + 2; @@ -2894,6 +2903,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi IndexData[IndexPos + 4] = VertexPos + 2; IndexData[IndexPos + 5] = VertexPos + 3; + // Batch the quad. QuadBatchPos++; VertexPos += 4; IndexPos += 6; diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index 6c7c066b7..6cce6afe1 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -248,7 +248,7 @@ public: void DrawBlendingRect (); FNativeTexture *CreateTexture (FTexture *gametex, bool wrapping); FNativePalette *CreatePalette (FRemapTable *remap); - void STACK_ARGS DrawTextureV (FTexture *img, int x, int y, uint32 tag, va_list tags); + void STACK_ARGS DrawTextureV (FTexture *img, double x, double y, uint32 tag, va_list tags); void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color); void Dim (PalEntry color, float amount, int x1, int y1, int w, int h); void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin); diff --git a/zdoom.vcproj b/zdoom.vcproj index 2a33a2c6b..681c2ce69 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - @@ -1868,6 +1860,14 @@ Outputs="$(IntDir)/$(InputName).obj" /> + + + @@ -2057,6 +2057,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -2067,14 +2075,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - + + + - - - + + + @@ -5343,14 +5351,6 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> - - - @@ -5629,7 +5629,7 @@ />