// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Context.h: Defines the Context class, managing all GL state and performing
// rendering operations. It is the GLES2 specific implementation of EGLContext.
#ifndef LIBGLES_CM_CONTEXT_H_
#define LIBGLES_CM_CONTEXT_H_
#include "libEGL/Context.hpp"
#include "ResourceManager.h"
#include "common/NameSpace.hpp"
#include "common/Object.hpp"
#include "common/Image.hpp"
#include "Renderer/Sampler.hpp"
#include "common/MatrixStack.hpp"
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <EGL/egl.h>
#include <map>
#include <string>
namespace gl { class Surface; }
namespace egl
{
class Display;
class Config;
}
namespace es1
{
struct TranslatedAttribute;
struct TranslatedIndexData;
class Device;
class Buffer;
class Texture;
class Texture2D;
class TextureExternal;
class Framebuffer;
class Renderbuffer;
class RenderbufferStorage;
class Colorbuffer;
class Depthbuffer;
class StreamingIndexBuffer;
class Stencilbuffer;
class DepthStencilbuffer;
class VertexDataManager;
class IndexDataManager;
enum
{
MAX_VERTEX_ATTRIBS = sw::MAX_VERTEX_INPUTS,
MAX_VARYING_VECTORS = 10,
MAX_TEXTURE_UNITS = 2,
MAX_DRAW_BUFFERS = 1,
MAX_LIGHTS = 8,
MAX_CLIP_PLANES = sw::MAX_CLIP_PLANES,
MAX_MODELVIEW_STACK_DEPTH = 32,
MAX_PROJECTION_STACK_DEPTH = 2,
MAX_TEXTURE_STACK_DEPTH = 2,
};
const GLenum compressedTextureFormats[] =
{
GL_ETC1_RGB8_OES,
GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
};
const GLint NUM_COMPRESSED_TEXTURE_FORMATS = sizeof(compressedTextureFormats) / sizeof(compressedTextureFormats[0]);
const GLint multisampleCount[] = {4, 2, 1};
const GLint NUM_MULTISAMPLE_COUNTS = sizeof(multisampleCount) / sizeof(multisampleCount[0]);
const GLint IMPLEMENTATION_MAX_SAMPLES = multisampleCount[0];
const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f;
const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f;
const float ALIASED_POINT_SIZE_RANGE_MIN = 0.125f;
const float ALIASED_POINT_SIZE_RANGE_MAX = 8192.0f;
const float SMOOTH_LINE_WIDTH_RANGE_MIN = 1.0f;
const float SMOOTH_LINE_WIDTH_RANGE_MAX = 1.0f;
const float SMOOTH_POINT_SIZE_RANGE_MIN = 0.125f;
const float SMOOTH_POINT_SIZE_RANGE_MAX = 8192.0f;
const float MAX_TEXTURE_MAX_ANISOTROPY = 16.0f;
struct Color
{
float red;
float green;
float blue;
float alpha;
};
struct Point
{
float x;
float y;
float z;
float w;
};
struct Vector
{
float x;
float y;
float z;
};
struct Attenuation
{
float constant;
float linear;
float quadratic;
};
struct Light
{
bool enabled;
Color ambient;
Color diffuse;
Color specular;
Point position;
Vector direction;
Attenuation attenuation;
float spotExponent;
float spotCutoffAngle;
};
// Helper structure describing a single vertex attribute
class VertexAttribute
{
public:
VertexAttribute() : mType(GL_FLOAT), mSize(4), mNormalized(false), mStride(0), mPointer(nullptr), mArrayEnabled(false)
{
mCurrentValue[0] = 0.0f;
mCurrentValue[1] = 0.0f;
mCurrentValue[2] = 0.0f;
mCurrentValue[3] = 1.0f;
}
int typeSize() const
{
switch(mType)
{
case GL_BYTE: return mSize * sizeof(GLbyte);
case GL_UNSIGNED_BYTE: return mSize * sizeof(GLubyte);
case GL_SHORT: return mSize * sizeof(GLshort);
case GL_UNSIGNED_SHORT: return mSize * sizeof(GLushort);
case GL_FIXED: return mSize * sizeof(GLfixed);
case GL_FLOAT: return mSize * sizeof(GLfloat);
default: UNREACHABLE(mType); return mSize * sizeof(GLfloat);
}
}
GLsizei stride() const
{
return mStride ? mStride : typeSize();
}
// From glVertexAttribPointer
GLenum mType;
GLint mSize;
bool mNormalized;
GLsizei mStride; // 0 means natural stride
union
{
const void *mPointer;
intptr_t mOffset;
};
gl::BindingPointer<Buffer> mBoundBuffer; // Captured when glVertexAttribPointer is called.
bool mArrayEnabled; // From glEnable/DisableVertexAttribArray
float mCurrentValue[4]; // From glVertexAttrib
};
typedef VertexAttribute VertexAttributeArray[MAX_VERTEX_ATTRIBS];
struct TextureUnit
{
Color color;
GLenum environmentMode;
GLenum combineRGB;
GLenum combineAlpha;
GLenum src0RGB;
GLenum src0Alpha;
GLenum src1RGB;
GLenum src1Alpha;
GLenum src2RGB;
GLenum src2Alpha;
GLenum operand0RGB;
GLenum operand0Alpha;
GLenum operand1RGB;
GLenum operand1Alpha;
GLenum operand2RGB;
GLenum operand2Alpha;
};
// Helper structure to store all raw state
struct State
{
Color colorClearValue;
GLclampf depthClearValue;
int stencilClearValue;
bool cullFaceEnabled;
GLenum cullMode;
GLenum frontFace;
bool depthTestEnabled;
GLenum depthFunc;
bool blendEnabled;
GLenum sourceBlendRGB;
GLenum destBlendRGB;
GLenum sourceBlendAlpha;
GLenum destBlendAlpha;
GLenum blendEquationRGB;
GLenum blendEquationAlpha;
bool stencilTestEnabled;
GLenum stencilFunc;
GLint stencilRef;
GLuint stencilMask;
GLenum stencilFail;
GLenum stencilPassDepthFail;
GLenum stencilPassDepthPass;
GLuint stencilWritemask;
bool polygonOffsetFillEnabled;
GLfloat polygonOffsetFactor;
GLfloat polygonOffsetUnits;
bool sampleAlphaToCoverageEnabled;
bool sampleCoverageEnabled;
GLclampf sampleCoverageValue;
bool sampleCoverageInvert;
bool scissorTestEnabled;
bool ditherEnabled;
GLenum shadeModel;
GLfloat lineWidth;
GLenum generateMipmapHint;
GLenum perspectiveCorrectionHint;
GLenum fogHint;
GLint viewportX;
GLint viewportY;
GLsizei viewportWidth;
GLsizei viewportHeight;
float zNear;
float zFar;
GLint scissorX;
GLint scissorY;
GLsizei scissorWidth;
GLsizei scissorHeight;
bool colorMaskRed;
bool colorMaskGreen;
bool colorMaskBlue;
bool colorMaskAlpha;
bool depthMask;
unsigned int activeSampler; // Active texture unit selector - GL_TEXTURE0
gl::BindingPointer<Buffer> arrayBuffer;
gl::BindingPointer<Buffer> elementArrayBuffer;
GLuint framebuffer;
gl::BindingPointer<Renderbuffer> renderbuffer;
VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS];
gl::BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][MAX_TEXTURE_UNITS];
GLint unpackAlignment;
GLint packAlignment;
TextureUnit textureUnit[MAX_TEXTURE_UNITS];
};
class [[clang::lto_visibility_public]] Context : public egl::Context
{
public:
Context(egl::Display *display, const Context *shareContext, const egl::Config *config);
void makeCurrent(gl::Surface *surface) override;
EGLint getClientVersion() const override;
EGLint getConfigID() const override;
void finish() override;
void markAllStateDirty();
// State manipulation
void setClearColor(float red, float green, float blue, float alpha);
void setClearDepth(float depth);
void setClearStencil(int stencil);
void setCullFaceEnabled(bool enabled);
bool isCullFaceEnabled() const;
void setCullMode(GLenum mode);
void setFrontFace(GLenum front);
void setDepthTestEnabled(bool enabled);
bool isDepthTestEnabled() const;
void setDepthFunc(GLenum depthFunc);
void setDepthRange(float zNear, float zFar);
void setAlphaTestEnabled(bool enabled);
bool isAlphaTestEnabled() const;
void setAlphaFunc(GLenum alphaFunc, GLclampf reference);
void setBlendEnabled(bool enabled);
bool isBlendEnabled() const;
void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);
void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation);
void setStencilTestEnabled(bool enabled);
bool isStencilTestEnabled() const;
void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask);
void setStencilWritemask(GLuint stencilWritemask);
void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass);
void setPolygonOffsetFillEnabled(bool enabled);
bool isPolygonOffsetFillEnabled() const;
void setPolygonOffsetParams(GLfloat factor, GLfloat units);
void setSampleAlphaToCoverageEnabled(bool enabled);
bool isSampleAlphaToCoverageEnabled() const;
void setSampleCoverageEnabled(bool enabled);
bool isSampleCoverageEnabled() const;
void setSampleCoverageParams(GLclampf value, bool invert);
void setShadeModel(GLenum mode);
void setDitherEnabled(bool enabled);
bool isDitherEnabled() const;
void setLightingEnabled(bool enabled);
bool isLightingEnabled() const;
void setLightEnabled(int index, bool enable);
bool isLightEnabled(int index) const;
void setLightAmbient(int index, float r, float g, float b, float a);
void setLightDiffuse(int index, float r, float g, float b, float a);
void setLightSpecular(int index, float r, float g, float b, float a);
void setLightPosition(int index, float x, float y, float z, float w);
void setLightDirection(int index, float x, float y, float z);
void setLightAttenuationConstant(int index, float constant);
void setLightAttenuationLinear(int index, float linear);
void setLightAttenuationQuadratic(int index, float quadratic);
void setSpotLightExponent(int index, float exponent);
void setSpotLightCutoff(int index, float cutoff);
void setGlobalAmbient(float red, float green, float blue, float alpha);
void setMaterialAmbient(float red, float green, float blue, float alpha);
void setMaterialDiffuse(float red, float green, float blue, float alpha);
void setMaterialSpecular(float red, float green, float blue, float alpha);
void setMaterialEmission(float red, float green, float blue, float alpha);
void setMaterialShininess(float shininess);
void setLightModelTwoSide(bool enable);
void setFogEnabled(bool enabled);
bool isFogEnabled() const;
void setFogMode(GLenum mode);
void setFogDensity(float fogDensity);
void setFogStart(float fogStart);
void setFogEnd(float fogEnd);
void setFogColor(float r, float g, float b, float a);
void setTexture2Denabled(bool enabled);
bool isTexture2Denabled() const;
void setTextureExternalEnabled(bool enabled);
bool isTextureExternalEnabled() const;
void clientActiveTexture(GLenum texture);
GLenum getClientActiveTexture() const;
unsigned int getActiveTexture() const;
void setTextureEnvMode(GLenum texEnvMode);
void setTextureEnvColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
void setCombineRGB(GLenum combineRGB);
void setCombineAlpha(GLenum combineAlpha);
void setOperand0RGB(GLenum operand);
void setOperand1RGB(GLenum operand);
void setOperand2RGB(GLenum operand);
void setOperand0Alpha(GLenum operand);
void setOperand1Alpha(GLenum operand);
void setOperand2Alpha(GLenum operand);
void setSrc0RGB(GLenum src);
void setSrc1RGB(GLenum src);
void setSrc2RGB(GLenum src);
void setSrc0Alpha(GLenum src);
void setSrc1Alpha(GLenum src);
void setSrc2Alpha(GLenum src);
void setLineWidth(GLfloat width);
void setGenerateMipmapHint(GLenum hint);
void setPerspectiveCorrectionHint(GLenum hint);
void setFogHint(GLenum hint);
void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
void setScissorTestEnabled(bool enabled);
bool isScissorTestEnabled() const;
void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height);
void setColorMask(bool red, bool green, bool blue, bool alpha);
void setDepthMask(bool mask);
void setActiveSampler(unsigned int active);
GLuint getFramebufferName() const;
GLuint getRenderbufferName() const;
GLuint getArrayBufferName() const;
void setVertexAttribArrayEnabled(unsigned int attribNum, bool enabled);
const VertexAttribute &getVertexAttribState(unsigned int attribNum);
void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type,
bool normalized, GLsizei stride, const void *pointer);
const void *getVertexAttribPointer(unsigned int attribNum) const;
const VertexAttributeArray &getVertexAttributes();
void setUnpackAlignment(GLint alignment);
GLint getUnpackAlignment() const;
void setPackAlignment(GLint alignment);
GLint getPackAlignment() const;
// These create and destroy methods are merely pass-throughs to
// ResourceManager, which owns these object types
GLuint createBuffer();
GLuint createTexture();
GLuint createRenderbuffer();
void deleteBuffer(GLuint buffer);
void deleteTexture(GLuint texture);
void deleteRenderbuffer(GLuint renderbuffer);
// Framebuffers are owned by the Context, so these methods do not pass through
GLuint createFramebuffer();
void deleteFramebuffer(GLuint framebuffer);
void bindArrayBuffer(GLuint buffer);
void bindElementArrayBuffer(GLuint buffer);
void bindTexture(TextureType type, GLuint texture);
void bindTextureExternal(GLuint texture);
void bindFramebuffer(GLuint framebuffer);
void bindRenderbuffer(GLuint renderbuffer);
void setFramebufferZero(Framebuffer *framebuffer);
void setRenderbufferStorage(RenderbufferStorage *renderbuffer);
void setVertexAttrib(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
Buffer *getBuffer(GLuint handle);
virtual Texture *getTexture(GLuint handle);
Framebuffer *getFramebuffer(GLuint handle);
virtual Renderbuffer *getRenderbuffer(GLuint handle);
Buffer *getArrayBuffer();
Buffer *getElementArrayBuffer();
Texture2D *getTexture2D();
TextureExternal *getTextureExternal();
Texture *getSamplerTexture(unsigned int sampler, TextureType type);
Framebuffer *getFramebuffer();
bool getFloatv(GLenum pname, GLfloat *params);
bool getIntegerv(GLenum pname, GLint *params);
bool getBooleanv(GLenum pname, GLboolean *params);
bool getPointerv(GLenum pname, const GLvoid **params);
int getQueryParameterNum(GLenum pname);
bool isQueryParameterInt(GLenum pname);
bool isQueryParameterFloat(GLenum pname);
bool isQueryParameterBool(GLenum pname);
bool isQueryParameterPointer(GLenum pname);
void drawArrays(GLenum mode, GLint first, GLsizei count);
void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
void drawTexture(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height);
void blit(sw::Surface *source, const sw::SliceRect &sRect, sw::Surface *dest, const sw::SliceRect &dRect) override;
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
void clear(GLbitfield mask);
void flush();
void recordInvalidEnum();
void recordInvalidValue();
void recordInvalidOperation();
void recordOutOfMemory();
void recordInvalidFramebufferOperation();
void recordMatrixStackOverflow();
void recordMatrixStackUnderflow();
GLenum getError();
static int getSupportedMultisampleCount(int requested);
void bindTexImage(gl::Surface *surface) override;
EGLenum validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel) override;
egl::Image *createSharedImage(EGLenum target, GLuint name, GLuint textureLevel) override;
egl::Image *getSharedImage(GLeglImageOES image);
Device *getDevice();
void setMatrixMode(GLenum mode);
void loadIdentity();
void load(const GLfloat *m);
void pushMatrix();
void popMatrix();
void rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
void translate(GLfloat x, GLfloat y, GLfloat z);
void scale(GLfloat x, GLfloat y, GLfloat z);
void multiply(const GLfloat *m);
void frustum(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
void ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
void setClipPlane(int index, const float plane[4]);
void setClipPlaneEnabled(int index, bool enable);
bool isClipPlaneEnabled(int index) const;
void setColorLogicOpEnabled(bool enable);
bool isColorLogicOpEnabled() const;
void setLogicalOperation(GLenum logicOp);
void setPointSmoothEnabled(bool enable);
bool isPointSmoothEnabled() const;
void setLineSmoothEnabled(bool enable);
bool isLineSmoothEnabled() const;
void setColorMaterialEnabled(bool enable);
bool isColorMaterialEnabled() const;
void setNormalizeEnabled(bool enable);
bool isNormalizeEnabled() const;
void setRescaleNormalEnabled(bool enable);
bool isRescaleNormalEnabled() const;
void setVertexArrayEnabled(bool enable);
bool isVertexArrayEnabled() const;
void setNormalArrayEnabled(bool enable);
bool isNormalArrayEnabled() const;
void setColorArrayEnabled(bool enable);
bool isColorArrayEnabled() const;
void setPointSizeArrayEnabled(bool enable);
bool isPointSizeArrayEnabled() const;
void setTextureCoordArrayEnabled(bool enable);
bool isTextureCoordArrayEnabled() const;
void setMultisampleEnabled(bool enable);
bool isMultisampleEnabled() const;
void setSampleAlphaToOneEnabled(bool enable);
bool isSampleAlphaToOneEnabled() const;
void setPointSpriteEnabled(bool enable);
bool isPointSpriteEnabled() const;
void setPointSizeMin(float min);
void setPointSizeMax(float max);
void setPointDistanceAttenuation(float a, float b, float c);
void setPointFadeThresholdSize(float threshold);
private:
~Context() override;
bool applyRenderTarget();
void applyState(GLenum drawMode);
GLenum applyVertexBuffer(GLint base, GLint first, GLsizei count);
GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
void applyTextures();
void applyTexture(int sampler, Texture *texture);
void detachBuffer(GLuint buffer);
void detachTexture(GLuint texture);
void detachFramebuffer(GLuint framebuffer);
void detachRenderbuffer(GLuint renderbuffer);
bool cullSkipsDraw(GLenum drawMode);
bool isTriangleMode(GLenum drawMode);
const egl::Config *const config;
State mState;
gl::BindingPointer<Texture2D> mTexture2DZero;
gl::BindingPointer<TextureExternal> mTextureExternalZero;
gl::NameSpace<Framebuffer> mFramebufferNameSpace;
VertexDataManager *mVertexDataManager;
IndexDataManager *mIndexDataManager;
bool lightingEnabled;
Light light[MAX_LIGHTS];
Color globalAmbient;
Color materialAmbient;
Color materialDiffuse;
Color materialSpecular;
Color materialEmission;
GLfloat materialShininess;
bool lightModelTwoSide;
// Recorded errors
bool mInvalidEnum;
bool mInvalidValue;
bool mInvalidOperation;
bool mOutOfMemory;
bool mInvalidFramebufferOperation;
bool mMatrixStackOverflow;
bool mMatrixStackUnderflow;
bool mHasBeenCurrent;
// state caching flags
bool mDepthStateDirty;
bool mMaskStateDirty;
bool mBlendStateDirty;
bool mStencilStateDirty;
bool mPolygonOffsetStateDirty;
bool mSampleStateDirty;
bool mFrontFaceDirty;
bool mDitherStateDirty;
sw::MatrixStack ¤tMatrixStack();
GLenum matrixMode;
sw::MatrixStack modelViewStack;
sw::MatrixStack projectionStack;
sw::MatrixStack textureStack0;
sw::MatrixStack textureStack1;
bool texture2Denabled[MAX_TEXTURE_UNITS];
bool textureExternalEnabled[MAX_TEXTURE_UNITS];
GLenum clientTexture;
int clipFlags;
bool alphaTestEnabled;
GLenum alphaTestFunc;
float alphaTestRef;
bool fogEnabled;
GLenum fogMode;
float fogDensity;
float fogStart;
float fogEnd;
Color fogColor;
bool lineSmoothEnabled;
bool colorMaterialEnabled;
bool normalizeEnabled;
bool rescaleNormalEnabled;
bool multisampleEnabled;
bool sampleAlphaToOneEnabled;
bool pointSpriteEnabled;
bool pointSmoothEnabled;
float pointSizeMin;
float pointSizeMax;
Attenuation pointDistanceAttenuation;
float pointFadeThresholdSize;
bool colorLogicOpEnabled;
GLenum logicalOperation;
Device *device;
ResourceManager *mResourceManager;
};
}
#endif // INCLUDE_CONTEXT_H_