blob: daf1829d4664e438df59a026ec2202d64a757f21 [file] [log] [blame]
//
// Copyright 2017 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// params:
// Parameter wrapper structs for OpenGL ES. These helpers cache re-used values
// in entry point routines.
#ifndef LIBANGLE_PARAMS_H_
#define LIBANGLE_PARAMS_H_
#include "angle_gl.h"
#include "common/Optional.h"
#include "common/PackedEnums.h"
#include "common/angleutils.h"
#include "common/mathutil.h"
#include "libANGLE/Error.h"
#include "libANGLE/entry_points_enum_autogen.h"
namespace gl
{
class Context;
template <EntryPoint EP>
struct EntryPointParam;
template <EntryPoint EP>
using EntryPointParamType = typename EntryPointParam<EP>::Type;
class ParamTypeInfo
{
public:
constexpr ParamTypeInfo(const char *selfClass, const ParamTypeInfo *parentType)
: mSelfClass(selfClass), mParentTypeInfo(parentType)
{
}
constexpr bool hasDynamicType(const ParamTypeInfo &typeInfo) const
{
return mSelfClass == typeInfo.mSelfClass ||
(mParentTypeInfo && mParentTypeInfo->hasDynamicType(typeInfo));
}
constexpr bool isValid() const { return mSelfClass != nullptr; }
private:
const char *mSelfClass;
const ParamTypeInfo *mParentTypeInfo;
};
#define ANGLE_PARAM_TYPE_INFO(NAME, BASENAME) \
static constexpr ParamTypeInfo TypeInfo = {#NAME, &BASENAME::TypeInfo}
class ParamsBase : angle::NonCopyable
{
public:
ParamsBase(Context *context, ...){};
template <EntryPoint EP, typename... ArgsT>
static void Factory(EntryPointParamType<EP> *objBuffer, ArgsT... args);
static constexpr ParamTypeInfo TypeInfo = {nullptr, nullptr};
};
// static
template <EntryPoint EP, typename... ArgsT>
ANGLE_INLINE void ParamsBase::Factory(EntryPointParamType<EP> *objBuffer, ArgsT... args)
{
new (objBuffer) EntryPointParamType<EP>(args...);
}
// Helper class that encompasses draw call parameters. It uses the HasIndexRange
// helper class to only pull index range info lazily to prevent unnecessary readback.
// It is also used when syncing state for the VertexArray implementation, since the
// vertex and index buffer updates depend on draw call parameters.
class DrawCallParams final : angle::NonCopyable
{
public:
// Called by DrawArrays.
DrawCallParams(PrimitiveMode mode, GLint firstVertex, GLsizei vertexCount, GLsizei instances)
: mMode(mode),
mFirstVertex(firstVertex),
mVertexCount(vertexCount),
mIndexCount(0),
mBaseVertex(0),
mType(GL_NONE),
mIndices(nullptr),
mInstances(instances),
mIndirect(nullptr)
{
}
// Called by DrawElements.
DrawCallParams(PrimitiveMode mode,
GLint indexCount,
GLenum type,
const void *indices,
GLint baseVertex,
GLsizei instances)
: mMode(mode),
mFirstVertex(0),
mVertexCount(0),
mIndexCount(indexCount),
mBaseVertex(baseVertex),
mType(type),
mIndices(indices),
mInstances(instances),
mIndirect(nullptr)
{
}
// Called by DrawArraysIndirect.
DrawCallParams(PrimitiveMode mode, const void *indirect);
// Called by DrawElementsIndirect.
DrawCallParams(PrimitiveMode mode, GLenum type, const void *indirect);
PrimitiveMode mode() const { return mMode; }
// Only applies to DrawArrays.
GLint firstVertex() const
{
return mFirstVertex;
}
size_t vertexCount() const
{
return mVertexCount;
}
GLsizei indexCount() const;
GLint baseVertex() const;
GLenum type() const;
const void *indices() const;
GLsizei instances() const;
const void *indirect() const;
bool isDrawElements() const { return (mType != GL_NONE); }
bool isDrawIndirect() const;
template <typename T>
T getClampedVertexCount() const;
template <EntryPoint EP, typename... ArgsT>
static void Factory(DrawCallParams *objBuffer, ArgsT... args);
ANGLE_PARAM_TYPE_INFO(DrawCallParams, ParamsBase);
private:
PrimitiveMode mMode;
mutable GLint mFirstVertex;
mutable size_t mVertexCount;
GLint mIndexCount;
GLint mBaseVertex;
GLenum mType;
const void *mIndices;
GLsizei mInstances;
const void *mIndirect;
};
template <typename T>
T DrawCallParams::getClampedVertexCount() const
{
constexpr size_t kMax = static_cast<size_t>(std::numeric_limits<T>::max());
return static_cast<T>(mVertexCount > kMax ? kMax : mVertexCount);
}
// Entry point funcs essentially re-map different entry point parameter arrays into
// the format the parameter type class expects. For example, for HasIndexRange, for the
// various indexed draw calls, they drop parameters that aren't useful and re-arrange
// the rest.
#define ANGLE_ENTRY_POINT_FUNC(NAME, CLASS, ...) \
\
template<> struct EntryPointParam<EntryPoint::NAME> \
{ \
using Type = CLASS; \
}; \
\
template<> inline void CLASS::Factory<EntryPoint::NAME>(__VA_ARGS__)
ANGLE_ENTRY_POINT_FUNC(DrawArrays,
DrawCallParams,
DrawCallParams *objBuffer,
Context *context,
PrimitiveMode mode,
GLint first,
GLsizei count)
{
return ParamsBase::Factory<EntryPoint::DrawArrays>(objBuffer, mode, first, count, 0);
}
ANGLE_ENTRY_POINT_FUNC(DrawArraysInstanced,
DrawCallParams,
DrawCallParams *objBuffer,
Context *context,
PrimitiveMode mode,
GLint first,
GLsizei count,
GLsizei instanceCount)
{
return ParamsBase::Factory<EntryPoint::DrawArraysInstanced>(objBuffer, mode, first, count,
instanceCount);
}
ANGLE_ENTRY_POINT_FUNC(DrawArraysInstancedANGLE,
DrawCallParams,
DrawCallParams *objBuffer,
Context *context,
PrimitiveMode mode,
GLint first,
GLsizei count,
GLsizei instanceCount)
{
return ParamsBase::Factory<EntryPoint::DrawArraysInstancedANGLE>(objBuffer, mode, first, count,
instanceCount);
}
ANGLE_ENTRY_POINT_FUNC(DrawArraysIndirect,
DrawCallParams,
DrawCallParams *objBuffer,
Context *context,
PrimitiveMode mode,
const void *indirect)
{
return ParamsBase::Factory<EntryPoint::DrawArraysIndirect>(objBuffer, mode, indirect);
}
ANGLE_ENTRY_POINT_FUNC(DrawElementsIndirect,
DrawCallParams,
DrawCallParams *objBuffer,
Context *context,
PrimitiveMode mode,
GLenum type,
const void *indirect)
{
return ParamsBase::Factory<EntryPoint::DrawElementsIndirect>(objBuffer, mode, type, indirect);
}
ANGLE_ENTRY_POINT_FUNC(DrawElements,
DrawCallParams,
DrawCallParams *objBuffer,
Context *context,
PrimitiveMode mode,
GLsizei count,
GLenum type,
const void *indices)
{
return ParamsBase::Factory<EntryPoint::DrawElements>(objBuffer, mode, count, type, indices, 0,
0);
}
ANGLE_ENTRY_POINT_FUNC(DrawElementsInstanced,
DrawCallParams,
DrawCallParams *objBuffer,
Context *context,
PrimitiveMode mode,
GLsizei count,
GLenum type,
const void *indices,
GLsizei instanceCount)
{
return ParamsBase::Factory<EntryPoint::DrawElementsInstanced>(objBuffer, mode, count, type,
indices, 0, instanceCount);
}
ANGLE_ENTRY_POINT_FUNC(DrawElementsInstancedANGLE,
DrawCallParams,
DrawCallParams *objBuffer,
Context *context,
PrimitiveMode mode,
GLsizei count,
GLenum type,
const void *indices,
GLsizei instanceCount)
{
return ParamsBase::Factory<EntryPoint::DrawElementsInstancedANGLE>(objBuffer, mode, count, type,
indices, 0, instanceCount);
}
ANGLE_ENTRY_POINT_FUNC(DrawRangeElements,
DrawCallParams,
DrawCallParams *objBuffer,
Context *context,
PrimitiveMode mode,
GLuint /*start*/,
GLuint /*end*/,
GLsizei count,
GLenum type,
const void *indices)
{
return ParamsBase::Factory<EntryPoint::DrawRangeElements>(objBuffer, mode, count, type, indices,
0, 0);
}
#undef ANGLE_ENTRY_POINT_FUNC
template <EntryPoint EP>
struct EntryPointParam
{
using Type = ParamsBase;
};
// A template struct for determining the default value to return for each entry point.
template <EntryPoint EP, typename ReturnType>
struct DefaultReturnValue;
// Default return values for each basic return type.
template <EntryPoint EP>
struct DefaultReturnValue<EP, GLint>
{
static constexpr GLint kValue = -1;
};
// This doubles as the GLenum return value.
template <EntryPoint EP>
struct DefaultReturnValue<EP, GLuint>
{
static constexpr GLuint kValue = 0;
};
template <EntryPoint EP>
struct DefaultReturnValue<EP, GLboolean>
{
static constexpr GLboolean kValue = GL_FALSE;
};
// Catch-all rules for pointer types.
template <EntryPoint EP, typename PointerType>
struct DefaultReturnValue<EP, const PointerType *>
{
static constexpr const PointerType *kValue = nullptr;
};
template <EntryPoint EP, typename PointerType>
struct DefaultReturnValue<EP, PointerType *>
{
static constexpr PointerType *kValue = nullptr;
};
// Overloaded to return invalid index
template <>
struct DefaultReturnValue<EntryPoint::GetUniformBlockIndex, GLuint>
{
static constexpr GLuint kValue = GL_INVALID_INDEX;
};
// Specialized enum error value.
template <>
struct DefaultReturnValue<EntryPoint::ClientWaitSync, GLenum>
{
static constexpr GLenum kValue = GL_WAIT_FAILED;
};
// glTestFenceNV should still return TRUE for an invalid fence.
template <>
struct DefaultReturnValue<EntryPoint::TestFenceNV, GLboolean>
{
static constexpr GLboolean kValue = GL_TRUE;
};
template <EntryPoint EP, typename ReturnType>
constexpr ANGLE_INLINE ReturnType GetDefaultReturnValue()
{
return DefaultReturnValue<EP, ReturnType>::kValue;
}
} // namespace gl
#endif // LIBANGLE_PARAMS_H_