Commit e45e53bd by Sami Väisänen Committed by Commit Bot

Support CHROMIUM_path_rendering

This is partial support for CHROMIUM_path_rendering and implements basic path management and non-instanced rendering. BUG=angleproject:1382 Change-Id: I9c0e88183e0a915d522889323933439d25b45b5f Reviewed-on: https://chromium-review.googlesource.com/348630Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 2e1ba274
......@@ -830,6 +830,126 @@ GL_APICALL void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components);
#endif
#endif /* GL_CHROMIUM_framebuffer_mixed_samples */
// needed by NV_path_rendering (and thus CHROMIUM_path_rendering)
// but CHROMIUM_path_rendering only needs MatrixLoadfEXT, MatrixLoadIdentityEXT
#ifndef GL_EXT_direct_state_access
#define GL_EXT_direct_state_access 1
typedef void(GL_APIENTRYP PFNGLMATRIXLOADFEXTPROC)(GLenum matrixMode, const GLfloat *m);
typedef void(GL_APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC)(GLenum matrixMode);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glMatrixLoadfEXT(GLenum matrixMode, const GLfloat *m);
GL_APICALL void GL_APIENTRY glMatrixLoadIdentityEXT(GLenum matrixMode);
#endif
#endif /* GL_EXT_direct_state_access */
#ifndef GL_CHROMIUM_path_rendering
#define GL_CHROMIUM_path_rendering 1
#define GL_PATH_MODELVIEW_CHROMIUM 0x1700
#define GL_PATH_PROJECTION_CHROMIUM 0x1701
#define GL_CLOSE_PATH_CHROMIUM 0x00
#define GL_MOVE_TO_CHROMIUM 0x02
#define GL_LINE_TO_CHROMIUM 0x04
#define GL_QUADRATIC_CURVE_TO_CHROMIUM 0x0A
#define GL_CUBIC_CURVE_TO_CHROMIUM 0x0C
#define GL_CONIC_CURVE_TO_CHROMIUM 0x1A
#define GL_PATH_MODELVIEW_MATRIX_CHROMIUM 0x0BA6
#define GL_PATH_PROJECTION_MATRIX_CHROMIUM 0x0BA7
#define GL_PATH_STROKE_WIDTH_CHROMIUM 0x9075
#define GL_PATH_END_CAPS_CHROMIUM 0x9076
#define GL_PATH_JOIN_STYLE_CHROMIUM 0x9079
#define GL_PATH_MITER_LIMIT_CHROMIUM 0x907a
#define GL_PATH_STROKE_BOUND_CHROMIUM 0x9086
#define GL_FLAT_CHROMIUM 0x1D00
#define GL_SQUARE_CHROMIUM 0x90a3
#define GL_ROUND_CHROMIUM 0x90a4
#define GL_BEVEL_CHROMIUM 0x90A6
#define GL_MITER_REVERT_CHROMIUM 0x90A7
#define GL_COUNT_UP_CHROMIUM 0x9088
#define GL_COUNT_DOWN_CHROMIUM 0x9089
#define GL_CONVEX_HULL_CHROMIUM 0x908B
#define GL_BOUNDING_BOX_CHROMIUM 0x908D
#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM 0x909C
#define GL_EYE_LINEAR_CHROMIUM 0x2400
#define GL_OBJECT_LINEAR_CHROMIUM 0x2401
#define GL_CONSTANT_CHROMIUM 0x8576
#define GL_TRANSLATE_X_CHROMIUM 0x908E
#define GL_TRANSLATE_Y_CHROMIUM 0x908F
#define GL_TRANSLATE_2D_CHROMIUM 0x9090
#define GL_TRANSLATE_3D_CHROMIUM 0x9091
#define GL_AFFINE_2D_CHROMIUM 0x9092
#define GL_AFFINE_3D_CHROMIUM 0x9094
#define GL_TRANSPOSE_AFFINE_2D_CHROMIUM 0x9096
#define GL_TRANSPOSE_AFFINE_3D_CHROMIUM 0x9098
typedef void(GL_APIENTRYP PFNGLMATRIXLOADFCHROMIUMPROC)(GLenum matrixMode, const GLfloat *m);
typedef void(GL_APIENTRYP PFNGLMATRIXLOADIDENTITYCHROMIUMPROC)(GLenum matrixMode);
typedef GLuint(GL_APIENTRYP PFNGLGENPATHSCHROMIUMPROC)(GLsizei range);
typedef void(GL_APIENTRYP PFNGLDELETEPATHSCHROMIUMPROC)(GLuint path, GLsizei range);
typedef GLboolean(GL_APIENTRYP PFNGLISPATHCHROMIUMPROC)(GLuint path);
typedef void(GL_APIENTRYP PFNGLPATHCOMMANDSCHROMIUMPROC)(GLuint path,
GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords);
typedef void(GL_APIENTRYP PFNGLPATHPARAMETERICHROMIUMPROC)(GLuint path, GLenum pname, GLint value);
typedef void(GL_APIENTRYP PFNGLPATHPARAMETERFCHROMIUMPROC)(GLuint path,
GLenum pname,
GLfloat value);
typedef void(GL_APIENTRYP PFNGLGETPATHPARAMETERIVCHROMIUMPROC)(GLuint path,
GLenum pname,
GLint *value);
typedef void(GL_APIENTRYP PFNGLGETPATHPARAMETERFVCHROMIUMPROC)(GLuint path,
GLenum pname,
GLfloat *value);
typedef void(GL_APIENTRYP PFNGLPATHSTENCILFUNCCHROMIUMPROC)(GLenum func, GLint ref, GLuint mask);
typedef void(GL_APIENTRYP PFNGLSTENCILFILLPATHCHROMIUMPROC)(GLuint path,
GLenum fillMode,
GLuint mask);
typedef void(GL_APIENTRYP PFNGLSTENCILSTROKEPATHCHROMIUMPROC)(GLuint path,
GLint reference,
GLuint mask);
typedef void(GL_APIENTRYP PFNGLCOVERFILLPATHCHROMIUMPROC)(GLuint path, GLenum coverMode);
typedef void(GL_APIENTRYP PFNGLCOVERSTROKEPATHCHROMIUMPROC)(GLuint path, GLenum coverMode);
typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHCHROMIUMPROC)(GLuint path,
GLenum fillMode,
GLuint mask,
GLenum coverMode);
typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHCHROMIUMPROC)(GLuint path,
GLint reference,
GLuint mask,
GLenum coverMode);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glMatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *m);
GL_APICALL void GL_APIENTRY glMatrixLoadIdentityCHROMIUM(GLenum matrixMode);
GL_APICALL GLuint GL_APIENTRY glGenPathsCHROMIUM(GLsizei range);
GL_APICALL void GL_APIENTRY glDeletePathsCHROMIUM(GLuint path, GLsizei range);
GL_APICALL GLboolean GL_APIENTRY glIsPathCHROMIUM(GLuint path);
GL_APICALL void GL_APIENTRY glPathCommandsCHROMIUM(GLuint path,
GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords);
GL_APICALL void GL_APIENTRY glPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value);
GL_APICALL void GL_APIENTRY glPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value);
GL_APICALL void GL_APIENTRY glGetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value);
GL_APICALL void GL_APIENTRY glGetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value);
GL_APICALL void GL_APIENTRY glPathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask);
GL_APICALL void GL_APIENTRY glStencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask);
GL_APICALL void GL_APIENTRY glStencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask);
GL_APICALL void GL_APIENTRY glCoverFillPathCHROMIUM(GLuint path, GLenum coverMode);
GL_APICALL void GL_APIENTRY glCoverStrokePathCHROMIUM(GLuint path, GLenum coverMode);
GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathCHROMIUM(GLuint path,
GLenum fillMode,
GLuint mask,
GLenum coverMode);
GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathCHROMIUM(GLuint path,
GLint reference,
GLuint mask,
GLenum coverMode);
#endif
#endif /* GL_CHROMIUM_path_rendering */
#ifndef GL_ANGLE_framebuffer_multisample
#define GL_ANGLE_framebuffer_multisample 1
#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB
......
......@@ -64,4 +64,4 @@ void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float
*blue = inputData->B * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
}
}
} // namespace gl
......@@ -721,8 +721,42 @@ inline bool isInf(float f)
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && !(bitCast<uint32_t>(f) & 0x7fffffu);
}
namespace priv
{
template <unsigned int N, unsigned int R>
struct iSquareRoot
{
static constexpr unsigned int solve()
{
return (R * R > N)
? 0
: ((R * R == N) ? R : static_cast<unsigned int>(iSquareRoot<N, R + 1>::value));
}
enum Result
{
value = iSquareRoot::solve()
};
};
template <unsigned int N>
struct iSquareRoot<N, N>
{
enum result
{
value = N
};
};
} // namespace priv
template <unsigned int N>
constexpr unsigned int iSquareRoot()
{
return priv::iSquareRoot<N, 1>::value;
}
} // namespace gl
namespace rx
{
......
......@@ -16,6 +16,7 @@
#include <vector>
#include "common/debug.h"
#include "common/mathutil.h"
namespace angle
{
......@@ -337,6 +338,42 @@ class Matrix
return result;
}
void setToIdentity()
{
ASSERT(rows() == columns());
const auto one = T(1);
const auto zero = T(0);
for (auto &e : mElements)
e = zero;
for (unsigned int i = 0; i < rows(); ++i)
{
const auto pos = i * columns() + (i % columns());
mElements[pos] = one;
}
}
template <unsigned int Size>
static void setToIdentity(T(&matrix)[Size])
{
static_assert(gl::iSquareRoot<Size>() != 0, "Matrix is not square.");
const auto cols = gl::iSquareRoot<Size>();
const auto one = T(1);
const auto zero = T(0);
for (auto &e : matrix)
e = zero;
for (unsigned int i = 0; i < cols; ++i)
{
const auto pos = i * cols + (i % cols);
matrix[pos] = one;
}
}
private:
std::vector<T> mElements;
unsigned int mRows;
......
......@@ -163,7 +163,8 @@ Extensions::Extensions()
colorBufferFloat(false),
multisampleCompatibility(false),
framebufferMixedSamples(false),
textureNorm16(false)
textureNorm16(false),
pathRendering(false)
{
}
......@@ -240,6 +241,7 @@ std::vector<std::string> Extensions::getStrings() const
InsertExtensionString("GL_EXT_multisample_compatibility", multisampleCompatibility, &extensionStrings);
InsertExtensionString("GL_CHROMIUM_framebuffer_mixed_samples", framebufferMixedSamples, &extensionStrings);
InsertExtensionString("GL_EXT_texture_norm16", textureNorm16, &extensionStrings);
InsertExtensionString("GL_CHROMIUM_path_rendering", pathRendering, &extensionStrings);
// clang-format on
return extensionStrings;
......
......@@ -303,6 +303,9 @@ struct Extensions
// GL_EXT_texture_norm16
// written against ES 3.1 but can apply to ES 3.0 as well.
bool textureNorm16;
// GL_CHROMIUM_path_rendering
bool pathRendering;
};
struct Limitations
......
......@@ -11,7 +11,9 @@
#include <iterator>
#include <sstream>
#include <string.h>
#include "common/matrix_utils.h"
#include "common/platform.h"
#include "common/utilities.h"
#include "libANGLE/Buffer.h"
......@@ -20,6 +22,7 @@
#include "libANGLE/Fence.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Path.h"
#include "libANGLE/Program.h"
#include "libANGLE/Query.h"
#include "libANGLE/Renderbuffer.h"
......@@ -437,6 +440,17 @@ GLsync Context::createFenceSync()
return reinterpret_cast<GLsync>(static_cast<uintptr_t>(handle));
}
GLuint Context::createPaths(GLsizei range)
{
auto resultOrError = mResourceManager->createPaths(mImplementation.get(), range);
if (resultOrError.isError())
{
handleError(resultOrError.getError());
return 0;
}
return resultOrError.getResult();
}
GLuint Context::createVertexArray()
{
GLuint vertexArray = mVertexArrayHandleAllocator.allocate();
......@@ -534,6 +548,96 @@ void Context::deleteFenceSync(GLsync fenceSync)
mResourceManager->deleteFenceSync(static_cast<GLuint>(reinterpret_cast<uintptr_t>(fenceSync)));
}
void Context::deletePaths(GLuint first, GLsizei range)
{
mResourceManager->deletePaths(first, range);
}
bool Context::hasPathData(GLuint path) const
{
const auto *pathObj = mResourceManager->getPath(path);
if (pathObj == nullptr)
return false;
return pathObj->hasPathData();
}
bool Context::hasPath(GLuint path) const
{
return mResourceManager->hasPath(path);
}
void Context::setPathCommands(GLuint path,
GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords)
{
auto *pathObject = mResourceManager->getPath(path);
handleError(pathObject->setCommands(numCommands, commands, numCoords, coordType, coords));
}
void Context::setPathParameterf(GLuint path, GLenum pname, GLfloat value)
{
auto *pathObj = mResourceManager->getPath(path);
switch (pname)
{
case GL_PATH_STROKE_WIDTH_CHROMIUM:
pathObj->setStrokeWidth(value);
break;
case GL_PATH_END_CAPS_CHROMIUM:
pathObj->setEndCaps(static_cast<GLenum>(value));
break;
case GL_PATH_JOIN_STYLE_CHROMIUM:
pathObj->setJoinStyle(static_cast<GLenum>(value));
break;
case GL_PATH_MITER_LIMIT_CHROMIUM:
pathObj->setMiterLimit(value);
break;
case GL_PATH_STROKE_BOUND_CHROMIUM:
pathObj->setStrokeBound(value);
break;
default:
UNREACHABLE();
break;
}
}
void Context::getPathParameterfv(GLuint path, GLenum pname, GLfloat *value) const
{
const auto *pathObj = mResourceManager->getPath(path);
switch (pname)
{
case GL_PATH_STROKE_WIDTH_CHROMIUM:
*value = pathObj->getStrokeWidth();
break;
case GL_PATH_END_CAPS_CHROMIUM:
*value = static_cast<GLfloat>(pathObj->getEndCaps());
break;
case GL_PATH_JOIN_STYLE_CHROMIUM:
*value = static_cast<GLfloat>(pathObj->getJoinStyle());
break;
case GL_PATH_MITER_LIMIT_CHROMIUM:
*value = pathObj->getMiterLimit();
break;
case GL_PATH_STROKE_BOUND_CHROMIUM:
*value = pathObj->getStrokeBound();
break;
default:
UNREACHABLE();
break;
}
}
void Context::setPathStencilFunc(GLenum func, GLint ref, GLuint mask)
{
mGLState.setPathStencilFunc(func, ref, mask);
}
void Context::deleteVertexArray(GLuint vertexArray)
{
auto iter = mVertexArrayMap.find(vertexArray);
......@@ -1016,6 +1120,16 @@ void Context::getFloatv(GLenum pname, GLfloat *params)
case GL_MAX_TEXTURE_LOD_BIAS:
*params = mCaps.maxLODBias;
break;
case GL_PATH_MODELVIEW_MATRIX_CHROMIUM:
case GL_PATH_PROJECTION_MATRIX_CHROMIUM:
{
ASSERT(mExtensions.pathRendering);
const GLfloat *m = mGLState.getPathRenderingMatrix(pname);
memcpy(params, m, 16 * sizeof(GLfloat));
}
break;
default:
mGLState.getFloatv(pname, params);
break;
......@@ -1269,6 +1383,94 @@ void Context::setCoverageModulation(GLenum components)
mGLState.setCoverageModulation(components);
}
void Context::loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix)
{
mGLState.loadPathRenderingMatrix(matrixMode, matrix);
}
void Context::loadPathRenderingIdentityMatrix(GLenum matrixMode)
{
GLfloat I[16];
angle::Matrix<GLfloat>::setToIdentity(I);
mGLState.loadPathRenderingMatrix(matrixMode, I);
}
void Context::stencilFillPath(GLuint path, GLenum fillMode, GLuint mask)
{
const auto *pathObj = mResourceManager->getPath(path);
if (!pathObj)
return;
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
syncRendererState();
mImplementation->stencilFillPath(pathObj, fillMode, mask);
}
void Context::stencilStrokePath(GLuint path, GLint reference, GLuint mask)
{
const auto *pathObj = mResourceManager->getPath(path);
if (!pathObj)
return;
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
syncRendererState();
mImplementation->stencilStrokePath(pathObj, reference, mask);
}
void Context::coverFillPath(GLuint path, GLenum coverMode)
{
const auto *pathObj = mResourceManager->getPath(path);
if (!pathObj)
return;
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
syncRendererState();
mImplementation->coverFillPath(pathObj, coverMode);
}
void Context::coverStrokePath(GLuint path, GLenum coverMode)
{
const auto *pathObj = mResourceManager->getPath(path);
if (!pathObj)
return;
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
syncRendererState();
mImplementation->coverStrokePath(pathObj, coverMode);
}
void Context::stencilThenCoverFillPath(GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode)
{
const auto *pathObj = mResourceManager->getPath(path);
if (!pathObj)
return;
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
syncRendererState();
mImplementation->stencilThenCoverFillPath(pathObj, fillMode, mask, coverMode);
}
void Context::stencilThenCoverStrokePath(GLuint path,
GLint reference,
GLuint mask,
GLenum coverMode)
{
const auto *pathObj = mResourceManager->getPath(path);
if (!pathObj)
return;
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
syncRendererState();
mImplementation->stencilThenCoverStrokePath(pathObj, reference, mask, coverMode);
}
void Context::handleError(const Error &error)
{
if (error.isError())
......
......@@ -81,6 +81,7 @@ class Context final : public ValidationContext
GLuint createSampler();
GLuint createTransformFeedback();
GLsync createFenceSync();
GLuint createPaths(GLsizei range);
void deleteBuffer(GLuint buffer);
void deleteShader(GLuint shader);
......@@ -90,6 +91,20 @@ class Context final : public ValidationContext
void deleteSampler(GLuint sampler);
void deleteTransformFeedback(GLuint transformFeedback);
void deleteFenceSync(GLsync fenceSync);
void deletePaths(GLuint first, GLsizei range);
// CHROMIUM_path_rendering
bool hasPathData(GLuint path) const;
bool hasPath(GLuint path) const;
void setPathCommands(GLuint path,
GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords);
void setPathParameterf(GLuint path, GLenum pname, GLfloat value);
void getPathParameterfv(GLuint path, GLenum pname, GLfloat *value) const;
void setPathStencilFunc(GLenum func, GLint ref, GLuint mask);
// Framebuffers are owned by the Context, so these methods do not pass through
GLuint createFramebuffer();
......@@ -467,6 +482,16 @@ class Context final : public ValidationContext
// CHROMIUM_framebuffer_mixed_samples
void setCoverageModulation(GLenum components);
// CHROMIUM_path_rendering
void loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix);
void loadPathRenderingIdentityMatrix(GLenum matrixMode);
void stencilFillPath(GLuint path, GLenum fillMode, GLuint mask);
void stencilStrokePath(GLuint path, GLint reference, GLuint mask);
void coverFillPath(GLuint path, GLenum coverMode);
void coverStrokePath(GLuint path, GLenum coverMode);
void stencilThenCoverFillPath(GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
void stencilThenCoverStrokePath(GLuint path, GLint reference, GLuint mask, GLenum coverMode);
void handleError(const Error &error) override;
GLenum getError();
......
......@@ -312,6 +312,18 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign
}
}
if (getExtensions().pathRendering)
{
switch (pname)
{
case GL_PATH_MODELVIEW_MATRIX_CHROMIUM:
case GL_PATH_PROJECTION_MATRIX_CHROMIUM:
*type = GL_FLOAT;
*numParams = 16;
return true;
}
}
// Check for ES3.0+ parameter names which are also exposed as ES2 extensions
switch (pname)
{
......
//
// Copyright (c) 2016 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.
//
// HandleRangeAllocator.cpp : Implementation for HandleRangeAllocator.h
#include "libANGLE/HandleRangeAllocator.h"
#include <algorithm>
#include <limits>
#include <utility>
#include "common/angleutils.h"
#include "common/debug.h"
namespace gl
{
const GLuint HandleRangeAllocator::kInvalidHandle = 0;
HandleRangeAllocator::HandleRangeAllocator()
{
// Simplify the code by making sure that lower_bound(id) never
// returns the beginning of the map, if id is valid (eg != kInvalidHandle).
mUsed.insert(std::make_pair(0u, 0u));
}
GLuint HandleRangeAllocator::allocate()
{
return allocateRange(1u);
}
GLuint HandleRangeAllocator::allocateAtOrAbove(GLuint wanted)
{
if (wanted == 0u || wanted == 1u)
return allocateRange(1u);
auto current = mUsed.lower_bound(wanted);
auto next = current;
if (current == mUsed.end() || current->first > wanted)
{
current--;
}
else
{
next++;
}
GLuint firstId = current->first;
GLuint lastId = current->second;
ASSERT(wanted >= firstId);
if (wanted - 1u <= lastId)
{
// Append to current range.
lastId++;
if (lastId == 0)
{
// The increment overflowed.
return allocateRange(1u);
}
current->second = lastId;
if (next != mUsed.end() && next->first - 1u == lastId)
{
// Merge with next range.
current->second = next->second;
mUsed.erase(next);
}
return lastId;
}
else if (next != mUsed.end() && next->first - 1u == wanted)
{
// Prepend to next range.
GLuint lastExisting = next->second;
mUsed.erase(next);
mUsed.insert(std::make_pair(wanted, lastExisting));
return wanted;
}
mUsed.insert(std::make_pair(wanted, wanted));
return wanted;
}
GLuint HandleRangeAllocator::allocateRange(GLuint range)
{
ASSERT(range != 0);
auto current = mUsed.begin();
auto next = current;
while (++next != mUsed.end())
{
if (next->first - current->second > range)
break;
current = next;
}
const GLuint firstId = current->second + 1u;
const GLuint lastId = firstId + range - 1u;
// deal with wraparound
if (firstId == 0u || lastId < firstId)
return kInvalidHandle;
current->second = lastId;
if (next != mUsed.end() && next->first - 1u == lastId)
{
// merge with next range
current->second = next->second;
mUsed.erase(next);
}
return firstId;
}
bool HandleRangeAllocator::markAsUsed(GLuint handle)
{
ASSERT(handle);
auto current = mUsed.lower_bound(handle);
if (current != mUsed.end() && current->first == handle)
return false;
auto next = current;
--current;
if (current->second >= handle)
return false;
ASSERT(current->first < handle && current->second < handle);
if (current->second + 1u == handle)
{
// Append to current range.
current->second = handle;
if (next != mUsed.end() && next->first - 1u == handle)
{
// Merge with next range.
current->second = next->second;
mUsed.erase(next);
}
return true;
}
else if (next != mUsed.end() && next->first - 1u == handle)
{
// Prepend to next range.
GLuint lastExisting = next->second;
mUsed.erase(next);
mUsed.insert(std::make_pair(handle, lastExisting));
return true;
}
mUsed.insert(std::make_pair(handle, handle));
return true;
}
void HandleRangeAllocator::release(GLuint handle)
{
releaseRange(handle, 1u);
}
void HandleRangeAllocator::releaseRange(GLuint first, GLuint range)
{
if (range == 0u || (first == 0u && range == 1u))
return;
if (first == 0u)
{
first++;
range--;
}
GLuint last = first + range - 1u;
if (last < first)
last = std::numeric_limits<GLuint>::max();
while (true)
{
auto current = mUsed.lower_bound(last);
if (current == mUsed.end() || current->first > last)
--current;
if (current->second < first)
return;
if (current->first >= first)
{
const GLuint lastExisting = current->second;
mUsed.erase(current);
if (last < lastExisting)
{
mUsed.insert(std::make_pair(last + 1u, lastExisting));
}
}
else if (current->second <= last)
{
current->second = first - 1u;
}
else
{
ASSERT(current->first < first && current->second > last);
const GLuint lastExisting = current->second;
current->second = first - 1u;
mUsed.insert(std::make_pair(last + 1u, lastExisting));
}
}
}
bool HandleRangeAllocator::isUsed(GLuint handle) const
{
if (handle == kInvalidHandle)
return false;
auto current = mUsed.lower_bound(handle);
if (current != mUsed.end())
{
if (current->first == handle)
return true;
}
--current;
return current->second >= handle;
}
} // namespace gl
\ No newline at end of file
//
// Copyright (c) 2002-2016 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.
//
// HandleRangeAllocator.h: Defines the gl::HandleRangeAllocator class, which is used to
// allocate contiguous ranges of GL path handles.
#ifndef LIBANGLE_HANDLERANGEALLOCATOR_H_
#define LIBANGLE_HANDLERANGEALLOCATOR_H_
#include <map>
#include "angle_gl.h"
#include "common/angleutils.h"
namespace gl
{
// Allocates contiguous ranges of path object handles.
class HandleRangeAllocator final : angle::NonCopyable
{
public:
static const GLuint kInvalidHandle;
HandleRangeAllocator();
// Allocates a new path handle.
GLuint allocate();
// Allocates a handle starting at or above the value of |wanted|.
// Note: may wrap if it starts near limit.
GLuint allocateAtOrAbove(GLuint wanted);
// Allocates |range| amount of contiguous paths.
// Returns the first id to |first_id| or |kInvalidHandle| if
// allocation failed.
GLuint allocateRange(GLuint range);
// Marks an id as used. Returns false if handle was already used.
bool markAsUsed(GLuint handle);
// Release handle.
void release(GLuint handle);
// Release a |range| amount of contiguous handles, starting from |first|
void releaseRange(GLuint first, GLuint range);
// Checks whether or not a resource ID is in use.
bool isUsed(GLuint handle) const;
private:
std::map<GLuint, GLuint> mUsed;
};
} // namespace gl
#endif // LIBANGLE_HANDLERANGEALLOCATOR_H_
\ No newline at end of file
//
// Copyright 2016 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.
//
// Unit tests for HandleRangeAllocator.
//
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "libANGLE/HandleRangeAllocator.h"
namespace
{
class HandleRangeAllocatorTest : public testing::Test
{
protected:
gl::HandleRangeAllocator *getAllocator() { return &mAllocator; }
private:
gl::HandleRangeAllocator mAllocator;
};
// Checks basic functionality: allocate, release, isUsed.
TEST_F(HandleRangeAllocatorTest, TestBasic)
{
auto *allocator = getAllocator();
// Check that resource 1 is not in use
EXPECT_FALSE(allocator->isUsed(1));
// Allocate an ID, check that it's in use.
GLuint id1 = allocator->allocate();
EXPECT_TRUE(allocator->isUsed(id1));
// Allocate another ID, check that it's in use, and different from the first
// one.
GLuint id2 = allocator->allocate();
EXPECT_TRUE(allocator->isUsed(id2));
EXPECT_NE(id1, id2);
// Free one of the IDs, check that it's not in use any more.
allocator->release(id1);
EXPECT_FALSE(allocator->isUsed(id1));
// Frees the other ID, check that it's not in use any more.
allocator->release(id2);
EXPECT_FALSE(allocator->isUsed(id2));
}
// Checks that the resource handles are re-used after being freed.
TEST_F(HandleRangeAllocatorTest, TestAdvanced)
{
auto *allocator = getAllocator();
// Allocate the highest possible ID, to make life awkward.
allocator->allocateAtOrAbove(~static_cast<GLuint>(0));
// Allocate a significant number of resources.
const unsigned int kNumResources = 100;
GLuint ids[kNumResources];
for (unsigned int i = 0; i < kNumResources; ++i)
{
ids[i] = allocator->allocate();
EXPECT_TRUE(allocator->isUsed(ids[i]));
}
// Check that a new allocation re-uses the resource we just freed.
GLuint id1 = ids[kNumResources / 2];
allocator->release(id1);
EXPECT_FALSE(allocator->isUsed(id1));
GLuint id2 = allocator->allocate();
EXPECT_TRUE(allocator->isUsed(id2));
EXPECT_EQ(id1, id2);
}
// Checks that we can choose our own ids and they won't be reused.
TEST_F(HandleRangeAllocatorTest, MarkAsUsed)
{
auto *allocator = getAllocator();
GLuint id = allocator->allocate();
allocator->release(id);
EXPECT_FALSE(allocator->isUsed(id));
EXPECT_TRUE(allocator->markAsUsed(id));
EXPECT_TRUE(allocator->isUsed(id));
GLuint id2 = allocator->allocate();
EXPECT_NE(id, id2);
EXPECT_TRUE(allocator->markAsUsed(id2 + 1));
GLuint id3 = allocator->allocate();
// Checks our algorithm. If the algorithm changes this check should be
// changed.
EXPECT_EQ(id3, id2 + 2);
}
// Checks allocateAtOrAbove.
TEST_F(HandleRangeAllocatorTest, AllocateAtOrAbove)
{
const GLuint kOffset = 123456;
auto *allocator = getAllocator();
GLuint id1 = allocator->allocateAtOrAbove(kOffset);
EXPECT_EQ(kOffset, id1);
GLuint id2 = allocator->allocateAtOrAbove(kOffset);
EXPECT_GT(id2, kOffset);
GLuint id3 = allocator->allocateAtOrAbove(kOffset);
EXPECT_GT(id3, kOffset);
}
// Checks that allocateAtOrAbove wraps around at the maximum value.
TEST_F(HandleRangeAllocatorTest, AllocateIdAtOrAboveWrapsAround)
{
const GLuint kMaxPossibleOffset = ~static_cast<GLuint>(0);
auto *allocator = getAllocator();
GLuint id1 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
EXPECT_EQ(kMaxPossibleOffset, id1);
GLuint id2 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
EXPECT_EQ(1u, id2);
GLuint id3 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
EXPECT_EQ(2u, id3);
}
// Checks that freeing an already freed range causes no harm.
TEST_F(HandleRangeAllocatorTest, RedundantFreeIsIgnored)
{
auto *allocator = getAllocator();
GLuint id1 = allocator->allocate();
allocator->release(0);
allocator->release(id1);
allocator->release(id1);
allocator->release(id1 + 1);
GLuint id2 = allocator->allocate();
GLuint id3 = allocator->allocate();
EXPECT_NE(id2, id3);
EXPECT_NE(allocator->kInvalidHandle, id2);
EXPECT_NE(allocator->kInvalidHandle, id3);
}
// Check allocating and releasing multiple ranges.
TEST_F(HandleRangeAllocatorTest, allocateRange)
{
const GLuint kMaxPossibleOffset = std::numeric_limits<GLuint>::max();
auto *allocator = getAllocator();
GLuint id1 = allocator->allocateRange(1);
EXPECT_EQ(1u, id1);
GLuint id2 = allocator->allocateRange(2);
EXPECT_EQ(2u, id2);
GLuint id3 = allocator->allocateRange(3);
EXPECT_EQ(4u, id3);
GLuint id4 = allocator->allocate();
EXPECT_EQ(7u, id4);
allocator->release(3);
GLuint id5 = allocator->allocateRange(1);
EXPECT_EQ(3u, id5);
allocator->release(5);
allocator->release(2);
allocator->release(4);
GLuint id6 = allocator->allocateRange(2);
EXPECT_EQ(4u, id6);
GLuint id7 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
EXPECT_EQ(kMaxPossibleOffset, id7);
GLuint id8 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
EXPECT_EQ(2u, id8);
GLuint id9 = allocator->allocateRange(50);
EXPECT_EQ(8u, id9);
GLuint id10 = allocator->allocateRange(50);
EXPECT_EQ(58u, id10);
// Remove all the low-numbered ids.
allocator->release(1);
allocator->release(15);
allocator->releaseRange(2, 107);
GLuint id11 = allocator->allocateRange(100);
EXPECT_EQ(1u, id11);
allocator->release(kMaxPossibleOffset);
GLuint id12 = allocator->allocateRange(100);
EXPECT_EQ(101u, id12);
GLuint id13 = allocator->allocateAtOrAbove(kMaxPossibleOffset - 2u);
EXPECT_EQ(kMaxPossibleOffset - 2u, id13);
GLuint id14 = allocator->allocateRange(3);
EXPECT_EQ(201u, id14);
}
// Checks that having allocated a high range doesn't interfere
// with normal low range allocation.
TEST_F(HandleRangeAllocatorTest, AllocateRangeEndNoEffect)
{
const GLuint kMaxPossibleOffset = std::numeric_limits<GLuint>::max();
auto *allocator = getAllocator();
GLuint id1 = allocator->allocateAtOrAbove(kMaxPossibleOffset - 2u);
EXPECT_EQ(kMaxPossibleOffset - 2u, id1);
GLuint id3 = allocator->allocateRange(3);
EXPECT_EQ(1u, id3);
GLuint id2 = allocator->allocateRange(2);
EXPECT_EQ(4u, id2);
}
// Checks allocating a range that consumes the whole uint32 space.
TEST_F(HandleRangeAllocatorTest, AllocateMax)
{
const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
auto *allocator = getAllocator();
GLuint id = allocator->allocateRange(kMaxPossibleRange);
EXPECT_EQ(1u, id);
allocator->releaseRange(id, kMaxPossibleRange - 1u);
GLuint id2 = allocator->allocateRange(kMaxPossibleRange);
EXPECT_EQ(0u, id2);
allocator->releaseRange(id, kMaxPossibleRange);
GLuint id3 = allocator->allocateRange(kMaxPossibleRange);
EXPECT_EQ(1u, id3);
}
// Checks allocating a range that consumes the whole uint32 space
// causes next allocation to fail.
// Subsequently checks that once the big range is reduced new allocations
// are possible.
TEST_F(HandleRangeAllocatorTest, AllocateFullRange)
{
const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
const GLuint kFreedId = 555u;
auto *allocator = getAllocator();
GLuint id1 = allocator->allocateRange(kMaxPossibleRange);
EXPECT_EQ(1u, id1);
GLuint id2 = allocator->allocate();
EXPECT_EQ(gl::HandleRangeAllocator::kInvalidHandle, id2);
allocator->release(kFreedId);
GLuint id3 = allocator->allocate();
EXPECT_EQ(kFreedId, id3);
GLuint id4 = allocator->allocate();
EXPECT_EQ(0u, id4);
allocator->release(kFreedId + 1u);
allocator->release(kFreedId + 4u);
allocator->release(kFreedId + 3u);
allocator->release(kFreedId + 5u);
allocator->release(kFreedId + 2u);
GLuint id5 = allocator->allocateRange(5);
EXPECT_EQ(kFreedId + 1u, id5);
}
// Checks that allocating a range that exceeds uint32
// does not wrap incorrectly and fails.
TEST_F(HandleRangeAllocatorTest, AllocateRangeNoWrapInRange)
{
const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
const GLuint kAllocId = 10u;
auto *allocator = getAllocator();
GLuint id1 = allocator->allocateAtOrAbove(kAllocId);
EXPECT_EQ(kAllocId, id1);
GLuint id2 = allocator->allocateRange(kMaxPossibleRange - 5u);
EXPECT_EQ(0u, id2);
GLuint id3 = allocator->allocateRange(kMaxPossibleRange - kAllocId);
EXPECT_EQ(kAllocId + 1u, id3);
}
// Check special cases for 0 range allocations and zero handles.
TEST_F(HandleRangeAllocatorTest, ZeroIdCases)
{
auto *allocator = getAllocator();
EXPECT_FALSE(allocator->isUsed(0));
GLuint id1 = allocator->allocateAtOrAbove(0);
EXPECT_NE(0u, id1);
EXPECT_FALSE(allocator->isUsed(0));
allocator->release(0);
EXPECT_FALSE(allocator->isUsed(0));
EXPECT_TRUE(allocator->isUsed(id1));
allocator->release(id1);
EXPECT_FALSE(allocator->isUsed(id1));
}
} // namespace
\ No newline at end of file
//
// Copyright (c) 2002-2016 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.
//
// Path.h: Defines the gl::Path class, representing CHROMIUM_path_rendering
// path object.
#include "libANGLE/Path.h"
#include "libANGLE/renderer/PathImpl.h"
#include "common/mathutil.h"
#include "common/debug.h"
namespace gl
{
Path::Path(rx::PathImpl *impl)
: mPath(impl),
mHasData(false),
mEndCaps(GL_FLAT_CHROMIUM),
mJoinStyle(GL_MITER_REVERT_CHROMIUM),
mStrokeWidth(1.0f),
mStrokeBound(0.2f),
mMiterLimit(4.0f)
{
}
Path::~Path()
{
delete mPath;
}
Error Path::setCommands(GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords)
{
ANGLE_TRY(mPath->setCommands(numCommands, commands, numCoords, coordType, coords));
mHasData = true;
return gl::NoError();
}
void Path::setStrokeWidth(GLfloat width)
{
mStrokeWidth = width;
mPath->setPathParameter(GL_PATH_STROKE_WIDTH_CHROMIUM, mStrokeWidth);
}
void Path::setStrokeBound(GLfloat bound)
{
mStrokeBound = clamp(bound, 0.0f, 1.0f);
mPath->setPathParameter(GL_PATH_STROKE_BOUND_CHROMIUM, mStrokeBound);
}
void Path::setEndCaps(GLenum type)
{
mEndCaps = type;
mPath->setPathParameter(GL_PATH_END_CAPS_CHROMIUM, static_cast<GLfloat>(type));
}
void Path::setJoinStyle(GLenum type)
{
mJoinStyle = type;
mPath->setPathParameter(GL_PATH_JOIN_STYLE_CHROMIUM, static_cast<GLfloat>(type));
}
void Path::setMiterLimit(GLfloat value)
{
mMiterLimit = value;
mPath->setPathParameter(GL_PATH_MITER_LIMIT_CHROMIUM, value);
}
} // gl
//
// Copyright (c) 2002-2016 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.
//
// Path.h: Defines the gl::Path class, representing CHROMIUM_path_rendering
// path object.
#ifndef LIBANGLE_PATH_H_
#define LIBANGLE_PATH_H_
#include "angle_gl.h"
#include "common/angleutils.h"
#include "libANGLE/Error.h"
#include "libANGLE/RefCountObject.h"
namespace rx
{
class PathImpl;
}
namespace gl
{
class Path final : angle::NonCopyable
{
public:
Path(rx::PathImpl *impl);
~Path();
Error setCommands(GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords);
void setStrokeWidth(GLfloat width);
void setStrokeBound(GLfloat bound);
void setEndCaps(GLenum type);
void setJoinStyle(GLenum type);
void setMiterLimit(GLfloat value);
GLfloat getStrokeWidth() const { return mStrokeWidth; }
GLfloat getStrokeBound() const { return mStrokeBound; }
GLfloat getMiterLimit() const { return mMiterLimit; }
GLenum getEndCaps() const { return mEndCaps; }
GLenum getJoinStyle() const { return mJoinStyle; }
bool hasPathData() const { return mHasData; }
const rx::PathImpl *getImplementation() const { return mPath; }
rx::PathImpl *getImplementation() { return mPath; }
private:
rx::PathImpl *mPath;
// a Path object is not actually considered "a path"
// untill it has been specified with data. So we'll
// keep this flag to support this semantics.
bool mHasData;
GLenum mEndCaps;
GLenum mJoinStyle;
GLfloat mStrokeWidth;
GLfloat mStrokeBound;
GLfloat mMiterLimit;
};
} // namespace gl
#endif // LIBANGLE_PATH_H_
\ No newline at end of file
......@@ -4,13 +4,14 @@
// found in the LICENSE file.
//
// ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and
// ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and
// retrieves objects which may be shared by multiple Contexts.
#include "libANGLE/ResourceManager.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Fence.h"
#include "libANGLE/Path.h"
#include "libANGLE/Program.h"
#include "libANGLE/Renderbuffer.h"
#include "libANGLE/Sampler.h"
......@@ -60,6 +61,12 @@ ResourceManager::~ResourceManager()
{
deleteFenceSync(mFenceSyncMap.begin()->first);
}
for (auto it = mPathMap.begin(); it != mPathMap.end(); ++it)
{
const auto *p = it->second;
delete p;
}
}
void ResourceManager::addRef()
......@@ -153,6 +160,31 @@ GLuint ResourceManager::createFenceSync(rx::GLImplFactory *factory)
return handle;
}
ErrorOrResult<GLuint> ResourceManager::createPaths(rx::GLImplFactory *factory, GLsizei range)
{
// Allocate client side handles.
const GLuint client = mPathHandleAllocator.allocateRange(static_cast<GLuint>(range));
if (client == HandleRangeAllocator::kInvalidHandle)
return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate path handle range.");
const auto &paths = factory->createPaths(range);
if (paths.empty())
{
mPathHandleAllocator.releaseRange(client, range);
return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate path objects.");
}
auto hint = mPathMap.begin();
for (GLsizei i = 0; i < range; ++i)
{
const auto impl = paths[static_cast<unsigned>(i)];
const auto id = client + i;
hint = mPathMap.insert(hint, std::make_pair(id, new Path(impl)));
}
return client;
}
void ResourceManager::deleteBuffer(GLuint buffer)
{
auto bufferObject = mBufferMap.find(buffer);
......@@ -197,7 +229,7 @@ void ResourceManager::deleteProgram(GLuint program)
mProgramMap.erase(programObject);
}
else
{
{
programObject->second->flagForDeletion();
}
}
......@@ -251,6 +283,21 @@ void ResourceManager::deleteFenceSync(GLuint fenceSync)
}
}
void ResourceManager::deletePaths(GLuint first, GLsizei range)
{
for (GLsizei i = 0; i < range; ++i)
{
const auto id = first + i;
const auto it = mPathMap.find(id);
if (it == mPathMap.end())
continue;
Path *p = it->second;
delete p;
mPathMap.erase(it);
}
mPathHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
}
Buffer *ResourceManager::getBuffer(unsigned int handle)
{
auto buffer = mBufferMap.find(handle);
......@@ -352,6 +399,28 @@ FenceSync *ResourceManager::getFenceSync(unsigned int handle)
}
}
const Path *ResourceManager::getPath(GLuint handle) const
{
auto it = mPathMap.find(handle);
if (it == std::end(mPathMap))
return nullptr;
return it->second;
}
Path *ResourceManager::getPath(GLuint handle)
{
auto it = mPathMap.find(handle);
if (it == std::end(mPathMap))
return nullptr;
return it->second;
}
bool ResourceManager::hasPath(GLuint handle) const
{
return mPathHandleAllocator.isUsed(handle);
}
void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
{
mRenderbufferMap[handle] = buffer;
......
......@@ -13,7 +13,9 @@
#include "angle_gl.h"
#include "common/angleutils.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/Error.h"
#include "libANGLE/HandleAllocator.h"
#include "libANGLE/HandleRangeAllocator.h"
namespace rx
{
......@@ -25,6 +27,7 @@ namespace gl
class Buffer;
class FenceSync;
struct Limitations;
class Path;
class Program;
class Renderbuffer;
class Sampler;
......@@ -49,6 +52,7 @@ class ResourceManager : angle::NonCopyable
GLuint createRenderbuffer();
GLuint createSampler();
GLuint createFenceSync(rx::GLImplFactory *factory);
ErrorOrResult<GLuint> createPaths(rx::GLImplFactory *factory, GLsizei range);
void deleteBuffer(GLuint buffer);
void deleteShader(GLuint shader);
......@@ -57,6 +61,7 @@ class ResourceManager : angle::NonCopyable
void deleteRenderbuffer(GLuint renderbuffer);
void deleteSampler(GLuint sampler);
void deleteFenceSync(GLuint fenceSync);
void deletePaths(GLuint first, GLsizei range);
Buffer *getBuffer(GLuint handle);
Shader *getShader(GLuint handle);
......@@ -66,6 +71,11 @@ class ResourceManager : angle::NonCopyable
Sampler *getSampler(GLuint handle);
FenceSync *getFenceSync(GLuint handle);
// CHROMIUM_path_rendering
const Path *getPath(GLuint path) const;
Path *getPath(GLuint path);
bool hasPath(GLuint path) const;
void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
Buffer *checkBufferAllocation(rx::GLImplFactory *factory, GLuint handle);
......@@ -78,7 +88,6 @@ class ResourceManager : angle::NonCopyable
private:
void createTextureInternal(GLuint handle);
;
std::size_t mRefCount;
ResourceMap<Buffer> mBufferMap;
......@@ -100,6 +109,9 @@ class ResourceManager : angle::NonCopyable
ResourceMap<FenceSync> mFenceSyncMap;
HandleAllocator mFenceSyncHandleAllocator;
ResourceMap<Path> mPathMap;
HandleRangeAllocator mPathHandleAllocator;
};
} // namespace gl
......
......@@ -8,7 +8,12 @@
#include "libANGLE/State.h"
#include <limits>
#include <string.h>
#include "common/BitSetIterator.h"
#include "common/matrix_utils.h"
#include "common/mathutil.h"
#include "libANGLE/Context.h"
#include "libANGLE/Caps.h"
#include "libANGLE/Debug.h"
......@@ -180,6 +185,12 @@ void State::initialize(const Caps &caps,
}
mCoverageModulation = GL_NONE;
angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
mPathStencilFunc = GL_ALWAYS;
mPathStencilRef = 0;
mPathStencilMask = std::numeric_limits<GLuint>::max();
}
void State::reset()
......@@ -227,6 +238,12 @@ void State::reset()
mProgram = NULL;
angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
mPathStencilFunc = GL_ALWAYS;
mPathStencilRef = 0;
mPathStencilMask = std::numeric_limits<GLuint>::max();
// TODO(jmadill): Is this necessary?
setAllDirtyBits();
}
......@@ -1362,6 +1379,62 @@ GLenum State::getCoverageModulation() const
return mCoverageModulation;
}
void State::loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix)
{
if (matrixMode == GL_PATH_MODELVIEW_CHROMIUM)
{
memcpy(mPathMatrixMV, matrix, 16 * sizeof(GLfloat));
mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_MATRIX_MV);
}
else if (matrixMode == GL_PATH_PROJECTION_CHROMIUM)
{
memcpy(mPathMatrixProj, matrix, 16 * sizeof(GLfloat));
mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ);
}
else
{
UNREACHABLE();
}
}
const GLfloat *State::getPathRenderingMatrix(GLenum which) const
{
if (which == GL_PATH_MODELVIEW_MATRIX_CHROMIUM)
{
return mPathMatrixMV;
}
else if (which == GL_PATH_PROJECTION_MATRIX_CHROMIUM)
{
return mPathMatrixProj;
}
UNREACHABLE();
return nullptr;
}
void State::setPathStencilFunc(GLenum func, GLint ref, GLuint mask)
{
mPathStencilFunc = func;
mPathStencilRef = ref;
mPathStencilMask = mask;
mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_STENCIL_STATE);
}
GLenum State::getPathStencilFunc() const
{
return mPathStencilFunc;
}
GLint State::getPathStencilRef() const
{
return mPathStencilRef;
}
GLuint State::getPathStencilMask() const
{
return mPathStencilMask;
}
void State::getBooleanv(GLenum pname, GLboolean *params)
{
switch (pname)
......
......@@ -276,6 +276,15 @@ class State : angle::NonCopyable
void setCoverageModulation(GLenum components);
GLenum getCoverageModulation() const;
// CHROMIUM_path_rendering
void loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix);
const GLfloat *getPathRenderingMatrix(GLenum which) const;
void setPathStencilFunc(GLenum func, GLint ref, GLuint mask);
GLenum getPathStencilFunc() const;
GLint getPathStencilRef() const;
GLuint getPathStencilMask() const;
// State query functions
void getBooleanv(GLenum pname, GLboolean *params);
void getFloatv(GLenum pname, GLfloat *params);
......@@ -344,7 +353,10 @@ class State : angle::NonCopyable
DIRTY_BIT_PROGRAM_BINDING,
DIRTY_BIT_MULTISAMPLING,
DIRTY_BIT_SAMPLE_ALPHA_TO_ONE,
DIRTY_BIT_COVERAGE_MODULATION, // CHROMIUM_framebuffer_mixed_samples
DIRTY_BIT_COVERAGE_MODULATION, // CHROMIUM_framebuffer_mixed_samples
DIRTY_BIT_PATH_RENDERING_MATRIX_MV, // CHROMIUM_path_rendering path model view matrix
DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ, // CHROMIUM_path_rendering path projection matrix
DIRTY_BIT_PATH_RENDERING_STENCIL_STATE,
DIRTY_BIT_CURRENT_VALUE_0,
DIRTY_BIT_CURRENT_VALUE_MAX = DIRTY_BIT_CURRENT_VALUE_0 + MAX_VERTEX_ATTRIBS,
DIRTY_BIT_INVALID = DIRTY_BIT_CURRENT_VALUE_MAX,
......@@ -452,6 +464,13 @@ class State : angle::NonCopyable
GLenum mCoverageModulation;
// CHROMIUM_path_rendering
GLfloat mPathMatrixMV[16];
GLfloat mPathMatrixProj[16];
GLenum mPathStencilFunc;
GLint mPathStencilRef;
GLuint mPathStencilMask;
DirtyBits mDirtyBits;
DirtyObjects mDirtyObjects;
};
......
......@@ -20,4 +20,40 @@ ContextImpl::~ContextImpl()
{
}
void ContextImpl::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
{
UNREACHABLE();
}
void ContextImpl::stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask)
{
UNREACHABLE();
}
void ContextImpl::coverFillPath(const gl::Path *path, GLenum coverMode)
{
UNREACHABLE();
}
void ContextImpl::coverStrokePath(const gl::Path *path, GLenum coverMode)
{
UNREACHABLE();
}
void ContextImpl::stencilThenCoverFillPath(const gl::Path *path,
GLenum fillMode,
GLuint mask,
GLenum coverMode)
{
UNREACHABLE();
}
void ContextImpl::stencilThenCoverStrokePath(const gl::Path *path,
GLint reference,
GLuint mask,
GLenum coverMode)
{
UNREACHABLE();
}
} // namespace rx
......@@ -14,6 +14,11 @@
#include "libANGLE/ContextState.h"
#include "libANGLE/renderer/GLImplFactory.h"
namespace gl
{
class Path;
}
namespace rx
{
class ContextImpl : public GLImplFactory
......@@ -54,6 +59,21 @@ class ContextImpl : public GLImplFactory
const GLvoid *indices,
const gl::IndexRange &indexRange) = 0;
// CHROMIUM_path_rendering path drawing methods.
virtual void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask);
virtual void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask);
virtual void coverFillPath(const gl::Path *path, GLenum coverMode);
virtual void coverStrokePath(const gl::Path *path, GLenum coverMode);
virtual void stencilThenCoverFillPath(const gl::Path *path,
GLenum fillMode,
GLuint mask,
GLenum coverMode);
virtual void stencilThenCoverStrokePath(const gl::Path *path,
GLint reference,
GLuint mask,
GLenum coverMode);
// TODO(jmadill): Investigate proper impl methods for this.
virtual void notifyDeviceLost() = 0;
virtual bool isDeviceLost() const = 0;
......
......@@ -10,6 +10,9 @@
#ifndef LIBANGLE_RENDERER_GLIMPLFACTORY_H_
#define LIBANGLE_RENDERER_GLIMPLFACTORY_H_
#include <vector>
#include "angle_gl.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/Program.h"
#include "libANGLE/Shader.h"
......@@ -28,6 +31,7 @@ class ContextImpl;
class FenceNVImpl;
class FenceSyncImpl;
class FramebufferImpl;
class PathImpl;
class ProgramImpl;
class QueryImpl;
class RenderbufferImpl;
......@@ -73,6 +77,8 @@ class GLImplFactory : angle::NonCopyable
// Sampler object creation
virtual SamplerImpl *createSampler() = 0;
virtual std::vector<PathImpl *> createPaths(GLsizei range) = 0;
};
} // namespace rx
......
//
// Copyright (c) 2002-2016 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.
//
// PathImpl.h: Defines the Path implementation interface for
// CHROMIUM_path_rendering path objects.
#ifndef LIBANGLE_RENDERER_PATHIMPL_H_
#define LIBANGLE_RENDERER_PATHIMPL_H_
#include "angle_gl.h"
#include "common/angleutils.h"
#include "libANGLE/Error.h"
namespace rx
{
class PathImpl : angle::NonCopyable
{
public:
virtual ~PathImpl() {}
virtual gl::Error setCommands(GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords) = 0;
virtual void setPathParameter(GLenum pname, GLfloat value) = 0;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_PATHIMPL_H_
\ No newline at end of file
......@@ -131,6 +131,11 @@ SamplerImpl *Context11::createSampler()
return new SamplerD3D();
}
std::vector<PathImpl *> Context11::createPaths(GLsizei)
{
return std::vector<PathImpl *>();
}
gl::Error Context11::flush()
{
return mRenderer->flush();
......
......@@ -55,6 +55,9 @@ class Context11 : public ContextImpl
// Sampler object creation
SamplerImpl *createSampler() override;
// Path object creation.
std::vector<PathImpl *> createPaths(GLsizei) override;
// Flush and finish.
gl::Error flush() override;
gl::Error finish() override;
......
......@@ -120,6 +120,11 @@ SamplerImpl *Context9::createSampler()
return new SamplerD3D();
}
std::vector<PathImpl *> Context9::createPaths(GLsizei)
{
return std::vector<PathImpl *>();
}
gl::Error Context9::flush()
{
return mRenderer->flush();
......
......@@ -55,6 +55,9 @@ class Context9 : public ContextImpl
// Sampler object creation
SamplerImpl *createSampler() override;
// Path object creation
std::vector<PathImpl *> createPaths(GLsizei) override;
// Flush and finish.
gl::Error flush() override;
gl::Error finish() override;
......
......@@ -13,7 +13,9 @@
#include "libANGLE/renderer/gl/CompilerGL.h"
#include "libANGLE/renderer/gl/FenceNVGL.h"
#include "libANGLE/renderer/gl/FenceSyncGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/PathGL.h"
#include "libANGLE/renderer/gl/ProgramGL.h"
#include "libANGLE/renderer/gl/QueryGL.h"
#include "libANGLE/renderer/gl/RenderbufferGL.h"
......@@ -110,6 +112,26 @@ SamplerImpl *ContextGL::createSampler()
return new SamplerGL(getFunctions(), getStateManager());
}
std::vector<PathImpl *> ContextGL::createPaths(GLsizei range)
{
const FunctionsGL *funcs = getFunctions();
std::vector<PathImpl *> ret;
ret.reserve(range);
const GLuint first = funcs->genPathsNV(range);
if (first == 0)
return ret;
for (GLsizei i = 0; i < range; ++i)
{
const auto id = first + i;
ret.push_back(new PathGL(funcs, id));
}
return ret;
}
gl::Error ContextGL::flush()
{
return mRenderer->flush();
......@@ -164,6 +186,42 @@ gl::Error ContextGL::drawRangeElements(GLenum mode,
return mRenderer->drawRangeElements(mState, mode, start, end, count, type, indices, indexRange);
}
void ContextGL::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
{
mRenderer->stencilFillPath(mState, path, fillMode, mask);
}
void ContextGL::stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask)
{
mRenderer->stencilStrokePath(mState, path, reference, mask);
}
void ContextGL::coverFillPath(const gl::Path *path, GLenum coverMode)
{
mRenderer->coverFillPath(mState, path, coverMode);
}
void ContextGL::coverStrokePath(const gl::Path *path, GLenum coverMode)
{
mRenderer->coverStrokePath(mState, path, coverMode);
}
void ContextGL::stencilThenCoverFillPath(const gl::Path *path,
GLenum fillMode,
GLuint mask,
GLenum coverMode)
{
mRenderer->stencilThenCoverFillPath(mState, path, fillMode, mask, coverMode);
}
void ContextGL::stencilThenCoverStrokePath(const gl::Path *path,
GLint reference,
GLuint mask,
GLenum coverMode)
{
mRenderer->stencilThenCoverStrokePath(mState, path, reference, mask, coverMode);
}
void ContextGL::notifyDeviceLost()
{
mRenderer->notifyDeviceLost();
......
......@@ -63,6 +63,9 @@ class ContextGL : public ContextImpl
// Sampler object creation
SamplerImpl *createSampler() override;
// Path object creation
std::vector<PathImpl *> createPaths(GLsizei range) override;
// Flush and finish.
gl::Error flush() override;
gl::Error finish() override;
......@@ -93,6 +96,20 @@ class ContextGL : public ContextImpl
const GLvoid *indices,
const gl::IndexRange &indexRange) override;
// CHROMIUM_path_rendering implementation
void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) override;
void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask) override;
void coverFillPath(const gl::Path *path, GLenum coverMode) override;
void coverStrokePath(const gl::Path *path, GLenum coverMode) override;
void stencilThenCoverFillPath(const gl::Path *path,
GLenum fillMode,
GLuint mask,
GLenum coverMode) override;
void stencilThenCoverStrokePath(const gl::Path *path,
GLint reference,
GLuint mask,
GLenum coverMode) override;
// TODO(jmadill): Investigate proper impl methods for this.
void notifyDeviceLost() override;
bool isDeviceLost() const override;
......
......@@ -418,6 +418,22 @@ FunctionsGL::FunctionsGL()
texImage3DMultisample(nullptr),
waitSync(nullptr),
matrixLoadEXT(nullptr),
genPathsNV(nullptr),
delPathsNV(nullptr),
pathCommandsNV(nullptr),
setPathParameterfNV(nullptr),
setPathParameteriNV(nullptr),
getPathParameterfNV(nullptr),
getPathParameteriNV(nullptr),
pathStencilFuncNV(nullptr),
stencilFillPathNV(nullptr),
stencilStrokePathNV(nullptr),
coverFillPathNV(nullptr),
coverStrokePathNV(nullptr),
stencilThenCoverFillPathNV(nullptr),
stencilThenCoverStrokePathNV(nullptr),
bindFragDataLocationIndexed(nullptr),
bindSampler(nullptr),
deleteSamplers(nullptr),
......@@ -824,6 +840,26 @@ void FunctionsGL::initializeProcsDesktopGL()
// Even though extensions are written against specific versions of GL, many drivers expose the extensions
// in even older versions. Always try loading the extensions regardless of GL version.
// EXT_direct_state_access (loading only functions relevant to GL_NV_path_rendering here)
AssignGLExtensionEntryPoint(extensions, "GL_EXT_direct_state_access", loadProcAddress("glMatrixLoadfEXT"), &matrixLoadEXT);
// GL_NV_path_rendering
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGenPathsNV"), &genPathsNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glDeletePathsNV"), &delPathsNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathCommandsNV"), &pathCommandsNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glIsPathNV"), &isPathNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathParameterfNV"), &setPathParameterfNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathParameteriNV"), &setPathParameteriNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGetPathParameterfvNV"), &getPathParameterfNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGetPathParameterivNV"), &getPathParameteriNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathStencilFuncNV"), &pathStencilFuncNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilFillPathNV"), &stencilFillPathNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilStrokePathNV"), &stencilStrokePathNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverFillPathNV"), &coverFillPathNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverStrokePathNV"), &coverStrokePathNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverFillPathNV"), &stencilThenCoverFillPathNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverStrokePathNV"), &stencilThenCoverStrokePathNV);
// GL_NV_framebuffer_mixed_samples
AssignGLExtensionEntryPoint(extensions, "GL_NV_framebuffer_mixed_samples", loadProcAddress("glCoverageModulationNV"), &coverageModulationNV);
......@@ -1722,6 +1758,25 @@ void FunctionsGL::initializeProcsGLES()
profile = 0;
// clang-format off
// EXT_direct_state_access (loading only functions relevant to GL_NV_path_rendering here)
AssignGLExtensionEntryPoint(extensions, "GL_EXT_direct_state_access", loadProcAddress("glMatrixLoadfEXT"), &matrixLoadEXT);
// GL_NV_path_rendering
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGenPathsNV"), &genPathsNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glDeletePathsNV"), &delPathsNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathCommandsNV"), &pathCommandsNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glIsPathNV"), &isPathNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathParameterfNV"), &setPathParameterfNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathParameteriNV"), &setPathParameteriNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGetPathParameterfvNV"), &getPathParameterfNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGetPathParameterivNV"), &getPathParameteriNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathStencilFuncNV"), &pathStencilFuncNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilFillPathNV"), &stencilFillPathNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilStrokePathNV"), &stencilStrokePathNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverFillPathNV"), &coverFillPathNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverStrokePathNV"), &coverStrokePathNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverFillPathNV"), &stencilThenCoverFillPathNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverStrokePathNV"), &stencilThenCoverStrokePathNV);
// GL_OES_texture_3D
AssignGLExtensionEntryPoint(extensions, "GL_OES_texture_3D", loadProcAddress("glTexImage3DOES"), &texImage3D);
......
......@@ -392,6 +392,27 @@ class FunctionsGL
PFNGLTEXIMAGE3DMULTISAMPLEPROC texImage3DMultisample;
PFNGLWAITSYNCPROC waitSync;
// EXT_direct_state_access. Needed by NV_path_rendering.
PFNGLMATRIXLOADFEXTPROC matrixLoadEXT;
// NV_path_rendering (originally written against 3.2 compatibility profile)
PFNGLGENPATHSNVPROC genPathsNV;
PFNGLDELETEPATHSNVPROC delPathsNV;
PFNGLPATHCOMMANDSNVPROC pathCommandsNV;
PFNGLISPATHNVPROC isPathNV;
PFNGLPATHPARAMETERFNVPROC setPathParameterfNV;
PFNGLPATHPARAMETERINVPROC setPathParameteriNV;
PFNGLGETPATHPARAMETERFVNVPROC getPathParameterfNV;
PFNGLGETPATHPARAMETERIVNVPROC getPathParameteriNV;
PFNGLPATHSTENCILFUNCNVPROC pathStencilFuncNV;
PFNGLSTENCILFILLPATHNVPROC stencilFillPathNV;
PFNGLSTENCILSTROKEPATHNVPROC stencilStrokePathNV;
PFNGLCOVERFILLPATHNVPROC coverFillPathNV;
PFNGLCOVERSTROKEPATHNVPROC coverStrokePathNV;
PFNGLSTENCILTHENCOVERFILLPATHNVPROC stencilThenCoverFillPathNV;
PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC stencilThenCoverStrokePathNV;
// 3.3
PFNGLBINDFRAGDATALOCATIONINDEXEDPROC bindFragDataLocationIndexed;
PFNGLBINDSAMPLERPROC bindSampler;
......
//
// Copyright (c) 2016 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.
//
// PathGL.cpp: Implementation for PathGL class.
#include "libANGLE/renderer/gl/PathGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
namespace rx
{
PathGL::PathGL(const FunctionsGL *functions, GLuint path) : mFunctions(functions), mPathID(path)
{
}
PathGL::~PathGL()
{
}
gl::Error PathGL::setCommands(GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords)
{
mFunctions->pathCommandsNV(mPathID, numCommands, commands, numCoords, coordType, coords);
return gl::Error(GL_NO_ERROR);
}
void PathGL::setPathParameter(GLenum pname, GLfloat value)
{
mFunctions->setPathParameterfNV(mPathID, pname, value);
}
} // rx
\ No newline at end of file
//
// Copyright (c) 2016 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.
//
// PathGL.h: Class definition for CHROMIUM_path_rendering path object for the
// GL backend.
#ifndef LIBANGLE_RENDERER_GL_PATHIMPL_H_
#define LIBANGLE_RENDERER_GL_PATHIMPL_H_
#include "libANGLE/renderer/PathImpl.h"
namespace rx
{
class FunctionsGL;
class PathGL : public PathImpl
{
public:
PathGL(const FunctionsGL *functions, GLuint path);
~PathGL();
gl::Error setCommands(GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords) override;
void setPathParameter(GLenum pname, GLfloat value) override;
GLuint getPathID() const { return mPathID; }
private:
const FunctionsGL *mFunctions;
GLuint mPathID;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_GL_PATHIMPL_H_
......@@ -13,6 +13,7 @@
#include "common/debug.h"
#include "libANGLE/AttributeMap.h"
#include "libANGLE/ContextState.h"
#include "libANGLE/Path.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/gl/BlitGL.h"
#include "libANGLE/renderer/gl/BufferGL.h"
......@@ -22,6 +23,7 @@
#include "libANGLE/renderer/gl/FenceSyncGL.h"
#include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/PathGL.h"
#include "libANGLE/renderer/gl/ProgramGL.h"
#include "libANGLE/renderer/gl/QueryGL.h"
#include "libANGLE/renderer/gl/RenderbufferGL.h"
......@@ -242,6 +244,77 @@ gl::Error RendererGL::drawRangeElements(const gl::ContextState &data,
return gl::Error(GL_NO_ERROR);
}
void RendererGL::stencilFillPath(const gl::ContextState &state,
const gl::Path *path,
GLenum fillMode,
GLuint mask)
{
const auto *pathObj = GetImplAs<PathGL>(path);
mFunctions->stencilFillPathNV(pathObj->getPathID(), fillMode, mask);
ASSERT(mFunctions->getError() == GL_NO_ERROR);
}
void RendererGL::stencilStrokePath(const gl::ContextState &state,
const gl::Path *path,
GLint reference,
GLuint mask)
{
const auto *pathObj = GetImplAs<PathGL>(path);
mFunctions->stencilStrokePathNV(pathObj->getPathID(), reference, mask);
ASSERT(mFunctions->getError() == GL_NO_ERROR);
}
void RendererGL::coverFillPath(const gl::ContextState &state,
const gl::Path *path,
GLenum coverMode)
{
const auto *pathObj = GetImplAs<PathGL>(path);
mFunctions->coverFillPathNV(pathObj->getPathID(), coverMode);
ASSERT(mFunctions->getError() == GL_NO_ERROR);
}
void RendererGL::coverStrokePath(const gl::ContextState &state,
const gl::Path *path,
GLenum coverMode)
{
const auto *pathObj = GetImplAs<PathGL>(path);
mFunctions->coverStrokePathNV(pathObj->getPathID(), coverMode);
ASSERT(mFunctions->getError() == GL_NO_ERROR);
}
void RendererGL::stencilThenCoverFillPath(const gl::ContextState &state,
const gl::Path *path,
GLenum fillMode,
GLuint mask,
GLenum coverMode)
{
const auto *pathObj = GetImplAs<PathGL>(path);
mFunctions->stencilThenCoverFillPathNV(pathObj->getPathID(), fillMode, mask, coverMode);
ASSERT(mFunctions->getError() == GL_NO_ERROR);
}
void RendererGL::stencilThenCoverStrokePath(const gl::ContextState &state,
const gl::Path *path,
GLint reference,
GLuint mask,
GLenum coverMode)
{
const auto *pathObj = GetImplAs<PathGL>(path);
mFunctions->stencilThenCoverStrokePathNV(pathObj->getPathID(), reference, mask, coverMode);
ASSERT(mFunctions->getError() == GL_NO_ERROR);
}
ContextImpl *RendererGL::createContext(const gl::ContextState &state)
{
return new ContextGL(state, this);
......
......@@ -18,6 +18,7 @@ namespace gl
{
class ContextState;
struct IndexRange;
class Path;
}
namespace egl
......@@ -77,6 +78,28 @@ class RendererGL : angle::NonCopyable
const GLvoid *indices,
const gl::IndexRange &indexRange);
// CHROMIUM_path_rendering implementation
void stencilFillPath(const gl::ContextState &state,
const gl::Path *path,
GLenum fillMode,
GLuint mask);
void stencilStrokePath(const gl::ContextState &state,
const gl::Path *path,
GLint reference,
GLuint mask);
void coverFillPath(const gl::ContextState &state, const gl::Path *path, GLenum coverMode);
void coverStrokePath(const gl::ContextState &state, const gl::Path *path, GLenum coverMode);
void stencilThenCoverFillPath(const gl::ContextState &state,
const gl::Path *path,
GLenum fillMode,
GLuint mask,
GLenum coverMode);
void stencilThenCoverStrokePath(const gl::ContextState &state,
const gl::Path *path,
GLint reference,
GLuint mask,
GLenum coverMode);
// EXT_debug_marker
void insertEventMarker(GLsizei length, const char *marker);
void pushGroupMarker(GLsizei length, const char *marker);
......
......@@ -8,7 +8,12 @@
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include <limits>
#include <string.h>
#include "common/BitSetIterator.h"
#include "common/mathutil.h"
#include "common/matrix_utils.h"
#include "libANGLE/ContextState.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/TransformFeedback.h"
......@@ -116,6 +121,9 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &ren
mMultisamplingEnabled(true),
mSampleAlphaToOneEnabled(false),
mCoverageModulation(GL_NONE),
mPathStencilFunc(GL_ALWAYS),
mPathStencilRef(0),
mPathStencilMask(std::numeric_limits<GLuint>::max()),
mLocalDirtyBits()
{
ASSERT(mFunctions);
......@@ -145,6 +153,9 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &ren
mFunctions->enable(GL_POINT_SPRITE);
}
}
angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
}
void StateManagerGL::deleteProgram(GLuint program)
......@@ -1523,6 +1534,18 @@ void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBit
case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
setCoverageModulation(state.getCoverageModulation());
break;
case gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_MV:
setPathRenderingModelViewMatrix(
state.getPathRenderingMatrix(GL_PATH_MODELVIEW_MATRIX_CHROMIUM));
break;
case gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ:
setPathRenderingProjectionMatrix(
state.getPathRenderingMatrix(GL_PATH_PROJECTION_MATRIX_CHROMIUM));
break;
case gl::State::DIRTY_BIT_PATH_RENDERING_STENCIL_STATE:
setPathRenderingStencilState(state.getPathStencilFunc(), state.getPathStencilRef(),
state.getPathStencilMask());
break;
default:
{
ASSERT(dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 &&
......@@ -1600,6 +1623,41 @@ void StateManagerGL::setCoverageModulation(GLenum components)
}
}
void StateManagerGL::setPathRenderingModelViewMatrix(const GLfloat *m)
{
if (memcmp(mPathMatrixMV, m, sizeof(mPathMatrixMV)) != 0)
{
memcpy(mPathMatrixMV, m, sizeof(mPathMatrixMV));
mFunctions->matrixLoadEXT(GL_PATH_MODELVIEW_CHROMIUM, m);
mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_MV);
}
}
void StateManagerGL::setPathRenderingProjectionMatrix(const GLfloat *m)
{
if (memcmp(mPathMatrixProj, m, sizeof(mPathMatrixProj)) != 0)
{
memcpy(mPathMatrixProj, m, sizeof(mPathMatrixProj));
mFunctions->matrixLoadEXT(GL_PATH_PROJECTION_CHROMIUM, m);
mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ);
}
}
void StateManagerGL::setPathRenderingStencilState(GLenum func, GLint ref, GLuint mask)
{
if (func != mPathStencilFunc || ref != mPathStencilRef || mask != mPathStencilMask)
{
mPathStencilFunc = func;
mPathStencilRef = ref;
mPathStencilMask = mask;
mFunctions->pathStencilFuncNV(func, ref, mask);
mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_STENCIL_STATE);
}
}
void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
{
if (mTextureCubemapSeamlessEnabled != enabled)
......
......@@ -129,6 +129,10 @@ class StateManagerGL final : angle::NonCopyable
void setCoverageModulation(GLenum components);
void setPathRenderingModelViewMatrix(const GLfloat *m);
void setPathRenderingProjectionMatrix(const GLfloat *m);
void setPathRenderingStencilState(GLenum func, GLint ref, GLuint mask);
void onDeleteQueryObject(QueryGL *query);
gl::Error setDrawArraysState(const gl::ContextState &data,
......@@ -266,6 +270,12 @@ class StateManagerGL final : angle::NonCopyable
GLenum mCoverageModulation;
GLfloat mPathMatrixMV[16];
GLfloat mPathMatrixProj[16];
GLenum mPathStencilFunc;
GLint mPathStencilRef;
GLuint mPathStencilMask;
gl::State::DirtyBits mLocalDirtyBits;
};
......
......@@ -670,6 +670,14 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
extensions->framebufferMixedSamples =
functions->hasGLExtension("GL_NV_framebuffer_mixed_samples") ||
functions->hasGLESExtension("GL_NV_framebuffer_mixed_samples");
// if NV_path_rendering is to be supported then EXT_direct_state_access
// must also be available. NV_path_rendering needs some of the matrix loads
// from this extension.
extensions->pathRendering = (functions->hasGLExtension("GL_NV_path_rendering") &&
functions->hasGLExtension("GL_EXT_direct_state_access")) ||
(functions->hasGLESExtension("GL_NV_path_rendering") &&
functions->hasGLESExtension("GL_EXT_direct_state_access"));
}
void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)
......
......@@ -263,4 +263,9 @@ SamplerImpl *ContextVk::createSampler()
return new SamplerVk();
}
std::vector<PathImpl *> ContextVk::createPaths(GLsizei)
{
return std::vector<PathImpl *>();
}
} // namespace rx
......@@ -116,6 +116,9 @@ class ContextVk : public ContextImpl
// Sampler object creation
SamplerImpl *createSampler() override;
// Path object creation
std::vector<PathImpl *> createPaths(GLsizei) override;
private:
RendererVk *mRenderer;
};
......
......@@ -190,6 +190,36 @@ bool ValidateBindUniformLocationCHROMIUM(Context *context,
bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components);
// CHROMIUM_path_rendering
bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix);
bool ValidateMatrixMode(Context *context, GLenum matrixMode);
bool ValidateGenPaths(Context *context, GLsizei range);
bool ValidateDeletePaths(Context *context, GLuint first, GLsizei range);
bool ValidatePathCommands(Context *context,
GLuint path,
GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords);
bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value);
bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value);
bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask);
bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask);
bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask);
bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode);
bool ValidateStencilThenCoverFillPath(Context *context,
GLuint path,
GLenum fillMode,
GLuint mask,
GLenum coverMode);
bool ValidateStencilThenCoverStrokePath(Context *context,
GLuint path,
GLint reference,
GLuint mask,
GLenum coverMode);
bool ValidateIsPath(Context *context);
} // namespace gl
#endif // LIBANGLE_VALIDATION_ES2_H_
......@@ -92,12 +92,16 @@
'libANGLE/FramebufferAttachment.h',
'libANGLE/HandleAllocator.cpp',
'libANGLE/HandleAllocator.h',
'libANGLE/HandleRangeAllocator.h',
'libANGLE/HandleRangeAllocator.cpp',
'libANGLE/Image.h',
'libANGLE/Image.cpp',
'libANGLE/ImageIndex.h',
'libANGLE/ImageIndex.cpp',
'libANGLE/IndexRangeCache.cpp',
'libANGLE/IndexRangeCache.h',
'libANGLE/Path.h',
'libANGLE/Path.cpp',
'libANGLE/Platform.cpp',
'libANGLE/Program.cpp',
'libANGLE/Program.h',
......@@ -453,6 +457,8 @@
'libANGLE/renderer/gl/FramebufferGL.h',
'libANGLE/renderer/gl/FunctionsGL.cpp',
'libANGLE/renderer/gl/FunctionsGL.h',
'libANGLE/renderer/gl/PathGL.h',
'libANGLE/renderer/gl/PathGL.cpp',
'libANGLE/renderer/gl/ProgramGL.cpp',
'libANGLE/renderer/gl/ProgramGL.h',
'libANGLE/renderer/gl/QueryGL.cpp',
......
......@@ -1400,4 +1400,269 @@ ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components)
context->setCoverageModulation(components);
}
}
// CHROMIUM_path_rendering
ANGLE_EXPORT void GL_APIENTRY MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix)
{
EVENT("(GLenum matrixMode = %u)", matrixMode);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() && !ValidateMatrix(context, matrixMode, matrix))
{
return;
}
context->loadPathRenderingMatrix(matrixMode, matrix);
}
}
ANGLE_EXPORT void GL_APIENTRY MatrixLoadIdentityCHROMIUM(GLenum matrixMode)
{
EVENT("(GLenum matrixMode = %u)", matrixMode);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() && !ValidateMatrixMode(context, matrixMode))
{
return;
}
context->loadPathRenderingIdentityMatrix(matrixMode);
}
}
ANGLE_EXPORT GLuint GL_APIENTRY GenPathsCHROMIUM(GLsizei range)
{
EVENT("(GLsizei range = %d)", range);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() && !ValidateGenPaths(context, range))
{
return 0;
}
return context->createPaths(range);
}
return 0;
}
ANGLE_EXPORT void GL_APIENTRY DeletePathsCHROMIUM(GLuint first, GLsizei range)
{
EVENT("(GLuint first = %u, GLsizei range = %d)", first, range);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() && !ValidateDeletePaths(context, first, range))
{
return;
}
context->deletePaths(first, range);
}
}
ANGLE_EXPORT GLboolean GL_APIENTRY IsPathCHROMIUM(GLuint path)
{
EVENT("(GLuint path = %u)", path);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() && !ValidateIsPath(context))
{
return GL_FALSE;
}
return context->hasPathData(path);
}
return GL_FALSE;
}
ANGLE_EXPORT void GL_APIENTRY PathCommandsCHROMIUM(GLuint path,
GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords)
{
EVENT(
"(GLuint path = %u, GLsizei numCommands = %d, commands = %p, "
"GLsizei numCoords = %d, GLenum coordType = %u, void* coords = %p)",
path, numCommands, commands, numCoords, coordType, coords);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation())
{
if (!ValidatePathCommands(context, path, numCommands, commands, numCoords, coordType,
coords))
{
return;
}
}
context->setPathCommands(path, numCommands, commands, numCoords, coordType, coords);
}
}
ANGLE_EXPORT void GL_APIENTRY PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value)
{
EVENT("(GLuint path = %u, GLenum pname = %u, GLfloat value = %f)", path, pname, value);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() && !ValidateSetPathParameter(context, path, pname, value))
{
return;
}
context->setPathParameterf(path, pname, value);
}
}
ANGLE_EXPORT void GL_APIENTRY PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value)
{
PathParameterfCHROMIUM(path, pname, static_cast<GLfloat>(value));
}
ANGLE_EXPORT void GL_APIENTRY GetPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat *value)
{
EVENT("(GLuint path = %u, GLenum pname = %u)", path, pname);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() && !ValidateGetPathParameter(context, path, pname, value))
{
return;
}
context->getPathParameterfv(path, pname, value);
}
}
ANGLE_EXPORT void GL_APIENTRY GetPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint *value)
{
GLfloat val = 0.0f;
GetPathParameterfCHROMIUM(path, pname, value != nullptr ? &val : nullptr);
if (value)
*value = static_cast<GLint>(val);
}
ANGLE_EXPORT void GL_APIENTRY PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask)
{
EVENT("(GLenum func = %u, GLint ref = %d, GLuint mask = %u)", func, ref, mask);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() && !ValidatePathStencilFunc(context, func, ref, mask))
{
return;
}
context->setPathStencilFunc(func, ref, mask);
}
}
ANGLE_EXPORT void GL_APIENTRY StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask)
{
EVENT("(GLuint path = %u, GLenum fillMode = %u, GLuint mask = %u)", path, fillMode, mask);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() && !ValidateStencilFillPath(context, path, fillMode, mask))
{
return;
}
context->stencilFillPath(path, fillMode, mask);
}
}
ANGLE_EXPORT void GL_APIENTRY StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask)
{
EVENT("(GLuint path = %u, GLint ference = %d, GLuint mask = %u)", path, reference, mask);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() &&
!ValidateStencilStrokePath(context, path, reference, mask))
{
return;
}
context->stencilStrokePath(path, reference, mask);
}
}
ANGLE_EXPORT void GL_APIENTRY CoverFillPathCHROMIUM(GLuint path, GLenum coverMode)
{
EVENT("(GLuint path = %u, GLenum coverMode = %u)", path, coverMode);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() && !ValidateCoverPath(context, path, coverMode))
{
return;
}
context->coverFillPath(path, coverMode);
}
}
ANGLE_EXPORT void GL_APIENTRY CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode)
{
EVENT("(GLuint path = %u, GLenum coverMode = %u)", path, coverMode);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() && !ValidateCoverPath(context, path, coverMode))
{
return;
}
context->coverStrokePath(path, coverMode);
}
}
ANGLE_EXPORT void GL_APIENTRY StencilThenCoverFillPathCHROMIUM(GLuint path,
GLenum fillMode,
GLuint mask,
GLenum coverMode)
{
EVENT("(GLuint path = %u, GLenum fillMode = %u, GLuint mask = %u, GLenum coverMode = %u)", path,
fillMode, mask, coverMode);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() &&
!ValidateStencilThenCoverFillPath(context, path, fillMode, mask, coverMode))
{
return;
}
context->stencilThenCoverFillPath(path, fillMode, mask, coverMode);
}
}
ANGLE_EXPORT void GL_APIENTRY StencilThenCoverStrokePathCHROMIUM(GLuint path,
GLint reference,
GLuint mask,
GLenum coverMode)
{
EVENT("(GLuint path = %u, GLint reference = %d, GLuint mask = %u, GLenum coverMode = %u)", path,
reference, mask, coverMode);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() &&
!ValidateStencilThenCoverStrokePath(context, path, reference, mask, coverMode))
{
return;
}
context->stencilThenCoverStrokePath(path, reference, mask, coverMode);
}
}
} // gl
......@@ -147,7 +147,38 @@ ANGLE_EXPORT void GL_APIENTRY BindUniformLocationCHROMIUM(GLuint program,
const GLchar *name);
// GL_CHROMIUM_framebuffer_mixed_samples
ANGLE_EXPORT void GL_APIENTRY MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix);
ANGLE_EXPORT void GL_APIENTRY MatrixLoadIdentityCHROMIUM(GLenum matrixMode);
ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components);
// GL_CHROMIUM_path_rendering
ANGLE_EXPORT GLuint GL_APIENTRY GenPathsCHROMIUM(GLsizei chromium);
ANGLE_EXPORT void GL_APIENTRY DeletePathsCHROMIUM(GLuint first, GLsizei range);
ANGLE_EXPORT GLboolean GL_APIENTRY IsPathCHROMIUM(GLuint path);
ANGLE_EXPORT void GL_APIENTRY PathCommandsCHROMIUM(GLuint path,
GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords);
ANGLE_EXPORT void GL_APIENTRY PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value);
ANGLE_EXPORT void GL_APIENTRY PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value);
ANGLE_EXPORT void GL_APIENTRY GetPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat *value);
ANGLE_EXPORT void GL_APIENTRY GetPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint *value);
ANGLE_EXPORT void GL_APIENTRY PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask);
ANGLE_EXPORT void GL_APIENTRY StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask);
ANGLE_EXPORT void GL_APIENTRY StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask);
ANGLE_EXPORT void GL_APIENTRY CoverFillPathCHROMIUM(GLuint path, GLenum coverMode);
ANGLE_EXPORT void GL_APIENTRY CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode);
ANGLE_EXPORT void GL_APIENTRY StencilThenCoverFillPathCHROMIUM(GLuint path,
GLenum fillMode,
GLuint mask,
GLenum coverMode);
ANGLE_EXPORT void GL_APIENTRY StencilThenCoverStrokePathCHROMIUM(GLuint path,
GLint reference,
GLuint mask,
GLenum coverMode);
}
#endif // LIBGLESV2_ENTRYPOINTGLES20EXT_H_
......@@ -1573,3 +1573,100 @@ void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components)
return gl::CoverageModulationCHROMIUM(components);
}
}
// CHROMIUM_path_rendendering
void GL_APIENTRY glMatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix)
{
gl::MatrixLoadfCHROMIUM(matrixMode, matrix);
}
void GL_APIENTRY glMatrixLoadIdentityCHROMIUM(GLenum matrixMode)
{
gl::MatrixLoadIdentityCHROMIUM(matrixMode);
}
GLuint GL_APIENTRY glGenPathsCHROMIUM(GLsizei range)
{
return gl::GenPathsCHROMIUM(range);
}
void GL_APIENTRY glDeletePathsCHROMIUM(GLuint first, GLsizei range)
{
gl::DeletePathsCHROMIUM(first, range);
}
GLboolean GL_APIENTRY glIsPathCHROMIUM(GLuint path)
{
return gl::IsPathCHROMIUM(path);
}
void GL_APIENTRY glPathCommandsCHROMIUM(GLuint path,
GLsizei numCommands,
const GLubyte *commands,
GLsizei numCoords,
GLenum coordType,
const void *coords)
{
gl::PathCommandsCHROMIUM(path, numCommands, commands, numCoords, coordType, coords);
}
void GL_APIENTRY glPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value)
{
gl::PathParameterfCHROMIUM(path, pname, value);
}
void GL_APIENTRY glPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value)
{
gl::PathParameterfCHROMIUM(path, pname, value);
}
void GL_APIENTRY glGetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value)
{
gl::GetPathParameterfCHROMIUM(path, pname, value);
}
void GL_APIENTRY glGetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value)
{
gl::GetPathParameteriCHROMIUM(path, pname, value);
}
void GL_APIENTRY glPathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask)
{
gl::PathStencilFuncCHROMIUM(func, ref, mask);
}
void GL_APIENTRY glStencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask)
{
gl::StencilFillPathCHROMIUM(path, fillMode, mask);
}
void GL_APIENTRY glStencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask)
{
gl::StencilStrokePathCHROMIUM(path, reference, mask);
}
void GL_APIENTRY glCoverFillPathCHROMIUM(GLuint path, GLenum coverMode)
{
gl::CoverFillPathCHROMIUM(path, coverMode);
}
void GL_APIENTRY glCoverStrokePathCHROMIUM(GLuint path, GLenum coverMode)
{
gl::CoverStrokePathCHROMIUM(path, coverMode);
}
void GL_APIENTRY glStencilThenCoverFillPathCHROMIUM(GLuint path,
GLenum fillMode,
GLuint mask,
GLenum coverMode)
{
gl::StencilThenCoverFillPathCHROMIUM(path, fillMode, mask, coverMode);
}
void GL_APIENTRY glStencilThenCoverStrokePathCHROMIUM(GLuint path,
GLint reference,
GLuint mask,
GLenum coverMode)
{
gl::StencilThenCoverStrokePathCHROMIUM(path, reference, mask, coverMode);
}
\ No newline at end of file
......@@ -205,6 +205,24 @@ EXPORTS
glBindUniformLocationCHROMIUM @318
glCoverageModulationCHROMIUM @319
glMatrixLoadfCHROMIUM @320
glMatrixLoadIdentityCHROMIUM @321
glGenPathsCHROMIUM @322
glDeletePathsCHROMIUM @323
glIsPathCHROMIUM @324
glPathCommandsCHROMIUM @325
glPathParameterfCHROMIUM @326
glPathParameteriCHROMIUM @327
glGetPathParameterfvCHROMIUM @328
glGetPathParameterivCHROMIUM @329
glPathStencilFuncCHROMIUM @330
glStencilFillPathCHROMIUM @331
glStencilStrokePathCHROMIUM @332
glCoverFillPathCHROMIUM @333
glCoverStrokePathCHROMIUM @334
glStencilThenCoverFillPathCHROMIUM @335
glStencilThenCoverStrokePathCHROMIUM @336
; GLES 3.0 Functions
glReadBuffer @180
glDrawRangeElements @181
......
......@@ -15,8 +15,6 @@
{
'angle_end2end_tests_sources':
[
'<(angle_path)/src/tests/gl_tests/MultisampleCompatibilityTest.cpp',
'<(angle_path)/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp',
'<(angle_path)/src/tests/gl_tests/BindUniformLocationTest.cpp',
'<(angle_path)/src/tests/gl_tests/BlendMinMaxTest.cpp',
'<(angle_path)/src/tests/gl_tests/BlitFramebufferANGLETest.cpp',
......@@ -35,6 +33,7 @@
'<(angle_path)/src/tests/gl_tests/DrawElementsTest.cpp',
'<(angle_path)/src/tests/gl_tests/ETCTextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/FenceSyncTests.cpp',
'<(angle_path)/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp',
'<(angle_path)/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp',
'<(angle_path)/src/tests/gl_tests/FramebufferTest.cpp',
'<(angle_path)/src/tests/gl_tests/GLSLTest.cpp',
......@@ -46,8 +45,10 @@
'<(angle_path)/src/tests/gl_tests/LineLoopTest.cpp',
'<(angle_path)/src/tests/gl_tests/MaxTextureSizeTest.cpp',
'<(angle_path)/src/tests/gl_tests/MipmapTest.cpp',
'<(angle_path)/src/tests/gl_tests/MultisampleCompatibilityTest.cpp',
'<(angle_path)/src/tests/gl_tests/media/pixel.inl',
'<(angle_path)/src/tests/gl_tests/PackUnpackTest.cpp',
'<(angle_path)/src/tests/gl_tests/PathRenderingTest.cpp',
'<(angle_path)/src/tests/gl_tests/PbufferTest.cpp',
'<(angle_path)/src/tests/gl_tests/PBOExtensionTest.cpp',
'<(angle_path)/src/tests/gl_tests/PointSpritesTest.cpp',
......
......@@ -24,6 +24,7 @@
'<(angle_path)/src/libANGLE/Config_unittest.cpp',
'<(angle_path)/src/libANGLE/Fence_unittest.cpp',
'<(angle_path)/src/libANGLE/HandleAllocator_unittest.cpp',
'<(angle_path)/src/libANGLE/HandleRangeAllocator_unittest.cpp',
'<(angle_path)/src/libANGLE/Image_unittest.cpp',
'<(angle_path)/src/libANGLE/ImageIndexIterator_unittest.cpp',
'<(angle_path)/src/libANGLE/Program_unittest.cpp',
......
......@@ -59,6 +59,11 @@ class NullFactory : public GLImplFactory
// Sampler object creation
SamplerImpl *createSampler() override { return nullptr; }
std::vector<PathImpl *> createPaths(GLsizei range) override
{
return std::vector<PathImpl *>();
}
};
// A class with all the factory methods mocked.
......@@ -79,6 +84,7 @@ class MockGLFactory : public GLImplFactory
MOCK_METHOD0(createFenceSync, FenceSyncImpl *());
MOCK_METHOD0(createTransformFeedback, TransformFeedbackImpl *());
MOCK_METHOD0(createSampler, SamplerImpl *());
MOCK_METHOD1(createPaths, std::vector<PathImpl *>(GLsizei));
};
class MockEGLFactory : public EGLImplFactory
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment