diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 4eb3653d7..5a37eeaea 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,12 @@ +December 19, 2007 +- Added a framework for drawing the 2D screen elements with Direct3D textures. + They are not actually drawn with it yet, nor is it complete, but it's + something to start with. +- Split up DCanvas::DrawTexture() into more pieces to make it easier to + virtualize. +- Removed support for non-32-bit palette textures from D3DFB. What kind of + card supports pixel shaders but not 32-bit textures? + December 17, 2007 - Fixed: In the video modes menu, pressing Enter tried to change the screen mode, even if the cursor wasn't on one of the mode items. diff --git a/src/d_main.cpp b/src/d_main.cpp index 11217887a..f4f4ac034 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -430,7 +430,7 @@ CVAR (Flag, compat_invisibility,compatflags, COMPATF_INVISIBILITY); // Draw current display, possibly wiping it from the previous // //========================================================================== - +CVAR(Bool,test2d,true,0) void D_Display (bool screenshot) { bool wipe; @@ -630,7 +630,25 @@ void D_Display (bool screenshot) M_Drawer (); // menu is drawn even on top of everything FStat::PrintStat (); if (!screenshot) + { +#if 0 + if (test2d) + screen->Begin2D(); + screen->DrawTexture(TexMan["M_HTIC"], 0, 0, + DTA_Clean, true, + TAG_DONE); + screen->DrawTexture(TexMan["XHAIRB3"], 200, 100, + DTA_DestWidth, 128, + DTA_DestHeight, 128, + DTA_Alpha, ((gametic & 31) + 1) << (16-5), +// DTA_RenderStyle, STYLE_Add, + DTA_FillColor, MAKEARGB(ColorMatcher.Pick(254,254,0),254,254,0), + DTA_AlphaChannel, true, + TAG_DONE); + screen->End2D(); +#endif screen->Update (); // page flip or blit buffer + } } else { diff --git a/src/r_data.h b/src/r_data.h index f4361cb2b..05f7080c7 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -236,6 +236,7 @@ public: const BYTE *GetColumn (unsigned int column, const Span **spans_out); const BYTE *GetPixels (); void Unload (); + FTextureFormat GetFormat (); protected: @@ -270,6 +271,7 @@ public: const BYTE *GetColumn (unsigned int column, const Span **spans_out); const BYTE *GetPixels (); void Unload (); + FTextureFormat GetFormat (); protected: static bool Check (FileReader &file); @@ -309,6 +311,7 @@ public: const BYTE *GetColumn (unsigned int column, const Span **spans_out); const BYTE *GetPixels (); void Unload (); + FTextureFormat GetFormat (); protected: @@ -356,6 +359,7 @@ public: const BYTE *GetColumn (unsigned int column, const Span **spans_out); const BYTE *GetPixels (); void Unload (); + FTextureFormat GetFormat (); protected: int SourceLump; diff --git a/src/r_defs.h b/src/r_defs.h index 17d1b9848..b4a10fad5 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -591,6 +591,22 @@ struct patch_t class FileReader; +// All FTextures present their data to the world in 8-bit format, but if +// the source data is something else, this is it. +enum FTextureFormat +{ + TEX_Pal, + TEX_Gray, + TEX_RGB, // Actually ARGB + TEX_DXT1, + TEX_DXT2, + TEX_DXT3, + TEX_DXT4, + TEX_DXT5, +}; + +class FNativeTexture; + // Base texture class class FTexture { @@ -651,6 +667,18 @@ public: virtual void Unload () = 0; + // Returns the native pixel format for this image + virtual FTextureFormat GetFormat(); + + // Returns a native 3D representation of the texture + FNativeTexture *GetNative(); + + // Frees the native 3D representation of the texture + void KillNative(); + + // Fill the native texture buffer with pixel data for this image + virtual void FillBuffer(BYTE *buff, int pitch, FTextureFormat fmt); + int GetWidth () { return Width; } int GetHeight () { return Height; } @@ -668,6 +696,7 @@ public: // last call to GetPixels(). This should be considered valid only if a call to CheckModified() // is immediately followed by a call to GetPixels(). virtual bool CheckModified (); + static void InitGrayMap(); void CopySize(FTexture *BaseTexture) @@ -695,6 +724,7 @@ public: protected: WORD Width, Height, WidthMask; static BYTE GrayMap[256]; + FNativeTexture *Native; FTexture (); diff --git a/src/textures/ddstexture.cpp b/src/textures/ddstexture.cpp index 868bd59d9..06dba93e9 100644 --- a/src/textures/ddstexture.cpp +++ b/src/textures/ddstexture.cpp @@ -3,7 +3,7 @@ ** Texture class for DDS images ** **--------------------------------------------------------------------------- -** Copyright 2006 Randy Heit +** Copyright 2006-2007 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -314,6 +314,19 @@ void FDDSTexture::Unload () } } +FTextureFormat FDDSTexture::GetFormat() +{ + switch (Format) + { + case ID_DXT1: return TEX_DXT1; + case ID_DXT2: return TEX_DXT2; + case ID_DXT3: return TEX_DXT3; + case ID_DXT4: return TEX_DXT4; + case ID_DXT5: return TEX_DXT5; + default: return TEX_RGB; + } +} + const BYTE *FDDSTexture::GetColumn (unsigned int column, const Span **spans_out) { if (Pixels == NULL) diff --git a/src/textures/jpegtexture.cpp b/src/textures/jpegtexture.cpp index 8efb5ba49..f9a178662 100644 --- a/src/textures/jpegtexture.cpp +++ b/src/textures/jpegtexture.cpp @@ -3,7 +3,7 @@ ** Texture class for JPEG images ** **--------------------------------------------------------------------------- -** Copyright 2006 Randy Heit +** Copyright 2006-2007 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -133,7 +133,7 @@ FTexture *FJPEGTexture::Create(FileReader & data, int lumpnum) { return NULL; } - if (BigShort (first4bytes.w[0]) <5) + if (BigShort (first4bytes.w[0]) < 5) { return NULL; } @@ -192,6 +192,11 @@ void FJPEGTexture::Unload () } } +FTextureFormat FJPEGTexture::GetFormat() +{ + return TEX_RGB; +} + const BYTE *FJPEGTexture::GetColumn (unsigned int column, const Span **spans_out) { if (Pixels == NULL) diff --git a/src/textures/pngtexture.cpp b/src/textures/pngtexture.cpp index 576ceeba3..17c6e85e1 100644 --- a/src/textures/pngtexture.cpp +++ b/src/textures/pngtexture.cpp @@ -3,7 +3,7 @@ ** Texture class for PNG images ** **--------------------------------------------------------------------------- -** Copyright 2004-2006 Randy Heit +** Copyright 2004-2007 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -89,8 +89,7 @@ FTexture *FPNGTexture::Create(FileReader & data, int lumpnum) return NULL; } - // Just for completeness, make sure the PNG has something more than an - // IHDR. + // Just for completeness, make sure the PNG has something more than an IHDR. data.Seek (4, SEEK_CUR); data.Read (first4bytes.b, 4); if (first4bytes.dw == 0) @@ -269,6 +268,16 @@ void FPNGTexture::Unload () } } +FTextureFormat FPNGTexture::GetFormat() +{ + switch (ColorType) + { + case 3: return TEX_Pal; + case 0: return TEX_Gray; + default: return TEX_RGB; + } +} + const BYTE *FPNGTexture::GetColumn (unsigned int column, const Span **spans_out) { if (Pixels == NULL) diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 7d10c1f3f..e9650a15c 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -3,7 +3,7 @@ ** The base texture class ** **--------------------------------------------------------------------------- -** Copyright 2004-2006 Randy Heit +** Copyright 2004-2007 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -38,6 +38,7 @@ #include "w_wad.h" #include "r_data.h" #include "templates.h" +#include "i_system.h" typedef bool (*CheckFunc)(FileReader & file); typedef FTexture * (*CreateFunc)(FileReader & file, int lumpnum); @@ -117,9 +118,9 @@ FTexture::FTexture () WidthBits(0), HeightBits(0), xScale(FRACUNIT), yScale(FRACUNIT), UseType(TEX_Any), bNoDecals(false), bNoRemap0(false), bWorldPanning(false), bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bIsPatch(false), - Rotations(0xFFFF), Width(0), Height(0), WidthMask(0) + Rotations(0xFFFF), Width(0), Height(0), WidthMask(0), Native(NULL) { - *Name=0; + *Name = 0; } FTexture::~FTexture () @@ -131,6 +132,11 @@ bool FTexture::CheckModified () return false; } +FTextureFormat FTexture::GetFormat() +{ + return TEX_Pal; +} + void FTexture::SetFrontSkyLayer () { bNoRemap0 = true; @@ -397,6 +403,83 @@ void FTexture::FlipNonSquareBlockRemap (BYTE *dst, const BYTE *src, int x, int y } } +FNativeTexture *FTexture::GetNative() +{ + if (Native != NULL) + { + return Native; + } + Native = screen->CreateTexture(this); + return Native; +} + +void FTexture::KillNative() +{ + if (Native != NULL) + { + delete Native; + Native = NULL; + } +} + +// For this generic implementation, we just call GetPixels and copy that data +// to the buffer. Texture formats that can do better than paletted images +// should provide their own implementation that may preserve the original +// color data. Note that the buffer expects row-major data, since that's +// generally more convenient for any non-Doom image formats, and it doesn't +// need to be used by any of Doom's column drawing routines. +void FTexture::FillBuffer(BYTE *buff, int pitch, FTextureFormat fmt) +{ + const BYTE *pix; + int x, y, w, h, stride; + + w = GetWidth(); + h = GetHeight(); + pix = GetPixels(); + + switch (fmt) + { + case TEX_Pal: + case TEX_Gray: + stride = pitch - w; + for (y = 0; y < h; ++y) + { + const BYTE *pix2 = pix; + for (x = 0; x < w; ++x) + { + *buff++ = *pix2; + pix2 += h; + } + pix++; + buff += stride; + } + break; + + case TEX_RGB: + stride = pitch - w * 4; + for (y = 0; y < h; ++y) + { + const BYTE *pix2 = pix; + for (x = 0; x < w; ++x) + { + const PalEntry *pal = &GPalette.BaseColors[*pix2]; + buff[0] = pal->b; + buff[1] = pal->g; + buff[2] = pal->r; + buff[3] = pal->a; + buff += 4; + pix2 += h; + } + pix++; + buff += stride; + } + break; + + default: + I_Error("FTexture::FillBuffer: Unsupported format %d", fmt); + } +} + FDummyTexture::FDummyTexture () { Width = 64; diff --git a/src/textures/tgatexture.cpp b/src/textures/tgatexture.cpp index 69add85d9..982acac35 100644 --- a/src/textures/tgatexture.cpp +++ b/src/textures/tgatexture.cpp @@ -110,6 +110,11 @@ void FTGATexture::Unload () } } +FTextureFormat FTGATexture::GetFormat() +{ + return TEX_RGB; +} + const BYTE *FTGATexture::GetColumn (unsigned int column, const Span **spans_out) { if (Pixels == NULL) diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 8a2eb908c..c9989a2d0 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -55,346 +55,44 @@ int CleanWidth, CleanHeight; CVAR (Bool, hud_scale, false, CVAR_ARCHIVE); -void STACK_ARGS DCanvas::DrawTexture (FTexture *img, int x0, int y0, int tags_first, ...) +void STACK_ARGS DCanvas::DrawTexture (FTexture *img, int x, int 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) { FTexture::Span unmaskedSpan[2]; const FTexture::Span **spanptr, *spans; static BYTE identitymap[256]; static short bottomclipper[MAXWIDTH], topclipper[MAXWIDTH]; - va_list tags; - DWORD tag; - INTBOOL boolval; - int intval; - if (img == NULL || img->UseType == FTexture::TEX_Null) + DrawParms parms; + + if (!ParseDrawTextureTags(img, x, y, tag, tags, &parms)) { return; } - int texwidth = img->GetScaledWidth(); - int texheight = img->GetScaledHeight(); - - int windowleft = 0; - int windowright = texwidth; - int dclip = this->GetHeight(); - int uclip = 0; - int lclip = 0; - int rclip = this->GetWidth(); - int destwidth = windowright << FRACBITS; - int destheight = texheight << FRACBITS; - int top = img->GetScaledTopOffset(); - int left = img->GetScaledLeftOffset(); - fixed_t alpha = FRACUNIT; - int fillcolor = -1; - const BYTE *translation = NULL; - INTBOOL alphaChannel = false; - INTBOOL flipX = false; - fixed_t shadowAlpha = 0; - int shadowColor = 0; - int virtWidth = this->GetWidth(); - int virtHeight = this->GetHeight(); - INTBOOL keepratio = false; - ERenderStyle style = STYLE_Count; - - x0 <<= FRACBITS; - y0 <<= FRACBITS; - - spanptr = &spans; - - // Parse the tag list for attributes - va_start (tags, tags_first); - tag = tags_first; - - while (tag != TAG_DONE) + if (parms.masked) { - va_list *more_p; - DWORD data; - - switch (tag) - { - case TAG_IGNORE: - default: - data = va_arg (tags, DWORD); - break; - - case TAG_MORE: - more_p = va_arg (tags, va_list *); - va_end (tags); -#ifdef __GNUC__ - __va_copy (tags, *more_p); -#else - tags = *more_p; -#endif - break; - - case DTA_DestWidth: - destwidth = va_arg (tags, int) << FRACBITS; - break; - - case DTA_DestHeight: - destheight = va_arg (tags, int) << FRACBITS; - break; - - case DTA_Clean: - boolval = va_arg (tags, INTBOOL); - if (boolval) - { - x0 = (x0 - 160*FRACUNIT) * CleanXfac + (Width * (FRACUNIT/2)); - y0 = (y0 - 100*FRACUNIT) * CleanYfac + (Height * (FRACUNIT/2)); - destwidth = texwidth * CleanXfac * FRACUNIT; - destheight = texheight * CleanYfac * FRACUNIT; - } - break; - - case DTA_CleanNoMove: - boolval = va_arg (tags, INTBOOL); - if (boolval) - { - destwidth = texwidth * CleanXfac * FRACUNIT; - destheight = texheight * CleanYfac * FRACUNIT; - } - break; - - case DTA_320x200: - boolval = va_arg (tags, INTBOOL); - if (boolval) - { - virtWidth = 320; - virtHeight = 200; - } - break; - - case DTA_HUDRules: - { - bool xright = x0 < 0; - bool ybot = y0 < 0; - intval = va_arg (tags, int); - - if (hud_scale) - { - x0 *= CleanXfac; - if (intval == HUD_HorizCenter) - x0 += Width * FRACUNIT / 2; - else if (xright) - x0 = Width * FRACUNIT + x0; - y0 *= CleanYfac; - if (ybot) - y0 = Height * FRACUNIT + y0; - destwidth = texwidth * CleanXfac * FRACUNIT; - destheight = texheight * CleanYfac * FRACUNIT; - } - else - { - if (intval == HUD_HorizCenter) - x0 += Width * FRACUNIT / 2; - else if (xright) - x0 = Width * FRACUNIT + x0; - if (ybot) - y0 = Height * FRACUNIT + y0; - } - } - break; - - case DTA_VirtualWidth: - virtWidth = va_arg (tags, int); - break; - - case DTA_VirtualHeight: - virtHeight = va_arg (tags, int); - break; - - case DTA_Alpha: - alpha = MIN (FRACUNIT, va_arg (tags, fixed_t)); - break; - - case DTA_AlphaChannel: - alphaChannel = va_arg (tags, INTBOOL); - break; - - case DTA_FillColor: - fillcolor = va_arg (tags, int); - break; - - case DTA_Translation: - translation = va_arg (tags, const BYTE *); - break; - - case DTA_FlipX: - flipX = va_arg (tags, INTBOOL); - break; - - case DTA_TopOffset: - top = va_arg (tags, int); - break; - - case DTA_LeftOffset: - left = va_arg (tags, int); - break; - - case DTA_CenterOffset: - if (va_arg (tags, int)) - { - left = texwidth / 2; - top = texheight / 2; - } - break; - - case DTA_CenterBottomOffset: - if (va_arg (tags, int)) - { - left = texwidth / 2; - top = texheight; - } - break; - - case DTA_WindowLeft: - windowleft = va_arg (tags, int); - break; - - case DTA_WindowRight: - windowright = va_arg (tags, int); - break; - - case DTA_ClipTop: - uclip = va_arg (tags, int); - if (uclip < 0) - { - uclip = 0; - } - break; - - case DTA_ClipBottom: - dclip = va_arg (tags, int); - if (dclip > this->GetHeight()) - { - dclip = this->GetHeight(); - } - break; - - case DTA_ClipLeft: - lclip = va_arg (tags, int); - if (lclip < 0) - { - lclip = 0; - } - break; - - case DTA_ClipRight: - rclip = va_arg (tags, int); - if (rclip > this->GetWidth()) - { - rclip = this->GetWidth(); - } - break; - - case DTA_ShadowAlpha: - shadowAlpha = MIN (FRACUNIT, va_arg (tags, fixed_t)); - break; - - case DTA_ShadowColor: - shadowColor = va_arg (tags, int); - break; - - case DTA_Shadow: - boolval = va_arg (tags, INTBOOL); - if (boolval) - { - shadowAlpha = FRACUNIT/2; - shadowColor = 0; - } - else - { - shadowAlpha = 0; - } - break; - - case DTA_Masked: - boolval = va_arg (tags, INTBOOL); - if (boolval) - { - spanptr = &spans; - } - else - { - spanptr = NULL; - } - break; - - case DTA_KeepRatio: - keepratio = va_arg (tags, INTBOOL); - break; - - case DTA_RenderStyle: - style = ERenderStyle(va_arg (tags, int)); - break; - } - tag = va_arg (tags, DWORD); + spanptr = &spans; } - va_end (tags); - - if (virtWidth != Width || virtHeight != Height) + else { - int myratio = CheckRatio (Width, Height); - int right = x0 + destwidth; - int bottom = y0 + destheight; - - if (myratio != 0 && myratio != 4 && !keepratio) - { // The target surface is not 4:3, 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. - x0 = Scale (x0-virtWidth*FRACUNIT/2, Width*960, virtWidth*BaseRatioSizes[myratio][0]) + Width*FRACUNIT/2; - destwidth = Scale (right-virtWidth*FRACUNIT/2, Width*960, virtWidth*BaseRatioSizes[myratio][0]) + Width*FRACUNIT/2 - x0; - } - else - { - x0 = Scale (x0, Width, virtWidth); - destwidth = Scale (right, Width, virtWidth) - x0; - } - y0 = Scale (y0, Height, virtHeight); - destheight = Scale (bottom, Height, virtHeight) - y0; - } - - if (destwidth <= 0 || destheight <= 0) - { - return; - } - - if (style == STYLE_Count) - { - if (fillcolor != -1) - { - if (alphaChannel) - { - style = STYLE_Shaded; - } - else if (alpha < FRACUNIT) - { - style = STYLE_TranslucentStencil; - } - else - { - style = STYLE_Stencil; - } - } - else if (alpha < FRACUNIT) - { - style = STYLE_Translucent; - } - else - { - style = STYLE_Normal; - } + spanptr = NULL; } fixedcolormap = identitymap; - ESPSResult mode = R_SetPatchStyle (style, alpha, 0, fillcolor); + ESPSResult mode = R_SetPatchStyle (parms.style, parms.alpha, 0, parms.fillcolor); - if (style != STYLE_Shaded) + if (parms.style != STYLE_Shaded) { - if (translation != NULL) + if (parms.translation != NULL) { - dc_colormap = (lighttable_t *)translation; + dc_colormap = (lighttable_t *)parms.translation; } else { @@ -405,8 +103,8 @@ void STACK_ARGS DCanvas::DrawTexture (FTexture *img, int x0, int y0, int tags_fi BYTE *destorgsave = dc_destorg; dc_destorg = screen->GetBuffer(); - x0 -= Scale (left, destwidth, texwidth); - y0 -= Scale (top, destheight, texheight); + fixed_t x0 = parms.x - Scale (parms.left, parms.destwidth, parms.texwidth); + fixed_t y0 = parms.y - Scale (parms.top, parms.destheight, parms.texheight); if (mode != DontDraw) { @@ -426,10 +124,10 @@ void STACK_ARGS DCanvas::DrawTexture (FTexture *img, int x0, int y0, int tags_fi centeryfrac = 0; sprtopscreen = y0; - spryscale = destheight / img->GetHeight(); + spryscale = parms.destheight / img->GetHeight(); // Fix precision errors that are noticeable at some resolutions - if (((y0 + destheight) >> FRACBITS) > ((y0 + spryscale * img->GetHeight()) >> FRACBITS)) + if (((y0 + parms.destheight) >> FRACBITS) > ((y0 + spryscale * img->GetHeight()) >> FRACBITS)) { spryscale++; } @@ -438,12 +136,12 @@ void STACK_ARGS DCanvas::DrawTexture (FTexture *img, int x0, int y0, int tags_fi dc_iscale = 0xffffffffu / (unsigned)spryscale; dc_texturemid = FixedMul (-y0, dc_iscale); fixed_t frac = 0; - fixed_t xiscale = DivScale32 (img->GetWidth(), destwidth); - int x2 = (x0 + destwidth) >> FRACBITS; + fixed_t xiscale = DivScale32 (img->GetWidth(), parms.destwidth); + int x2 = (x0 + parms.destwidth) >> FRACBITS; - if (bottomclipper[0] != dclip) + if (bottomclipper[0] != parms.dclip) { - clearbufshort (bottomclipper, screen->GetWidth(), (short)dclip); + clearbufshort (bottomclipper, screen->GetWidth(), (short)parms.dclip); if (identitymap[1] != 1) { for (int i = 0; i < 256; ++i) @@ -452,11 +150,11 @@ void STACK_ARGS DCanvas::DrawTexture (FTexture *img, int x0, int y0, int tags_fi } } } - if (uclip != 0) + if (parms.uclip != 0) { - if (topclipper[0] != uclip) + if (topclipper[0] != parms.uclip) { - clearbufshort (topclipper, screen->GetWidth(), (short)uclip); + clearbufshort (topclipper, screen->GetWidth(), (short)parms.uclip); } mceilingclip = topclipper; } @@ -466,31 +164,31 @@ void STACK_ARGS DCanvas::DrawTexture (FTexture *img, int x0, int y0, int tags_fi } mfloorclip = bottomclipper; - if (flipX) + if (parms.flipX) { frac = (img->GetWidth() << FRACBITS) - 1; xiscale = -xiscale; } dc_x = x0 >> FRACBITS; - if (windowleft > 0 || windowright < texwidth) + if (parms.windowleft > 0 || parms.windowright < parms.texwidth) { - fixed_t xscale = destwidth / texwidth; - dc_x += (windowleft * xscale) >> FRACBITS; - frac += windowleft << FRACBITS; - x2 -= ((texwidth - windowright) * xscale) >> FRACBITS; + fixed_t xscale = parms.destwidth / parms.texwidth; + dc_x += (parms.windowleft * xscale) >> FRACBITS; + frac += parms.windowleft << FRACBITS; + x2 -= ((parms.texwidth - parms.windowright) * xscale) >> FRACBITS; } - if (dc_x < lclip) + if (dc_x < parms.lclip) { - frac += (lclip - dc_x) * xiscale; - dc_x = lclip; + frac += (parms.lclip - dc_x) * xiscale; + dc_x = parms.lclip; } - if (x2 > rclip) + if (x2 > parms.rclip) { - x2 = rclip; + x2 = parms.rclip; } - if (destheight < 32*FRACUNIT) + if (parms.destheight < 32*FRACUNIT) { mode = DoDraw0; } @@ -549,6 +247,328 @@ void STACK_ARGS DCanvas::DrawTexture (FTexture *img, int x0, int y0, int tags_fi } } +bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_list tags, DrawParms *parms) const +{ + INTBOOL boolval; + int intval; + + if (img == NULL || img->UseType == FTexture::TEX_Null) + { + return false; + } + + parms->texwidth = img->GetScaledWidth(); + parms->texheight = img->GetScaledHeight(); + + parms->windowleft = 0; + parms->windowright = parms->texwidth; + parms->dclip = this->GetHeight(); + parms->uclip = 0; + parms->lclip = 0; + parms->rclip = this->GetWidth(); + parms->destwidth = parms->windowright << FRACBITS; + parms->destheight = parms->texheight << FRACBITS; + parms->top = img->GetScaledTopOffset(); + parms->left = img->GetScaledLeftOffset(); + parms->alpha = FRACUNIT; + parms->fillcolor = -1; + parms->translation = NULL; + parms->alphaChannel = false; + parms->flipX = false; + parms->shadowAlpha = 0; + parms->shadowColor = 0; + parms->virtWidth = this->GetWidth(); + parms->virtHeight = this->GetHeight(); + parms->keepratio = false; + parms->style = STYLE_Count; + parms->masked = true; + + parms->x = x << FRACBITS; + parms->y = y << FRACBITS; + + // Parse the tag list for attributes + while (tag != TAG_DONE) + { + va_list *more_p; + DWORD data; + + switch (tag) + { + case TAG_IGNORE: + default: + data = va_arg (tags, DWORD); + break; + + case TAG_MORE: + more_p = va_arg (tags, va_list *); + va_end (tags); +#ifdef __GNUC__ + __va_copy (tags, *more_p); +#else + tags = *more_p; +#endif + break; + + case DTA_DestWidth: + parms->destwidth = va_arg (tags, int) << FRACBITS; + break; + + case DTA_DestHeight: + parms->destheight = va_arg (tags, int) << FRACBITS; + break; + + case DTA_Clean: + 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; + } + break; + + case DTA_CleanNoMove: + boolval = va_arg (tags, INTBOOL); + if (boolval) + { + parms->destwidth = parms->texwidth * CleanXfac * FRACUNIT; + parms->destheight = parms->texheight * CleanYfac * FRACUNIT; + } + break; + + case DTA_320x200: + boolval = va_arg (tags, INTBOOL); + if (boolval) + { + parms->virtWidth = 320; + parms->virtHeight = 200; + } + break; + + case DTA_HUDRules: + { + bool xright = parms->x < 0; + bool ybot = parms->y < 0; + intval = va_arg (tags, int); + + if (hud_scale) + { + parms->x *= CleanXfac; + if (intval == HUD_HorizCenter) + parms->x += Width * FRACUNIT / 2; + else if (xright) + parms->x = Width * FRACUNIT + 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; + } + else + { + if (intval == HUD_HorizCenter) + parms->x += Width * FRACUNIT / 2; + else if (xright) + parms->x = Width * FRACUNIT + parms->x; + if (ybot) + parms->y = Height * FRACUNIT + parms->y; + } + } + break; + + case DTA_VirtualWidth: + parms->virtWidth = va_arg (tags, int); + break; + + case DTA_VirtualHeight: + parms->virtHeight = va_arg (tags, int); + break; + + case DTA_Alpha: + parms->alpha = MIN (FRACUNIT, va_arg (tags, fixed_t)); + break; + + case DTA_AlphaChannel: + parms->alphaChannel = va_arg (tags, INTBOOL); + break; + + case DTA_FillColor: + parms->fillcolor = va_arg (tags, int); + break; + + case DTA_Translation: + parms->translation = va_arg (tags, const BYTE *); + break; + + case DTA_FlipX: + parms->flipX = va_arg (tags, INTBOOL); + break; + + case DTA_TopOffset: + parms->top = va_arg (tags, int); + break; + + case DTA_LeftOffset: + parms->left = va_arg (tags, int); + break; + + case DTA_CenterOffset: + if (va_arg (tags, int)) + { + parms->left = parms->texwidth / 2; + parms->top = parms->texheight / 2; + } + break; + + case DTA_CenterBottomOffset: + if (va_arg (tags, int)) + { + parms->left = parms->texwidth / 2; + parms->top = parms->texheight; + } + break; + + case DTA_WindowLeft: + parms->windowleft = va_arg (tags, int); + break; + + case DTA_WindowRight: + parms->windowright = va_arg (tags, int); + break; + + case DTA_ClipTop: + parms->uclip = va_arg (tags, int); + if (parms->uclip < 0) + { + parms->uclip = 0; + } + break; + + case DTA_ClipBottom: + parms->dclip = va_arg (tags, int); + if (parms->dclip > this->GetHeight()) + { + parms->dclip = this->GetHeight(); + } + break; + + case DTA_ClipLeft: + parms->lclip = va_arg (tags, int); + if (parms->lclip < 0) + { + parms->lclip = 0; + } + break; + + case DTA_ClipRight: + parms->rclip = va_arg (tags, int); + if (parms->rclip > this->GetWidth()) + { + parms->rclip = this->GetWidth(); + } + break; + + case DTA_ShadowAlpha: + parms->shadowAlpha = MIN (FRACUNIT, va_arg (tags, fixed_t)); + break; + + case DTA_ShadowColor: + parms->shadowColor = va_arg (tags, int); + break; + + case DTA_Shadow: + boolval = va_arg (tags, INTBOOL); + if (boolval) + { + parms->shadowAlpha = FRACUNIT/2; + parms->shadowColor = 0; + } + else + { + parms->shadowAlpha = 0; + } + break; + + case DTA_Masked: + parms->masked = va_arg (tags, INTBOOL); + break; + + case DTA_KeepRatio: + parms->keepratio = va_arg (tags, INTBOOL); + break; + + case DTA_RenderStyle: + parms->style = ERenderStyle(va_arg (tags, int)); + break; + } + tag = va_arg (tags, DWORD); + } + va_end (tags); + + if (parms->virtWidth != Width || parms->virtHeight != Height) + { + int myratio = CheckRatio (Width, Height); + int right = parms->x + parms->destwidth; + int bottom = parms->y + parms->destheight; + + if (myratio != 0 && myratio != 4 && !parms->keepratio) + { // The target surface is not 4:3, 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. + parms->x = Scale(parms->x - parms->virtWidth*FRACUNIT/2, + Width*960, + parms->virtWidth*BaseRatioSizes[myratio][0]) + + Width*FRACUNIT/2; + parms->destwidth = Scale(right - parms->virtWidth*FRACUNIT/2, + Width*960, + parms->virtWidth*BaseRatioSizes[myratio][0]) + + Width*FRACUNIT/2 - parms->x; + } + else + { + parms->x = Scale (parms->x, Width, parms->virtWidth); + parms->destwidth = Scale (right, Width, parms->virtWidth) - parms->x; + } + parms->y = Scale (parms->y, Height, parms->virtHeight); + parms->destheight = Scale (bottom, Height, parms->virtHeight) - parms->y; + } + + if (parms->destwidth <= 0 || parms->destheight <= 0) + { + return false; + } + + if (parms->style == STYLE_Count) + { + if (parms->fillcolor != -1) + { + if (parms->alphaChannel) + { + parms->style = STYLE_Shaded; + } + else if (parms->alpha < FRACUNIT) + { + parms->style = STYLE_TranslucentStencil; + } + else + { + parms->style = STYLE_Stencil; + } + } + else if (parms->alpha < FRACUNIT) + { + parms->style = STYLE_Translucent; + } + else + { + parms->style = STYLE_Normal; + } + } + return true; +} + void DCanvas::FillBorder (FTexture *img) { int myratio = CheckRatio (Width, Height); diff --git a/src/v_video.cpp b/src/v_video.cpp index 92b7143d9..e7ef1d255 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -671,11 +671,13 @@ DFrameBuffer::DFrameBuffer (int width, int height) : DSimpleCanvas (width, height) { LastMS = LastSec = FrameCount = LastCount = LastTic = 0; + IsComposited = false; } void DFrameBuffer::DrawRateStuff () { // Draws frame time and cumulative fps + RateX = 0; if (vid_fps) { DWORD ms = I_MSTime (); @@ -686,9 +688,10 @@ void DFrameBuffer::DrawRateStuff () int chars; chars = sprintf (fpsbuff, "%2u ms (%3u fps)", howlong, LastCount); - Clear (Width - chars * 8, 0, Width, 8, 0); + RateX = Width - chars * 8; + Clear (RateX, 0, Width, 8, 0); SetFont (ConFont); - DrawText (CR_WHITE, Width - chars * 8, 0, (char *)&fpsbuff[0], TAG_DONE); + DrawText (CR_WHITE, RateX, 0, (char *)&fpsbuff[0], TAG_DONE); SetFont (SmallFont); DWORD thisSec = ms/1000; @@ -772,6 +775,32 @@ void DFrameBuffer::SetVSync (bool vsync) { } +void DFrameBuffer::SetBlendingRect (int x1, int y1, int x2, int y2) +{ +} + +void DFrameBuffer::Begin2D () +{ +} + +void DFrameBuffer::End2D () +{ +} + +FNativeTexture *DFrameBuffer::CreateTexture(FTexture *gametex) +{ + return NULL; +} + +FNativeTexture *DFrameBuffer::CreatePalette(const PalEntry *pal) +{ + return NULL; +} + +FNativeTexture::~FNativeTexture() +{ +} + CCMD(clean) { Printf ("CleanXfac: %d\nCleanYfac: %d\n", CleanXfac, CleanYfac); diff --git a/src/v_video.h b/src/v_video.h index 72093d53d..13a7d63ec 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -81,7 +81,7 @@ enum DTA_Clean, // bool: scale texture size and position by CleanXfac and CleanYfac DTA_320x200, // bool: scale texture size and position to fit on a virtual 320x200 screen DTA_CleanNoMove, // bool: like DTA_Clean but does not reposition output position - DTA_FlipX, // bool: flip image horizontally + DTA_FlipX, // bool: flip image horizontally //FIXME: Does not work with DTA_Window(Left|Right) DTA_ShadowColor, // color of shadow DTA_ShadowAlpha, // alpha of shadow DTA_Shadow, // set shadow color and alphas to defaults @@ -100,10 +100,10 @@ enum DTA_Masked, // true(default)=use masks from texture, false=ignore masks DTA_HUDRules, // use fullscreen HUD rules to position and size textures DTA_KeepRatio, // doesn't adjust screen size for DTA_Virtual* if the aspect ratio is not 4:3 - DTA_TextLen, // for DrawText: stop after this many characters, even if \0 not hit DTA_RenderStyle, // same as render style for actors // For DrawText calls: + DTA_TextLen, // stop after this many characters, even if \0 not hit DTA_CellX, // horizontal size of character cell DTA_CellY, // vertical size of character cell }; @@ -173,7 +173,7 @@ public: virtual void SetFont (FFont *font); // 2D Texture drawing - void STACK_ARGS DrawTexture (FTexture *img, int x, int y, int tags, ...); + virtual void STACK_ARGS DrawTexture (FTexture *img, int x, int y, int tags, ...); void FillBorder (FTexture *img); // Fills the border around a 4:3 part of the screen on non-4:3 displays // 2D Text drawing @@ -187,7 +187,38 @@ protected: int Pitch; int LockCount; + struct DrawParms + { + fixed_t x, y; + int texwidth; + int texheight; + int windowleft; + int windowright; + int dclip; + int uclip; + int lclip; + int rclip; + fixed_t destwidth; + fixed_t destheight; + int top; + int left; + fixed_t alpha; + int fillcolor; + const BYTE *translation; + INTBOOL alphaChannel; + INTBOOL flipX; + fixed_t shadowAlpha; + int shadowColor; + int virtWidth; + int virtHeight; + INTBOOL keepratio; + INTBOOL masked; + ERenderStyle style; + }; + bool ClipBox (int &left, int &top, int &width, int &height, const BYTE *&src, const int srcpitch) const; + 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) const; DCanvas() {} @@ -220,6 +251,7 @@ protected: // for actually implementing this. Built on top of SimpleCanvas, because it // needs a system memory buffer when buffered output is enabled. +class FNativeTexture; class DFrameBuffer : public DSimpleCanvas { DECLARE_ABSTRACT_CLASS (DFrameBuffer, DSimpleCanvas) @@ -265,7 +297,24 @@ public: virtual void SetVSync (bool vsync); // Set the rect defining the area effected by blending. - virtual void SetBlendingRect (int x1, int y1, int x2, int y2) {} + virtual void SetBlendingRect (int x1, int y1, int x2, int y2); + + bool IsComposited; // If true, the following functions can be used. + + // Begin 2D drawing operations. This is like Update, but it doesn't end + // the scene, and it doesn't present the image yet. + virtual void Begin2D(); + + // DrawTexture calls between Begin2D/End2D now use native textures. + + // Finish 2D drawing operations. + virtual void End2D(); + + // Create a native texture from a game texture. + virtual FNativeTexture *CreateTexture(FTexture *gametex); + + // Create a palette texture from a 256-entry palette. + virtual FNativeTexture *CreatePalette(const PalEntry *pal); #ifdef _WIN32 virtual void PaletteChanged () = 0; @@ -278,10 +327,19 @@ protected: DFrameBuffer () {} + int RateX; + private: DWORD LastMS, LastSec, FrameCount, LastCount, LastTic; }; +// This class represents a native texture, as opposed to an FTexture. +class FNativeTexture +{ +public: + virtual ~FNativeTexture(); +}; + extern FColorMatcher ColorMatcher; // This is the screen updated by I_FinishUpdate. diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index dd969d89f..90ba57252 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -81,6 +81,27 @@ struct FBVERTEX }; #define D3DFVF_FBVERTEX (D3DFVF_XYZRHW|D3DFVF_TEX1) +class D3DTex : public FNativeTexture +{ +public: + D3DTex(FTexture *tex, IDirect3DDevice9 *D3DDevice); + ~D3DTex(); + + FTexture *GameTex; + IDirect3DTexture9 *Tex; + + // Texture coordinates to use for the lower-right corner, should this + // texture prove to be larger than the game texture it represents. + FLOAT TX, TY; + + bool IsGray; + + bool Create(IDirect3DDevice9 *D3DDevice); + bool Update(); + D3DFORMAT GetTexFormat(); + FTextureFormat ToTexFmt(D3DFORMAT fmt); +}; + // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -101,6 +122,7 @@ EXTERN_CVAR (Bool, fullscreen) EXTERN_CVAR (Float, Gamma) EXTERN_CVAR (Int, vid_displaybits) EXTERN_CVAR (Bool, vid_vsync) +EXTERN_CVAR (Float, transsouls) extern IDirect3D9 *D3D; @@ -108,75 +130,7 @@ extern cycle_t BlitCycles; // PRIVATE DATA DEFINITIONS ------------------------------------------------ -#if 0 -// This is the HLSL code: - -// Technically, Palette only needs to be a sampler1D, but that -// produces assembly code to copy index.x to index.y, which is -// totally unnecessary. - -sampler2D Image : register(s0); -sampler2D Palette : register(s1); -float4 Flash : register(c0); -float4 InvFlash : register(c1); - -float4 main (float2 texCoord : TEXCOORD0) : COLOR -{ - float4 index = tex2D (Image, texCoord); - float4 rgb = tex2D (Palette, index); - return Flash + rgb * InvFlash; -} -#endif -#if 0 -// -// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000 -// -// fxc paltex.ps /Tps_1_4 /VnPalTexShaderDef /Fh -// -// -// Parameters: -// -// float4 Flash; -// sampler2D Image; -// float4 InvFlash; -// sampler2D Palette; -// -// -// Registers: -// -// Name Reg Size -// ------------ ----- ---- -// Flash c0 1 -// InvFlash c1 1 -// Image s0 1 -// Palette s1 1 -// - - ps_1_4 - texld r0, t0 - phase - texld r1, r0 - mad r0, r1, c1, c0 - -// approximately 3 instruction slots used (2 texture, 1 arithmetic) -#endif - -const DWORD PalTexShaderDef[] = -{ - 0xffff0104, 0x003bfffe, 0x42415443, 0x0000001c, 0x000000b4, 0xffff0104, - 0x00000004, 0x0000001c, 0x00000100, 0x000000ad, 0x0000006c, 0x00000002, - 0x00020001, 0x00000074, 0x00000000, 0x00000084, 0x00000003, 0x00000001, - 0x0000008c, 0x00000000, 0x0000009c, 0x00010002, 0x00020001, 0x00000074, - 0x00000000, 0x000000a5, 0x00010003, 0x00000001, 0x0000008c, 0x00000000, - 0x73616c46, 0xabab0068, 0x00030001, 0x00040001, 0x00000001, 0x00000000, - 0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, - 0x46766e49, 0x6873616c, 0x6c615000, 0x65747465, 0x5f737000, 0x00345f31, - 0x7263694d, 0x666f736f, 0x52282074, 0x33442029, 0x20395844, 0x64616853, - 0x43207265, 0x69706d6f, 0x2072656c, 0x35312e39, 0x3937372e, 0x3030302e, - 0xabab0030, 0x00000042, 0x800f0000, 0xb0e40000, 0x0000fffd, 0x00000042, - 0x800f0001, 0x80e40000, 0x00000004, 0x800f0000, 0x80e40001, 0xa0e40001, - 0xa0e40000, 0x0000ffff -}; +#include "fb_d3d9_shaders.h" // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -192,6 +146,8 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) VertexBuffer = NULL; FBTexture = NULL; PaletteTexture = NULL; + StencilPaletteTexture = NULL; + ShadedPaletteTexture = NULL; PalTexShader = NULL; FBFormat = D3DFMT_UNKNOWN; PalFormat = D3DFMT_UNKNOWN; @@ -202,10 +158,11 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) BlendingRect.right = FBWidth; BlendingRect.bottom = FBHeight; UseBlendingRect = false; + In2D = 0; Gamma = 1.0; - memset (FlashConstants, 0, sizeof(FlashConstants)); - FlashConstants[1][3] = 1.f; // Always use alpha from palette (which is always 1, so meh) + FlashConstants[0][3] = FlashConstants[0][2] = FlashConstants[0][1] = FlashConstants[0][0] = 0; + FlashConstants[1][3] = FlashConstants[1][2] = FlashConstants[1][1] = FlashConstants[1][0] = 1; FlashColor = 0; FlashAmount = 0; @@ -250,7 +207,7 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) { d3dpp.BackBufferFormat = D3DFMT_R5G6B5; if (FAILED(D3D->CreateDevice (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window, - D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &D3DDevice))) + D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &d3dpp, &D3DDevice))) { D3DDevice = NULL; } @@ -321,7 +278,14 @@ bool D3DFB::CreateResources () { return false; } - if (!CreateFBTexture() || !CreatePaletteTexture()) + if (FAILED(D3DDevice->CreatePixelShader (PlainShaderDef, &PlainShader))) + { + return false; + } + if (!CreateFBTexture() || + !CreatePaletteTexture() || + !CreateStencilPaletteTexture() || + !CreateShadedPaletteTexture()) { return false; } @@ -351,11 +315,26 @@ void D3DFB::ReleaseResources () PaletteTexture->Release(); PaletteTexture = NULL; } + if (StencilPaletteTexture != NULL) + { + StencilPaletteTexture->Release(); + StencilPaletteTexture = NULL; + } + if (ShadedPaletteTexture != NULL) + { + ShadedPaletteTexture->Release(); + ShadedPaletteTexture = NULL; + } if (PalTexShader != NULL) { PalTexShader->Release(); PalTexShader = NULL; } + if (PlainShader != NULL) + { + PlainShader->Release(); + PlainShader = NULL; + } } bool D3DFB::Reset () @@ -426,11 +405,7 @@ void D3DFB::DoOffByOneCheck () { 255.5f, 0.5f, 0.5f, 1.f, texright, texbot }, { -0.5f, 0.5f, 0.5f, 1.f, 0.f, texbot } }; - float flash[2][4] = - { - { 0.f, 0.f, 0.f, 0.f }, - { 1.f, 1.f, 1.f, 1.f } - }; + float ps_constants[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } }; union { @@ -445,29 +420,18 @@ void D3DFB::DoOffByOneCheck () } // Create an easily recognizable R3G3B2 palette. - if (PalFormat == D3DFMT_A8R8G8B8) + for (i = 0; i < 256; ++i) { - for (i = 0; i < 256; ++i) - { - Pal32[i][0] = BYTE(i & 0x03) << 6; // blue - Pal32[i][1] = BYTE(i & 0x1C) << 3; // green - Pal32[i][2] = BYTE(i & 0xE0); // red; - Pal32[i][3] = 255; - } - } - else - { - for (i = 0; i < 256; ++i) - { - Pal16[i] = WORD((i & 0xE0) << 8) | // red - ((i & 0x1C) << 6) | // green - ((i & 0x03) << 3); // blue - } + Pal32[i][0] = BYTE(i & 0x03) << 6; // blue + Pal32[i][1] = BYTE(i & 0x1C) << 3; // green + Pal32[i][2] = BYTE(i & 0xE0); // red; + Pal32[i][3] = 255; } + // Upload the palette if (SUCCEEDED(PaletteTexture->LockRect (0, &lockrect, NULL, 0))) { - memcpy (lockrect.pBits, Pal32, 256 * ((PalFormat == D3DFMT_A8R8G8B8) ? 4 : 2)); + memcpy (lockrect.pBits, Pal32, 256 * 4); PaletteTexture->UnlockRect (0); } else @@ -513,7 +477,7 @@ void D3DFB::DoOffByOneCheck () D3DDevice->SetTexture (1, PaletteTexture); D3DDevice->SetFVF (D3DFVF_FBVERTEX); D3DDevice->SetPixelShader (PalTexShader); - D3DDevice->SetPixelShaderConstantF (0, flash[0], 2); + D3DDevice->SetPixelShaderConstantF (0, ps_constants[0], 2); D3DDevice->DrawPrimitiveUP (D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); D3DDevice->EndScene(); D3DDevice->SetRenderTarget (0, savedrendertarget); @@ -612,18 +576,50 @@ bool D3DFB::CreatePaletteTexture () { if (FAILED(D3DDevice->CreateTexture (256, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &PaletteTexture, NULL))) { - if (FAILED(D3DDevice->CreateTexture (256, 1, 1, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &PaletteTexture, NULL))) - { - return false; - } - else - { - PalFormat = D3DFMT_R5G6B5; - } + return false; } - else + PalFormat = D3DFMT_A8R8G8B8; + return true; +} + +bool D3DFB::CreateStencilPaletteTexture() +{ + // The stencil palette is a special palette where the first entry is zero alpha, + // and everything else is white with full alpha. + if (FAILED(D3DDevice->CreateTexture(256, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &StencilPaletteTexture, NULL))) { - PalFormat = D3DFMT_A8R8G8B8; + return false; + } + D3DLOCKED_RECT lockrect; + if (SUCCEEDED(StencilPaletteTexture->LockRect(0, &lockrect, NULL, 0))) + { + DWORD *pix = (DWORD *)lockrect.pBits; + *pix = 0; + memset(pix + 1, 0xFF, 255*4); + StencilPaletteTexture->UnlockRect(0); + } + return true; +} + +bool D3DFB::CreateShadedPaletteTexture() +{ + // The shaded palette is similar to the stencil palette, except each entry's + // alpha is the same as its index. + if (FAILED(D3DDevice->CreateTexture(256, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &ShadedPaletteTexture, NULL))) + { + return false; + } + D3DLOCKED_RECT lockrect; + if (SUCCEEDED(ShadedPaletteTexture->LockRect(0, &lockrect, NULL, 0))) + { + BYTE *pix = (BYTE *)lockrect.pBits; + for (int i = 0; i < 256; ++i) + { + pix[3] = i; + pix[2] = pix[1] = pix[0] = 255; + pix += 4; + } + ShadedPaletteTexture->UnlockRect(0); } return true; } @@ -805,8 +801,22 @@ void D3DFB::Unlock () } } +// When In2D == 0: Copy buffer to screen and present +// When In2D == 1: Copy buffer to screen but do not present +// When In2D == 2: Do nothing +// When In2D == 3: Present and set In2D to 0 void D3DFB::Update () { + assert(In2D != 2); + + if (In2D == 3) + { + D3DDevice->EndScene(); + D3DDevice->Present(NULL, NULL, NULL, NULL); + In2D = false; + return; + } + if (LockCount != 1) { //I_FatalError ("Framebuffer must have exactly 1 lock to be updated"); @@ -837,6 +847,11 @@ void D3DFB::Update () LockCount = 0; PaintToWindow (); + if (In2D == 0) + { + D3DDevice->EndScene(); + D3DDevice->Present(NULL, NULL, NULL, NULL); + } unclock (BlitCycles); LOG1 ("cycles = %d\n", BlitCycles); @@ -847,8 +862,6 @@ void D3DFB::Update () bool D3DFB::PaintToWindow () { - RECT texrect = { 0, 0, Width, Height }; - D3DLOCKED_RECT lockrect; HRESULT hr; if (LockCount != 0) @@ -864,7 +877,17 @@ bool D3DFB::PaintToWindow () return false; } } - if ((FBWidth == Width && FBHeight == Height && SUCCEEDED(FBTexture->LockRect (0, &lockrect, NULL, D3DLOCK_DISCARD))) || + Draw3DPart(); + return true; +} + +void D3DFB::Draw3DPart() +{ + RECT texrect = { 0, 0, Width, Height }; + D3DLOCKED_RECT lockrect; + + if ((FBWidth == Width && FBHeight == Height && + SUCCEEDED(FBTexture->LockRect (0, &lockrect, NULL, D3DLOCK_DISCARD))) || SUCCEEDED(FBTexture->LockRect (0, &lockrect, &texrect, 0))) { if (lockrect.Pitch == Pitch) @@ -898,6 +921,7 @@ bool D3DFB::PaintToWindow () D3DDevice->SetFVF (D3DFVF_FBVERTEX); D3DDevice->SetPixelShader (PalTexShader); D3DDevice->SetPixelShaderConstantF (0, FlashConstants[0], 2); + D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); if (!UseBlendingRect || FlashConstants[1][0] == 1) { // The whole screen as a single quad. D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2); @@ -907,9 +931,7 @@ bool D3DFB::PaintToWindow () D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 24, 2); // middle // The rest is drawn unblended, so reset the shader constant. - static const float FlashZero[2][4] = - { { 0, 0, 0, 0 }, - { 1, 1, 1, 0 } }; + static const float FlashZero[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } }; D3DDevice->SetPixelShaderConstantF (0, FlashZero[0], 2); D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 4, 2); // left @@ -917,8 +939,26 @@ bool D3DFB::PaintToWindow () D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 12, 4); // bottom D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 18, 4); // top } - D3DDevice->EndScene(); - return SUCCEEDED(D3DDevice->Present(NULL, NULL, NULL, NULL)); + if (UseBlendingRect && FlashConstants[1][0] != 1 && RateX) + { + float left = float(RateX) - 0.5f; + float top = (TrueHeight - Height) * 0.5f - 0.5f; + float right = float(Width) - 0.5f; + float bot = float(8) + top; + float texleft = float(RateX) / float(FBWidth); + float texright = float(Width) / float(FBWidth); + float texbot = float(8) / float(FBHeight); + + // Redraw the vid_fps part without the flash + FBVERTEX verts[4] = + { + { left, top, 0.5f, 1.f, texleft, 0.f }, + { right, top, 0.5f, 1.f, texright, 0.f }, + { right, bot, 0.5f, 1.f, texright, texbot }, + { left, bot, 0.5f, 1.f, texleft, texbot } + }; + D3DDevice->DrawPrimitiveUP (D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); + } } void D3DFB::UploadPalette () @@ -936,39 +976,21 @@ void D3DFB::UploadPalette () // check yet. Otherwise, wait until the next time the palette changes. NeedPalUpdate = (OffByOneAt < 0); - if (PalFormat == D3DFMT_A8R8G8B8) + BYTE *pix = (BYTE *)lockrect.pBits; + for (i = 0; i < OffByOneAt; ++i, pix += 4) { - BYTE *pix = (BYTE *)lockrect.pBits; - for (i = 0; i < OffByOneAt; ++i, pix += 4) - { - pix[0] = GammaTable[SourcePalette[i].b]; - pix[1] = GammaTable[SourcePalette[i].g]; - pix[2] = GammaTable[SourcePalette[i].r]; - pix[3] = 255; - } - for (; i < 256; ++i, pix += 4) - { - pix[0] = GammaTable[SourcePalette[i-1].b]; - pix[1] = GammaTable[SourcePalette[i-1].g]; - pix[2] = GammaTable[SourcePalette[i-1].r]; - pix[3] = 255; - } + pix[0] = GammaTable[SourcePalette[i].b]; + pix[1] = GammaTable[SourcePalette[i].g]; + pix[2] = GammaTable[SourcePalette[i].r]; + pix[3] = (i == 0 ? 0 : 255); + // To let masked textures work, the first palette entry's alpha is 0. } - else + for (; i < 256; ++i, pix += 4) { - WORD *pix = (WORD *)lockrect.pBits; - for (i = 0; i < OffByOneAt; ++i, ++pix) - { - *pix = ((GammaTable[SourcePalette[i].r] >> 3) << 11) | - ((GammaTable[SourcePalette[i].g] >> 2) << 5) | - (GammaTable[SourcePalette[i].b] >> 3); - } - for (; i < 256; ++i, ++pix) - { - *pix = ((GammaTable[SourcePalette[i-1].r] >> 3) << 11) | - ((GammaTable[SourcePalette[i-1].g] >> 2) << 5) | - (GammaTable[SourcePalette[i-1].b] >> 3); - } + pix[0] = GammaTable[SourcePalette[i-1].b]; + pix[1] = GammaTable[SourcePalette[i-1].g]; + pix[2] = GammaTable[SourcePalette[i-1].r]; + pix[3] = 255; } PaletteTexture->UnlockRect (0); } @@ -1065,3 +1087,433 @@ void D3DFB::SetBlendingRect(int x1, int y1, int x2, int y2) } } } + +/**************************************************************************/ +/* 2D Stuff */ +/**************************************************************************/ + +//========================================================================== +// +// D3DTex Constructor +// +//========================================================================== + +D3DTex::D3DTex(FTexture *tex, IDirect3DDevice9 *D3DDevice) +{ + GameTex = tex; + Tex = NULL; + IsGray = false; + + Create(D3DDevice); +} + +//========================================================================== +// +// D3DTex Destructor +// +//========================================================================== + +D3DTex::~D3DTex() +{ + if (Tex != NULL) + { + Tex->Release(); + Tex = NULL; + } +} + +//========================================================================== +// +// D3DTex :: Create +// +// Creates an IDirect3DTexture9 for the texture and copies the image data +// to it. Note that unlike FTexture, this image is row-major. +// +//========================================================================== + +bool D3DTex::Create(IDirect3DDevice9 *D3DDevice) +{ + HRESULT hr; + int w, h; + + if (Tex != NULL) + { + Tex->Release(); + Tex = NULL; + } + + w = GameTex->GetWidth(); + h = GameTex->GetHeight(); + + // We don't really want mip-maps, but specifying the flag is the only + // way to use D3DPOOL_MANAGED, according to the docs. + hr = D3DDevice->CreateTexture(w, h, 1, 0, + GetTexFormat(), D3DPOOL_MANAGED, &Tex, NULL); + if (FAILED(hr)) + { // Try again, using power-of-2 sizes + int i; + + for (i = 1; i < w; i <<= 1) {} w = i; + for (i = 1; i < h; i <<= 1) {} h = i; + hr = D3DDevice->CreateTexture(w, h, 1, 0, + GetTexFormat(), D3DPOOL_MANAGED, &Tex, NULL); + if (FAILED(hr)) + { + return false; + } + } + if (!Update()) + { + Tex->Release(); + Tex = NULL; + return false; + } + return true; +} + +//========================================================================== +// +// D3DTex :: Update +// +// Copies image data from the underlying FTexture to the D3D texture. +// +//========================================================================== + +bool D3DTex::Update() +{ + D3DSURFACE_DESC desc; + D3DLOCKED_RECT lrect; + RECT rect; + + assert(Tex != NULL); + assert(GameTex != NULL); + + if (FAILED(Tex->GetLevelDesc(0, &desc))) + { + return false; + } + rect.left = 0; + rect.top = 0; + rect.right = GameTex->GetWidth(); + rect.bottom = GameTex->GetHeight(); + if (FAILED(Tex->LockRect(0, &lrect, &rect, 0))) + { + return false; + } + GameTex->FillBuffer((BYTE *)lrect.pBits, lrect.Pitch, ToTexFmt(desc.Format)); + Tex->UnlockRect(0); + return true; +} + +//========================================================================== +// +// D3DTex :: GetTexFormat +// +// Returns the texture format that would best fit this texture. +// +//========================================================================== + +D3DFORMAT D3DTex::GetTexFormat() +{ + FTextureFormat fmt = GameTex->GetFormat(); + + IsGray = false; + + switch (fmt) + { + case TEX_Pal: return D3DFMT_L8; + case TEX_Gray: IsGray = true; return D3DFMT_L8; + case TEX_RGB: return D3DFMT_A8R8G8B8; + case TEX_DXT1: return D3DFMT_DXT1; + case TEX_DXT2: return D3DFMT_DXT2; + case TEX_DXT3: return D3DFMT_DXT3; + case TEX_DXT4: return D3DFMT_DXT4; + case TEX_DXT5: return D3DFMT_DXT5; + default: I_FatalError ("GameTex->GetFormat() returned invalid format."); + } + return D3DFMT_L8; +} + +//========================================================================== +// +// D3DTex :: ToTexFmt +// +// Converts a D3DFORMAT constant to something the FTexture system +// understands. +// +//========================================================================== + +FTextureFormat D3DTex::ToTexFmt(D3DFORMAT fmt) +{ + switch (fmt) + { + case D3DFMT_L8: return IsGray ? TEX_Gray : TEX_Pal; + case D3DFMT_A8R8G8B8: return TEX_RGB; + case D3DFMT_DXT1: return TEX_DXT1; + case D3DFMT_DXT2: return TEX_DXT2; + case D3DFMT_DXT3: return TEX_DXT3; + case D3DFMT_DXT4: return TEX_DXT4; + case D3DFMT_DXT5: return TEX_DXT5; + default: + assert(0); // LOL WUT? + return TEX_Pal; + } +} + +//========================================================================== +// +// D3DFB :: Begin2D +// +// Begins 2D mode drawing operations. In particular, DrawTexture is +// rerouted to use Direct3D instead of the software renderer. +// +//========================================================================== + +void D3DFB::Begin2D() +{ + if (In2D) + { + return; + } + In2D = 1; + Update(); + In2D = 2; + + // Set default state for 2D rendering. + float ps_constants[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } }; + D3DDevice->SetPixelShaderConstantF (0, ps_constants[0], 2); + D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + D3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + D3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + + // This is set by Update() + //D3DDevice->SetTexture(1, PaletteTexture); +} + +void D3DFB::End2D() +{ + if (In2D == 2) + { + In2D = 3; + } +} + +FNativeTexture *D3DFB::CreateTexture(FTexture *gametex) +{ + return new D3DTex(gametex, D3DDevice); +} + +//========================================================================== +// +// D3DFB :: DrawTexture +// +// If not in 2D mode, just call the normal software version. +// If in 2D mode, then use Direct3D calls to perform the drawing. +// +//========================================================================== + +void STACK_ARGS D3DFB::DrawTexture (FTexture *img, int x, int y, int tags_first, ...) +{ + va_list tags; + va_start(tags, tags_first); + + if (In2D < 2) + { + DrawTextureV(img, x, y, tags_first, tags); + return; + } + + DrawParms parms; + + if (!ParseDrawTextureTags(img, x, y, tags_first, tags, &parms)) + { + return; + } + + D3DTex *tex = static_cast(img->GetNative()); + + if (tex == NULL) + { + assert(tex != NULL); + return; + } + + 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; + float u0 = 0.f; + float v0 = 0.f; + float u1 = 1.f; + float v1 = 1.f; + float uscale = 1.f / parms.texwidth / u1; + float vscale = 1.f / parms.texheight / v1 / yscale; + + if (y0 < parms.uclip) + { + v0 += float(parms.uclip - y0) * vscale; + y0 = float(parms.uclip); + } + if (y1 > parms.dclip) + { + v1 -= float(y1 - parms.dclip) * vscale; + y1 = float(parms.dclip); + } + + if (parms.flipX) + { + swap(u0, u1); + } + if (parms.windowleft > 0 || parms.windowright < parms.texwidth) + { + x0 += parms.windowleft * xscale; + u0 += parms.windowleft * uscale; + x1 -= (parms.texwidth - parms.windowright) * xscale; + u1 -= (parms.texwidth - parms.windowright) * uscale; + } + if (x0 < parms.lclip) + { + u0 += float(parms.lclip - x0) * uscale / xscale; + x0 = float(parms.lclip); + } + if (x1 > parms.rclip) + { + u1 -= float(x1 - parms.rclip) * uscale / xscale; + x1 = float(parms.rclip); + } + + x0 -= 0.5f; + y0 -= 0.5f; + x1 -= 0.5f; + y1 -= 0.5f; + + FBVERTEX verts[4] = + { + { x0, y0, 0.5f, 1.f, u0, v0 }, + { x1, y0, 0.5f, 1.f, u1, v0 }, + { x1, y1, 0.5f, 1.f, u1, v1 }, + { x0, y1, 0.5f, 1.f, u0, v1 } + }; + + if (!SetStyle(parms.style, parms.alpha, parms.fillcolor, parms.masked)) + { + return; + } + + D3DDevice->SetTexture(0, tex->Tex); + D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, &verts, sizeof(FBVERTEX)); +} + +//========================================================================== +// +// D3DFB :: SetStyle +// +// Patterned after R_SetPatchStyle. +// +//========================================================================== + +bool D3DFB::SetStyle(int style, fixed_t alpha_fixed, DWORD color, INTBOOL masked) +{ + D3DBLEND fglevel, bglevel; + float alpha; + bool stencilling; + + alpha = clamp (alpha_fixed, 0, FRACUNIT) / 65536.f; + + if (style == STYLE_OptFuzzy) + { + style = STYLE_Translucent; + } + else if (style == STYLE_SoulTrans) + { + style = STYLE_Translucent; + alpha = transsouls; + } + + // FIXME: STYLE_Fuzzy is not written + if (style == STYLE_Fuzzy) + { + style = STYLE_Translucent; + alpha = transsouls; + } + + stencilling = false; + + switch (style) + { + // Special modes + case STYLE_Shaded: + if (alpha > 0) + { + float constant[4] = { RPART(color)/255.f,GPART(color)/255.f,BPART(color)/255.f,alpha }; + D3DDevice->SetPixelShaderConstantF(1, constant, 1); + D3DDevice->SetTexture(1, ShadedPaletteTexture); + D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + D3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + D3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + return true; + } + return false; + + // Standard modes + case STYLE_Stencil: + stencilling = true; + case STYLE_Normal: + fglevel = D3DBLEND_SRCALPHA; + bglevel = D3DBLEND_INVSRCALPHA; + alpha = 1; + break; + + case STYLE_TranslucentStencil: + stencilling = true; + case STYLE_Translucent: + fglevel = D3DBLEND_SRCALPHA; + bglevel = D3DBLEND_INVSRCALPHA; + if (alpha == 0) + { + return false; + } + if (alpha == 1 && style == STYLE_Translucent) + { + style = STYLE_Normal; + } + break; + + case STYLE_Add: + fglevel = D3DBLEND_SRCALPHA; + bglevel = D3DBLEND_ONE; + break; + + default: + return false; + } + + // Masking can only be turned off for STYLE_Normal, because it requires + // turning off the alpha blend. + if (!masked && style == STYLE_Normal) + { + D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + } + else + { + D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + D3DDevice->SetRenderState(D3DRS_SRCBLEND, fglevel); + D3DDevice->SetRenderState(D3DRS_DESTBLEND, bglevel); + + if (!stencilling) + { + float constant[4] = { 1,1,1,alpha }; + D3DDevice->SetPixelShaderConstantF(1, constant, 1); + D3DDevice->SetTexture(1, PaletteTexture); + } + else + { + float constant[4] = { RPART(color)/255.f,GPART(color)/255.f,BPART(color)/255.f,alpha }; + D3DDevice->SetPixelShaderConstantF(1, constant, 1); + D3DDevice->SetTexture(1, StencilPaletteTexture); + } + } + return true; +} \ No newline at end of file diff --git a/src/win32/fb_d3d9_shaders.h b/src/win32/fb_d3d9_shaders.h new file mode 100644 index 000000000..da553ab18 --- /dev/null +++ b/src/win32/fb_d3d9_shaders.h @@ -0,0 +1,131 @@ +#define HLSL_SOURCE_CODE 0 +#define SHADER_ASSEMBLY_CODE 0 + +// A paletted texture shader + +#if HLSL_SOURCE_CODE +// Technically, Palette only needs to be a sampler1D, but that +// produces assembly code to copy index.x to index.y, which is +// totally unnecessary. + +sampler2D Image : register(s0); +sampler2D Palette : register(s1); +float4 Flash : register(c0); +float4 InvFlash : register(c1); + +float4 main (float2 texCoord : TEXCOORD0) : COLOR +{ + float4 index = tex2D (Image, texCoord); + float4 rgb = tex2D (Palette, index); + return Flash + rgb * InvFlash; +} +#endif +#if SHADER_ASSEMBLY_CODE +// +// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000 +// +// fxc paltex.ps /Tps_1_4 /VnPalTexShaderDef /Fh +// +// +// Parameters: +// +// float4 Flash; +// sampler2D Image; +// float4 InvFlash; +// sampler2D Palette; +// +// +// Registers: +// +// Name Reg Size +// ------------ ----- ---- +// Flash c0 1 +// InvFlash c1 1 +// Image s0 1 +// Palette s1 1 +// + + ps_1_4 + texld r0, t0 + phase + texld r1, r0 + mad r0, r1, c1, c0 + +// approximately 3 instruction slots used (2 texture, 1 arithmetic) +#endif + +const DWORD PalTexShaderDef[] = +{ + 0xffff0104, 0x003bfffe, 0x42415443, 0x0000001c, 0x000000b4, 0xffff0104, + 0x00000004, 0x0000001c, 0x00000100, 0x000000ad, 0x0000006c, 0x00000002, + 0x00020001, 0x00000074, 0x00000000, 0x00000084, 0x00000003, 0x00000001, + 0x0000008c, 0x00000000, 0x0000009c, 0x00010002, 0x00020001, 0x00000074, + 0x00000000, 0x000000a5, 0x00010003, 0x00000001, 0x0000008c, 0x00000000, + 0x73616c46, 0xabab0068, 0x00030001, 0x00040001, 0x00000001, 0x00000000, + 0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, + 0x46766e49, 0x6873616c, 0x6c615000, 0x65747465, 0x5f737000, 0x00345f31, + 0x7263694d, 0x666f736f, 0x52282074, 0x33442029, 0x20395844, 0x64616853, + 0x43207265, 0x69706d6f, 0x2072656c, 0x35312e39, 0x3937372e, 0x3030302e, + 0xabab0030, 0x00000042, 0x800f0000, 0xb0e40000, 0x0000fffd, 0x00000042, + 0x800f0001, 0x80e40000, 0x00000004, 0x800f0000, 0x80e40001, 0xa0e40001, + 0xa0e40000, 0x0000ffff +}; + +// A texture that doesn't look up colors from a palette. +// Can be used for shaded L8 textures or RGB textures. + +#if HLSL_SOURCE_CODE +sampler2D Image : register(s0); +float4 Flash : register(c0); +float4 InvFlash : register(c1); + +float4 main (float2 texCoord : TEXCOORD0) : COLOR +{ + float4 index = tex2D (Image, texCoord); + return Flash + index * InvFlash; +} +#endif +#if SHADER_ASSEMBLY_CODE +// +// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000 +// +// fxc shadetex.ps /Tps_1_4 /VnPlainShaderDef /Fh +// +// +// Parameters: +// +// float4 Flash; +// sampler2D Image; +// float4 InvFlash; +// +// +// Registers: +// +// Name Reg Size +// ------------ ----- ---- +// Flash c0 1 +// InvFlash c1 1 +// Image s0 1 +// + + ps_1_4 + texld r0, t0 + mad r0, r0, c1, c0 + +// approximately 2 instruction slots used (1 texture, 1 arithmetic) +#endif + +const DWORD PlainShaderDef[] = +{ + 0xffff0104, 0x0034fffe, 0x42415443, 0x0000001c, 0x00000098, 0xffff0104, + 0x00000003, 0x0000001c, 0x00000100, 0x00000091, 0x00000058, 0x00000002, + 0x00020001, 0x00000060, 0x00000000, 0x00000070, 0x00000003, 0x00000001, + 0x00000078, 0x00000000, 0x00000088, 0x00010002, 0x00020001, 0x00000060, + 0x00000000, 0x73616c46, 0xabab0068, 0x00030001, 0x00040001, 0x00000001, + 0x00000000, 0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, + 0x00000000, 0x46766e49, 0x6873616c, 0x5f737000, 0x00345f31, 0x7263694d, + 0x666f736f, 0x52282074, 0x33442029, 0x20395844, 0x64616853, 0x43207265, + 0x69706d6f, 0x2072656c, 0x35312e39, 0x3937372e, 0x3030302e, 0xabab0030, + 0x00000042, 0x800f0000, 0xb0e40000, 0x00000004, 0x800f0000, 0x80e40000, + 0xa0e40001, 0xa0e40000, 0x0000ffff +}; diff --git a/src/win32/fb_ddraw.cpp b/src/win32/fb_ddraw.cpp index 7a05ccf82..f2415a0a9 100644 --- a/src/win32/fb_ddraw.cpp +++ b/src/win32/fb_ddraw.cpp @@ -620,7 +620,7 @@ void DDrawFB::MaybeCreatePalette () { pal.head.palPalEntry[i].peFlags = 0; } - GDIPalette = CreatePalette (&pal.head); + GDIPalette = ::CreatePalette (&pal.head); LOG ("Created GDI palette\n"); if (GDIPalette != NULL) { diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index 5d656e8b1..05117c972 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -230,6 +230,11 @@ public: bool PaintToWindow (); void SetVSync (bool vsync); void SetBlendingRect (int x1, int y1, int x2, int y2); + void Begin2D (); + void End2D (); + FNativeTexture *CreateTexture (FTexture *gametex); + FNativeTexture *CreatePalette (FTexture *pal); + void STACK_ARGS DrawTexture (FTexture *img, int x, int y, int tags, ...); HRESULT GetHR (); private: @@ -237,12 +242,16 @@ private: void ReleaseResources(); bool CreateFBTexture(); bool CreatePaletteTexture(); + bool CreateStencilPaletteTexture(); + bool CreateShadedPaletteTexture(); bool CreateVertexes(); void DoOffByOneCheck(); void UploadPalette(); void FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync); bool UploadVertices(); bool Reset(); + void Draw3DPart(); + bool SetStyle(int style, fixed_t alpha, DWORD color, INTBOOL masked); BYTE GammaTable[256]; PalEntry SourcePalette[256]; @@ -261,12 +270,16 @@ private: bool VSync; RECT BlendingRect; bool UseBlendingRect; + int In2D; IDirect3DDevice9 *D3DDevice; IDirect3DVertexBuffer9 *VertexBuffer; IDirect3DTexture9 *FBTexture; IDirect3DTexture9 *PaletteTexture; + IDirect3DTexture9 *StencilPaletteTexture; + IDirect3DTexture9 *ShadedPaletteTexture; IDirect3DPixelShader9 *PalTexShader; + IDirect3DPixelShader9 *PlainShader; D3DFB() {} }; diff --git a/zdoom.vcproj b/zdoom.vcproj index 1808526f2..d44a7d771 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -2717,14 +2725,6 @@ GeneratePreprocessedFile="0" /> - - - @@ -2747,7 +2747,7 @@ /> - - - @@ -4794,6 +4784,16 @@ Outputs="$(IntDir)/$(InputName).obj" /> + + + @@ -4818,16 +4818,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -4838,6 +4828,16 @@ Outputs="$(IntDir)/$(InputName).obj" /> + + + @@ -4862,16 +4862,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -4882,6 +4872,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -4906,16 +4906,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -4926,6 +4916,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -4950,16 +4950,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -4970,6 +4960,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -5033,6 +5033,10 @@ RelativePath=".\src\win32\fb_d3d9.cpp" > + + @@ -5049,7 +5053,7 @@ /> + + + @@ -5388,14 +5400,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - - - - @@ -5630,6 +5626,14 @@ GeneratePreprocessedFile="0" /> + + + @@ -5651,7 +5655,7 @@ /> + + + @@ -9136,14 +9148,6 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> - - - @@ -9318,7 +9322,7 @@ />