blob: b50c1273df374f124cbe64e4f62f123c31870af3 [file] [log] [blame]
// SwiftShader Software Renderer
//
// Copyright(c) 2005-2013 TransGaming Inc.
//
// All rights reserved. No part of this software may be copied, distributed, transmitted,
// transcribed, stored in a retrieval system, translated into any human or computer
// language by any means, or disclosed to third parties without the explicit written
// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
// or implied, including but not limited to any patent rights, are granted to you.
//
#ifndef sw_Surface_hpp
#define sw_Surface_hpp
#include "Color.hpp"
#include "Main/Config.hpp"
#include "Common/Resource.hpp"
namespace sw
{
class Resource;
struct Rect
{
Rect() {}
Rect(int x0i, int y0i, int x1i, int y1i) : x0(x0i), y0(y0i), x1(x1i), y1(y1i) {}
void clip(int minX, int minY, int maxX, int maxY);
int x0; // Inclusive
int y0; // Inclusive
int x1; // Exclusive
int y1; // Exclusive
};
struct SliceRect : public Rect
{
SliceRect() : slice(0) {}
SliceRect(const Rect& rect) : Rect(rect), slice(0) {}
SliceRect(const Rect& rect, int s) : Rect(rect), slice(s) {}
SliceRect(int x0, int y0, int x1, int y1, int s) : Rect(x0, y0, x1, y1), slice(s) {}
int slice;
};
enum Format : unsigned char
{
FORMAT_NULL,
FORMAT_A8,
FORMAT_R8,
FORMAT_R3G3B2,
FORMAT_A8R3G3B2,
FORMAT_X4R4G4B4,
FORMAT_A4R4G4B4,
FORMAT_R5G6B5,
FORMAT_R8G8B8,
FORMAT_X8R8G8B8,
FORMAT_A8R8G8B8,
FORMAT_X8B8G8R8,
FORMAT_A8B8G8R8,
FORMAT_X1R5G5B5,
FORMAT_A1R5G5B5,
FORMAT_G8R8,
FORMAT_G16R16,
FORMAT_A2R10G10B10,
FORMAT_A2B10G10R10,
FORMAT_A16B16G16R16,
// Paletted formats
FORMAT_P8,
FORMAT_A8P8,
// Compressed formats
FORMAT_DXT1,
FORMAT_DXT3,
FORMAT_DXT5,
FORMAT_ATI1,
FORMAT_ATI2,
FORMAT_ETC1,
// Floating-point formats
FORMAT_R16F,
FORMAT_G16R16F,
FORMAT_A16B16G16R16F,
FORMAT_R32F,
FORMAT_G32R32F,
FORMAT_A32B32G32R32F,
// Bump map formats
FORMAT_V8U8,
FORMAT_L6V5U5,
FORMAT_Q8W8V8U8,
FORMAT_X8L8V8U8,
FORMAT_A2W10V10U10,
FORMAT_V16U16,
FORMAT_A16W16V16U16,
FORMAT_Q16W16V16U16,
// Luminance formats
FORMAT_L8,
FORMAT_A4L4,
FORMAT_L16,
FORMAT_A8L8,
// Depth/stencil formats
FORMAT_D16,
FORMAT_D32,
FORMAT_D24X8,
FORMAT_D24S8,
FORMAT_D24FS8,
FORMAT_D32F, // Quad layout
FORMAT_D32F_COMPLEMENTARY, // Quad layout, 1 - z
FORMAT_D32F_LOCKABLE, // Linear layout
FORMAT_D32FS8_TEXTURE, // Linear layout, no PCF
FORMAT_D32FS8_SHADOW, // Linear layout, PCF
FORMAT_DF24S8,
FORMAT_DF16S8,
FORMAT_INTZ,
FORMAT_S8,
// Quad layout framebuffer
FORMAT_X8G8R8B8Q,
FORMAT_A8G8R8B8Q,
FORMAT_LAST = FORMAT_A8G8R8B8Q
};
enum Lock
{
LOCK_UNLOCKED,
LOCK_READONLY,
LOCK_WRITEONLY,
LOCK_READWRITE,
LOCK_DISCARD
};
class Surface
{
private:
struct Buffer
{
public:
void write(int x, int y, int z, const Color<float> &color);
void write(int x, int y, const Color<float> &color);
void write(void *element, const Color<float> &color);
Color<float> read(int x, int y, int z) const;
Color<float> read(int x, int y) const;
Color<float> read(void *element) const;
Color<float> sample(float x, float y, float z) const;
Color<float> sample(float x, float y) const;
void *lockRect(int x, int y, int z, Lock lock);
void unlockRect();
void *buffer;
int width;
int height;
int depth;
int bytes;
int pitchB;
int pitchP;
int sliceB;
int sliceP;
Format format;
Lock lock;
bool dirty;
};
public:
Surface(Resource *texture, int width, int height, int depth, Format format, bool lockable, bool renderTarget);
virtual ~Surface();
void *lockExternal(int x, int y, int z, Lock lock, Accessor client);
void unlockExternal();
inline int getExternalWidth() const;
inline int getExternalHeight() const;
inline int getExternalDepth() const;
inline Format getExternalFormat() const;
inline int getExternalPitchB() const;
inline int getExternalPitchP() const;
inline int getExternalSliceB() const;
inline int getExternalSliceP() const;
virtual void *lockInternal(int x, int y, int z, Lock lock, Accessor client);
virtual void unlockInternal();
inline int getInternalWidth() const;
inline int getInternalHeight() const;
inline int getInternalDepth() const;
inline Format getInternalFormat() const;
inline int getInternalPitchB() const;
inline int getInternalPitchP() const;
inline int getInternalSliceB() const;
inline int getInternalSliceP() const;
void *lockStencil(int front, Accessor client);
void unlockStencil();
inline int getStencilPitchB() const;
inline int getStencilPitchP() const;
inline int getStencilSliceB() const;
inline int getMultiSampleCount() const;
inline int getSuperSampleCount() const;
void clearColorBuffer(unsigned int colorARGB, unsigned int rgbaMask, int x0, int y0, int width, int height);
void clearDepthBuffer(float depth, int x0, int y0, int width, int height);
void clearStencilBuffer(unsigned char stencil, unsigned char mask, int x0, int y0, int width, int height);
void fill(const Color<float> &color, int x0, int y0, int width, int height);
Color<float> readExternal(int x, int y, int z) const;
Color<float> readExternal(int x, int y) const;
Color<float> sampleExternal(float x, float y, float z) const;
Color<float> sampleExternal(float x, float y) const;
void writeExternal(int x, int y, int z, const Color<float> &color);
void writeExternal(int x, int y, const Color<float> &color);
Color<float> readInternal(int x, int y, int z) const;
Color<float> readInternal(int x, int y) const;
Color<float> sampleInternal(float x, float y, float z) const;
Color<float> sampleInternal(float x, float y) const;
void writeInternal(int x, int y, int z, const Color<float> &color);
void writeInternal(int x, int y, const Color<float> &color);
bool hasStencil() const;
bool hasDepth() const;
bool hasPalette() const;
bool isRenderTarget() const;
bool hasDirtyMipmaps() const;
void cleanMipmaps();
Resource *getResource();
static int bytes(Format format);
static int pitchB(int width, Format format, bool target);
static int pitchP(int width, Format format, bool target);
static int sliceB(int width, int height, Format format, bool target);
static int sliceP(int width, int height, Format format, bool target);
static unsigned int size(int width, int height, int depth, Format format); // FIXME: slice * depth
static bool isStencil(Format format);
static bool isDepth(Format format);
static bool isPalette(Format format);
static bool isFloatFormat(Format format);
static bool isUnsignedComponent(Format format, int component);
static bool isSRGBreadable(Format format);
static bool isSRGBwritable(Format format);
static bool isCompressed(Format format);
static int componentCount(Format format);
static void setTexturePalette(unsigned int *palette);
protected:
sw::Resource *resource;
private:
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned int dword;
typedef uint64_t qword;
#if S3TC_SUPPORT
struct DXT1
{
word c0;
word c1;
dword lut;
};
struct DXT3
{
qword a;
word c0;
word c1;
dword lut;
};
struct DXT5
{
union
{
struct
{
byte a0;
byte a1;
};
qword alut; // Skip first 16 bit
};
word c0;
word c1;
dword clut;
};
#endif
struct ATI2
{
union
{
struct
{
byte y0;
byte y1;
};
qword ylut; // Skip first 16 bit
};
union
{
struct
{
byte x0;
byte x1;
};
qword xlut; // Skip first 16 bit
};
};
struct ATI1
{
union
{
struct
{
byte r0;
byte r1;
};
qword rlut; // Skip first 16 bit
};
};
static void decodeR8G8B8(Buffer &destination, const Buffer &source);
static void decodeR5G6B5(Buffer &destination, const Buffer &source);
static void decodeX1R5G5B5(Buffer &destination, const Buffer &source);
static void decodeA1R5G5B5(Buffer &destination, const Buffer &source);
static void decodeX4R4G4B4(Buffer &destination, const Buffer &source);
static void decodeA4R4G4B4(Buffer &destination, const Buffer &source);
static void decodeP8(Buffer &destination, const Buffer &source);
#if S3TC_SUPPORT
static void decodeDXT1(Buffer &internal, const Buffer &external);
static void decodeDXT3(Buffer &internal, const Buffer &external);
static void decodeDXT5(Buffer &internal, const Buffer &external);
#endif
static void decodeATI1(Buffer &internal, const Buffer &external);
static void decodeATI2(Buffer &internal, const Buffer &external);
static void decodeETC1(Buffer &internal, const Buffer &external);
static void update(Buffer &destination, Buffer &source);
static void genericUpdate(Buffer &destination, Buffer &source);
static void *allocateBuffer(int width, int height, int depth, Format format);
static void memfill4(void *buffer, int pattern, int bytes);
bool identicalFormats() const;
Format selectInternalFormat(Format format) const;
void resolve();
Buffer external;
Buffer internal;
Buffer stencil;
const bool lockable;
const bool renderTarget;
bool dirtyMipmaps;
unsigned int paletteUsed;
static unsigned int *palette; // FIXME: Not multi-device safe
static unsigned int paletteID;
bool hasParent;
};
}
#undef min
#undef max
namespace sw
{
int Surface::getExternalWidth() const
{
return external.width;
}
int Surface::getExternalHeight() const
{
return external.height;
}
int Surface::getExternalDepth() const
{
return external.depth;
}
Format Surface::getExternalFormat() const
{
return external.format;
}
int Surface::getExternalPitchB() const
{
return external.pitchB;
}
int Surface::getExternalPitchP() const
{
return external.pitchP;
}
int Surface::getExternalSliceB() const
{
return external.sliceB;
}
int Surface::getExternalSliceP() const
{
return external.sliceP;
}
int Surface::getInternalWidth() const
{
return internal.width;
}
int Surface::getInternalHeight() const
{
return internal.height;
}
int Surface::getInternalDepth() const
{
return internal.depth;
}
Format Surface::getInternalFormat() const
{
return internal.format;
}
int Surface::getInternalPitchB() const
{
return internal.pitchB;
}
int Surface::getInternalPitchP() const
{
return internal.pitchP;
}
int Surface::getInternalSliceB() const
{
return internal.sliceB;
}
int Surface::getInternalSliceP() const
{
return internal.sliceP;
}
int Surface::getStencilPitchB() const
{
return stencil.pitchB;
}
int Surface::getStencilPitchP() const
{
return stencil.pitchP;
}
int Surface::getStencilSliceB() const
{
return stencil.sliceB;
}
int Surface::getMultiSampleCount() const
{
return sw::min(internal.depth, 4);
}
int Surface::getSuperSampleCount() const
{
return internal.depth > 4 ? internal.depth / 4 : 1;
}
}
#endif // sw_Surface_hpp