From dbb6c7ca27e7fd8017906356c73b50b6a903415a Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 18 Nov 2016 01:58:39 +0100 Subject: [PATCH] Add support for specifying a viewport out of screen bounds and fixed statusbar by doing just that! --- .../fixedfunction/drawtrianglecodegen.cpp | 16 ++--- src/r_poly.cpp | 13 ++-- src/r_poly_decal.cpp | 4 -- src/r_poly_particle.cpp | 4 -- src/r_poly_plane.cpp | 8 --- src/r_poly_sky.cpp | 4 -- src/r_poly_sprite.cpp | 4 -- src/r_poly_triangle.cpp | 66 ++++++++++++++----- src/r_poly_triangle.h | 9 +-- src/r_poly_wall.cpp | 4 -- src/r_poly_wallsprite.cpp | 4 -- 11 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/r_compiler/fixedfunction/drawtrianglecodegen.cpp b/src/r_compiler/fixedfunction/drawtrianglecodegen.cpp index 6f9af51fc..8bf4779e2 100644 --- a/src/r_compiler/fixedfunction/drawtrianglecodegen.cpp +++ b/src/r_compiler/fixedfunction/drawtrianglecodegen.cpp @@ -78,10 +78,10 @@ void DrawTriangleCodegen::Setup(TriDrawVariant variant, bool truecolor) FDY31 = DY31 << 4; // Bounding rectangle - minx = SSAInt::MAX((SSAInt::MIN(SSAInt::MIN(X1, X2), X3) + 0xF) >> 4, clipleft); - maxx = SSAInt::MIN((SSAInt::MAX(SSAInt::MAX(X1, X2), X3) + 0xF) >> 4, clipright - 1); - miny = SSAInt::MAX((SSAInt::MIN(SSAInt::MIN(Y1, Y2), Y3) + 0xF) >> 4, cliptop); - maxy = SSAInt::MIN((SSAInt::MAX(SSAInt::MAX(Y1, Y2), Y3) + 0xF) >> 4, clipbottom - 1); + minx = SSAInt::MAX((SSAInt::MIN(SSAInt::MIN(X1, X2), X3) + 0xF).ashr(4), clipleft); + maxx = SSAInt::MIN((SSAInt::MAX(SSAInt::MAX(X1, X2), X3) + 0xF).ashr(4), clipright - 1); + miny = SSAInt::MAX((SSAInt::MIN(SSAInt::MIN(Y1, Y2), Y3) + 0xF).ashr(4), cliptop); + maxy = SSAInt::MIN((SSAInt::MAX(SSAInt::MAX(Y1, Y2), Y3) + 0xF).ashr(4), clipbottom - 1); SSAIfBlock if0; if0.if_block(minx >= maxx || miny >= maxy); @@ -221,7 +221,7 @@ void DrawTriangleCodegen::LoopBlockX(TriDrawVariant variant, bool truecolor) branch.if_block(!(a == SSAInt(0) || b == SSAInt(0) || c == SSAInt(0))); // Check if block needs clipping - SSABool clipneeded = clipleft > x || clipright < (x + q) || cliptop > y || clipbottom < (y + q); + SSABool clipneeded = x < clipleft || (x + q) > clipright || y < cliptop || (y + q) > clipbottom; // Calculate varying variables for affine block SSAFloat offx0 = SSAFloat(x - minx); @@ -401,7 +401,7 @@ void DrawTriangleCodegen::LoopPartialBlock(TriDrawVariant variant, bool truecolo varying[i] = stack_varying[i].load(); loopx.loop_block(ix < SSAInt(q), q); { - SSABool visible = (ix + x >= clipleft) && (ix + x < clipright) && (cliptop <= y + iy) && (clipbottom > y + iy); + SSABool visible = (ix + x >= clipleft) && (ix + x < clipright) && (iy + y >= cliptop) && (iy + y < clipbottom); SSABool covered = CX1 > SSAInt(0) && CX2 > SSAInt(0) && CX3 > SSAInt(0) && visible; if (variant == TriDrawVariant::DrawSubsector || variant == TriDrawVariant::DrawShadedSubsector || variant == TriDrawVariant::FillSubsector) @@ -589,9 +589,9 @@ void DrawTriangleCodegen::LoadArgs(TriDrawVariant variant, bool truecolor, SSAVa v1 = LoadTriVertex(args[0][2].load(true)); v2 = LoadTriVertex(args[0][3].load(true)); v3 = LoadTriVertex(args[0][4].load(true)); - clipleft = args[0][5].load(true); + clipleft = SSAInt(0);// args[0][5].load(true); clipright = args[0][6].load(true); - cliptop = args[0][7].load(true); + cliptop = SSAInt(0);// args[0][7].load(true); clipbottom = args[0][8].load(true); texturePixels = args[0][9].load(true); textureWidth = args[0][10].load(true); diff --git a/src/r_poly.cpp b/src/r_poly.cpp index ade89571e..7a06a471e 100644 --- a/src/r_poly.cpp +++ b/src/r_poly.cpp @@ -62,8 +62,8 @@ void RenderPolyScene::ClearBuffers() SectorSpriteRanges.resize(numsectors); SortedSprites.clear(); TranslucentObjects.clear(); - PolyStencilBuffer::Instance()->Clear(viewwidth, viewheight, 0); - PolySubsectorGBuffer::Instance()->Resize(dc_pitch, viewheight); + PolyStencilBuffer::Instance()->Clear(screen->GetWidth(), screen->GetHeight(), 0); + PolySubsectorGBuffer::Instance()->Resize(screen->GetPitch(), screen->GetHeight()); NextSubsectorDepth = 0; } @@ -79,14 +79,12 @@ void RenderPolyScene::SetupPerspectiveMatrix() int height; if (screenblocks >= 10) - { height = SCREENHEIGHT; - } else - { height = (screenblocks*SCREENHEIGHT / 10) & ~7; - } - viewheight = height; // So viewheight was calculated incorrectly. That's just.. wonderful. + + int bottom = SCREENHEIGHT - (height + viewwindowy - ((height - viewheight) / 2)); + PolyTriangleDrawer::set_viewport(viewwindowx, SCREENHEIGHT - bottom - height, viewwidth, height, screen); // Code provided courtesy of Graf Zahl. Now we just have to plug it into the viewmatrix code... // We have to scale the pitch to account for the pixel stretching, because the playsim doesn't know about this and treats it as 1:1. @@ -105,6 +103,7 @@ void RenderPolyScene::SetupPerspectiveMatrix() TriMatrix::scale(1.0f, glset.pixelstretch, 1.0f) * TriMatrix::swapYZ() * TriMatrix::translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z); + WorldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView; } diff --git a/src/r_poly_decal.cpp b/src/r_poly_decal.cpp index 011ce83e4..0c6c427a8 100644 --- a/src/r_poly_decal.cpp +++ b/src/r_poly_decal.cpp @@ -148,10 +148,6 @@ void RenderPolyDecal::Render(const TriMatrix &worldToClip, DBaseDecal *decal, co args.vcount = 4; args.mode = TriangleDrawMode::Fan; args.ccw = true; - args.clipleft = 0; - args.cliptop = 0; - args.clipright = viewwidth; - args.clipbottom = viewheight; args.stenciltestvalue = 0; args.stencilwritevalue = 1; args.SetTexture(tex); diff --git a/src/r_poly_particle.cpp b/src/r_poly_particle.cpp index f0b221988..be8030071 100644 --- a/src/r_poly_particle.cpp +++ b/src/r_poly_particle.cpp @@ -92,10 +92,6 @@ void RenderPolyParticle::Render(const TriMatrix &worldToClip, particle_t *partic args.vcount = 4; args.mode = TriangleDrawMode::Fan; args.ccw = true; - args.clipleft = 0; - args.cliptop = 0; - args.clipright = viewwidth; - args.clipbottom = viewheight; args.stenciltestvalue = 0; args.stencilwritevalue = 1; args.solidcolor = (alpha << 24) | (particle->color & 0xffffff); diff --git a/src/r_poly_plane.cpp b/src/r_poly_plane.cpp index 5b0e912a8..9a425598b 100644 --- a/src/r_poly_plane.cpp +++ b/src/r_poly_plane.cpp @@ -137,10 +137,6 @@ void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, subsector_t *s args.vcount = sub->numlines; args.mode = TriangleDrawMode::Fan; args.ccw = true; - args.clipleft = 0; - args.cliptop = 0; - args.clipright = viewwidth; - args.clipbottom = viewheight; args.stenciltestvalue = 0; args.stencilwritevalue = 1; args.SetTexture(tex); @@ -233,10 +229,6 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, subsector_t *sub, uin args.vcount = sub->numlines; args.mode = TriangleDrawMode::Fan; args.ccw = ccw; - args.clipleft = 0; - args.cliptop = 0; - args.clipright = viewwidth; - args.clipbottom = viewheight; args.stenciltestvalue = 0; args.stencilwritevalue = 1; diff --git a/src/r_poly_sky.cpp b/src/r_poly_sky.cpp index 03a4bfdb2..fc6963dbb 100644 --- a/src/r_poly_sky.cpp +++ b/src/r_poly_sky.cpp @@ -59,10 +59,6 @@ void PolySkyDome::Render(const TriMatrix &worldToClip) PolyDrawArgs args; args.uniforms = uniforms; - args.clipleft = 0; - args.cliptop = 0; - args.clipright = viewwidth; - args.clipbottom = viewheight; args.stenciltestvalue = 255; args.stencilwritevalue = 1; args.SetTexture(frontskytex); diff --git a/src/r_poly_sprite.cpp b/src/r_poly_sprite.cpp index 1701b24ef..e1c6fcc14 100644 --- a/src/r_poly_sprite.cpp +++ b/src/r_poly_sprite.cpp @@ -133,10 +133,6 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, AActor *thing, subse args.vcount = 4; args.mode = TriangleDrawMode::Fan; args.ccw = true; - args.clipleft = 0; - args.cliptop = 0; - args.clipright = viewwidth; - args.clipbottom = viewheight; args.stenciltestvalue = 0; args.stencilwritevalue = 1; args.SetTexture(tex); diff --git a/src/r_poly_triangle.cpp b/src/r_poly_triangle.cpp index 64611376b..d661fe0d7 100644 --- a/src/r_poly_triangle.cpp +++ b/src/r_poly_triangle.cpp @@ -40,9 +40,41 @@ #include #endif +int PolyTriangleDrawer::viewport_x; +int PolyTriangleDrawer::viewport_y; +int PolyTriangleDrawer::viewport_width; +int PolyTriangleDrawer::viewport_height; +int PolyTriangleDrawer::dest_pitch; +int PolyTriangleDrawer::dest_width; +int PolyTriangleDrawer::dest_height; +uint8_t *PolyTriangleDrawer::dest; +bool PolyTriangleDrawer::dest_bgra; + +void PolyTriangleDrawer::set_viewport(int x, int y, int width, int height, DCanvas *canvas) +{ + dest = (uint8_t*)canvas->GetBuffer(); + dest_width = canvas->GetWidth(); + dest_height = canvas->GetHeight(); + dest_pitch = canvas->GetPitch(); + dest_bgra = canvas->IsBgra(); + + int offsetx = clamp(x, 0, dest_width); + int offsety = clamp(y, 0, dest_height); + int pixelsize = dest_bgra ? 4 : 1; + + viewport_x = x - offsetx; + viewport_y = y - offsety; + viewport_width = width; + viewport_height = height; + + dest += (offsetx + offsety * dest_pitch) * pixelsize; + dest_width = clamp(viewport_x + viewport_width, 0, dest_width - offsetx); + dest_height = clamp(viewport_y + viewport_height, 0, dest_height - offsety); +} + void PolyTriangleDrawer::draw(const PolyDrawArgs &args, TriDrawVariant variant) { - if (r_swtruecolor) + if (dest_bgra) DrawerCommandQueue::QueueCommand(args, variant); else draw_arrays(args, variant, nullptr); @@ -59,33 +91,33 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, TriDrawVarian switch (variant) { default: - case TriDrawVariant::Draw: drawfunc = r_swtruecolor ? llvm->TriDraw32: llvm->TriDraw8; break; - case TriDrawVariant::Fill: drawfunc = r_swtruecolor ? llvm->TriFill32 : llvm->TriFill8; break; - case TriDrawVariant::DrawSubsector: drawfunc = r_swtruecolor ? llvm->TriDrawSubsector32 : llvm->TriDrawSubsector8; break; - case TriDrawVariant::DrawShadedSubsector: drawfunc = r_swtruecolor ? llvm->TriDrawShadedSubsector32 : llvm->TriDrawShadedSubsector8; break; - case TriDrawVariant::FillSubsector: drawfunc = r_swtruecolor ? llvm->TriFillSubsector32 : llvm->TriFillSubsector8; break; + case TriDrawVariant::Draw: drawfunc = dest_bgra ? llvm->TriDraw32: llvm->TriDraw8; break; + case TriDrawVariant::Fill: drawfunc = dest_bgra ? llvm->TriFill32 : llvm->TriFill8; break; + case TriDrawVariant::DrawSubsector: drawfunc = dest_bgra ? llvm->TriDrawSubsector32 : llvm->TriDrawSubsector8; break; + case TriDrawVariant::DrawShadedSubsector: drawfunc = dest_bgra ? llvm->TriDrawShadedSubsector32 : llvm->TriDrawShadedSubsector8; break; + case TriDrawVariant::FillSubsector: drawfunc = dest_bgra ? llvm->TriFillSubsector32 : llvm->TriFillSubsector8; break; case TriDrawVariant::Stencil: drawfunc = llvm->TriStencil; break; } #else switch (variant) { default: - case TriDrawVariant::Draw: drawfunc = r_swtruecolor ? ScreenPolyTriangleDrawer::draw32 : ScreenPolyTriangleDrawer::draw; break; + case TriDrawVariant::Draw: drawfunc = dest_bgra ? ScreenPolyTriangleDrawer::draw32 : ScreenPolyTriangleDrawer::draw; break; case TriDrawVariant::FillSubsector: - case TriDrawVariant::Fill: drawfunc = r_swtruecolor ? ScreenPolyTriangleDrawer::fill32 : ScreenPolyTriangleDrawer::fill; break; + case TriDrawVariant::Fill: drawfunc = dest_bgra ? ScreenPolyTriangleDrawer::fill32 : ScreenPolyTriangleDrawer::fill; break; case TriDrawVariant::DrawShadedSubsector: - case TriDrawVariant::DrawSubsector: drawfunc = r_swtruecolor ? ScreenPolyTriangleDrawer::drawsubsector32 : llvm->TriDrawSubsector8; break; + case TriDrawVariant::DrawSubsector: drawfunc = dest_bgra ? ScreenPolyTriangleDrawer::drawsubsector32 : llvm->TriDrawSubsector8; break; case TriDrawVariant::Stencil: drawfunc = ScreenPolyTriangleDrawer::stencil; break; } #endif TriDrawTriangleArgs args; - args.dest = dc_destorg; - args.pitch = dc_pitch; - args.clipleft = drawargs.clipleft; - args.clipright = drawargs.clipright; - args.cliptop = drawargs.cliptop; - args.clipbottom = drawargs.clipbottom; + args.dest = dest; + args.pitch = dest_pitch; + args.clipleft = 0; + args.clipright = dest_width; + args.cliptop = 0; + args.clipbottom = dest_height; args.texturePixels = drawargs.texturePixels; args.textureWidth = drawargs.textureWidth; args.textureHeight = drawargs.textureHeight; @@ -163,8 +195,8 @@ void PolyTriangleDrawer::draw_shaded_triangle(const TriVertex *vert, bool ccw, T v.z *= v.w; // Apply viewport scale to get screen coordinates: - v.x = viewwidth * (1.0f + v.x) * 0.5f; - v.y = viewheight * (1.0f - v.y) * 0.5f; + v.x = viewport_x + viewport_width * (1.0f + v.x) * 0.5f; + v.y = viewport_y + viewport_height * (1.0f - v.y) * 0.5f; } // Draw screen triangles diff --git a/src/r_poly_triangle.h b/src/r_poly_triangle.h index f3f63f8f1..8f2fcf3d0 100644 --- a/src/r_poly_triangle.h +++ b/src/r_poly_triangle.h @@ -36,10 +36,6 @@ public: int vcount = 0; TriangleDrawMode mode = TriangleDrawMode::Normal; bool ccw = false; - int clipleft = 0; - int clipright = 0; - int cliptop = 0; - int clipbottom = 0; const uint8_t *texturePixels = nullptr; int textureWidth = 0; int textureHeight = 0; @@ -61,6 +57,7 @@ public: class PolyTriangleDrawer { public: + static void set_viewport(int x, int y, int width, int height, DCanvas *canvas); static void draw(const PolyDrawArgs &args, TriDrawVariant variant); private: @@ -70,6 +67,10 @@ private: static bool cullhalfspace(float clipdistance1, float clipdistance2, float &t1, float &t2); static void clipedge(const TriVertex *verts, TriVertex *clippedvert, int &numclipvert); + static int viewport_x, viewport_y, viewport_width, viewport_height, dest_pitch, dest_width, dest_height; + static bool dest_bgra; + static uint8_t *dest; + enum { max_additional_vertices = 16 }; friend class DrawPolyTrianglesCommand; diff --git a/src/r_poly_wall.cpp b/src/r_poly_wall.cpp index 2ed225cf2..1f1908ab4 100644 --- a/src/r_poly_wall.cpp +++ b/src/r_poly_wall.cpp @@ -187,10 +187,6 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip) args.vcount = 4; args.mode = TriangleDrawMode::Fan; args.ccw = true; - args.clipleft = 0; - args.cliptop = 0; - args.clipright = viewwidth; - args.clipbottom = viewheight; args.stenciltestvalue = 0; args.stencilwritevalue = 1; args.SetTexture(tex); diff --git a/src/r_poly_wallsprite.cpp b/src/r_poly_wallsprite.cpp index c6b3a6569..e2d1a9e86 100644 --- a/src/r_poly_wallsprite.cpp +++ b/src/r_poly_wallsprite.cpp @@ -118,10 +118,6 @@ void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, AActor *thing, s args.vcount = 4; args.mode = TriangleDrawMode::Fan; args.ccw = true; - args.clipleft = 0; - args.cliptop = 0; - args.clipright = viewwidth; - args.clipbottom = viewheight; args.stenciltestvalue = 0; args.stencilwritevalue = 1; args.SetTexture(tex);