gzdoom-gles/src/gl/system/gl_swframebuffer.h

502 lines
13 KiB
C
Raw Normal View History

#ifndef __GL_SWFRAMEBUFFER
#define __GL_SWFRAMEBUFFER
#ifdef _WIN32
#include "win32iface.h"
#include "win32gliface.h"
#endif
#include "SkylineBinPack.h"
#include <memory>
class FGLDebug;
#ifdef _WIN32
class OpenGLSWFrameBuffer : public Win32GLFrameBuffer
{
typedef Win32GLFrameBuffer Super;
DECLARE_CLASS(OpenGLSWFrameBuffer, Win32GLFrameBuffer)
#else
#include "sdlglvideo.h"
class OpenGLSWFrameBuffer : public SDLGLFB
{
// typedef SDLGLFB Super; //[C]commented, DECLARE_CLASS defines this in linux
DECLARE_CLASS(OpenGLSWFrameBuffer, SDLGLFB)
#endif
public:
explicit OpenGLSWFrameBuffer() {}
OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen, bool bgra);
~OpenGLSWFrameBuffer();
bool IsValid() override;
bool Lock(bool buffered) override;
void Unlock() override;
void Update() override;
PalEntry *GetPalette() override;
void GetFlashedPalette(PalEntry palette[256]) override;
void UpdatePalette() override;
bool SetGamma(float gamma) override;
bool SetFlash(PalEntry rgb, int amount) override;
void GetFlash(PalEntry &rgb, int &amount) override;
int GetPageCount() override;
void SetVSync(bool vsync) override;
void NewRefreshRate() override;
void GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type) override;
void ReleaseScreenshotBuffer() override;
void SetBlendingRect(int x1, int y1, int x2, int y2) override;
bool Begin2D(bool copy3d) override;
void DrawBlendingRect() override;
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 color) override;
void Dim(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 realcolor) override;
void DrawPixel(int x, int y, int palcolor, uint32 rgbcolor) override;
void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints, double originx, double originy, double scalex, double scaley, DAngle rotation, FDynamicColormap *colormap, int lightlevel, int bottomclip) override;
2016-10-11 12:37:57 +00:00
bool WipeStartScreen(int type) override;
void WipeEndScreen() override;
bool WipeDo(int ticks) override;
void WipeCleanup() override;
#ifdef WIN32
void PaletteChanged() override { }
int QueryNewPalette() override { return 0; }
void Blank() override { }
bool PaintToWindow() override;
bool Is8BitMode() override { return false; }
int GetTrueHeight() override { return TrueHeight; }
#endif
private:
struct FBVERTEX
{
2016-10-11 12:37:57 +00:00
float x, y, z, rhw;
uint32_t color0, color1;
2016-10-11 12:37:57 +00:00
float tu, tv;
};
struct BURNVERTEX
{
float x, y, z, rhw;
float tu0, tv0;
float tu1, tv1;
};
enum
{
PSCONST_Desaturation,
PSCONST_PaletteMod,
PSCONST_Weights,
PSCONST_Gamma,
PSCONST_ScreenSize,
NumPSCONST
};
struct GammaRamp
{
uint16_t red[256], green[256], blue[256];
};
struct LTRBRect
{
int left, top, right, bottom;
};
class HWTexture
{
public:
HWTexture() { Buffers[0] = 0; Buffers[1] = 0; }
~HWTexture();
int Texture = 0;
int Buffers[2];
int CurrentBuffer = 0;
int WrapS = 0;
int WrapT = 0;
int Format = 0;
};
2016-10-11 11:09:32 +00:00
class HWFrameBuffer
{
public:
~HWFrameBuffer();
int Framebuffer = 0;
HWTexture *Texture = nullptr;
};
class HWVertexBuffer
{
public:
~HWVertexBuffer();
FBVERTEX *Lock();
void Unlock();
int VertexArray = 0;
int Buffer = 0;
int Size = 0;
};
class HWIndexBuffer
{
public:
~HWIndexBuffer();
uint16_t *Lock();
void Unlock();
int Buffer = 0;
int Size = 0;
private:
int LockedOldBinding = 0;
};
class HWPixelShader
{
public:
~HWPixelShader();
int Program = 0;
int VertexShader = 0;
int FragmentShader = 0;
int ConstantLocations[NumPSCONST];
int ImageLocation = -1;
int PaletteLocation = -1;
int NewScreenLocation = -1;
int BurnLocation = -1;
};
2016-10-11 11:09:32 +00:00
bool CreateFrameBuffer(const FString &name, int width, int height, HWFrameBuffer **outFramebuffer);
bool CreatePixelShader(FString vertexsrc, FString fragmentsrc, const FString &defines, HWPixelShader **outShader);
bool CreateVertexBuffer(int size, HWVertexBuffer **outVertexBuffer);
bool CreateIndexBuffer(int size, HWIndexBuffer **outIndexBuffer);
bool CreateTexture(const FString &name, int width, int height, int levels, int format, HWTexture **outTexture);
void SetGammaRamp(const GammaRamp *ramp);
void SetPixelShaderConstantF(int uniformIndex, const float *data, int vec4fcount);
void SetHWPixelShader(HWPixelShader *shader);
void SetStreamSource(HWVertexBuffer *vertexBuffer);
void SetIndices(HWIndexBuffer *indexBuffer);
void DrawTriangleFans(int count, const FBVERTEX *vertices);
2016-10-11 12:37:57 +00:00
void DrawTriangleFans(int count, const BURNVERTEX *vertices);
void DrawPoints(int count, const FBVERTEX *vertices);
void DrawLineList(int count);
void DrawTriangleList(int minIndex, int numVertices, int startIndex, int primitiveCount);
void Present();
void BindFBBuffer();
void *MappedMemBuffer = nullptr;
bool UseMappedMemBuffer = true;
static uint32_t ColorARGB(uint32_t a, uint32_t r, uint32_t g, uint32_t b) { return ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b) & 0xff); }
static uint32_t ColorRGBA(uint32_t r, uint32_t g, uint32_t b, uint32_t a) { return ColorARGB(a, r, g, b); }
static uint32_t ColorXRGB(uint32_t r, uint32_t g, uint32_t b) { return ColorARGB(0xff, r, g, b); }
static uint32_t ColorValue(float r, float g, float b, float a) { return ColorRGBA((uint32_t)(r * 255.0f), (uint32_t)(g * 255.0f), (uint32_t)(b * 255.0f), (uint32_t)(a * 255.0f)); }
static void *MapBuffer(int target, int size);
// The number of points for the vertex buffer.
enum { NUM_VERTS = 10240 };
// The number of indices for the index buffer.
enum { NUM_INDEXES = ((NUM_VERTS * 6) / 4) };
// The number of quads we can batch together.
enum { MAX_QUAD_BATCH = (NUM_INDEXES / 6) };
// The default size for a texture atlas.
enum { DEF_ATLAS_WIDTH = 512 };
enum { DEF_ATLAS_HEIGHT = 512 };
// TYPES -------------------------------------------------------------------
struct Atlas;
struct PackedTexture
{
Atlas *Owner;
PackedTexture **Prev, *Next;
// Pixels this image covers
LTRBRect Area;
// Texture coordinates for this image
float Left, Top, Right, Bottom;
// Texture has extra space on the border?
bool Padded;
};
struct Atlas
{
Atlas(OpenGLSWFrameBuffer *fb, int width, int height, int format);
~Atlas();
PackedTexture *AllocateImage(const Rect &rect, bool padded);
void FreeBox(PackedTexture *box);
SkylineBinPack Packer;
Atlas *Next;
HWTexture *Tex;
int Format;
PackedTexture *UsedList; // Boxes that contain images
int Width, Height;
bool OneUse;
};
class OpenGLTex : public FNativeTexture
{
public:
OpenGLTex(FTexture *tex, OpenGLSWFrameBuffer *fb, bool wrapping);
~OpenGLTex();
FTexture *GameTex;
PackedTexture *Box;
OpenGLTex **Prev;
OpenGLTex *Next;
bool IsGray;
bool Create(OpenGLSWFrameBuffer *fb, bool wrapping);
bool Update();
bool CheckWrapping(bool wrapping);
int GetTexFormat();
FTextureFormat ToTexFmt(int fmt);
};
class OpenGLPal : public FNativePalette
{
public:
OpenGLPal(FRemapTable *remap, OpenGLSWFrameBuffer *fb);
~OpenGLPal();
OpenGLPal **Prev;
OpenGLPal *Next;
HWTexture *Tex;
uint32_t BorderColor;
bool DoColorSkip;
bool Update();
FRemapTable *Remap;
int RoundedPaletteSize;
};
// Flags for a buffered quad
enum
{
BQF_GamePalette = 1,
BQF_CustomPalette = 7,
BQF_Paletted = 7,
BQF_Bilinear = 8,
BQF_WrapUV = 16,
BQF_InvertSource = 32,
BQF_DisableAlphaTest = 64,
BQF_Desaturated = 128,
};
// Shaders for a buffered quad
enum
{
BQS_PalTex,
BQS_Plain,
BQS_RedToAlpha,
BQS_ColorOnly,
BQS_SpecialColormap,
BQS_InGameColormap,
};
struct BufferedTris
{
uint8_t Flags;
uint8_t ShaderNum;
int BlendOp;
int SrcBlend;
int DestBlend;
uint8_t Desat;
OpenGLPal *Palette;
HWTexture *Texture;
uint16_t NumVerts; // Number of _unique_ vertices used by this set.
uint16_t NumTris; // Number of triangles used by this set.
void ClearSetup()
{
Flags = 0;
ShaderNum = 0;
BlendOp = 0;
SrcBlend = 0;
DestBlend = 0;
}
bool IsSameSetup(const BufferedTris &other) const
{
return Flags == other.Flags && ShaderNum == other.ShaderNum && BlendOp == other.BlendOp && SrcBlend == other.SrcBlend && DestBlend == other.DestBlend;
}
};
enum
{
SHADER_NormalColor,
SHADER_NormalColorPal,
SHADER_NormalColorInv,
SHADER_NormalColorPalInv,
SHADER_RedToAlpha,
SHADER_RedToAlphaInv,
SHADER_VertexColor,
SHADER_SpecialColormap,
SHADER_SpecialColormapPal,
SHADER_InGameColormap,
SHADER_InGameColormapDesat,
SHADER_InGameColormapInv,
SHADER_InGameColormapInvDesat,
SHADER_InGameColormapPal,
SHADER_InGameColormapPalDesat,
SHADER_InGameColormapPalInv,
SHADER_InGameColormapPalInvDesat,
SHADER_BurnWipe,
SHADER_GammaCorrection,
NUM_SHADERS
};
static const char *const ShaderDefines[NUM_SHADERS];
void Flip();
void SetInitialState();
bool CreateResources();
void ReleaseResources();
bool LoadShaders();
bool CreateFBTexture();
bool CreatePaletteTexture();
bool CreateVertexes();
void UploadPalette();
2016-10-12 05:34:07 +00:00
void CalcFullscreenCoords(FBVERTEX verts[4], bool viewarea_only, uint32_t color0, uint32_t color1) const;
bool Reset();
2016-10-11 12:37:57 +00:00
HWTexture *CopyCurrentScreen();
void ReleaseDefaultPoolItems();
void KillNativePals();
void KillNativeTexs();
PackedTexture *AllocPackedTexture(int width, int height, bool wrapping, int format);
void DrawPackedTextures(int packnum);
2016-10-12 05:34:07 +00:00
void DrawLetterbox(int x, int y, int width, int height);
void Draw3DPart(bool copy3d);
bool SetStyle(OpenGLTex *tex, DrawParms &parms, uint32_t &color0, uint32_t &color1, BufferedTris &quad);
static int GetStyleAlpha(int type);
static void SetColorOverlay(uint32_t color, float alpha, uint32_t &color0, uint32_t &color1);
void AddColorOnlyQuad(int left, int top, int width, int height, uint32_t color);
void AddColorOnlyRect(int left, int top, int width, int height, uint32_t color);
void CheckQuadBatch(int numtris = 2, int numverts = 4);
void BeginQuadBatch();
void EndQuadBatch();
void BeginLineBatch();
void EndLineBatch();
void EndBatch();
// State
void EnableAlphaTest(bool enabled);
void SetAlphaBlend(int op, int srcblend = 0, int destblend = 0);
void SetConstant(int cnum, float r, float g, float b, float a);
void SetPixelShader(HWPixelShader *shader);
void SetTexture(int tnum, HWTexture *texture);
void SetSamplerWrapS(int tnum, int mode);
void SetSamplerWrapT(int tnum, int mode);
void SetPaletteTexture(HWTexture *texture, int count, uint32_t border_color);
template<typename T> static void SafeRelease(T &x) { if (x != nullptr) { delete x; x = nullptr; } }
bool Valid = false;
std::shared_ptr<FGLDebug> Debug;
2016-10-11 12:37:57 +00:00
std::unique_ptr<HWVertexBuffer> StreamVertexBuffer, StreamVertexBufferBurn;
float ShaderConstants[NumPSCONST * 4];
HWPixelShader *CurrentShader = nullptr;
2016-10-11 11:09:32 +00:00
HWFrameBuffer *OutputFB = nullptr;
bool AlphaTestEnabled = false;
bool AlphaBlendEnabled = false;
int AlphaBlendOp = 0;
int AlphaSrcBlend = 0;
int AlphaDestBlend = 0;
float Constant[3][4];
uint32_t CurBorderColor;
HWPixelShader *CurPixelShader;
HWTexture *Texture[5];
int SamplerWrapS[5], SamplerWrapT[5];
PalEntry SourcePalette[256];
uint32_t BorderColor;
uint32_t FlashColor0, FlashColor1;
PalEntry FlashColor;
int FlashAmount;
int TrueHeight;
int PixelDoubling;
float Gamma;
bool UpdatePending;
bool NeedPalUpdate;
bool NeedGammaUpdate;
LTRBRect BlendingRect;
int In2D;
bool InScene;
bool GatheringWipeScreen;
bool AALines;
uint8_t BlockNum;
OpenGLPal *Palettes = nullptr;
OpenGLTex *Textures = nullptr;
Atlas *Atlases = nullptr;
HWTexture *FBTexture = nullptr;
HWTexture *PaletteTexture = nullptr;
HWTexture *ScreenshotTexture = nullptr;
HWVertexBuffer *VertexBuffer = nullptr;
FBVERTEX *VertexData = nullptr;
HWIndexBuffer *IndexBuffer = nullptr;
uint16_t *IndexData = nullptr;
BufferedTris *QuadExtra = nullptr;
int VertexPos;
int IndexPos;
int QuadBatchPos;
enum { BATCH_None, BATCH_Quads, BATCH_Lines } BatchType;
HWPixelShader *Shaders[NUM_SHADERS];
HWTexture *InitialWipeScreen = nullptr, *FinalWipeScreen = nullptr;
class Wiper
{
public:
virtual ~Wiper();
virtual bool Run(int ticks, OpenGLSWFrameBuffer *fb) = 0;
2016-10-11 12:37:57 +00:00
void DrawScreen(OpenGLSWFrameBuffer *fb, HWTexture *tex, int blendop = 0, uint32_t color0 = 0, uint32_t color1 = 0xFFFFFFF);
};
class Wiper_Melt; friend class Wiper_Melt;
class Wiper_Burn; friend class Wiper_Burn;
class Wiper_Crossfade; friend class Wiper_Crossfade;
Wiper *ScreenWipe;
};
#endif //__GL_SWFRAMEBUFFER