diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 194454a26..b1a2f4812 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,5 +1,24 @@ +January 2, 2008 +- Tried adding bilinear filtering support for paletted textures, but the + shader seems to be producing crappy output, so it's disabled for now. + Specifically, it produces distorted output at regular intervals for + textures that aren't power-of-2-sized, and it's still doing visible + filtering when the texture is rendered at its original size, so + obviously it's not doing something right. +- Fixed the use of power-of-2-sized native textures for smaller game + textures again. +- Fixed: D3DFB did not restore all the state it needed to after resetting + the device. +- Fixed: R_DrawTopBorder() must clip itself around the 3D view, since it's + now drawn later. +- With full software rendering, palette flashes once again effect the whole + screen. + January 1, 2008 -- The mouse is no longer grabbed at all unless you're actually in a level. +- The mouse is no longer grabbed at all unless you're actually in a level, + since I couldn't think of any reason why it should be grabbed at any other + time. (This only applies to windowed mode, where it makes sense to let the + OS have control of the pointer.) - Moved the view border drawing into the 2D mode part. When using Begin2D() now, the only part of the software buffer that gets updated to the screen is the part with the actual 3D scene and only if you tell it to. diff --git a/src/d_main.cpp b/src/d_main.cpp index 4c8811c9f..7b4410aaf 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -807,6 +807,7 @@ void D_PageDrawer (void) DTA_VirtualWidth, Page->GetWidth(), DTA_VirtualHeight, Page->GetHeight(), DTA_Masked, false, + DTA_BilinearFilter, true, TAG_DONE); screen->FillBorder (NULL); } diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 5db315d4b..7e4e3b99a 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -1489,12 +1489,14 @@ void R_DrawTopBorder () if (realviewwidth == SCREENWIDTH) return; - R_DrawBorder (0, 0, SCREENWIDTH, 34); offset = gameinfo.border->offset; size = gameinfo.border->size; - if (viewwindowy < 35) + if (viewwindowy < 34) { + R_DrawBorder (0, 0, viewwindowx, 34); + R_DrawBorder (viewwindowx, 0, viewwindowx+realviewwidth, viewwindowy); + R_DrawBorder (viewwindowx+realviewwidth, 0, SCREENWIDTH, 34); p1 = TexMan(gameinfo.border->t); for (x = viewwindowx; x < viewwindowx + realviewwidth; x += size) { @@ -1515,6 +1517,10 @@ void R_DrawTopBorder () p1 = TexMan(gameinfo.border->tr); screen->DrawTexture (p1, viewwindowx+realviewwidth, viewwindowy - offset, TAG_DONE); } + else + { + R_DrawBorder (0, 0, SCREENWIDTH, 34); + } } diff --git a/src/v_draw.cpp b/src/v_draw.cpp index fae771e2a..a415ebf13 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -298,6 +298,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l parms->keepratio = false; parms->style = STYLE_Count; parms->masked = true; + parms->bilinear = false; parms->x = x << FRACBITS; parms->y = y << FRACBITS; @@ -514,6 +515,10 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l parms->masked = va_arg (tags, INTBOOL); break; + case DTA_BilinearFilter: + parms->bilinear = va_arg (tags, INTBOOL); + break; + case DTA_KeepRatio: parms->keepratio = va_arg (tags, INTBOOL); break; diff --git a/src/v_video.h b/src/v_video.h index 1c05b53c6..5992b3a07 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -101,7 +101,8 @@ enum 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_RenderStyle, // same as render style for actors - DTA_ColorOverlay, // DWORD: ARGB to overlay on top of image. Limited under software. + DTA_ColorOverlay, // DWORD: ARGB to overlay on top of image; limited to black for software + DTA_BilinearFilter, // bool: apply bilinear filtering to the image // For DrawText calls: DTA_TextLen, // stop after this many characters, even if \0 not hit @@ -229,6 +230,7 @@ protected: int virtHeight; INTBOOL keepratio; INTBOOL masked; + INTBOOL bilinear; ERenderStyle style; }; diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 74280c0f9..d0a7b1c38 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -71,7 +71,7 @@ // MACROS ------------------------------------------------------------------ // The number of vertices the vertex buffer should hold. -#define NUM_VERTS 28 +#define NUM_VERTS 12 // TYPES ------------------------------------------------------------------- @@ -171,6 +171,7 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) StencilPaletteTexture = NULL; ShadedPaletteTexture = NULL; PalTexShader = NULL; + PalTexBilinearShader = NULL; PlainShader = NULL; PlainStencilShader = NULL; DimShader = NULL; @@ -183,13 +184,13 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) BlendingRect.top = 0; BlendingRect.right = FBWidth; BlendingRect.bottom = FBHeight; - UseBlendingRect = false; In2D = 0; Palettes = NULL; Textures = NULL; Accel2D = true; GatheringWipeScreen = false; ScreenWipe = NULL; + InScene = false; Gamma = 1.0; FlashConstants[0][3] = FlashConstants[0][2] = FlashConstants[0][1] = FlashConstants[0][0] = 0; @@ -246,12 +247,7 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) if (D3DDevice != NULL) { CreateResources (); - - // Be sure we know what the alpha blend is - D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - AlphaBlendEnabled = FALSE; - AlphaSrcBlend = D3DBLEND(0); - AlphaDestBlend = D3DBLEND(0); + SetInitialState (); } } @@ -264,6 +260,29 @@ D3DFB::~D3DFB () } } +// Called after initial device creation and reset, when everything is set +// to D3D's defaults. +void D3DFB::SetInitialState() +{ + D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + AlphaBlendEnabled = FALSE; + AlphaSrcBlend = D3DBLEND(0); + AlphaDestBlend = D3DBLEND(0); + + CurPixelShader = NULL; + memset(Constant, 0, sizeof(Constant)); + + Texture[0] = NULL; + Texture[1] = NULL; + D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + + SetGamma (Gamma); + OldRenderTarget = NULL; +} + void D3DFB::FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync) { memset (pp, 0, sizeof(*pp)); @@ -327,13 +346,15 @@ bool D3DFB::CreateResources () Printf ("Windowed mode gamma will not work.\n"); GammaFixerShader = NULL; } + if (FAILED(D3DDevice->CreatePixelShader(PalTexBilinearDef, &PalTexBilinearShader))) + { + PalTexBilinearShader = PalTexShader; + } if (FAILED(D3DDevice->CreatePixelShader (BurnShaderDef, &BurnShader))) { Printf ("Burn screenwipe will not work in D3D mode.\n"); BurnShader = NULL; } - CurPixelShader = NULL; - memset(Constant, 0, sizeof(Constant)); if (!CreateFBTexture() || !CreatePaletteTexture() || !CreateStencilPaletteTexture() || @@ -345,9 +366,6 @@ bool D3DFB::CreateResources () { return false; } - SetGamma (Gamma); - OldRenderTarget = NULL; - return true; } @@ -372,6 +390,14 @@ void D3DFB::ReleaseResources () ShadedPaletteTexture->Release(); ShadedPaletteTexture = NULL; } + if (PalTexBilinearShader != NULL) + { + if (PalTexBilinearShader != PalTexShader) + { + PalTexBilinearShader->Release(); + } + PalTexBilinearShader = NULL; + } if (PalTexShader != NULL) { PalTexShader->Release(); @@ -457,6 +483,7 @@ bool D3DFB::Reset () { return false; } + SetInitialState(); return true; } @@ -587,39 +614,13 @@ bool D3DFB::CreateVertexes () bool D3DFB::UploadVertices() { - float top = GatheringWipeScreen ? -0.5f : LBOffset - 0.5f; + float top = LBOffset - 0.5f; float right = float(Width) - 0.5f; float bot = float(Height) + top; float texright = float(Width) / float(FBWidth); float texbot = float(Height) / float(FBHeight); void *pverts; - if ((BlendingRect.left <= 0 && BlendingRect.right >= FBWidth && - BlendingRect.top <= 0 && BlendingRect.bottom >= FBHeight) || - BlendingRect.left >= BlendingRect.right || - BlendingRect.top >= BlendingRect.bottom) - { - // Blending rect covers the whole screen, so only need 4 verts. - FBVERTEX verts[4] = - { - { -0.5f, top, 0.5f, 1.f, 0.f, 0.f }, - { right, top, 0.5f, 1.f, texright, 0.f }, - { right, bot, 0.5f, 1.f, texright, texbot }, - { -0.5f, bot, 0.5f, 1.f, 0.f, texbot } - }; - if (SUCCEEDED(VertexBuffer->Lock(0, sizeof(verts), &pverts, 0))) - { - memcpy (pverts, verts, sizeof(verts)); - VertexBuffer->Unlock(); - return true; - } - return false; - } - // Only the 3D area of the screen is effected by palette flashes. - // So we create some boxes around it that can be drawn without the - // flash. These include the corners of the view area so I can be - // sure the texture interpolation is consistant. (Well, actually, - // since it's a 1-to-1 pixel mapping, it shouldn't matter.) float mxl = float(BlendingRect.left) - 0.5f; float mxr = float(BlendingRect.right) - 0.5f; float myt = float(BlendingRect.top) + top; @@ -628,56 +629,26 @@ bool D3DFB::UploadVertices() float tmxr = float(BlendingRect.right) / float(Width) * texright; float tmyt = float(BlendingRect.top) / float(Height) * texbot; float tmyb = float(BlendingRect.bottom) / float(Height) * texbot; - /* +-------------------+ - | | - +-----+-------+-----+ - | | | | - | | | | - | | | | - +-----+-------+-----+ - | | - +-------------------+ */ - FBVERTEX verts[28] = + + FBVERTEX verts[NUM_VERTS] = { - // The whole screen, for when no blending is happening + // The whole screen { -0.5f, top, 0.5f, 1.f, 0.f, 0.f }, // 0 { right, top, 0.5f, 1.f, texright, 0.f }, { right, bot, 0.5f, 1.f, texright, texbot }, { -0.5f, bot, 0.5f, 1.f, 0.f, texbot }, - // Left area - { -0.5f, myt, 0.5f, 1.f, 0.f, tmyt }, // 4 - { mxl, myt, 0.5f, 1.f, tmxl, tmyt }, - { mxl, myb, 0.5f, 1.f, tmxl, tmyb }, - { -0.5f, myb, 0.5f, 1.f, 0.f, tmyb }, - - // Right area - { mxr, myt, 0.5f, 1.f, tmxr, tmyt }, // 8 - { right, myt, 0.5f, 1.f, texright, tmyt }, - { right, myb, 0.5f, 1.f, texright, tmyb }, - { mxr, myb, 0.5f, 1.f, tmxr, tmyb }, - - // Bottom area - { -0.5f, bot, 0.5f, 1.f, 0.f, texbot }, // 12 - { -0.5f, myb, 0.5f, 1.f, 0.f, tmyb }, - { mxl, myb, 0.5f, 1.f, tmxl, tmyb }, - { mxr, myb, 0.5f, 1.f, tmxr, tmyb }, - { right, myb, 0.5f, 1.f, texright, tmyb }, - { right, bot, 0.5f, 1.f, texright, texbot }, - - // Top area - { right, top, 0.5f, 1.f, texright, 0.f }, // 18 - { right, myt, 0.5f, 1.f, texright, tmyt }, - { mxr, myt, 0.5f, 1.f, tmxr, tmyt }, - { mxl, myt, 0.5f, 1.f, tmxl, tmyt }, - { -0.5f, myt, 0.5f, 1.f, 0.f, tmyt }, - { -0.5f, top, 0.5f, 1.f, 0.f, 0.f }, - - // Middle (blended) area - { mxl, myt, 0.5f, 1.f, tmxl, tmyt }, // 24 + // 3D view part of the screen + { mxl, myt, 0.5f, 1.f, tmxl, tmyt }, // 4 { mxr, myt, 0.5f, 1.f, tmxr, tmyt }, { mxr, myb, 0.5f, 1.f, tmxr, tmyb }, - { mxl, myb, 0.5f, 1.f, tmxl, tmyb } + { mxl, myb, 0.5f, 1.f, tmxl, tmyb }, + + // Used when getting the end screen for wipes + { -0.5f, -0.5f, 0.5f, 1.f, 0.f, 0.f }, // 8 + { right, -0.5f, 0.5f, 1.f, texright, 0.f }, + { right, float(Height) - 0.5f, 0.5f, 1.f, texright, texbot }, + { -0.5f, float(Height) - 0.5f, 0.5f, 1.f, 0.f, texbot }, }; if (SUCCEEDED(VertexBuffer->Lock(0, sizeof(verts), &pverts, 0))) { @@ -760,10 +731,14 @@ void D3DFB::Update () { if (In2D == 3) { - DrawRateStuff(); - DoWindowedGamma(); - D3DDevice->EndScene(); - D3DDevice->Present(NULL, NULL, NULL, NULL); + if (InScene) + { + DrawRateStuff(); + DoWindowedGamma(); + D3DDevice->EndScene(); + D3DDevice->Present(NULL, NULL, NULL, NULL); + InScene = false; + } In2D = 0; return; } @@ -803,7 +778,7 @@ void D3DFB::Update () } psgamma[2] = psgamma[1] = psgamma[0] = igamma; psgamma[3] = 1; - D3DDevice->SetPixelShaderConstantF(4, psgamma, 1); + D3DDevice->SetPixelShaderConstantF(7, psgamma, 1); NeedPalUpdate = true; } @@ -828,6 +803,7 @@ void D3DFB::Update () DoWindowedGamma(); D3DDevice->EndScene(); D3DDevice->Present(NULL, NULL, NULL, NULL); + InScene = false; } unclock (BlitCycles); @@ -888,6 +864,7 @@ void D3DFB::Draw3DPart(bool copy3d) } } DrawLetterbox(); + InScene = true; D3DDevice->BeginScene(); assert(OldRenderTarget == NULL); if (TempRenderTexture != NULL && @@ -908,7 +885,7 @@ void D3DFB::Draw3DPart(bool copy3d) } SetTexture (0, FBTexture); - SetPaletteTexture(PaletteTexture, 256); + SetPaletteTexture(PaletteTexture, 256, false); D3DDevice->SetStreamSource (0, VertexBuffer, 0, sizeof(FBVERTEX)); D3DDevice->SetFVF (D3DFVF_FBVERTEX); D3DDevice->SetPixelShaderConstantF (0, FlashConstants[0], 2); @@ -916,27 +893,7 @@ void D3DFB::Draw3DPart(bool copy3d) SetAlphaBlend(FALSE); if (copy3d) { - if (!UseBlendingRect || FlashConstants[1][0] == 1) - { // The whole screen as a single quad. - D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2); - } - else - { // The screen split up so that only the 3D view is blended. - D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 24, 2); // middle - - if (!In2D) - { - // The rest is drawn unblended, so reset the shader constant. - static const float FlashZero[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } }; - D3DDevice->SetPixelShaderConstantF (0, FlashZero[0], 2); - memcpy(Constant, FlashZero, sizeof(FlashZero)); - - D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 4, 2); // left - D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 8, 2); // right - D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 12, 4); // bottom - D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 18, 4); // top - } - } + D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, !test2d ? 0 : OldRenderTarget != NULL ? 8 : 4, 2); } } @@ -1079,12 +1036,7 @@ void D3DFB::SetBlendingRect(int x1, int y1, int x2, int y2) BlendingRect.right = x2; BlendingRect.bottom = y2; - if (UploadVertices()) - { - UseBlendingRect = ((x1 > 0 || x2 < FBWidth || y1 > 0 || y2 < FBHeight) - && BlendingRect.left < BlendingRect.right - && BlendingRect.top < BlendingRect.bottom); - } + UploadVertices(); } } @@ -1165,8 +1117,12 @@ bool D3DTex::Create(IDirect3DDevice9 *D3DDevice) w = GameTex->GetWidth(); h = GameTex->GetHeight(); +#if 1 hr = D3DDevice->CreateTexture(w, h, 1, 0, GetTexFormat(), D3DPOOL_MANAGED, &Tex, NULL); +#else + hr = E_FAIL; +#endif if (SUCCEEDED(hr)) { TX = 1; @@ -1401,7 +1357,6 @@ bool D3DPal::Update() bool D3DFB::Begin2D(bool copy3d) { - copy3d = true; if (!test2d) { return false; @@ -1470,6 +1425,10 @@ void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint3 Super::Clear(left, top, right, bottom, palcolor, color); return; } + if (!InScene) + { + return; + } if (palcolor >= 0) { color = GPalette.BaseColors[palcolor]; @@ -1493,13 +1452,18 @@ void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint3 void D3DFB::Dim (PalEntry color, float amount, int x1, int y1, int w, int h) { if (amount <= 0) + { return; - + } if (In2D < 2) { Super::Dim(color, amount, x1, y1, w, h); return; } + if (!InScene) + { + return; + } if (amount >= 1) { D3DRECT rect = { x1, y1, x1 + w, y1 + h }; @@ -1542,7 +1506,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi DrawParms parms; - if (!ParseDrawTextureTags(img, x, y, tags_first, tags, &parms, true)) + if (!InScene || !ParseDrawTextureTags(img, x, y, tags_first, tags, &parms, true)) { return; } @@ -1565,17 +1529,17 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi float v0 = 0.f; float u1 = tex->TX; float v1 = tex->TY; - float uscale = 1.f / parms.texwidth / u1; - float vscale = 1.f / parms.texheight / v1 / yscale; + 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; + v0 += (float(parms.uclip) - y0) * vscale; y0 = float(parms.uclip); } if (y1 > parms.dclip) { - v1 -= float(y1 - parms.dclip) * vscale; + v1 -= (y1 - float(parms.dclip)) * vscale; y1 = float(parms.dclip); } @@ -1615,6 +1579,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi { x0, y1, 0.5f, 1.f, u0, v1 } }; + parms.bilinear = false; if (!SetStyle(tex, parms)) { return; @@ -1668,7 +1633,11 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms) if (alpha > 0) { SetConstant(1, RPART(parms.fillcolor)/255.f, GPART(parms.fillcolor)/255.f, BPART(parms.fillcolor)/255.f, alpha); - SetPaletteTexture(ShadedPaletteTexture, 256); + SetPaletteTexture(ShadedPaletteTexture, 256, parms.bilinear); + if (parms.bilinear) + { + SetPalTexBilinearConstants(tex); + } SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); return true; } @@ -1715,8 +1684,11 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms) SetColorOverlay(parms.colorOverlay, 1); if (fmt == D3DFMT_L8 && !tex->IsGray) { - SetPaletteTexture(PaletteTexture, 256); - SetPixelShader(PalTexShader); + SetPaletteTexture(PaletteTexture, 256, parms.bilinear); + if (parms.bilinear) + { + SetPalTexBilinearConstants(tex); + } } else { @@ -1734,7 +1706,11 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms) if (parms.remap != NULL) { D3DPal *pal = reinterpret_cast(parms.remap->GetNative()); - SetPaletteTexture(pal->Tex, pal->RoundedPaletteSize); + SetPaletteTexture(pal->Tex, pal->RoundedPaletteSize, parms.bilinear); + if (parms.bilinear) + { + SetPalTexBilinearConstants(tex); + } } else if (tex->IsGray) { @@ -1742,9 +1718,12 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms) } else { - SetPaletteTexture(PaletteTexture, 256); + SetPaletteTexture(PaletteTexture, 256, parms.bilinear); + if (parms.bilinear) + { + SetPalTexBilinearConstants(tex); + } } - SetPixelShader(PalTexShader); } else { @@ -1760,8 +1739,8 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms) BPART(parms.fillcolor)/255.f, alpha); if (fmt == D3DFMT_L8) { - SetPaletteTexture(StencilPaletteTexture, 256); - SetPixelShader(PalTexShader); + // Doesn't seem to be much point in allowing bilinear with a stencil + SetPaletteTexture(StencilPaletteTexture, 256, false); } else { @@ -1857,7 +1836,7 @@ void D3DFB::SetTexture(int tnum, IDirect3DTexture9 *texture) } } -void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count) +void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count, INTBOOL bilinear) { if (count == 256 || SM14) { @@ -1881,5 +1860,27 @@ void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count) SetConstant(2, 255 * fcount, 0.5f * fcount, 0, 0); } SetTexture(1, texture); - SetPixelShader(PalTexShader); + SetPixelShader(!bilinear ? PalTexShader : PalTexBilinearShader); +} + +void D3DFB::SetPalTexBilinearConstants(D3DTex *tex) +{ + float con[8]; + + // Don't bother doing anything if the constants won't be used. + if (PalTexShader == PalTexBilinearShader) + { + return; + } + + con[0] = tex->GameTex->GetWidth() / tex->TX; + con[1] = tex->GameTex->GetHeight() / tex->TY; + con[2] = 0; + con[3] = 1 / con[0]; + con[4] = 0; + con[5] = 1 / con[1]; + con[6] = con[5]; + con[7] = con[3]; + + D3DDevice->SetPixelShaderConstantF(3, con, 2); } diff --git a/src/win32/fb_d3d9_shaders.h b/src/win32/fb_d3d9_shaders.h index 843ebb6ea..6a343d899 100644 --- a/src/win32/fb_d3d9_shaders.h +++ b/src/win32/fb_d3d9_shaders.h @@ -114,6 +114,152 @@ const DWORD PalTexShader20Def[] = 0x0000ffff }; +// A paletted texture shader that does bilinear filtering ------------------- + +#if HLSL_SOURCE_CODE +sampler2D Image : register(s0); +sampler2D Palette : register(s1); +float4 Flash : register(c0); +float4 InvFlash : register(c1); +float4 PaletteMod : register(c2); + +//#define texture_size_x 512.0f +//#define texture_size_y 256.0f +//#define texel_size_x 1.0f / 512.0f +//#define texel_size_y 1.0f / 256.0f + +// texture_size_x, texture_size_y, 0, texel_size_x +float4 size_a : register(c3); + +// 0, texel_size_y, texel_size_y, texel_size_x +float4 size_b : register(c4); + +float4 main (float2 texCoord : TEXCOORD0) : COLOR +{ + float2 f = frac (texCoord.xy * size_a/*float2(texture_size_x, texture_size_y)*/); + + float4 t00 = tex2D(Image, texCoord); + float4 t10 = tex2D(Image, texCoord + size_a.wz/*float2(texel_size_x, 0)*/); + + t00.x = t00.x * PaletteMod.x + PaletteMod.y; + t10.x = t10.x * PaletteMod.x + PaletteMod.y; + + float4 c00 = tex2D(Palette, t00); + float4 c10 = tex2D(Palette, t10); + + float4 cA = lerp(c00, c10, f.x); + + float4 t01 = tex2D(Image, texCoord + size_b.xy/*float2(0, texel_size_y)*/); + float4 t11 = tex2D(Image, texCoord + size_b.wz/*float2(texel_size_x, texel_size_y)*/); + + t01.x = t01.x * PaletteMod.x + PaletteMod.y; + t11.x = t11.x * PaletteMod.x + PaletteMod.y; + + float4 c01 = tex2D(Palette, t01); + float4 c11 = tex2D(Palette, t11); + + float4 cB = lerp(c01, c11, f.x); + + return Flash + lerp(cA, cB, f.y) * InvFlash; +} +#elif SHADER_ASSEMBLY_CODE +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.19.949.2111 +// +// fxc paltex_bilinear.ps /Tps_2_0 /VnPalTexBilinearDef /Fhpaltex_bilinea +// +// +// Parameters: +// +// float4 Flash; +// sampler2D Image; +// float4 InvFlash; +// sampler2D Palette; +// float4 PaletteMod; +// float4 size_a; +// float4 size_b; +// +// +// Registers: +// +// Name Reg Size +// ------------ ----- ---- +// Flash c0 1 +// InvFlash c1 1 +// PaletteMod c2 1 +// size_a c3 1 +// size_b c4 1 +// Image s0 1 +// Palette s1 1 +// + + ps_2_0 + dcl t0.xy + dcl_2d s0 + dcl_2d s1 + add r0.xy, t0, c4 + add r1.xy, t0, c4.wzyx + add r2.xy, t0, c3.wzyx + texld r0, r0, s0 + texld r1, r1, s0 + texld r2, r2, s0 + texld r3, t0, s0 + mad r0.x, r0.x, c2.x, c2.y + mad r1.x, r1.x, c2.x, c2.y + mad r2.x, r2.x, c2.x, c2.y + mad r3.x, r3.x, c2.x, c2.y + texld r0, r0, s1 + texld r1, r1, s1 + texld r2, r2, s1 + texld r3, r3, s1 + mul r4.xy, t0, c3 + frc r4.xy, r4 + lrp r5, r4.x, r1, r0 + lrp r0, r4.x, r2, r3 + lrp r1, r4.y, r5, r0 + mov r0, c1 + mad r0, r1, r0, c0 + mov oC0, r0 + +// approximately 23 instruction slots used (8 texture, 15 arithmetic) +#endif + +const DWORD PalTexBilinearDef[] = +{ + 0xffff0200, 0x0050fffe, 0x42415443, 0x0000001c, 0x00000109, 0xffff0200, + 0x00000007, 0x0000001c, 0x20000100, 0x00000102, 0x000000a8, 0x00000002, + 0x00020001, 0x000000b0, 0x00000000, 0x000000c0, 0x00000003, 0x00020001, + 0x000000c8, 0x00000000, 0x000000d8, 0x00010002, 0x00060001, 0x000000b0, + 0x00000000, 0x000000e1, 0x00010003, 0x00060001, 0x000000c8, 0x00000000, + 0x000000e9, 0x00020002, 0x000a0001, 0x000000b0, 0x00000000, 0x000000f4, + 0x00030002, 0x000e0001, 0x000000b0, 0x00000000, 0x000000fb, 0x00040002, + 0x00120001, 0x000000b0, 0x00000000, 0x73616c46, 0xabab0068, 0x00030001, + 0x00040001, 0x00000001, 0x00000000, 0x67616d49, 0xabab0065, 0x000c0004, + 0x00010001, 0x00000001, 0x00000000, 0x46766e49, 0x6873616c, 0x6c615000, + 0x65747465, 0x6c615000, 0x65747465, 0x00646f4d, 0x657a6973, 0x7300615f, + 0x5f657a69, 0x73700062, 0x305f325f, 0x63694d00, 0x6f736f72, 0x28207466, + 0x48202952, 0x204c534c, 0x64616853, 0x43207265, 0x69706d6f, 0x2072656c, + 0x39312e39, 0x3934392e, 0x3131322e, 0xabab0031, 0x0200001f, 0x80000000, + 0xb0030000, 0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000, + 0xa00f0801, 0x03000002, 0x80030000, 0xb0e40000, 0xa0e40004, 0x03000002, + 0x80030001, 0xb0e40000, 0xa01b0004, 0x03000002, 0x80030002, 0xb0e40000, + 0xa01b0003, 0x03000042, 0x800f0000, 0x80e40000, 0xa0e40800, 0x03000042, + 0x800f0001, 0x80e40001, 0xa0e40800, 0x03000042, 0x800f0002, 0x80e40002, + 0xa0e40800, 0x03000042, 0x800f0003, 0xb0e40000, 0xa0e40800, 0x04000004, + 0x80010000, 0x80000000, 0xa0000002, 0xa0550002, 0x04000004, 0x80010001, + 0x80000001, 0xa0000002, 0xa0550002, 0x04000004, 0x80010002, 0x80000002, + 0xa0000002, 0xa0550002, 0x04000004, 0x80010003, 0x80000003, 0xa0000002, + 0xa0550002, 0x03000042, 0x800f0000, 0x80e40000, 0xa0e40801, 0x03000042, + 0x800f0001, 0x80e40001, 0xa0e40801, 0x03000042, 0x800f0002, 0x80e40002, + 0xa0e40801, 0x03000042, 0x800f0003, 0x80e40003, 0xa0e40801, 0x03000005, + 0x80030004, 0xb0e40000, 0xa0e40003, 0x02000013, 0x80030004, 0x80e40004, + 0x04000012, 0x800f0005, 0x80000004, 0x80e40001, 0x80e40000, 0x04000012, + 0x800f0000, 0x80000004, 0x80e40002, 0x80e40003, 0x04000012, 0x800f0001, + 0x80550004, 0x80e40005, 0x80e40000, 0x02000001, 0x800f0000, 0xa0e40001, + 0x04000004, 0x800f0000, 0x80e40001, 0x80e40000, 0xa0e40000, 0x02000001, + 0x800f0800, 0x80e40000, 0x0000ffff +}; + // A shader that doesn't look up colors from a palette. --------------------- // Can be used for RGB textures. @@ -277,7 +423,7 @@ const DWORD DimShaderDef[] = #if HLSL_SOURCE_CODE sampler2D Image : register(s0); -float4 Gamma : register(c4); +float4 Gamma : register(c7); float4 main (float2 texCoord : TEXCOORD0) : COLOR { @@ -287,9 +433,9 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR } #elif SHADER_ASSEMBLY_CODE // -// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000 +// Generated by Microsoft (R) HLSL Shader Compiler 9.19.949.2111 // -// fxc gammafixer.ps /Tps_2_0 /VnGammaFixerDef /Fh +// fxc gammafixer.ps /Tps_2_0 /VnGammaFixerDef /Fhgammafixer.h // // // Parameters: @@ -302,7 +448,7 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR // // Name Reg Size // ------------ ----- ---- -// Gamma c4 1 +// Gamma c7 1 // Image s0 1 // @@ -310,13 +456,13 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR dcl t0.xy dcl_2d s0 texld r0, t0, s0 - log r0.x, r0.x - log r0.y, r0.y - log r0.z, r0.z - mul r0.xyz, r0, c4 - exp r0.x, r0.x - exp r0.y, r0.y - exp r0.z, r0.z + log r1.x, r0.x + log r1.y, r0.y + log r1.z, r0.z + mul r1.xyz, r1, c7 + exp r0.x, r1.x + exp r0.y, r1.y + exp r0.z, r1.z mov oC0, r0 // approximately 9 instruction slots used (1 texture, 8 arithmetic) @@ -324,20 +470,20 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR const DWORD GammaFixerDef[] = { - 0xffff0200, 0x002dfffe, 0x42415443, 0x0000001c, 0x0000007b, 0xffff0200, - 0x00000002, 0x0000001c, 0x00000100, 0x00000074, 0x00000044, 0x00040002, - 0x00020001, 0x0000004c, 0x00000000, 0x0000005c, 0x00000003, 0x00000001, + 0xffff0200, 0x002cfffe, 0x42415443, 0x0000001c, 0x0000007b, 0xffff0200, + 0x00000002, 0x0000001c, 0x20000100, 0x00000074, 0x00000044, 0x00070002, + 0x001e0001, 0x0000004c, 0x00000000, 0x0000005c, 0x00000003, 0x00020001, 0x00000064, 0x00000000, 0x6d6d6147, 0xabab0061, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, 0x325f7370, 0x4d00305f, 0x6f726369, 0x74666f73, - 0x29522820, 0x44334420, 0x53203958, 0x65646168, 0x6f432072, 0x6c69706d, - 0x39207265, 0x2e35312e, 0x2e393737, 0x30303030, 0xababab00, 0x0200001f, - 0x80000000, 0xb0030000, 0x0200001f, 0x90000000, 0xa00f0800, 0x03000042, - 0x800f0000, 0xb0e40000, 0xa0e40800, 0x0200000f, 0x80010000, 0x80000000, - 0x0200000f, 0x80020000, 0x80550000, 0x0200000f, 0x80040000, 0x80aa0000, - 0x03000005, 0x80070000, 0x80e40000, 0xa0e40004, 0x0200000e, 0x80010000, - 0x80000000, 0x0200000e, 0x80020000, 0x80550000, 0x0200000e, 0x80040000, - 0x80aa0000, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff + 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, + 0x2e392072, 0x392e3931, 0x322e3934, 0x00313131, 0x0200001f, 0x80000000, + 0xb0030000, 0x0200001f, 0x90000000, 0xa00f0800, 0x03000042, 0x800f0000, + 0xb0e40000, 0xa0e40800, 0x0200000f, 0x80010001, 0x80000000, 0x0200000f, + 0x80020001, 0x80550000, 0x0200000f, 0x80040001, 0x80aa0000, 0x03000005, + 0x80070001, 0x80e40001, 0xa0e40007, 0x0200000e, 0x80010000, 0x80000001, + 0x0200000e, 0x80020000, 0x80550001, 0x0200000e, 0x80040000, 0x80aa0001, + 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff }; // The shader used by the burn effect screen wipe --------------------------- diff --git a/src/win32/fb_d3d9_wipe.cpp b/src/win32/fb_d3d9_wipe.cpp index ca2918725..8547d3813 100644 --- a/src/win32/fb_d3d9_wipe.cpp +++ b/src/win32/fb_d3d9_wipe.cpp @@ -262,7 +262,6 @@ bool D3DFB::WipeStartScreen(int type) // Even fullscreen will render to the TempRenderTexture, so we can have // a copy of the new screen readily available. GatheringWipeScreen = true; - UploadVertices(); return true; } @@ -338,7 +337,6 @@ bool D3DFB::WipeDo(int ticks) if (GatheringWipeScreen) { // This is the first time we've been called for this wipe. GatheringWipeScreen = false; - UploadVertices(); if (OldRenderTarget == NULL) { @@ -349,6 +347,7 @@ bool D3DFB::WipeDo(int ticks) else { // This is the second or later time we've been called for this wipe. D3DDevice->BeginScene(); + InScene = true; } if (OldRenderTarget != NULL) { @@ -468,7 +467,6 @@ bool D3DFB::Wiper_Crossfade::Run(int ticks, D3DFB *fb) fb->SetConstant(0, 0, 0, 0, clamp(Clock / 32.f, 0.f, 1.f)); fb->SetConstant(1, 1, 1, 1, 0); fb->SetPixelShader(fb->PlainShader); - // FIXME: The FinalWipeScreen gets junk at the top in letterbox modes. fb->D3DDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2); return Clock >= 32; @@ -681,12 +679,9 @@ bool D3DFB::Wiper_Burn::Run(int ticks, D3DFB *fb) fb->SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); fb->SetPixelShader(fb->BurnShader); fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(BURNVERTEX)); fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); - fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); + fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX); // The fire may not always stabilize, so the wipe is forced to end // after an arbitrary maximum time. diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index bb9a64396..93285d46b 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -252,6 +252,7 @@ private: friend class D3DTex; friend class D3DPal; + void SetInitialState(); bool CreateResources(); void ReleaseResources(); bool CreateFBTexture(); @@ -278,7 +279,8 @@ private: void SetConstant(int cnum, float r, float g, float b, float a); void SetPixelShader(IDirect3DPixelShader9 *shader); void SetTexture(int tnum, IDirect3DTexture9 *texture); - void SetPaletteTexture(IDirect3DTexture9 *texture, int count); + void SetPaletteTexture(IDirect3DTexture9 *texture, int count, INTBOOL bilinear); + void SetPalTexBilinearConstants(D3DTex *texture); BOOL AlphaBlendEnabled; D3DBLEND AlphaSrcBlend; @@ -303,8 +305,8 @@ private: int FBWidth, FBHeight; bool VSync; RECT BlendingRect; - bool UseBlendingRect; int In2D; + bool InScene; bool SM14; bool GatheringWipeScreen; D3DPal *Palettes; @@ -317,12 +319,14 @@ private: IDirect3DTexture9 *PaletteTexture; IDirect3DTexture9 *StencilPaletteTexture; IDirect3DTexture9 *ShadedPaletteTexture; - IDirect3DPixelShader9 *PalTexShader; + + IDirect3DPixelShader9 *PalTexShader, *PalTexBilinearShader; IDirect3DPixelShader9 *PlainShader; IDirect3DPixelShader9 *PlainStencilShader; IDirect3DPixelShader9 *DimShader; IDirect3DPixelShader9 *GammaFixerShader; IDirect3DPixelShader9 *BurnShader; + IDirect3DSurface9 *OldRenderTarget; IDirect3DTexture9 *InitialWipeScreen, *FinalWipeScreen;