From f3db5f3803815f5ba65886f4c96c1640e4099021 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Mar 2017 13:06:24 +0200 Subject: [PATCH] - added a clipping rectangle to DCanvas that can be used independently of DrawTexture calls. Currently this is only being used for draw operations that are not automap related, i.e. DrawLine, DrawPixel and FillSimplePoly are not subjected to it. --- src/g_statusbar/shared_sbar.cpp | 1 + src/gl/system/gl_framebuffer.cpp | 5 +- src/gl/system/gl_framebuffer.h | 4 +- src/gl/system/gl_swframebuffer.cpp | 5 +- src/gl/system/gl_swframebuffer.h | 4 +- src/menu/menu.cpp | 1 + src/v_draw.cpp | 108 ++++++++++++++++++++++++----- src/v_video.cpp | 37 +--------- src/v_video.h | 12 +++- src/wi_stuff.cpp | 1 + src/win32/fb_d3d9.cpp | 7 +- src/win32/win32swiface.h | 4 +- 12 files changed, 119 insertions(+), 70 deletions(-) diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 06f5bed40..8b6b23170 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -1135,6 +1135,7 @@ void DBaseStatusBar::CallDraw(EHudState state) GlobalVMStack.Call(func, params, countof(params), nullptr, 0); } else Draw(state); + screen->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind. } diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 43c56018a..08afb72ae 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -361,6 +361,7 @@ FNativePalette *OpenGLFrameBuffer::CreatePalette(FRemapTable *remap) //========================================================================== bool OpenGLFrameBuffer::Begin2D(bool) { + ClearClipRect(); gl_RenderState.mViewMatrix.loadIdentity(); gl_RenderState.mProjectionMatrix.ortho(0, GetWidth(), GetHeight(), 0, -1.0f, 1.0f); gl_RenderState.ApplyMatrices(); @@ -428,7 +429,7 @@ void OpenGLFrameBuffer::Dim(PalEntry) Super::Dim(0); } -void OpenGLFrameBuffer::Dim(PalEntry color, float damount, int x1, int y1, int w, int h) +void OpenGLFrameBuffer::DoDim(PalEntry color, float damount, int x1, int y1, int w, int h) { if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr) GLRenderer->m2DDrawer->AddDim(color, damount, x1, y1, w, h); @@ -451,7 +452,7 @@ void OpenGLFrameBuffer::FlatFill (int left, int top, int right, int bottom, FTex // // //========================================================================== -void OpenGLFrameBuffer::Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) +void OpenGLFrameBuffer::DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color) { if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr) GLRenderer->m2DDrawer->AddClear(left, top, right, bottom, palcolor, color); diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 67d5969e5..72bdb7315 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -63,9 +63,9 @@ public: void DrawTextureParms(FTexture *img, DrawParms &parms); void DrawLine(int x1, int y1, int x2, int y2, int palcolor, uint32_t color); void DrawPixel(int x1, int y1, int palcolor, uint32_t color); - void Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color); + void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color); void Dim(PalEntry color=0); - void Dim (PalEntry color, float damount, int x1, int y1, int w, int h); + void DoDim (PalEntry color, float damount, int x1, int y1, int w, int h); void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin=false); void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints, diff --git a/src/gl/system/gl_swframebuffer.cpp b/src/gl/system/gl_swframebuffer.cpp index 6ff2e0943..acf5dc40b 100644 --- a/src/gl/system/gl_swframebuffer.cpp +++ b/src/gl/system/gl_swframebuffer.cpp @@ -2410,6 +2410,7 @@ bool OpenGLSWFrameBuffer::OpenGLPal::Update() bool OpenGLSWFrameBuffer::Begin2D(bool copy3d) { + ClearClipRect(); if (!Accel2D) { return false; @@ -2488,7 +2489,7 @@ FNativePalette *OpenGLSWFrameBuffer::CreatePalette(FRemapTable *remap) // //========================================================================== -void OpenGLSWFrameBuffer::Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) +void OpenGLSWFrameBuffer::DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color) { if (In2D < 2) { @@ -2517,7 +2518,7 @@ void OpenGLSWFrameBuffer::Clear(int left, int top, int right, int bottom, int pa // //========================================================================== -void OpenGLSWFrameBuffer::Dim(PalEntry color, float amount, int x1, int y1, int w, int h) +void OpenGLSWFrameBuffer::DoDim(PalEntry color, float amount, int x1, int y1, int w, int h) { if (amount <= 0) { diff --git a/src/gl/system/gl_swframebuffer.h b/src/gl/system/gl_swframebuffer.h index dc202a05c..03cc5a4e0 100644 --- a/src/gl/system/gl_swframebuffer.h +++ b/src/gl/system/gl_swframebuffer.h @@ -55,8 +55,8 @@ public: FNativeTexture *CreateTexture(FTexture *gametex, bool wrapping) override; FNativePalette *CreatePalette(FRemapTable *remap) override; void DrawTextureParms(FTexture *img, DrawParms &parms) override; - void Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) override; - void Dim(PalEntry color, float amount, int x1, int y1, int w, int h) override; + void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color) override; + void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h) override; void FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin) override; void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor) override; void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor) override; diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 2050c4834..6d82bd680 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -279,6 +279,7 @@ void DMenu::CallDrawer() { VMValue params[] = { (DObject*)this }; GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); + screen->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind. } } diff --git a/src/v_draw.cpp b/src/v_draw.cpp index d06628d43..a2caded53 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -155,6 +155,22 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) } } +void DCanvas::SetClipRect(int x, int y, int w, int h) +{ + clipleft = clamp(x, 0, GetWidth()); + clipwidth = clamp(w, 0, GetWidth() - x); + cliptop = clamp(y, 0, GetHeight()); + clipwidth = clamp(w, 0, GetHeight() - y); +} + +void DCanvas::GetClipRect(int *x, int *y, int *w, int *h) +{ + if (x) *x = clipleft; + if (y) *y = cliptop; + if (w) *w = clipwidth; + if (h) *h = clipheight; +} + bool DCanvas::SetTextureParms(DrawParms *parms, FTexture *img, double xx, double yy) const { if (img != NULL) @@ -692,6 +708,15 @@ bool DCanvas::ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t t parms->remap = nullptr; } + // intersect with the canvas's clipping rectangle. + if (clipwidth >= 0 && clipheight >= 0) + { + if (parms->lclip < clipleft) parms->lclip = clipleft; + if (parms->rclip > clipleft + clipwidth) parms->rclip = clipleft + clipwidth; + if (parms->uclip < cliptop) parms->uclip = cliptop; + if (parms->dclip < cliptop + clipheight) parms->uclip = cliptop + clipheight; + } + if (parms->uclip >= parms->dclip || parms->lclip >= parms->rclip) { return false; @@ -800,22 +825,6 @@ DEFINE_ACTION_FUNCTION(_Screen, VirtualToRealCoords) return MIN(numret, 2); } -void DCanvas::VirtualToRealCoordsFixed(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, - int vwidth, int vheight, bool vbottom, bool handleaspect) const -{ - double dx, dy, dw, dh; - - dx = FIXED2DBL(x); - dy = FIXED2DBL(y); - dw = FIXED2DBL(w); - dh = FIXED2DBL(h); - VirtualToRealCoords(dx, dy, dw, dh, vwidth, vheight, vbottom, handleaspect); - x = FLOAT2FIXED(dx); - y = FLOAT2FIXED(dy); - w = FLOAT2FIXED(dw); - h = FLOAT2FIXED(dh); -} - void DCanvas::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom, bool handleaspect) const { @@ -900,7 +909,7 @@ void DCanvas::DrawPixel(int x, int y, int palColor, uint32_t realcolor) // //========================================================================== -void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color) +void DCanvas::DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color) { #ifndef NO_SWRENDER if (palcolor < 0 && APART(color) != 255) @@ -914,6 +923,33 @@ void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uin #endif } +void DCanvas::Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) +{ + if (clipwidth >= 0 && clipheight >= 0) + { + int w = right - left; + int h = bottom - top; + if (left < clipleft) + { + w -= (clipleft - left); + left = clipleft; + } + if (w > clipwidth) w = clipwidth; + if (w <= 0) return; + + if (top < cliptop) + { + h -= (cliptop - top); + top = cliptop; + } + if (h > clipheight) w = clipheight; + if (h <= 0) return; + right = left + w; + bottom = top + h; + } + DoClear(left, top, right, bottom, palcolor, color); +} + DEFINE_ACTION_FUNCTION(_Screen, Clear) { PARAM_PROLOGUE; @@ -935,13 +971,49 @@ DEFINE_ACTION_FUNCTION(_Screen, Clear) // //========================================================================== -void DCanvas::Dim(PalEntry color, float damount, int x1, int y1, int w, int h) +void DCanvas::DoDim(PalEntry color, float damount, int x1, int y1, int w, int h) { #ifndef NO_SWRENDER SWCanvas::Dim(this, color, damount, x1, y1, w, h); #endif } +void DCanvas::Dim(PalEntry color, float damount, int x1, int y1, int w, int h) +{ + if (clipwidth >= 0 && clipheight >= 0) + { + if (x1 < clipleft) + { + w -= (clipleft - x1); + x1 = clipleft; + } + if (w > clipwidth) w = clipwidth; + if (w <= 0) return; + + if (y1 < cliptop) + { + h -= (cliptop - y1); + y1 = cliptop; + } + if (h > clipheight) w = clipheight; + if (h <= 0) return; + } + DoDim(color, damount, x1, y1, w, h); +} + +DEFINE_ACTION_FUNCTION(_Screen, Dim) +{ + PARAM_PROLOGUE; + PARAM_INT(color); + PARAM_FLOAT(amount); + PARAM_INT(x1); + PARAM_INT(y1); + PARAM_INT(w); + PARAM_INT(h); + screen->Dim(color, float(amount), x1, y1, w, h); + return 0; +} + //========================================================================== // // DCanvas :: FillSimplePoly diff --git a/src/v_video.cpp b/src/v_video.cpp index a6482a90c..3dea831be 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -204,8 +204,6 @@ void V_MarkRect (int x, int y, int width, int height) { } -DCanvas *DCanvas::CanvasChain = NULL; - //========================================================================== // // DCanvas Constructor @@ -220,10 +218,6 @@ DCanvas::DCanvas (int _width, int _height, bool _bgra) Width = _width; Height = _height; Bgra = _bgra; - - // Add to list of active canvases - Next = CanvasChain; - CanvasChain = this; } //========================================================================== @@ -234,22 +228,6 @@ DCanvas::DCanvas (int _width, int _height, bool _bgra) DCanvas::~DCanvas () { - // Remove from list of active canvases - DCanvas *probe = CanvasChain, **prev; - - prev = &CanvasChain; - probe = CanvasChain; - - while (probe != NULL) - { - if (probe == this) - { - *prev = probe->Next; - break; - } - prev = &probe->Next; - probe = probe->Next; - } } //========================================================================== @@ -336,20 +314,6 @@ void DCanvas::Dim (PalEntry color) Dim (dimmer, amount, 0, 0, Width, Height); } -DEFINE_ACTION_FUNCTION(_Screen, Dim) -{ - PARAM_PROLOGUE; - PARAM_INT(color); - PARAM_FLOAT(amount); - PARAM_INT(x1); - PARAM_INT(y1); - PARAM_INT(w); - PARAM_INT(h); - screen->Dim(color, float(amount), x1, y1, w, h); - return 0; -} - - //========================================================================== // // DCanvas :: GetScreenshotBuffer @@ -1168,6 +1132,7 @@ void DFrameBuffer::SetBlendingRect (int x1, int y1, int x2, int y2) bool DFrameBuffer::Begin2D (bool copy3d) { + ClearClipRect(); return false; } diff --git a/src/v_video.h b/src/v_video.h index 444e80f04..56041a228 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -225,7 +225,8 @@ public: virtual void Dim (PalEntry color = 0); // Dim part of the canvas - virtual void Dim (PalEntry color, float amount, int x1, int y1, int w, int h); + virtual void Dim (PalEntry color, float amount, int x1, int y1, int w, int h) final; + virtual void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h); // Fill an area with a texture virtual void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin=false); @@ -236,7 +237,8 @@ public: const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip); // Set an area to a specified color - virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color); + virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color) final; + virtual void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color); // Draws a line virtual void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor); @@ -259,6 +261,10 @@ public: // Text drawing functions ----------------------------------------------- // 2D Texture drawing + void ClearClipRect() { clipleft = cliptop = 0; clipwidth = clipheight = -1; } + void SetClipRect(int x, int y, int w, int h); + void GetClipRect(int *x, int *y, int *w, int *h); + bool SetTextureParms(DrawParms *parms, FTexture *img, double x, double y) const; void DrawTexture (FTexture *img, double x, double y, int tags, ...); void DrawTexture(FTexture *img, double x, double y, VMVa_List &); @@ -266,7 +272,6 @@ public: void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom=false, bool handleaspect=true) const; // Code that uses these (i.e. SBARINFO) should probably be evaluated for using doubles all around instead. - void VirtualToRealCoordsFixed(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; void VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; #ifdef DrawText @@ -285,6 +290,7 @@ protected: int Pitch; int LockCount; bool Bgra; + int clipleft = 0, cliptop = 0, clipwidth = -1, clipheight = -1; void DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms); diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 9e2fc7ed7..f9a49eb0d 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -730,6 +730,7 @@ void WI_Drawer() { VMValue self = WI_Screen; GlobalVMStack.Call(func, &self, 1, nullptr, 0); + screen->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind. // The internal handling here is somewhat poor. After being set to 'LeavingIntermission' // the screen is needed for one more draw operation so we cannot delete it right away but only here. diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 3c07b9c14..4fd198a1b 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -2557,6 +2557,7 @@ bool D3DPal::Update() bool D3DFB::Begin2D(bool copy3d) { + ClearClipRect(); if (!Accel2D) { return false; @@ -2635,11 +2636,11 @@ FNativePalette *D3DFB::CreatePalette(FRemapTable *remap) // //========================================================================== -void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color) +void D3DFB::DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color) { if (In2D < 2) { - Super::Clear(left, top, right, bottom, palcolor, color); + //Super::Clear(left, top, right, bottom, palcolor, color); return; } if (!InScene) @@ -2664,7 +2665,7 @@ 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) +void D3DFB::DoDim (PalEntry color, float amount, int x1, int y1, int w, int h) { if (amount <= 0) { diff --git a/src/win32/win32swiface.h b/src/win32/win32swiface.h index ecd5a49df..5c0a456e4 100644 --- a/src/win32/win32swiface.h +++ b/src/win32/win32swiface.h @@ -132,8 +132,8 @@ public: FNativeTexture *CreateTexture (FTexture *gametex, bool wrapping); FNativePalette *CreatePalette (FRemapTable *remap); void DrawTextureParms (FTexture *img, DrawParms &parms); - void Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color); - void Dim (PalEntry color, float amount, int x1, int y1, int w, int h); + void DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color); + void DoDim (PalEntry color, float amount, int x1, int y1, int w, int h); void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin); void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor); void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor);