summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/command_buffer')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py165
-rw-r--r--gpu/command_buffer/client/gles2_c_lib_autogen.h106
-rw-r--r--gpu/command_buffer/client/gles2_cmd_helper_autogen.h119
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc163
-rw-r--r--gpu/command_buffer/client/gles2_implementation.h2
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h41
-rw-r--r--gpu/command_buffer/client/gles2_implementation_impl_autogen.h117
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest_autogen.h132
-rw-r--r--gpu/command_buffer/client/gles2_interface_autogen.h30
-rw-r--r--gpu/command_buffer/client/gles2_interface_stub_autogen.h28
-rw-r--r--gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h54
-rw-r--r--gpu/command_buffer/client/gles2_trace_implementation_autogen.h28
-rw-r--r--gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h93
-rw-r--r--gpu/command_buffer/client/share_group.cc32
-rw-r--r--gpu/command_buffer/client/share_group.h32
-rw-r--r--gpu/command_buffer/cmd_buffer_functions.txt13
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format.h3
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_autogen.h584
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_test_autogen.h189
-rw-r--r--gpu/command_buffer/common/gles2_cmd_ids_autogen.h15
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.cc17
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.h2
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_autogen.h4
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h151
-rw-r--r--gpu/command_buffer/service/BUILD.gn2
-rw-r--r--gpu/command_buffer/service/context_group.cc8
-rw-r--r--gpu/command_buffer/service/context_group.h5
-rw-r--r--gpu/command_buffer/service/context_state_autogen.h3
-rw-r--r--gpu/command_buffer/service/context_state_impl_autogen.h48
-rw-r--r--gpu/command_buffer/service/feature_info.cc23
-rw-r--r--gpu/command_buffer/service/feature_info.h3
-rw-r--r--gpu/command_buffer/service/feature_info_unittest.cc43
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc497
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h52
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h5
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_4_autogen.h15
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc941
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h49
-rw-r--r--gpu/command_buffer/service/gles2_cmd_validation_autogen.h6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h53
-rw-r--r--gpu/command_buffer/service/gpu_switches.cc42
-rw-r--r--gpu/command_buffer/service/gpu_switches.h1
-rw-r--r--gpu/command_buffer/service/path_manager.cc252
-rw-r--r--gpu/command_buffer/service/path_manager.h68
-rw-r--r--gpu/command_buffer/service/path_manager_unittest.cc164
-rw-r--r--gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc532
46 files changed, 4881 insertions, 51 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index dd6a050..09cdc7b 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -540,6 +540,31 @@ _STATES = {
},
],
},
+ 'PathStencilFuncCHROMIUM': {
+ 'type': 'Normal',
+ 'func': 'PathStencilFuncNV',
+ 'extension_flag': 'chromium_path_rendering',
+ 'states': [
+ {
+ 'name': 'stencil_path_func',
+ 'type': 'GLenum',
+ 'enum': 'GL_PATH_STENCIL_FUNC_CHROMIUM',
+ 'default': 'GL_ALWAYS',
+ },
+ {
+ 'name': 'stencil_path_ref',
+ 'type': 'GLint',
+ 'enum': 'GL_PATH_STENCIL_REF_CHROMIUM',
+ 'default': '0',
+ },
+ {
+ 'name': 'stencil_path_mask',
+ 'type': 'GLuint',
+ 'enum': 'GL_PATH_STENCIL_VALUE_MASK_CHROMIUM',
+ 'default': '0xFFFFFFFFU',
+ },
+ ],
+ },
}
# Named type info object represents a named type that is used in OpenGL call
@@ -1479,6 +1504,57 @@ _NAMED_TYPE_INFO = {
'GL_UNSIGNED_BYTE_3_3_2',
],
},
+ 'PathCoordType': {
+ 'type': 'GLenum',
+ 'valid': [
+ 'GL_BYTE',
+ 'GL_UNSIGNED_BYTE',
+ 'GL_SHORT',
+ 'GL_UNSIGNED_SHORT',
+ 'GL_FLOAT',
+ ],
+ },
+ 'PathCoverMode': {
+ 'type': 'GLenum',
+ 'valid': [
+ 'GL_CONVEX_HULL_CHROMIUM',
+ 'GL_BOUNDING_BOX_CHROMIUM',
+ ],
+ },
+ 'PathFillMode': {
+ 'type': 'GLenum',
+ 'valid': [
+ 'GL_INVERT',
+ 'GL_COUNT_UP_CHROMIUM',
+ 'GL_COUNT_DOWN_CHROMIUM',
+ ],
+ },
+ 'PathParameter': {
+ 'type': 'GLenum',
+ 'valid': [
+ 'GL_PATH_STROKE_WIDTH_CHROMIUM',
+ 'GL_PATH_END_CAPS_CHROMIUM',
+ 'GL_PATH_JOIN_STYLE_CHROMIUM',
+ 'GL_PATH_MITER_LIMIT_CHROMIUM',
+ 'GL_PATH_STROKE_BOUND_CHROMIUM',
+ ]
+ },
+ 'PathParameterCapValues': {
+ 'type': 'GLint',
+ 'valid': [
+ 'GL_FLAT',
+ 'GL_SQUARE_CHROMIUM',
+ 'GL_ROUND_CHROMIUM',
+ ]
+ },
+ 'PathParameterJoinValues': {
+ 'type': 'GLint',
+ 'valid': [
+ 'GL_MITER_REVERT_CHROMIUM',
+ 'GL_BEVEL_CHROMIUM',
+ 'GL_ROUND_CHROMIUM',
+ ]
+ },
'ReadPixelType': {
'type': 'GLenum',
'valid': [
@@ -3969,6 +4045,94 @@ _FUNCTION_INFO = {
'extension': True,
'extension_flag': 'chromium_path_rendering',
},
+ 'GenPathsCHROMIUM': {
+ 'type': 'Custom',
+ 'cmd_args': 'GLuint first_client_id, GLsizei range',
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'DeletePathsCHROMIUM': {
+ 'type': 'Custom',
+ 'cmd_args': 'GLuint first_client_id, GLsizei range',
+ 'impl_func': False,
+ 'unit_test': False,
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'IsPathCHROMIUM': {
+ 'type': 'Is',
+ 'decoder_func': 'DoIsPathCHROMIUM',
+ 'gl_test_func': 'glIsPathNV',
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'PathCommandsCHROMIUM': {
+ 'type': 'Manual',
+ 'immediate': False,
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'PathParameterfCHROMIUM': {
+ 'type': 'Custom',
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'PathParameteriCHROMIUM': {
+ 'type': 'Custom',
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'PathStencilFuncCHROMIUM': {
+ 'type': 'StateSet',
+ 'state': 'PathStencilFuncCHROMIUM',
+ 'decoder_func': 'glPathStencilFuncNV',
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'StencilFillPathCHROMIUM': {
+ 'type': 'Custom',
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'StencilStrokePathCHROMIUM': {
+ 'type': 'Custom',
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'CoverFillPathCHROMIUM': {
+ 'type': 'Custom',
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'CoverStrokePathCHROMIUM': {
+ 'type': 'Custom',
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'StencilThenCoverFillPathCHROMIUM': {
+ 'type': 'Custom',
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'StencilThenCoverStrokePathCHROMIUM': {
+ 'type': 'Custom',
+ 'chromium': True,
+ 'extension': True,
+ 'extension_flag': 'chromium_path_rendering',
+ },
+
}
@@ -7939,6 +8103,7 @@ TEST_P(%(test_name)s, %(name)sInvalidArgsBadSharedMemoryId) {
def WriteServiceImplementation(self, func, file):
"""Overrriden from TypeHandler."""
self.WriteServiceHandlerFunctionHeader(func, file)
+ self.WriteHandlerExtensionCheck(func, file)
args = func.GetOriginalArgs()
for arg in args:
arg.WriteGetCode(file)
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 4f96672a..4e304c1 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -1410,6 +1410,59 @@ void GLES2MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) {
void GLES2MatrixLoadIdentityCHROMIUM(GLenum matrixMode) {
gles2::GetGLContext()->MatrixLoadIdentityCHROMIUM(matrixMode);
}
+GLuint GLES2GenPathsCHROMIUM(GLsizei range) {
+ return gles2::GetGLContext()->GenPathsCHROMIUM(range);
+}
+void GLES2DeletePathsCHROMIUM(GLuint path, GLsizei range) {
+ gles2::GetGLContext()->DeletePathsCHROMIUM(path, range);
+}
+GLboolean GLES2IsPathCHROMIUM(GLuint path) {
+ return gles2::GetGLContext()->IsPathCHROMIUM(path);
+}
+void GLES2PathCommandsCHROMIUM(GLuint path,
+ GLsizei numCommands,
+ const GLubyte* commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const GLvoid* coords) {
+ gles2::GetGLContext()->PathCommandsCHROMIUM(path, numCommands, commands,
+ numCoords, coordType, coords);
+}
+void GLES2PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value) {
+ gles2::GetGLContext()->PathParameterfCHROMIUM(path, pname, value);
+}
+void GLES2PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value) {
+ gles2::GetGLContext()->PathParameteriCHROMIUM(path, pname, value);
+}
+void GLES2PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask) {
+ gles2::GetGLContext()->PathStencilFuncCHROMIUM(func, ref, mask);
+}
+void GLES2StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask) {
+ gles2::GetGLContext()->StencilFillPathCHROMIUM(path, fillMode, mask);
+}
+void GLES2StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask) {
+ gles2::GetGLContext()->StencilStrokePathCHROMIUM(path, reference, mask);
+}
+void GLES2CoverFillPathCHROMIUM(GLuint path, GLenum coverMode) {
+ gles2::GetGLContext()->CoverFillPathCHROMIUM(path, coverMode);
+}
+void GLES2CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode) {
+ gles2::GetGLContext()->CoverStrokePathCHROMIUM(path, coverMode);
+}
+void GLES2StencilThenCoverFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode) {
+ gles2::GetGLContext()->StencilThenCoverFillPathCHROMIUM(path, fillMode, mask,
+ coverMode);
+}
+void GLES2StencilThenCoverStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode) {
+ gles2::GetGLContext()->StencilThenCoverStrokePathCHROMIUM(path, reference,
+ mask, coverMode);
+}
GLenum GLES2GetGraphicsResetStatusKHR() {
return gles2::GetGLContext()->GetGraphicsResetStatusKHR();
}
@@ -2648,6 +2701,59 @@ extern const NameToFunc g_gles2_function_table[] = {
reinterpret_cast<GLES2FunctionPointer>(glMatrixLoadIdentityCHROMIUM),
},
{
+ "glGenPathsCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glGenPathsCHROMIUM),
+ },
+ {
+ "glDeletePathsCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glDeletePathsCHROMIUM),
+ },
+ {
+ "glIsPathCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glIsPathCHROMIUM),
+ },
+ {
+ "glPathCommandsCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glPathCommandsCHROMIUM),
+ },
+ {
+ "glPathParameterfCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glPathParameterfCHROMIUM),
+ },
+ {
+ "glPathParameteriCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glPathParameteriCHROMIUM),
+ },
+ {
+ "glPathStencilFuncCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glPathStencilFuncCHROMIUM),
+ },
+ {
+ "glStencilFillPathCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glStencilFillPathCHROMIUM),
+ },
+ {
+ "glStencilStrokePathCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glStencilStrokePathCHROMIUM),
+ },
+ {
+ "glCoverFillPathCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glCoverFillPathCHROMIUM),
+ },
+ {
+ "glCoverStrokePathCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glCoverStrokePathCHROMIUM),
+ },
+ {
+ "glStencilThenCoverFillPathCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glStencilThenCoverFillPathCHROMIUM),
+ },
+ {
+ "glStencilThenCoverStrokePathCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(
+ glStencilThenCoverStrokePathCHROMIUM),
+ },
+ {
"glGetGraphicsResetStatusKHR",
reinterpret_cast<GLES2FunctionPointer>(glGetGraphicsResetStatusKHR),
},
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index ce32148..abf4902 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -2833,6 +2833,125 @@ void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) {
}
}
+void GenPathsCHROMIUM(GLuint first_client_id, GLsizei range) {
+ gles2::cmds::GenPathsCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::GenPathsCHROMIUM>();
+ if (c) {
+ c->Init(first_client_id, range);
+ }
+}
+
+void DeletePathsCHROMIUM(GLuint first_client_id, GLsizei range) {
+ gles2::cmds::DeletePathsCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::DeletePathsCHROMIUM>();
+ if (c) {
+ c->Init(first_client_id, range);
+ }
+}
+
+void IsPathCHROMIUM(GLuint path,
+ uint32_t result_shm_id,
+ uint32_t result_shm_offset) {
+ gles2::cmds::IsPathCHROMIUM* c = GetCmdSpace<gles2::cmds::IsPathCHROMIUM>();
+ if (c) {
+ c->Init(path, result_shm_id, result_shm_offset);
+ }
+}
+
+void PathCommandsCHROMIUM(GLuint path,
+ GLsizei numCommands,
+ uint32_t commands_shm_id,
+ uint32_t commands_shm_offset,
+ GLsizei numCoords,
+ GLenum coordType,
+ uint32_t coords_shm_id,
+ uint32_t coords_shm_offset) {
+ gles2::cmds::PathCommandsCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::PathCommandsCHROMIUM>();
+ if (c) {
+ c->Init(path, numCommands, commands_shm_id, commands_shm_offset, numCoords,
+ coordType, coords_shm_id, coords_shm_offset);
+ }
+}
+
+void PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value) {
+ gles2::cmds::PathParameterfCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::PathParameterfCHROMIUM>();
+ if (c) {
+ c->Init(path, pname, value);
+ }
+}
+
+void PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value) {
+ gles2::cmds::PathParameteriCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::PathParameteriCHROMIUM>();
+ if (c) {
+ c->Init(path, pname, value);
+ }
+}
+
+void PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask) {
+ gles2::cmds::PathStencilFuncCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::PathStencilFuncCHROMIUM>();
+ if (c) {
+ c->Init(func, ref, mask);
+ }
+}
+
+void StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask) {
+ gles2::cmds::StencilFillPathCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::StencilFillPathCHROMIUM>();
+ if (c) {
+ c->Init(path, fillMode, mask);
+ }
+}
+
+void StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask) {
+ gles2::cmds::StencilStrokePathCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::StencilStrokePathCHROMIUM>();
+ if (c) {
+ c->Init(path, reference, mask);
+ }
+}
+
+void CoverFillPathCHROMIUM(GLuint path, GLenum coverMode) {
+ gles2::cmds::CoverFillPathCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::CoverFillPathCHROMIUM>();
+ if (c) {
+ c->Init(path, coverMode);
+ }
+}
+
+void CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode) {
+ gles2::cmds::CoverStrokePathCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::CoverStrokePathCHROMIUM>();
+ if (c) {
+ c->Init(path, coverMode);
+ }
+}
+
+void StencilThenCoverFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode) {
+ gles2::cmds::StencilThenCoverFillPathCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::StencilThenCoverFillPathCHROMIUM>();
+ if (c) {
+ c->Init(path, fillMode, mask, coverMode);
+ }
+}
+
+void StencilThenCoverStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode) {
+ gles2::cmds::StencilThenCoverStrokePathCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::StencilThenCoverStrokePathCHROMIUM>();
+ if (c) {
+ c->Init(path, reference, mask, coverMode);
+ }
+}
+
void BlendBarrierKHR() {
gles2::cmds::BlendBarrierKHR* c = GetCmdSpace<gles2::cmds::BlendBarrierKHR>();
if (c) {
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 5cc28ddc..5dcc9dd 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -255,6 +255,11 @@ IdHandlerInterface* GLES2Implementation::GetIdHandler(int namespace_id) const {
return share_group_->GetIdHandler(namespace_id);
}
+RangeIdHandlerInterface* GLES2Implementation::GetRangeIdHandler(
+ int namespace_id) const {
+ return share_group_->GetRangeIdHandler(namespace_id);
+}
+
IdAllocator* GLES2Implementation::GetIdAllocator(int namespace_id) const {
if (namespace_id == id_namespaces::kQueries)
return query_id_allocator_.get();
@@ -5824,6 +5829,164 @@ void GLES2Implementation::GetInternalformativ(
CheckGLError();
}
+GLuint GLES2Implementation::GenPathsCHROMIUM(GLsizei range) {
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenPathsCHROMIUM(" << range
+ << ")");
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ static const char kFunctionName[] = "glGenPathsCHROMIUM";
+ if (range < 0) {
+ SetGLError(GL_INVALID_VALUE, kFunctionName, "range < 0");
+ return 0;
+ }
+ if (!base::IsValueInRangeForNumericType<int32_t>(range)) {
+ SetGLError(GL_INVALID_OPERATION, kFunctionName, "range more than 32-bit");
+ return 0;
+ }
+ if (range == 0)
+ return 0;
+
+ GLuint first_client_id = 0;
+ GetRangeIdHandler(id_namespaces::kPaths)
+ ->MakeIdRange(this, range, &first_client_id);
+
+ if (first_client_id == 0) {
+ // Ran out of id space. Is not specified to raise any gl errors.
+ return 0;
+ }
+
+ helper_->GenPathsCHROMIUM(first_client_id, range);
+
+ GPU_CLIENT_LOG_CODE_BLOCK({
+ for (GLsizei i = 0; i < range; ++i) {
+ GPU_CLIENT_LOG(" " << i << ": " << (first_client_id + i));
+ }
+ });
+ CheckGLError();
+ return first_client_id;
+}
+
+void GLES2Implementation::DeletePathsCHROMIUM(GLuint first_client_id,
+ GLsizei range) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeletePathsCHROMIUM("
+ << first_client_id << ", " << range << ")");
+ static const char kFunctionName[] = "glDeletePathsCHROMIUM";
+
+ if (range < 0) {
+ SetGLError(GL_INVALID_VALUE, kFunctionName, "range < 0");
+ return;
+ }
+ if (!base::IsValueInRangeForNumericType<int32_t>(range)) {
+ SetGLError(GL_INVALID_OPERATION, kFunctionName, "range more than 32-bit");
+ return;
+ }
+ if (range == 0)
+ return;
+
+ GLuint last_client_id;
+ if (!SafeAddUint32(first_client_id, range - 1, &last_client_id)) {
+ SetGLError(GL_INVALID_OPERATION, kFunctionName, "overflow");
+ return;
+ }
+
+ GetRangeIdHandler(id_namespaces::kPaths)
+ ->FreeIdRange(this, first_client_id, range,
+ &GLES2Implementation::DeletePathsCHROMIUMStub);
+ CheckGLError();
+}
+
+void GLES2Implementation::DeletePathsCHROMIUMStub(GLuint first_client_id,
+ GLsizei range) {
+ helper_->DeletePathsCHROMIUM(first_client_id, range);
+}
+
+void GLES2Implementation::PathCommandsCHROMIUM(GLuint path,
+ GLsizei num_commands,
+ const GLubyte* commands,
+ GLsizei num_coords,
+ GLenum coord_type,
+ const void* coords) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPathCommandsCHROMIUM(" << path
+ << ", " << num_commands << ", " << commands << ", "
+ << num_coords << ", " << coords << ")");
+ static const char kFunctionName[] = "glPathCommandsCHROMIUM";
+ if (path == 0) {
+ SetGLError(GL_INVALID_VALUE, kFunctionName, "invalid path object");
+ return;
+ }
+ if (num_commands < 0) {
+ SetGLError(GL_INVALID_VALUE, kFunctionName, "numCommands < 0");
+ return;
+ }
+ if (num_commands != 0 && !commands) {
+ SetGLError(GL_INVALID_VALUE, kFunctionName, "missing commands");
+ return;
+ }
+ if (num_coords < 0) {
+ SetGLError(GL_INVALID_VALUE, kFunctionName, "numCoords < 0");
+ return;
+ }
+ if (num_coords != 0 && !coords) {
+ SetGLError(GL_INVALID_VALUE, kFunctionName, "missing coords");
+ return;
+ }
+ uint32 coord_type_size = GLES2Util::GetGLTypeSizeForPathCoordType(coord_type);
+ if (coord_type_size == 0) {
+ SetGLError(GL_INVALID_ENUM, kFunctionName, "invalid coordType");
+ return;
+ }
+ if (num_commands == 0) {
+ // No commands must mean no coords, thus nothing to memcpy. Let
+ // the service validate the call. Validate coord_type above, so
+ // that the parameters will be checked the in the same order
+ // regardless of num_commands.
+ helper_->PathCommandsCHROMIUM(path, num_commands, 0, 0, num_coords,
+ coord_type, 0, 0);
+ CheckGLError();
+ return;
+ }
+
+ uint32 coords_size;
+ if (!SafeMultiplyUint32(num_coords, coord_type_size, &coords_size)) {
+ SetGLError(GL_INVALID_OPERATION, kFunctionName, "overflow");
+ return;
+ }
+
+ uint32 required_buffer_size;
+ if (!SafeAddUint32(coords_size, num_commands, &required_buffer_size)) {
+ SetGLError(GL_INVALID_OPERATION, kFunctionName, "overflow");
+ return;
+ }
+
+ ScopedTransferBufferPtr buffer(required_buffer_size, helper_,
+ transfer_buffer_);
+ if (!buffer.valid() || buffer.size() < required_buffer_size) {
+ SetGLError(GL_OUT_OF_MEMORY, kFunctionName, "too large");
+ return;
+ }
+
+ uint32 coords_shm_id = 0;
+ uint32 coords_shm_offset = 0;
+ // Copy coords first because they need more strict alignment.
+ if (coords_size > 0) {
+ unsigned char* coords_addr = static_cast<unsigned char*>(buffer.address());
+ memcpy(coords_addr, coords, coords_size);
+ coords_shm_id = buffer.shm_id();
+ coords_shm_offset = buffer.offset();
+ }
+
+ DCHECK(num_commands > 0);
+ unsigned char* commands_addr =
+ static_cast<unsigned char*>(buffer.address()) + coords_size;
+ memcpy(commands_addr, commands, num_commands);
+
+ helper_->PathCommandsCHROMIUM(path, num_commands, buffer.shm_id(),
+ buffer.offset() + coords_size, num_coords,
+ coord_type, coords_shm_id, coords_shm_offset);
+ CheckGLError();
+}
+
// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index c642f9a..3446e76 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -510,6 +510,7 @@ class GLES2_IMPL_EXPORT GLES2Implementation
void DeleteFramebuffersStub(GLsizei n, const GLuint* framebuffers);
void DeleteRenderbuffersStub(GLsizei n, const GLuint* renderbuffers);
void DeleteTexturesStub(GLsizei n, const GLuint* textures);
+ void DeletePathsCHROMIUMStub(GLuint first_client_id, GLsizei range);
void DeleteProgramStub(GLsizei n, const GLuint* programs);
void DeleteShaderStub(GLsizei n, const GLuint* shaders);
void DeleteVertexArraysOESStub(GLsizei n, const GLuint* arrays);
@@ -593,6 +594,7 @@ class GLES2_IMPL_EXPORT GLES2Implementation
bool SetCapabilityState(GLenum cap, bool enabled);
IdHandlerInterface* GetIdHandler(int id_namespace) const;
+ RangeIdHandlerInterface* GetRangeIdHandler(int id_namespace) const;
// IdAllocators for objects that can't be shared among contexts.
// For now, used only for Queries. TODO(hj.r.chung) Should be added for
// Framebuffer and Vertex array objects.
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 5cb7a65..bee4f9c 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -1053,6 +1053,47 @@ void MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) override;
void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) override;
+GLuint GenPathsCHROMIUM(GLsizei range) override;
+
+void DeletePathsCHROMIUM(GLuint path, GLsizei range) override;
+
+GLboolean IsPathCHROMIUM(GLuint path) override;
+
+void PathCommandsCHROMIUM(GLuint path,
+ GLsizei numCommands,
+ const GLubyte* commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const GLvoid* coords) override;
+
+void PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value) override;
+
+void PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value) override;
+
+void PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask) override;
+
+void StencilFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask) override;
+
+void StencilStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask) override;
+
+void CoverFillPathCHROMIUM(GLuint path, GLenum coverMode) override;
+
+void CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode) override;
+
+void StencilThenCoverFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode) override;
+
+void StencilThenCoverStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode) override;
+
GLenum GetGraphicsResetStatusKHR() override;
void BlendBarrierKHR() override;
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
index 8586fe3..79a7650 100644
--- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -3462,6 +3462,123 @@ void GLES2Implementation::MatrixLoadIdentityCHROMIUM(GLenum matrixMode) {
CheckGLError();
}
+GLboolean GLES2Implementation::IsPathCHROMIUM(GLuint path) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ TRACE_EVENT0("gpu", "GLES2Implementation::IsPathCHROMIUM");
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsPathCHROMIUM(" << path << ")");
+ typedef cmds::IsPathCHROMIUM::Result Result;
+ Result* result = GetResultAs<Result*>();
+ if (!result) {
+ return GL_FALSE;
+ }
+ *result = 0;
+ helper_->IsPathCHROMIUM(path, GetResultShmId(), GetResultShmOffset());
+ WaitForCmd();
+ GLboolean result_value = *result != 0;
+ GPU_CLIENT_LOG("returned " << result_value);
+ CheckGLError();
+ return result_value;
+}
+
+void GLES2Implementation::PathParameterfCHROMIUM(GLuint path,
+ GLenum pname,
+ GLfloat value) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPathParameterfCHROMIUM(" << path
+ << ", " << GLES2Util::GetStringPathParameter(pname) << ", "
+ << value << ")");
+ helper_->PathParameterfCHROMIUM(path, pname, value);
+ CheckGLError();
+}
+
+void GLES2Implementation::PathParameteriCHROMIUM(GLuint path,
+ GLenum pname,
+ GLint value) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPathParameteriCHROMIUM(" << path
+ << ", " << GLES2Util::GetStringPathParameter(pname) << ", "
+ << value << ")");
+ helper_->PathParameteriCHROMIUM(path, pname, value);
+ CheckGLError();
+}
+
+void GLES2Implementation::PathStencilFuncCHROMIUM(GLenum func,
+ GLint ref,
+ GLuint mask) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPathStencilFuncCHROMIUM("
+ << GLES2Util::GetStringCmpFunction(func) << ", " << ref
+ << ", " << mask << ")");
+ helper_->PathStencilFuncCHROMIUM(func, ref, mask);
+ CheckGLError();
+}
+
+void GLES2Implementation::StencilFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glStencilFillPathCHROMIUM(" << path
+ << ", " << GLES2Util::GetStringPathFillMode(fillMode)
+ << ", " << mask << ")");
+ helper_->StencilFillPathCHROMIUM(path, fillMode, mask);
+ CheckGLError();
+}
+
+void GLES2Implementation::StencilStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glStencilStrokePathCHROMIUM("
+ << path << ", " << reference << ", " << mask << ")");
+ helper_->StencilStrokePathCHROMIUM(path, reference, mask);
+ CheckGLError();
+}
+
+void GLES2Implementation::CoverFillPathCHROMIUM(GLuint path, GLenum coverMode) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCoverFillPathCHROMIUM(" << path
+ << ", " << GLES2Util::GetStringPathCoverMode(coverMode)
+ << ")");
+ helper_->CoverFillPathCHROMIUM(path, coverMode);
+ CheckGLError();
+}
+
+void GLES2Implementation::CoverStrokePathCHROMIUM(GLuint path,
+ GLenum coverMode) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCoverStrokePathCHROMIUM(" << path
+ << ", " << GLES2Util::GetStringPathCoverMode(coverMode)
+ << ")");
+ helper_->CoverStrokePathCHROMIUM(path, coverMode);
+ CheckGLError();
+}
+
+void GLES2Implementation::StencilThenCoverFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG(
+ "[" << GetLogPrefix() << "] glStencilThenCoverFillPathCHROMIUM(" << path
+ << ", " << GLES2Util::GetStringPathFillMode(fillMode) << ", " << mask
+ << ", " << GLES2Util::GetStringPathCoverMode(coverMode) << ")");
+ helper_->StencilThenCoverFillPathCHROMIUM(path, fillMode, mask, coverMode);
+ CheckGLError();
+}
+
+void GLES2Implementation::StencilThenCoverStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix()
+ << "] glStencilThenCoverStrokePathCHROMIUM(" << path
+ << ", " << reference << ", " << mask << ", "
+ << GLES2Util::GetStringPathCoverMode(coverMode) << ")");
+ helper_->StencilThenCoverStrokePathCHROMIUM(path, reference, mask, coverMode);
+ CheckGLError();
+}
+
void GLES2Implementation::BlendBarrierKHR() {
GPU_CLIENT_SINGLE_THREAD_CHECK();
GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBlendBarrierKHR("
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
index 7cf70eb..fef96d9 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -3119,4 +3119,136 @@ TEST_F(GLES2ImplementationTest, MatrixLoadIdentityCHROMIUM) {
gl_->MatrixLoadIdentityCHROMIUM(GL_PATH_PROJECTION_CHROMIUM);
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
}
+// TODO(zmo): Implement unit test for GenPathsCHROMIUM
+
+TEST_F(GLES2ImplementationTest, DeletePathsCHROMIUM) {
+ struct Cmds {
+ cmds::DeletePathsCHROMIUM cmd;
+ };
+ Cmds expected;
+ expected.cmd.Init(1, 2);
+
+ gl_->DeletePathsCHROMIUM(1, 2);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
+
+TEST_F(GLES2ImplementationTest, IsPathCHROMIUM) {
+ struct Cmds {
+ cmds::IsPathCHROMIUM cmd;
+ };
+
+ Cmds expected;
+ ExpectedMemoryInfo result1 =
+ GetExpectedResultMemory(sizeof(cmds::IsPathCHROMIUM::Result));
+ expected.cmd.Init(1, result1.id, result1.offset);
+
+ EXPECT_CALL(*command_buffer(), OnFlush())
+ .WillOnce(SetMemory(result1.ptr, uint32_t(GL_TRUE)))
+ .RetiresOnSaturation();
+
+ GLboolean result = gl_->IsPathCHROMIUM(1);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+ EXPECT_TRUE(result);
+}
+// TODO(zmo): Implement unit test for PathCommandsCHROMIUM
+
+TEST_F(GLES2ImplementationTest, PathParameterfCHROMIUM) {
+ struct Cmds {
+ cmds::PathParameterfCHROMIUM cmd;
+ };
+ Cmds expected;
+ expected.cmd.Init(1, GL_PATH_STROKE_WIDTH_CHROMIUM, 3);
+
+ gl_->PathParameterfCHROMIUM(1, GL_PATH_STROKE_WIDTH_CHROMIUM, 3);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
+
+TEST_F(GLES2ImplementationTest, PathParameteriCHROMIUM) {
+ struct Cmds {
+ cmds::PathParameteriCHROMIUM cmd;
+ };
+ Cmds expected;
+ expected.cmd.Init(1, GL_PATH_STROKE_WIDTH_CHROMIUM, 3);
+
+ gl_->PathParameteriCHROMIUM(1, GL_PATH_STROKE_WIDTH_CHROMIUM, 3);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
+
+TEST_F(GLES2ImplementationTest, PathStencilFuncCHROMIUM) {
+ struct Cmds {
+ cmds::PathStencilFuncCHROMIUM cmd;
+ };
+ Cmds expected;
+ expected.cmd.Init(GL_NEVER, 2, 3);
+
+ gl_->PathStencilFuncCHROMIUM(GL_NEVER, 2, 3);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
+
+TEST_F(GLES2ImplementationTest, StencilFillPathCHROMIUM) {
+ struct Cmds {
+ cmds::StencilFillPathCHROMIUM cmd;
+ };
+ Cmds expected;
+ expected.cmd.Init(1, GL_INVERT, 3);
+
+ gl_->StencilFillPathCHROMIUM(1, GL_INVERT, 3);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
+
+TEST_F(GLES2ImplementationTest, StencilStrokePathCHROMIUM) {
+ struct Cmds {
+ cmds::StencilStrokePathCHROMIUM cmd;
+ };
+ Cmds expected;
+ expected.cmd.Init(1, 2, 3);
+
+ gl_->StencilStrokePathCHROMIUM(1, 2, 3);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
+
+TEST_F(GLES2ImplementationTest, CoverFillPathCHROMIUM) {
+ struct Cmds {
+ cmds::CoverFillPathCHROMIUM cmd;
+ };
+ Cmds expected;
+ expected.cmd.Init(1, GL_CONVEX_HULL_CHROMIUM);
+
+ gl_->CoverFillPathCHROMIUM(1, GL_CONVEX_HULL_CHROMIUM);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
+
+TEST_F(GLES2ImplementationTest, CoverStrokePathCHROMIUM) {
+ struct Cmds {
+ cmds::CoverStrokePathCHROMIUM cmd;
+ };
+ Cmds expected;
+ expected.cmd.Init(1, GL_CONVEX_HULL_CHROMIUM);
+
+ gl_->CoverStrokePathCHROMIUM(1, GL_CONVEX_HULL_CHROMIUM);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
+
+TEST_F(GLES2ImplementationTest, StencilThenCoverFillPathCHROMIUM) {
+ struct Cmds {
+ cmds::StencilThenCoverFillPathCHROMIUM cmd;
+ };
+ Cmds expected;
+ expected.cmd.Init(1, GL_INVERT, 3, GL_CONVEX_HULL_CHROMIUM);
+
+ gl_->StencilThenCoverFillPathCHROMIUM(1, GL_INVERT, 3,
+ GL_CONVEX_HULL_CHROMIUM);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
+
+TEST_F(GLES2ImplementationTest, StencilThenCoverStrokePathCHROMIUM) {
+ struct Cmds {
+ cmds::StencilThenCoverStrokePathCHROMIUM cmd;
+ };
+ Cmds expected;
+ expected.cmd.Init(1, 2, 3, GL_CONVEX_HULL_CHROMIUM);
+
+ gl_->StencilThenCoverStrokePathCHROMIUM(1, 2, 3, GL_CONVEX_HULL_CHROMIUM);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_UNITTEST_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index 5e61f11..99d0577 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -781,6 +781,36 @@ virtual void ScheduleOverlayPlaneCHROMIUM(GLint plane_z_order,
virtual void SwapInterval(GLint interval) = 0;
virtual void MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) = 0;
virtual void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) = 0;
+virtual GLuint GenPathsCHROMIUM(GLsizei range) = 0;
+virtual void DeletePathsCHROMIUM(GLuint path, GLsizei range) = 0;
+virtual GLboolean IsPathCHROMIUM(GLuint path) = 0;
+virtual void PathCommandsCHROMIUM(GLuint path,
+ GLsizei numCommands,
+ const GLubyte* commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const GLvoid* coords) = 0;
+virtual void PathParameterfCHROMIUM(GLuint path,
+ GLenum pname,
+ GLfloat value) = 0;
+virtual void PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value) = 0;
+virtual void PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask) = 0;
+virtual void StencilFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask) = 0;
+virtual void StencilStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask) = 0;
+virtual void CoverFillPathCHROMIUM(GLuint path, GLenum coverMode) = 0;
+virtual void CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode) = 0;
+virtual void StencilThenCoverFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode) = 0;
+virtual void StencilThenCoverStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode) = 0;
virtual GLenum GetGraphicsResetStatusKHR() = 0;
virtual void BlendBarrierKHR() = 0;
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index 1f70750..41358fb 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -759,6 +759,34 @@ void ScheduleOverlayPlaneCHROMIUM(GLint plane_z_order,
void SwapInterval(GLint interval) override;
void MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) override;
void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) override;
+GLuint GenPathsCHROMIUM(GLsizei range) override;
+void DeletePathsCHROMIUM(GLuint path, GLsizei range) override;
+GLboolean IsPathCHROMIUM(GLuint path) override;
+void PathCommandsCHROMIUM(GLuint path,
+ GLsizei numCommands,
+ const GLubyte* commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const GLvoid* coords) override;
+void PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value) override;
+void PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value) override;
+void PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask) override;
+void StencilFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask) override;
+void StencilStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask) override;
+void CoverFillPathCHROMIUM(GLuint path, GLenum coverMode) override;
+void CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode) override;
+void StencilThenCoverFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode) override;
+void StencilThenCoverStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode) override;
GLenum GetGraphicsResetStatusKHR() override;
void BlendBarrierKHR() override;
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
index cf1baa2..6058760 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -1290,6 +1290,60 @@ void GLES2InterfaceStub::MatrixLoadfCHROMIUM(GLenum /* matrixMode */,
}
void GLES2InterfaceStub::MatrixLoadIdentityCHROMIUM(GLenum /* matrixMode */) {
}
+GLuint GLES2InterfaceStub::GenPathsCHROMIUM(GLsizei /* range */) {
+ return 0;
+}
+void GLES2InterfaceStub::DeletePathsCHROMIUM(GLuint /* path */,
+ GLsizei /* range */) {
+}
+GLboolean GLES2InterfaceStub::IsPathCHROMIUM(GLuint /* path */) {
+ return 0;
+}
+void GLES2InterfaceStub::PathCommandsCHROMIUM(GLuint /* path */,
+ GLsizei /* numCommands */,
+ const GLubyte* /* commands */,
+ GLsizei /* numCoords */,
+ GLenum /* coordType */,
+ const GLvoid* /* coords */) {
+}
+void GLES2InterfaceStub::PathParameterfCHROMIUM(GLuint /* path */,
+ GLenum /* pname */,
+ GLfloat /* value */) {
+}
+void GLES2InterfaceStub::PathParameteriCHROMIUM(GLuint /* path */,
+ GLenum /* pname */,
+ GLint /* value */) {
+}
+void GLES2InterfaceStub::PathStencilFuncCHROMIUM(GLenum /* func */,
+ GLint /* ref */,
+ GLuint /* mask */) {
+}
+void GLES2InterfaceStub::StencilFillPathCHROMIUM(GLuint /* path */,
+ GLenum /* fillMode */,
+ GLuint /* mask */) {
+}
+void GLES2InterfaceStub::StencilStrokePathCHROMIUM(GLuint /* path */,
+ GLint /* reference */,
+ GLuint /* mask */) {
+}
+void GLES2InterfaceStub::CoverFillPathCHROMIUM(GLuint /* path */,
+ GLenum /* coverMode */) {
+}
+void GLES2InterfaceStub::CoverStrokePathCHROMIUM(GLuint /* path */,
+ GLenum /* coverMode */) {
+}
+void GLES2InterfaceStub::StencilThenCoverFillPathCHROMIUM(
+ GLuint /* path */,
+ GLenum /* fillMode */,
+ GLuint /* mask */,
+ GLenum /* coverMode */) {
+}
+void GLES2InterfaceStub::StencilThenCoverStrokePathCHROMIUM(
+ GLuint /* path */,
+ GLint /* reference */,
+ GLuint /* mask */,
+ GLenum /* coverMode */) {
+}
GLenum GLES2InterfaceStub::GetGraphicsResetStatusKHR() {
return 0;
}
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index 30743ea..ed48158 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -759,6 +759,34 @@ void ScheduleOverlayPlaneCHROMIUM(GLint plane_z_order,
void SwapInterval(GLint interval) override;
void MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) override;
void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) override;
+GLuint GenPathsCHROMIUM(GLsizei range) override;
+void DeletePathsCHROMIUM(GLuint path, GLsizei range) override;
+GLboolean IsPathCHROMIUM(GLuint path) override;
+void PathCommandsCHROMIUM(GLuint path,
+ GLsizei numCommands,
+ const GLubyte* commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const GLvoid* coords) override;
+void PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value) override;
+void PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value) override;
+void PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask) override;
+void StencilFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask) override;
+void StencilStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask) override;
+void CoverFillPathCHROMIUM(GLuint path, GLenum coverMode) override;
+void CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode) override;
+void StencilThenCoverFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode) override;
+void StencilThenCoverStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode) override;
GLenum GetGraphicsResetStatusKHR() override;
void BlendBarrierKHR() override;
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_TRACE_IMPLEMENTATION_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
index 13c215f..a0b41a2 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -2206,6 +2206,99 @@ void GLES2TraceImplementation::MatrixLoadIdentityCHROMIUM(GLenum matrixMode) {
gl_->MatrixLoadIdentityCHROMIUM(matrixMode);
}
+GLuint GLES2TraceImplementation::GenPathsCHROMIUM(GLsizei range) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GenPathsCHROMIUM");
+ return gl_->GenPathsCHROMIUM(range);
+}
+
+void GLES2TraceImplementation::DeletePathsCHROMIUM(GLuint path, GLsizei range) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DeletePathsCHROMIUM");
+ gl_->DeletePathsCHROMIUM(path, range);
+}
+
+GLboolean GLES2TraceImplementation::IsPathCHROMIUM(GLuint path) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::IsPathCHROMIUM");
+ return gl_->IsPathCHROMIUM(path);
+}
+
+void GLES2TraceImplementation::PathCommandsCHROMIUM(GLuint path,
+ GLsizei numCommands,
+ const GLubyte* commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const GLvoid* coords) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::PathCommandsCHROMIUM");
+ gl_->PathCommandsCHROMIUM(path, numCommands, commands, numCoords, coordType,
+ coords);
+}
+
+void GLES2TraceImplementation::PathParameterfCHROMIUM(GLuint path,
+ GLenum pname,
+ GLfloat value) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::PathParameterfCHROMIUM");
+ gl_->PathParameterfCHROMIUM(path, pname, value);
+}
+
+void GLES2TraceImplementation::PathParameteriCHROMIUM(GLuint path,
+ GLenum pname,
+ GLint value) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::PathParameteriCHROMIUM");
+ gl_->PathParameteriCHROMIUM(path, pname, value);
+}
+
+void GLES2TraceImplementation::PathStencilFuncCHROMIUM(GLenum func,
+ GLint ref,
+ GLuint mask) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::PathStencilFuncCHROMIUM");
+ gl_->PathStencilFuncCHROMIUM(func, ref, mask);
+}
+
+void GLES2TraceImplementation::StencilFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::StencilFillPathCHROMIUM");
+ gl_->StencilFillPathCHROMIUM(path, fillMode, mask);
+}
+
+void GLES2TraceImplementation::StencilStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::StencilStrokePathCHROMIUM");
+ gl_->StencilStrokePathCHROMIUM(path, reference, mask);
+}
+
+void GLES2TraceImplementation::CoverFillPathCHROMIUM(GLuint path,
+ GLenum coverMode) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::CoverFillPathCHROMIUM");
+ gl_->CoverFillPathCHROMIUM(path, coverMode);
+}
+
+void GLES2TraceImplementation::CoverStrokePathCHROMIUM(GLuint path,
+ GLenum coverMode) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::CoverStrokePathCHROMIUM");
+ gl_->CoverStrokePathCHROMIUM(path, coverMode);
+}
+
+void GLES2TraceImplementation::StencilThenCoverFillPathCHROMIUM(
+ GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+ "GLES2Trace::StencilThenCoverFillPathCHROMIUM");
+ gl_->StencilThenCoverFillPathCHROMIUM(path, fillMode, mask, coverMode);
+}
+
+void GLES2TraceImplementation::StencilThenCoverStrokePathCHROMIUM(
+ GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode) {
+ TRACE_EVENT_BINARY_EFFICIENT0(
+ "gpu", "GLES2Trace::StencilThenCoverStrokePathCHROMIUM");
+ gl_->StencilThenCoverStrokePathCHROMIUM(path, reference, mask, coverMode);
+}
+
GLenum GLES2TraceImplementation::GetGraphicsResetStatusKHR() {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetGraphicsResetStatusKHR");
return gl_->GetGraphicsResetStatusKHR();
diff --git a/gpu/command_buffer/client/share_group.cc b/gpu/command_buffer/client/share_group.cc
index 32e853b..e6ed66d 100644
--- a/gpu/command_buffer/client/share_group.cc
+++ b/gpu/command_buffer/client/share_group.cc
@@ -318,6 +318,35 @@ class NonReusedIdHandler : public IdHandlerInterface {
GLuint last_id_;
};
+class RangeIdHandler : public RangeIdHandlerInterface {
+ public:
+ RangeIdHandler() {}
+
+ void MakeIdRange(GLES2Implementation* /*gl_impl*/,
+ GLsizei n,
+ GLuint* first_id) override {
+ base::AutoLock auto_lock(lock_);
+ *first_id = id_allocator_.AllocateIDRange(n);
+ }
+
+ void FreeIdRange(GLES2Implementation* gl_impl,
+ const GLuint first_id,
+ GLsizei range,
+ DeleteRangeFn delete_fn) override {
+ base::AutoLock auto_lock(lock_);
+ DCHECK(range > 0);
+ id_allocator_.FreeIDRange(first_id, range);
+ (gl_impl->*delete_fn)(first_id, range);
+ gl_impl->helper()->CommandBufferHelper::OrderingBarrier();
+ }
+
+ void FreeContext(GLES2Implementation* gl_impl) override {}
+
+ private:
+ base::Lock lock_;
+ IdAllocator id_allocator_;
+};
+
ShareGroup::ShareGroup(bool bind_generates_resource)
: bind_generates_resource_(bind_generates_resource) {
if (bind_generates_resource) {
@@ -338,6 +367,9 @@ ShareGroup::ShareGroup(bool bind_generates_resource)
}
}
program_info_manager_.reset(new ProgramInfoManager);
+ for (auto& range_id_handler : range_id_handlers_) {
+ range_id_handler.reset(new RangeIdHandler());
+ }
}
void ShareGroup::set_program_info_manager(ProgramInfoManager* manager) {
diff --git a/gpu/command_buffer/client/share_group.h b/gpu/command_buffer/client/share_group.h
index c150004..2a6acc5 100644
--- a/gpu/command_buffer/client/share_group.h
+++ b/gpu/command_buffer/client/share_group.h
@@ -19,6 +19,8 @@ class GLES2ImplementationTest;
class ProgramInfoManager;
typedef void (GLES2Implementation::*DeleteFn)(GLsizei n, const GLuint* ids);
+typedef void (GLES2Implementation::*DeleteRangeFn)(const GLuint first_id,
+ GLsizei range);
typedef void (GLES2Implementation::*BindFn)(GLenum target, GLuint id);
typedef void (GLES2Implementation::*BindIndexedFn)( \
GLenum target, GLuint index, GLuint id);
@@ -86,6 +88,27 @@ class IdHandlerInterface {
virtual void FreeContext(GLES2Implementation* gl_impl) = 0;
};
+class RangeIdHandlerInterface {
+ public:
+ RangeIdHandlerInterface() {}
+ virtual ~RangeIdHandlerInterface() {}
+
+ // Makes a continuous range of ids. Stores the first allocated id to
+ // |first_id| or 0 if allocation failed.
+ virtual void MakeIdRange(GLES2Implementation* gl_impl,
+ GLsizei n,
+ GLuint* first_id) = 0;
+
+ // Frees a continuous |range| of ids beginning at |first_id|.
+ virtual void FreeIdRange(GLES2Implementation* gl_impl,
+ const GLuint first_id,
+ GLsizei range,
+ DeleteRangeFn delete_fn) = 0;
+
+ // Called when a context in the share group is destructed.
+ virtual void FreeContext(GLES2Implementation* gl_impl) = 0;
+};
+
// ShareGroup manages shared resources for contexts that are sharing resources.
class GLES2_IMPL_EXPORT ShareGroup
: public gpu::RefCountedThreadSafe<ShareGroup> {
@@ -100,6 +123,10 @@ class GLES2_IMPL_EXPORT ShareGroup
return id_handlers_[namespace_id].get();
}
+ RangeIdHandlerInterface* GetRangeIdHandler(int range_namespace_id) const {
+ return range_id_handlers_[range_namespace_id].get();
+ }
+
ProgramInfoManager* program_info_manager() {
return program_info_manager_.get();
}
@@ -108,6 +135,9 @@ class GLES2_IMPL_EXPORT ShareGroup
for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
id_handlers_[i]->FreeContext(gl_impl);
}
+ for (auto& range_id_handler : range_id_handlers_) {
+ range_id_handler->FreeContext(gl_impl);
+ }
}
private:
@@ -119,6 +149,8 @@ class GLES2_IMPL_EXPORT ShareGroup
void set_program_info_manager(ProgramInfoManager* manager);
scoped_ptr<IdHandlerInterface> id_handlers_[id_namespaces::kNumIdNamespaces];
+ scoped_ptr<RangeIdHandlerInterface>
+ range_id_handlers_[id_namespaces::kNumRangeIdNamespaces];
scoped_ptr<ProgramInfoManager> program_info_manager_;
bool bind_generates_resource_;
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index bcd4204..890a5db 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -314,6 +314,19 @@ GL_APICALL void GL_APIENTRY glSwapInterval (GLint interval);
// Extension CHROMIUM_path_rendering.
GL_APICALL void GL_APIENTRY glMatrixLoadfCHROMIUM (GLenumMatrixMode matrixMode, const GLfloat* m);
GL_APICALL void GL_APIENTRY glMatrixLoadIdentityCHROMIUM (GLenumMatrixMode matrixMode);
+GL_APICALL GLuint GL_APIENTRY glGenPathsCHROMIUM (GLsizei range);
+GL_APICALL void GL_APIENTRY glDeletePathsCHROMIUM (GLidPath path, GLsizei range);
+GL_APICALL GLboolean GL_APIENTRY glIsPathCHROMIUM (GLidPath path);
+GL_APICALL void GL_APIENTRY glPathCommandsCHROMIUM (GLidPath path, GLsizei numCommands, const GLubyte* commands, GLsizei numCoords, GLenumPathCoordType coordType, const GLvoid* coords);
+GL_APICALL void GL_APIENTRY glPathParameterfCHROMIUM (GLidPath path, GLenumPathParameter pname, GLfloat value);
+GL_APICALL void GL_APIENTRY glPathParameteriCHROMIUM (GLidPath path, GLenumPathParameter pname, GLint value);
+GL_APICALL void GL_APIENTRY glPathStencilFuncCHROMIUM (GLenumCmpFunction func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFillPathCHROMIUM (GLidPath path, GLenumPathFillMode fillMode, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilStrokePathCHROMIUM (GLidPath path, GLint reference, GLuint mask);
+GL_APICALL void GL_APIENTRY glCoverFillPathCHROMIUM (GLidPath path, GLenumPathCoverMode coverMode);
+GL_APICALL void GL_APIENTRY glCoverStrokePathCHROMIUM (GLidPath path, GLenumPathCoverMode coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathCHROMIUM (GLidPath path, GLenumPathFillMode fillMode, GLuint mask, GLenumPathCoverMode coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathCHROMIUM (GLidPath path, GLint reference, GLuint mask, GLenumPathCoverMode coverMode);
// Extension KHR_robustness
GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void);
diff --git a/gpu/command_buffer/common/gles2_cmd_format.h b/gpu/command_buffer/common/gles2_cmd_format.h
index db63594..325c334 100644
--- a/gpu/command_buffer/common/gles2_cmd_format.h
+++ b/gpu/command_buffer/common/gles2_cmd_format.h
@@ -70,12 +70,15 @@ enum IdNamespaces {
kNumIdNamespaces
};
+enum RangeIdNamespaces { kPaths, kNumRangeIdNamespaces };
+
// These numbers must not change
static_assert(kBuffers == 0, "kBuffers should equal 0");
static_assert(kFramebuffers == 1, "kFramebuffers should equal 1");
static_assert(kProgramsAndShaders == 2, "kProgramsAndShaders should equal 2");
static_assert(kRenderbuffers == 3, "kRenderbuffers should equal 3");
static_assert(kTextures == 4, "kTextures should equal 4");
+static_assert(kPaths == 0, "kPaths should equal 0");
} // namespace id_namespaces
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index e7a6272..ded8b6f 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -13780,6 +13780,590 @@ static_assert(offsetof(MatrixLoadIdentityCHROMIUM, header) == 0,
static_assert(offsetof(MatrixLoadIdentityCHROMIUM, matrixMode) == 4,
"offset of MatrixLoadIdentityCHROMIUM matrixMode should be 4");
+struct GenPathsCHROMIUM {
+ typedef GenPathsCHROMIUM ValueType;
+ static const CommandId kCmdId = kGenPathsCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _first_client_id, GLsizei _range) {
+ SetHeader();
+ first_client_id = _first_client_id;
+ range = _range;
+ }
+
+ void* Set(void* cmd, GLuint _first_client_id, GLsizei _range) {
+ static_cast<ValueType*>(cmd)->Init(_first_client_id, _range);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t first_client_id;
+ int32_t range;
+};
+
+static_assert(sizeof(GenPathsCHROMIUM) == 12,
+ "size of GenPathsCHROMIUM should be 12");
+static_assert(offsetof(GenPathsCHROMIUM, header) == 0,
+ "offset of GenPathsCHROMIUM header should be 0");
+static_assert(offsetof(GenPathsCHROMIUM, first_client_id) == 4,
+ "offset of GenPathsCHROMIUM first_client_id should be 4");
+static_assert(offsetof(GenPathsCHROMIUM, range) == 8,
+ "offset of GenPathsCHROMIUM range should be 8");
+
+struct DeletePathsCHROMIUM {
+ typedef DeletePathsCHROMIUM ValueType;
+ static const CommandId kCmdId = kDeletePathsCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _first_client_id, GLsizei _range) {
+ SetHeader();
+ first_client_id = _first_client_id;
+ range = _range;
+ }
+
+ void* Set(void* cmd, GLuint _first_client_id, GLsizei _range) {
+ static_cast<ValueType*>(cmd)->Init(_first_client_id, _range);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t first_client_id;
+ int32_t range;
+};
+
+static_assert(sizeof(DeletePathsCHROMIUM) == 12,
+ "size of DeletePathsCHROMIUM should be 12");
+static_assert(offsetof(DeletePathsCHROMIUM, header) == 0,
+ "offset of DeletePathsCHROMIUM header should be 0");
+static_assert(offsetof(DeletePathsCHROMIUM, first_client_id) == 4,
+ "offset of DeletePathsCHROMIUM first_client_id should be 4");
+static_assert(offsetof(DeletePathsCHROMIUM, range) == 8,
+ "offset of DeletePathsCHROMIUM range should be 8");
+
+struct IsPathCHROMIUM {
+ typedef IsPathCHROMIUM ValueType;
+ static const CommandId kCmdId = kIsPathCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ typedef uint32_t Result;
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _path,
+ uint32_t _result_shm_id,
+ uint32_t _result_shm_offset) {
+ SetHeader();
+ path = _path;
+ result_shm_id = _result_shm_id;
+ result_shm_offset = _result_shm_offset;
+ }
+
+ void* Set(void* cmd,
+ GLuint _path,
+ uint32_t _result_shm_id,
+ uint32_t _result_shm_offset) {
+ static_cast<ValueType*>(cmd)
+ ->Init(_path, _result_shm_id, _result_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t path;
+ uint32_t result_shm_id;
+ uint32_t result_shm_offset;
+};
+
+static_assert(sizeof(IsPathCHROMIUM) == 16,
+ "size of IsPathCHROMIUM should be 16");
+static_assert(offsetof(IsPathCHROMIUM, header) == 0,
+ "offset of IsPathCHROMIUM header should be 0");
+static_assert(offsetof(IsPathCHROMIUM, path) == 4,
+ "offset of IsPathCHROMIUM path should be 4");
+static_assert(offsetof(IsPathCHROMIUM, result_shm_id) == 8,
+ "offset of IsPathCHROMIUM result_shm_id should be 8");
+static_assert(offsetof(IsPathCHROMIUM, result_shm_offset) == 12,
+ "offset of IsPathCHROMIUM result_shm_offset should be 12");
+
+struct PathCommandsCHROMIUM {
+ typedef PathCommandsCHROMIUM ValueType;
+ static const CommandId kCmdId = kPathCommandsCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _path,
+ GLsizei _numCommands,
+ uint32_t _commands_shm_id,
+ uint32_t _commands_shm_offset,
+ GLsizei _numCoords,
+ GLenum _coordType,
+ uint32_t _coords_shm_id,
+ uint32_t _coords_shm_offset) {
+ SetHeader();
+ path = _path;
+ numCommands = _numCommands;
+ commands_shm_id = _commands_shm_id;
+ commands_shm_offset = _commands_shm_offset;
+ numCoords = _numCoords;
+ coordType = _coordType;
+ coords_shm_id = _coords_shm_id;
+ coords_shm_offset = _coords_shm_offset;
+ }
+
+ void* Set(void* cmd,
+ GLuint _path,
+ GLsizei _numCommands,
+ uint32_t _commands_shm_id,
+ uint32_t _commands_shm_offset,
+ GLsizei _numCoords,
+ GLenum _coordType,
+ uint32_t _coords_shm_id,
+ uint32_t _coords_shm_offset) {
+ static_cast<ValueType*>(cmd)
+ ->Init(_path, _numCommands, _commands_shm_id, _commands_shm_offset,
+ _numCoords, _coordType, _coords_shm_id, _coords_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t path;
+ int32_t numCommands;
+ uint32_t commands_shm_id;
+ uint32_t commands_shm_offset;
+ int32_t numCoords;
+ uint32_t coordType;
+ uint32_t coords_shm_id;
+ uint32_t coords_shm_offset;
+};
+
+static_assert(sizeof(PathCommandsCHROMIUM) == 36,
+ "size of PathCommandsCHROMIUM should be 36");
+static_assert(offsetof(PathCommandsCHROMIUM, header) == 0,
+ "offset of PathCommandsCHROMIUM header should be 0");
+static_assert(offsetof(PathCommandsCHROMIUM, path) == 4,
+ "offset of PathCommandsCHROMIUM path should be 4");
+static_assert(offsetof(PathCommandsCHROMIUM, numCommands) == 8,
+ "offset of PathCommandsCHROMIUM numCommands should be 8");
+static_assert(offsetof(PathCommandsCHROMIUM, commands_shm_id) == 12,
+ "offset of PathCommandsCHROMIUM commands_shm_id should be 12");
+static_assert(
+ offsetof(PathCommandsCHROMIUM, commands_shm_offset) == 16,
+ "offset of PathCommandsCHROMIUM commands_shm_offset should be 16");
+static_assert(offsetof(PathCommandsCHROMIUM, numCoords) == 20,
+ "offset of PathCommandsCHROMIUM numCoords should be 20");
+static_assert(offsetof(PathCommandsCHROMIUM, coordType) == 24,
+ "offset of PathCommandsCHROMIUM coordType should be 24");
+static_assert(offsetof(PathCommandsCHROMIUM, coords_shm_id) == 28,
+ "offset of PathCommandsCHROMIUM coords_shm_id should be 28");
+static_assert(offsetof(PathCommandsCHROMIUM, coords_shm_offset) == 32,
+ "offset of PathCommandsCHROMIUM coords_shm_offset should be 32");
+
+struct PathParameterfCHROMIUM {
+ typedef PathParameterfCHROMIUM ValueType;
+ static const CommandId kCmdId = kPathParameterfCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _path, GLenum _pname, GLfloat _value) {
+ SetHeader();
+ path = _path;
+ pname = _pname;
+ value = _value;
+ }
+
+ void* Set(void* cmd, GLuint _path, GLenum _pname, GLfloat _value) {
+ static_cast<ValueType*>(cmd)->Init(_path, _pname, _value);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t path;
+ uint32_t pname;
+ float value;
+};
+
+static_assert(sizeof(PathParameterfCHROMIUM) == 16,
+ "size of PathParameterfCHROMIUM should be 16");
+static_assert(offsetof(PathParameterfCHROMIUM, header) == 0,
+ "offset of PathParameterfCHROMIUM header should be 0");
+static_assert(offsetof(PathParameterfCHROMIUM, path) == 4,
+ "offset of PathParameterfCHROMIUM path should be 4");
+static_assert(offsetof(PathParameterfCHROMIUM, pname) == 8,
+ "offset of PathParameterfCHROMIUM pname should be 8");
+static_assert(offsetof(PathParameterfCHROMIUM, value) == 12,
+ "offset of PathParameterfCHROMIUM value should be 12");
+
+struct PathParameteriCHROMIUM {
+ typedef PathParameteriCHROMIUM ValueType;
+ static const CommandId kCmdId = kPathParameteriCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _path, GLenum _pname, GLint _value) {
+ SetHeader();
+ path = _path;
+ pname = _pname;
+ value = _value;
+ }
+
+ void* Set(void* cmd, GLuint _path, GLenum _pname, GLint _value) {
+ static_cast<ValueType*>(cmd)->Init(_path, _pname, _value);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t path;
+ uint32_t pname;
+ int32_t value;
+};
+
+static_assert(sizeof(PathParameteriCHROMIUM) == 16,
+ "size of PathParameteriCHROMIUM should be 16");
+static_assert(offsetof(PathParameteriCHROMIUM, header) == 0,
+ "offset of PathParameteriCHROMIUM header should be 0");
+static_assert(offsetof(PathParameteriCHROMIUM, path) == 4,
+ "offset of PathParameteriCHROMIUM path should be 4");
+static_assert(offsetof(PathParameteriCHROMIUM, pname) == 8,
+ "offset of PathParameteriCHROMIUM pname should be 8");
+static_assert(offsetof(PathParameteriCHROMIUM, value) == 12,
+ "offset of PathParameteriCHROMIUM value should be 12");
+
+struct PathStencilFuncCHROMIUM {
+ typedef PathStencilFuncCHROMIUM ValueType;
+ static const CommandId kCmdId = kPathStencilFuncCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLenum _func, GLint _ref, GLuint _mask) {
+ SetHeader();
+ func = _func;
+ ref = _ref;
+ mask = _mask;
+ }
+
+ void* Set(void* cmd, GLenum _func, GLint _ref, GLuint _mask) {
+ static_cast<ValueType*>(cmd)->Init(_func, _ref, _mask);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t func;
+ int32_t ref;
+ uint32_t mask;
+};
+
+static_assert(sizeof(PathStencilFuncCHROMIUM) == 16,
+ "size of PathStencilFuncCHROMIUM should be 16");
+static_assert(offsetof(PathStencilFuncCHROMIUM, header) == 0,
+ "offset of PathStencilFuncCHROMIUM header should be 0");
+static_assert(offsetof(PathStencilFuncCHROMIUM, func) == 4,
+ "offset of PathStencilFuncCHROMIUM func should be 4");
+static_assert(offsetof(PathStencilFuncCHROMIUM, ref) == 8,
+ "offset of PathStencilFuncCHROMIUM ref should be 8");
+static_assert(offsetof(PathStencilFuncCHROMIUM, mask) == 12,
+ "offset of PathStencilFuncCHROMIUM mask should be 12");
+
+struct StencilFillPathCHROMIUM {
+ typedef StencilFillPathCHROMIUM ValueType;
+ static const CommandId kCmdId = kStencilFillPathCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _path, GLenum _fillMode, GLuint _mask) {
+ SetHeader();
+ path = _path;
+ fillMode = _fillMode;
+ mask = _mask;
+ }
+
+ void* Set(void* cmd, GLuint _path, GLenum _fillMode, GLuint _mask) {
+ static_cast<ValueType*>(cmd)->Init(_path, _fillMode, _mask);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t path;
+ uint32_t fillMode;
+ uint32_t mask;
+};
+
+static_assert(sizeof(StencilFillPathCHROMIUM) == 16,
+ "size of StencilFillPathCHROMIUM should be 16");
+static_assert(offsetof(StencilFillPathCHROMIUM, header) == 0,
+ "offset of StencilFillPathCHROMIUM header should be 0");
+static_assert(offsetof(StencilFillPathCHROMIUM, path) == 4,
+ "offset of StencilFillPathCHROMIUM path should be 4");
+static_assert(offsetof(StencilFillPathCHROMIUM, fillMode) == 8,
+ "offset of StencilFillPathCHROMIUM fillMode should be 8");
+static_assert(offsetof(StencilFillPathCHROMIUM, mask) == 12,
+ "offset of StencilFillPathCHROMIUM mask should be 12");
+
+struct StencilStrokePathCHROMIUM {
+ typedef StencilStrokePathCHROMIUM ValueType;
+ static const CommandId kCmdId = kStencilStrokePathCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _path, GLint _reference, GLuint _mask) {
+ SetHeader();
+ path = _path;
+ reference = _reference;
+ mask = _mask;
+ }
+
+ void* Set(void* cmd, GLuint _path, GLint _reference, GLuint _mask) {
+ static_cast<ValueType*>(cmd)->Init(_path, _reference, _mask);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t path;
+ int32_t reference;
+ uint32_t mask;
+};
+
+static_assert(sizeof(StencilStrokePathCHROMIUM) == 16,
+ "size of StencilStrokePathCHROMIUM should be 16");
+static_assert(offsetof(StencilStrokePathCHROMIUM, header) == 0,
+ "offset of StencilStrokePathCHROMIUM header should be 0");
+static_assert(offsetof(StencilStrokePathCHROMIUM, path) == 4,
+ "offset of StencilStrokePathCHROMIUM path should be 4");
+static_assert(offsetof(StencilStrokePathCHROMIUM, reference) == 8,
+ "offset of StencilStrokePathCHROMIUM reference should be 8");
+static_assert(offsetof(StencilStrokePathCHROMIUM, mask) == 12,
+ "offset of StencilStrokePathCHROMIUM mask should be 12");
+
+struct CoverFillPathCHROMIUM {
+ typedef CoverFillPathCHROMIUM ValueType;
+ static const CommandId kCmdId = kCoverFillPathCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _path, GLenum _coverMode) {
+ SetHeader();
+ path = _path;
+ coverMode = _coverMode;
+ }
+
+ void* Set(void* cmd, GLuint _path, GLenum _coverMode) {
+ static_cast<ValueType*>(cmd)->Init(_path, _coverMode);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t path;
+ uint32_t coverMode;
+};
+
+static_assert(sizeof(CoverFillPathCHROMIUM) == 12,
+ "size of CoverFillPathCHROMIUM should be 12");
+static_assert(offsetof(CoverFillPathCHROMIUM, header) == 0,
+ "offset of CoverFillPathCHROMIUM header should be 0");
+static_assert(offsetof(CoverFillPathCHROMIUM, path) == 4,
+ "offset of CoverFillPathCHROMIUM path should be 4");
+static_assert(offsetof(CoverFillPathCHROMIUM, coverMode) == 8,
+ "offset of CoverFillPathCHROMIUM coverMode should be 8");
+
+struct CoverStrokePathCHROMIUM {
+ typedef CoverStrokePathCHROMIUM ValueType;
+ static const CommandId kCmdId = kCoverStrokePathCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _path, GLenum _coverMode) {
+ SetHeader();
+ path = _path;
+ coverMode = _coverMode;
+ }
+
+ void* Set(void* cmd, GLuint _path, GLenum _coverMode) {
+ static_cast<ValueType*>(cmd)->Init(_path, _coverMode);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t path;
+ uint32_t coverMode;
+};
+
+static_assert(sizeof(CoverStrokePathCHROMIUM) == 12,
+ "size of CoverStrokePathCHROMIUM should be 12");
+static_assert(offsetof(CoverStrokePathCHROMIUM, header) == 0,
+ "offset of CoverStrokePathCHROMIUM header should be 0");
+static_assert(offsetof(CoverStrokePathCHROMIUM, path) == 4,
+ "offset of CoverStrokePathCHROMIUM path should be 4");
+static_assert(offsetof(CoverStrokePathCHROMIUM, coverMode) == 8,
+ "offset of CoverStrokePathCHROMIUM coverMode should be 8");
+
+struct StencilThenCoverFillPathCHROMIUM {
+ typedef StencilThenCoverFillPathCHROMIUM ValueType;
+ static const CommandId kCmdId = kStencilThenCoverFillPathCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _path, GLenum _fillMode, GLuint _mask, GLenum _coverMode) {
+ SetHeader();
+ path = _path;
+ fillMode = _fillMode;
+ mask = _mask;
+ coverMode = _coverMode;
+ }
+
+ void* Set(void* cmd,
+ GLuint _path,
+ GLenum _fillMode,
+ GLuint _mask,
+ GLenum _coverMode) {
+ static_cast<ValueType*>(cmd)->Init(_path, _fillMode, _mask, _coverMode);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t path;
+ uint32_t fillMode;
+ uint32_t mask;
+ uint32_t coverMode;
+};
+
+static_assert(sizeof(StencilThenCoverFillPathCHROMIUM) == 20,
+ "size of StencilThenCoverFillPathCHROMIUM should be 20");
+static_assert(offsetof(StencilThenCoverFillPathCHROMIUM, header) == 0,
+ "offset of StencilThenCoverFillPathCHROMIUM header should be 0");
+static_assert(offsetof(StencilThenCoverFillPathCHROMIUM, path) == 4,
+ "offset of StencilThenCoverFillPathCHROMIUM path should be 4");
+static_assert(
+ offsetof(StencilThenCoverFillPathCHROMIUM, fillMode) == 8,
+ "offset of StencilThenCoverFillPathCHROMIUM fillMode should be 8");
+static_assert(offsetof(StencilThenCoverFillPathCHROMIUM, mask) == 12,
+ "offset of StencilThenCoverFillPathCHROMIUM mask should be 12");
+static_assert(
+ offsetof(StencilThenCoverFillPathCHROMIUM, coverMode) == 16,
+ "offset of StencilThenCoverFillPathCHROMIUM coverMode should be 16");
+
+struct StencilThenCoverStrokePathCHROMIUM {
+ typedef StencilThenCoverStrokePathCHROMIUM ValueType;
+ static const CommandId kCmdId = kStencilThenCoverStrokePathCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _path, GLint _reference, GLuint _mask, GLenum _coverMode) {
+ SetHeader();
+ path = _path;
+ reference = _reference;
+ mask = _mask;
+ coverMode = _coverMode;
+ }
+
+ void* Set(void* cmd,
+ GLuint _path,
+ GLint _reference,
+ GLuint _mask,
+ GLenum _coverMode) {
+ static_cast<ValueType*>(cmd)->Init(_path, _reference, _mask, _coverMode);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t path;
+ int32_t reference;
+ uint32_t mask;
+ uint32_t coverMode;
+};
+
+static_assert(sizeof(StencilThenCoverStrokePathCHROMIUM) == 20,
+ "size of StencilThenCoverStrokePathCHROMIUM should be 20");
+static_assert(
+ offsetof(StencilThenCoverStrokePathCHROMIUM, header) == 0,
+ "offset of StencilThenCoverStrokePathCHROMIUM header should be 0");
+static_assert(offsetof(StencilThenCoverStrokePathCHROMIUM, path) == 4,
+ "offset of StencilThenCoverStrokePathCHROMIUM path should be 4");
+static_assert(
+ offsetof(StencilThenCoverStrokePathCHROMIUM, reference) == 8,
+ "offset of StencilThenCoverStrokePathCHROMIUM reference should be 8");
+static_assert(offsetof(StencilThenCoverStrokePathCHROMIUM, mask) == 12,
+ "offset of StencilThenCoverStrokePathCHROMIUM mask should be 12");
+static_assert(
+ offsetof(StencilThenCoverStrokePathCHROMIUM, coverMode) == 16,
+ "offset of StencilThenCoverStrokePathCHROMIUM coverMode should be 16");
+
struct BlendBarrierKHR {
typedef BlendBarrierKHR ValueType;
static const CommandId kCmdId = kBlendBarrierKHR;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index cb4145a6..b6b81be 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -4887,6 +4887,195 @@ TEST_F(GLES2FormatTest, MatrixLoadIdentityCHROMIUM) {
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, GenPathsCHROMIUM) {
+ cmds::GenPathsCHROMIUM& cmd = *GetBufferAs<cmds::GenPathsCHROMIUM>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLsizei>(12));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::GenPathsCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.first_client_id);
+ EXPECT_EQ(static_cast<GLsizei>(12), cmd.range);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, DeletePathsCHROMIUM) {
+ cmds::DeletePathsCHROMIUM& cmd = *GetBufferAs<cmds::DeletePathsCHROMIUM>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLsizei>(12));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::DeletePathsCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.first_client_id);
+ EXPECT_EQ(static_cast<GLsizei>(12), cmd.range);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, IsPathCHROMIUM) {
+ cmds::IsPathCHROMIUM& cmd = *GetBufferAs<cmds::IsPathCHROMIUM>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12),
+ static_cast<uint32_t>(13));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::IsPathCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.path);
+ EXPECT_EQ(static_cast<uint32_t>(12), cmd.result_shm_id);
+ EXPECT_EQ(static_cast<uint32_t>(13), cmd.result_shm_offset);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, PathCommandsCHROMIUM) {
+ cmds::PathCommandsCHROMIUM& cmd = *GetBufferAs<cmds::PathCommandsCHROMIUM>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLsizei>(12),
+ static_cast<uint32_t>(13), static_cast<uint32_t>(14),
+ static_cast<GLsizei>(15), static_cast<GLenum>(16),
+ static_cast<uint32_t>(17), static_cast<uint32_t>(18));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::PathCommandsCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.path);
+ EXPECT_EQ(static_cast<GLsizei>(12), cmd.numCommands);
+ EXPECT_EQ(static_cast<uint32_t>(13), cmd.commands_shm_id);
+ EXPECT_EQ(static_cast<uint32_t>(14), cmd.commands_shm_offset);
+ EXPECT_EQ(static_cast<GLsizei>(15), cmd.numCoords);
+ EXPECT_EQ(static_cast<GLenum>(16), cmd.coordType);
+ EXPECT_EQ(static_cast<uint32_t>(17), cmd.coords_shm_id);
+ EXPECT_EQ(static_cast<uint32_t>(18), cmd.coords_shm_offset);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, PathParameterfCHROMIUM) {
+ cmds::PathParameterfCHROMIUM& cmd =
+ *GetBufferAs<cmds::PathParameterfCHROMIUM>();
+ void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11),
+ static_cast<GLenum>(12), static_cast<GLfloat>(13));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::PathParameterfCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.path);
+ EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+ EXPECT_EQ(static_cast<GLfloat>(13), cmd.value);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, PathParameteriCHROMIUM) {
+ cmds::PathParameteriCHROMIUM& cmd =
+ *GetBufferAs<cmds::PathParameteriCHROMIUM>();
+ void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11),
+ static_cast<GLenum>(12), static_cast<GLint>(13));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::PathParameteriCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.path);
+ EXPECT_EQ(static_cast<GLenum>(12), cmd.pname);
+ EXPECT_EQ(static_cast<GLint>(13), cmd.value);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, PathStencilFuncCHROMIUM) {
+ cmds::PathStencilFuncCHROMIUM& cmd =
+ *GetBufferAs<cmds::PathStencilFuncCHROMIUM>();
+ void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11),
+ static_cast<GLint>(12), static_cast<GLuint>(13));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::PathStencilFuncCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLenum>(11), cmd.func);
+ EXPECT_EQ(static_cast<GLint>(12), cmd.ref);
+ EXPECT_EQ(static_cast<GLuint>(13), cmd.mask);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, StencilFillPathCHROMIUM) {
+ cmds::StencilFillPathCHROMIUM& cmd =
+ *GetBufferAs<cmds::StencilFillPathCHROMIUM>();
+ void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11),
+ static_cast<GLenum>(12), static_cast<GLuint>(13));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::StencilFillPathCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.path);
+ EXPECT_EQ(static_cast<GLenum>(12), cmd.fillMode);
+ EXPECT_EQ(static_cast<GLuint>(13), cmd.mask);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, StencilStrokePathCHROMIUM) {
+ cmds::StencilStrokePathCHROMIUM& cmd =
+ *GetBufferAs<cmds::StencilStrokePathCHROMIUM>();
+ void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11),
+ static_cast<GLint>(12), static_cast<GLuint>(13));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::StencilStrokePathCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.path);
+ EXPECT_EQ(static_cast<GLint>(12), cmd.reference);
+ EXPECT_EQ(static_cast<GLuint>(13), cmd.mask);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, CoverFillPathCHROMIUM) {
+ cmds::CoverFillPathCHROMIUM& cmd =
+ *GetBufferAs<cmds::CoverFillPathCHROMIUM>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLenum>(12));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::CoverFillPathCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.path);
+ EXPECT_EQ(static_cast<GLenum>(12), cmd.coverMode);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, CoverStrokePathCHROMIUM) {
+ cmds::CoverStrokePathCHROMIUM& cmd =
+ *GetBufferAs<cmds::CoverStrokePathCHROMIUM>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLenum>(12));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::CoverStrokePathCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.path);
+ EXPECT_EQ(static_cast<GLenum>(12), cmd.coverMode);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, StencilThenCoverFillPathCHROMIUM) {
+ cmds::StencilThenCoverFillPathCHROMIUM& cmd =
+ *GetBufferAs<cmds::StencilThenCoverFillPathCHROMIUM>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLenum>(12),
+ static_cast<GLuint>(13), static_cast<GLenum>(14));
+ EXPECT_EQ(
+ static_cast<uint32_t>(cmds::StencilThenCoverFillPathCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.path);
+ EXPECT_EQ(static_cast<GLenum>(12), cmd.fillMode);
+ EXPECT_EQ(static_cast<GLuint>(13), cmd.mask);
+ EXPECT_EQ(static_cast<GLenum>(14), cmd.coverMode);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, StencilThenCoverStrokePathCHROMIUM) {
+ cmds::StencilThenCoverStrokePathCHROMIUM& cmd =
+ *GetBufferAs<cmds::StencilThenCoverStrokePathCHROMIUM>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLint>(12),
+ static_cast<GLuint>(13), static_cast<GLenum>(14));
+ EXPECT_EQ(
+ static_cast<uint32_t>(cmds::StencilThenCoverStrokePathCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.path);
+ EXPECT_EQ(static_cast<GLint>(12), cmd.reference);
+ EXPECT_EQ(static_cast<GLuint>(13), cmd.mask);
+ EXPECT_EQ(static_cast<GLenum>(14), cmd.coverMode);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
TEST_F(GLES2FormatTest, BlendBarrierKHR) {
cmds::BlendBarrierKHR& cmd = *GetBufferAs<cmds::BlendBarrierKHR>();
void* next_cmd = cmd.Set(&cmd);
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index 4a3a3d6..4661ac8 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -302,7 +302,20 @@
OP(SwapInterval) /* 543 */ \
OP(MatrixLoadfCHROMIUMImmediate) /* 544 */ \
OP(MatrixLoadIdentityCHROMIUM) /* 545 */ \
- OP(BlendBarrierKHR) /* 546 */
+ OP(GenPathsCHROMIUM) /* 546 */ \
+ OP(DeletePathsCHROMIUM) /* 547 */ \
+ OP(IsPathCHROMIUM) /* 548 */ \
+ OP(PathCommandsCHROMIUM) /* 549 */ \
+ OP(PathParameterfCHROMIUM) /* 550 */ \
+ OP(PathParameteriCHROMIUM) /* 551 */ \
+ OP(PathStencilFuncCHROMIUM) /* 552 */ \
+ OP(StencilFillPathCHROMIUM) /* 553 */ \
+ OP(StencilStrokePathCHROMIUM) /* 554 */ \
+ OP(CoverFillPathCHROMIUM) /* 555 */ \
+ OP(CoverStrokePathCHROMIUM) /* 556 */ \
+ OP(StencilThenCoverFillPathCHROMIUM) /* 557 */ \
+ OP(StencilThenCoverStrokePathCHROMIUM) /* 558 */ \
+ OP(BlendBarrierKHR) /* 559 */
enum CommandId {
kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index 7a33ab1..1471456 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -702,6 +702,23 @@ size_t GLES2Util::GetGLTypeSizeForTexturesAndBuffers(uint32 type) {
}
}
+size_t GLES2Util::GetGLTypeSizeForPathCoordType(uint32 type) {
+ switch (type) {
+ case GL_BYTE:
+ return sizeof(GLbyte); // NOLINT
+ case GL_UNSIGNED_BYTE:
+ return sizeof(GLubyte); // NOLINT
+ case GL_SHORT:
+ return sizeof(GLshort); // NOLINT
+ case GL_UNSIGNED_SHORT:
+ return sizeof(GLushort); // NOLINT
+ case GL_FLOAT:
+ return sizeof(GLfloat); // NOLINT
+ default:
+ return 0;
+ }
+}
+
uint32 GLES2Util::GLErrorToErrorBit(uint32 error) {
switch (error) {
case GL_INVALID_ENUM:
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
index 12b1551..4946205 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -127,6 +127,8 @@ class GLES2_UTILS_EXPORT GLES2Util {
static size_t GetGLTypeSizeForTexturesAndBuffers(uint32_t type);
+ static size_t GetGLTypeSizeForPathCoordType(uint32_t type);
+
static uint32_t GLErrorToErrorBit(uint32_t gl_error);
static uint32_t GLErrorBitToGLError(uint32_t error_bit);
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
index 6e3d161..0099155 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
@@ -46,6 +46,10 @@ static std::string GetStringInternalFormatParameter(uint32_t value);
static std::string GetStringInvalidateFrameBufferTarget(uint32_t value);
static std::string GetStringMapBufferAccess(uint32_t value);
static std::string GetStringMatrixMode(uint32_t value);
+static std::string GetStringPathCoordType(uint32_t value);
+static std::string GetStringPathCoverMode(uint32_t value);
+static std::string GetStringPathFillMode(uint32_t value);
+static std::string GetStringPathParameter(uint32_t value);
static std::string GetStringPixelStore(uint32_t value);
static std::string GetStringPixelType(uint32_t value);
static std::string GetStringProgramParameter(uint32_t value);
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
index 3dd31ca..6b061d4 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -141,6 +141,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_SHADER_BINARY_VIV",
},
{
+ 0x90A7,
+ "GL_MITER_REVERT_CHROMIUM",
+ },
+ {
0x9130,
"GL_SGX_PROGRAM_BINARY_IMG",
},
@@ -581,6 +585,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL",
},
{
+ 0x90a4,
+ "GL_ROUND_CHROMIUM",
+ },
+ {
0x8A48,
"GL_TEXTURE_SRGB_DECODE_EXT",
},
@@ -589,6 +597,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_CONTEXT_LOST",
},
{
+ 0x90a3,
+ "GL_SQUARE_CHROMIUM",
+ },
+ {
0x02000000,
"GL_MULTISAMPLE_BUFFER_BIT1_QCOM",
},
@@ -749,6 +761,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_RENDERBUFFER",
},
{
+ 0x90B7,
+ "GL_PATH_STENCIL_FUNC_CHROMIUM",
+ },
+ {
0x8A3A,
"GL_UNIFORM_BLOCK_INDEX",
},
@@ -761,10 +777,22 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_DITHER",
},
{
+ 0x90B9,
+ "GL_PATH_STENCIL_VALUE_MASK_CHROMIUM",
+ },
+ {
+ 0x90B8,
+ "GL_PATH_STENCIL_REF_CHROMIUM",
+ },
+ {
0x93D3,
"GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR",
},
{
+ 0x1D00,
+ "GL_FLAT_CHROMIUM",
+ },
+ {
0x9144,
"GL_MAX_DEBUG_LOGGED_MESSAGES_KHR",
},
@@ -981,6 +1009,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_UNSIGNED_INT_24_8_OES",
},
{
+ 0x0A,
+ "GL_QUADRATIC_CURVE_TO_CHROMIUM",
+ },
+ {
0x92D4,
"GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT",
},
@@ -1085,6 +1117,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_SAMPLE_COVERAGE",
},
{
+ 0x0C,
+ "GL_CUBIC_CURVE_TO_CHROMIUM",
+ },
+ {
0x928F,
"GL_DST_ATOP_NV",
},
@@ -1629,6 +1665,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_BGRA_EXT",
},
{
+ 0x908B,
+ "GL_CONVEX_HULL_CHROMIUM",
+ },
+ {
0x8ED7,
"GL_COVERAGE_AUTOMATIC_NV",
},
@@ -1889,6 +1929,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT",
},
{
+ 0x04,
+ "GL_LINE_TO_CHROMIUM",
+ },
+ {
0x0BE2,
"GL_BLEND",
},
@@ -1949,10 +1993,18 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_LINEARLIGHT_NV",
},
{
+ 0x00,
+ "GL_CLOSE_PATH_CHROMIUM",
+ },
+ {
0x8DCF,
"GL_INT_SAMPLER_2D_ARRAY",
},
{
+ 0x02,
+ "GL_MOVE_TO_CHROMIUM",
+ },
+ {
0x886A,
"GL_VERTEX_ATTRIB_ARRAY_NORMALIZED",
},
@@ -1961,10 +2013,22 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_SRGB8_NV",
},
{
+ 0x9079,
+ "GL_PATH_JOIN_STYLE_CHROMIUM",
+ },
+ {
0x0C01,
"GL_DRAW_BUFFER_EXT",
},
{
+ 0x9075,
+ "GL_PATH_STROKE_WIDTH_CHROMIUM",
+ },
+ {
+ 0x9076,
+ "GL_PATH_END_CAPS_CHROMIUM",
+ },
+ {
0x886C,
"GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT",
},
@@ -2477,8 +2541,8 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_TEXTURE10",
},
{
- 0x0BA7,
- "GL_PATH_PROJECTION_MATRIX_CHROMIUM",
+ 0x78F1,
+ "GL_MAP_CHROMIUM",
},
{
0x84CF,
@@ -3057,6 +3121,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_TEXTURE4",
},
{
+ 0x1A,
+ "GL_CONIC_CURVE_TO_CHROMIUM",
+ },
+ {
0x821C,
"GL_MINOR_VERSION",
},
@@ -3261,6 +3329,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_UNSIGNED_INT_VEC3",
},
{
+ 0x90A6,
+ "GL_BEVEL_CHROMIUM",
+ },
+ {
0x1701,
"GL_PATH_PROJECTION_CHROMIUM",
},
@@ -3393,6 +3465,14 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_BUFFER_MAP_OFFSET",
},
{
+ 0x9089,
+ "GL_COUNT_DOWN_CHROMIUM",
+ },
+ {
+ 0x9088,
+ "GL_COUNT_UP_CHROMIUM",
+ },
+ {
0x00004000,
"GL_COLOR_BUFFER_BIT",
},
@@ -3473,6 +3553,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_FENCE_STATUS_NV",
},
{
+ 0x908D,
+ "GL_BOUNDING_BOX_CHROMIUM",
+ },
+ {
0x88E6,
"GL_STATIC_COPY",
},
@@ -3589,6 +3673,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_UNIFORM_BUFFER_SIZE",
},
{
+ 0x0BA7,
+ "GL_PATH_PROJECTION_MATRIX_CHROMIUM",
+ },
+ {
0x0DE1,
"GL_TEXTURE_2D",
},
@@ -3677,6 +3765,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_R8UI",
},
{
+ 0x90A4,
+ "GL_ROUND_CHROMIUM",
+ },
+ {
0x150A,
"GL_INVERT",
},
@@ -4141,10 +4233,18 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_VERTEX_ATTRIB_ARRAY_SIZE",
},
{
+ 0x9086,
+ "GL_PATH_STROKE_BOUND_CHROMIUM",
+ },
+ {
0x8DB9,
"GL_FRAMEBUFFER_SRGB_EXT",
},
{
+ 0x907a,
+ "GL_PATH_MITER_LIMIT_CHROMIUM",
+ },
+ {
0x9307,
"GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT",
},
@@ -4373,10 +4473,6 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
"GL_WRITEONLY_RENDERING_QCOM",
},
{
- 0x78F1,
- "GL_MAP_CHROMIUM",
- },
- {
0x8824,
"GL_MAX_DRAW_BUFFERS_EXT",
},
@@ -5034,6 +5130,49 @@ std::string GLES2Util::GetStringMatrixMode(uint32_t value) {
arraysize(string_table), value);
}
+std::string GLES2Util::GetStringPathCoordType(uint32_t value) {
+ static const EnumToString string_table[] = {
+ {GL_BYTE, "GL_BYTE"},
+ {GL_UNSIGNED_BYTE, "GL_UNSIGNED_BYTE"},
+ {GL_SHORT, "GL_SHORT"},
+ {GL_UNSIGNED_SHORT, "GL_UNSIGNED_SHORT"},
+ {GL_FLOAT, "GL_FLOAT"},
+ };
+ return GLES2Util::GetQualifiedEnumString(string_table,
+ arraysize(string_table), value);
+}
+
+std::string GLES2Util::GetStringPathCoverMode(uint32_t value) {
+ static const EnumToString string_table[] = {
+ {GL_CONVEX_HULL_CHROMIUM, "GL_CONVEX_HULL_CHROMIUM"},
+ {GL_BOUNDING_BOX_CHROMIUM, "GL_BOUNDING_BOX_CHROMIUM"},
+ };
+ return GLES2Util::GetQualifiedEnumString(string_table,
+ arraysize(string_table), value);
+}
+
+std::string GLES2Util::GetStringPathFillMode(uint32_t value) {
+ static const EnumToString string_table[] = {
+ {GL_INVERT, "GL_INVERT"},
+ {GL_COUNT_UP_CHROMIUM, "GL_COUNT_UP_CHROMIUM"},
+ {GL_COUNT_DOWN_CHROMIUM, "GL_COUNT_DOWN_CHROMIUM"},
+ };
+ return GLES2Util::GetQualifiedEnumString(string_table,
+ arraysize(string_table), value);
+}
+
+std::string GLES2Util::GetStringPathParameter(uint32_t value) {
+ static const EnumToString string_table[] = {
+ {GL_PATH_STROKE_WIDTH_CHROMIUM, "GL_PATH_STROKE_WIDTH_CHROMIUM"},
+ {GL_PATH_END_CAPS_CHROMIUM, "GL_PATH_END_CAPS_CHROMIUM"},
+ {GL_PATH_JOIN_STYLE_CHROMIUM, "GL_PATH_JOIN_STYLE_CHROMIUM"},
+ {GL_PATH_MITER_LIMIT_CHROMIUM, "GL_PATH_MITER_LIMIT_CHROMIUM"},
+ {GL_PATH_STROKE_BOUND_CHROMIUM, "GL_PATH_STROKE_BOUND_CHROMIUM"},
+ };
+ return GLES2Util::GetQualifiedEnumString(string_table,
+ arraysize(string_table), value);
+}
+
std::string GLES2Util::GetStringPixelStore(uint32_t value) {
static const EnumToString string_table[] = {
{GL_PACK_ALIGNMENT, "GL_PACK_ALIGNMENT"},
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index 14f2402..62fce76 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -100,6 +100,8 @@ source_set("service_sources") {
"mailbox_manager_sync.h",
"memory_program_cache.cc",
"memory_program_cache.h",
+ "path_manager.cc",
+ "path_manager.h",
"program_cache.cc",
"program_cache.h",
"program_manager.cc",
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index 4a82c56..1cc8f24 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -16,6 +16,7 @@
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "gpu/command_buffer/service/memory_tracking.h"
+#include "gpu/command_buffer/service/path_manager.h"
#include "gpu/command_buffer/service/program_manager.h"
#include "gpu/command_buffer/service/renderbuffer_manager.h"
#include "gpu/command_buffer/service/shader_manager.h"
@@ -294,6 +295,8 @@ bool ContextGroup::Initialize(
feature_info_->workarounds().max_vertex_uniform_vectors));
}
+ path_manager_.reset(new PathManager());
+
program_manager_.reset(new ProgramManager(
program_cache_, max_varying_vectors_));
@@ -365,6 +368,11 @@ void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) {
texture_manager_.reset();
}
+ if (path_manager_ != NULL) {
+ path_manager_->Destroy(have_context);
+ path_manager_.reset();
+ }
+
if (program_manager_ != NULL) {
program_manager_->Destroy(have_context);
program_manager_.reset();
diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h
index 466f918..32dbbf3 100644
--- a/gpu/command_buffer/service/context_group.h
+++ b/gpu/command_buffer/service/context_group.h
@@ -32,6 +32,7 @@ class GLES2Decoder;
class FramebufferManager;
class MailboxManager;
class RenderbufferManager;
+class PathManager;
class ProgramManager;
class ShaderManager;
class TextureManager;
@@ -153,6 +154,8 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> {
return texture_manager_.get();
}
+ PathManager* path_manager() const { return path_manager_.get(); }
+
ProgramManager* program_manager() const {
return program_manager_.get();
}
@@ -291,6 +294,8 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> {
scoped_ptr<TextureManager> texture_manager_;
+ scoped_ptr<PathManager> path_manager_;
+
scoped_ptr<ProgramManager> program_manager_;
scoped_ptr<ShaderManager> shader_manager_;
diff --git a/gpu/command_buffer/service/context_state_autogen.h b/gpu/command_buffer/service/context_state_autogen.h
index e2b65bf..7ca2faa 100644
--- a/gpu/command_buffer/service/context_state_autogen.h
+++ b/gpu/command_buffer/service/context_state_autogen.h
@@ -74,6 +74,9 @@ GLenum hint_fragment_shader_derivative;
GLfloat line_width;
GLfloat modelview_matrix[16];
GLfloat projection_matrix[16];
+GLenum stencil_path_func;
+GLint stencil_path_ref;
+GLuint stencil_path_mask;
GLint pack_alignment;
GLint unpack_alignment;
GLfloat polygon_offset_factor;
diff --git a/gpu/command_buffer/service/context_state_impl_autogen.h b/gpu/command_buffer/service/context_state_impl_autogen.h
index fa5462f..2dde530 100644
--- a/gpu/command_buffer/service/context_state_impl_autogen.h
+++ b/gpu/command_buffer/service/context_state_impl_autogen.h
@@ -104,6 +104,9 @@ void ContextState::Initialize() {
projection_matrix[13] = 0.0f;
projection_matrix[14] = 0.0f;
projection_matrix[15] = 1.0f;
+ stencil_path_func = GL_ALWAYS;
+ stencil_path_ref = 0;
+ stencil_path_mask = 0xFFFFFFFFU;
pack_alignment = 4;
unpack_alignment = 4;
polygon_offset_factor = 0.0f;
@@ -276,6 +279,12 @@ void ContextState::InitState(const ContextState* prev_state) const {
glMatrixLoadfEXT(GL_PATH_PROJECTION_CHROMIUM, projection_matrix);
}
}
+ if (feature_info_->feature_flags().chromium_path_rendering)
+ if ((stencil_path_func != prev_state->stencil_path_func) ||
+ (stencil_path_ref != prev_state->stencil_path_ref) ||
+ (stencil_path_mask != prev_state->stencil_path_mask))
+ glPathStencilFuncNV(stencil_path_func, stencil_path_ref,
+ stencil_path_mask);
if (prev_state->pack_alignment != pack_alignment) {
glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment);
}
@@ -355,6 +364,9 @@ void ContextState::InitState(const ContextState* prev_state) const {
if (feature_info_->feature_flags().chromium_path_rendering) {
glMatrixLoadfEXT(GL_PATH_PROJECTION_CHROMIUM, projection_matrix);
}
+ if (feature_info_->feature_flags().chromium_path_rendering)
+ glPathStencilFuncNV(stencil_path_func, stencil_path_ref,
+ stencil_path_mask);
glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment);
glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment);
glPolygonOffset(polygon_offset_factor, polygon_offset_units);
@@ -547,6 +559,24 @@ bool ContextState::GetStateAsGLint(GLenum pname,
}
}
return true;
+ case GL_PATH_STENCIL_FUNC_CHROMIUM:
+ *num_written = 1;
+ if (params) {
+ params[0] = static_cast<GLint>(stencil_path_func);
+ }
+ return true;
+ case GL_PATH_STENCIL_REF_CHROMIUM:
+ *num_written = 1;
+ if (params) {
+ params[0] = static_cast<GLint>(stencil_path_ref);
+ }
+ return true;
+ case GL_PATH_STENCIL_VALUE_MASK_CHROMIUM:
+ *num_written = 1;
+ if (params) {
+ params[0] = static_cast<GLint>(stencil_path_mask);
+ }
+ return true;
case GL_PACK_ALIGNMENT:
*num_written = 1;
if (params) {
@@ -897,6 +927,24 @@ bool ContextState::GetStateAsGLfloat(GLenum pname,
memcpy(params, projection_matrix, sizeof(GLfloat) * 16);
}
return true;
+ case GL_PATH_STENCIL_FUNC_CHROMIUM:
+ *num_written = 1;
+ if (params) {
+ params[0] = static_cast<GLfloat>(stencil_path_func);
+ }
+ return true;
+ case GL_PATH_STENCIL_REF_CHROMIUM:
+ *num_written = 1;
+ if (params) {
+ params[0] = static_cast<GLfloat>(stencil_path_ref);
+ }
+ return true;
+ case GL_PATH_STENCIL_VALUE_MASK_CHROMIUM:
+ *num_written = 1;
+ if (params) {
+ params[0] = static_cast<GLfloat>(stencil_path_mask);
+ }
+ return true;
case GL_PACK_ALIGNMENT:
*num_written = 1;
if (params) {
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 0ce9980..8caf05c 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -209,6 +209,9 @@ void FeatureInfo::InitializeBasicState(const base::CommandLine& command_line) {
enable_unsafe_es3_apis_switch_ =
command_line.HasSwitch(switches::kEnableUnsafeES3APIs);
+ enable_gl_path_rendering_switch_ =
+ command_line.HasSwitch(switches::kEnableGLPathRendering);
+
unsafe_es3_apis_enabled_ = false;
}
@@ -1004,14 +1007,18 @@ void FeatureInfo::InitializeFeatures() {
}
}
- if (extensions.Contains("GL_NV_path_rendering")) {
- if (extensions.Contains("GL_EXT_direct_state_access") ||
- gl_version_info_->is_es3) {
- AddExtensionString("GL_CHROMIUM_path_rendering");
- feature_flags_.chromium_path_rendering = true;
- validators_.g_l_state.AddValue(GL_PATH_MODELVIEW_MATRIX_CHROMIUM);
- validators_.g_l_state.AddValue(GL_PATH_PROJECTION_MATRIX_CHROMIUM);
- }
+ if (enable_gl_path_rendering_switch_ &&
+ !workarounds_.disable_gl_path_rendering &&
+ extensions.Contains("GL_NV_path_rendering") &&
+ (extensions.Contains("GL_EXT_direct_state_access") ||
+ gl_version_info_->is_es3)) {
+ AddExtensionString("GL_CHROMIUM_path_rendering");
+ feature_flags_.chromium_path_rendering = true;
+ validators_.g_l_state.AddValue(GL_PATH_MODELVIEW_MATRIX_CHROMIUM);
+ validators_.g_l_state.AddValue(GL_PATH_PROJECTION_MATRIX_CHROMIUM);
+ validators_.g_l_state.AddValue(GL_PATH_STENCIL_FUNC_CHROMIUM);
+ validators_.g_l_state.AddValue(GL_PATH_STENCIL_REF_CHROMIUM);
+ validators_.g_l_state.AddValue(GL_PATH_STENCIL_VALUE_MASK_CHROMIUM);
}
if ((gl_version_info_->is_es3 || gl_version_info_->is_desktop_core_profile ||
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h
index 1ebff2a..aa9c0ba 100644
--- a/gpu/command_buffer/service/feature_info.h
+++ b/gpu/command_buffer/service/feature_info.h
@@ -164,6 +164,9 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> {
bool unsafe_es3_apis_enabled_;
+ // Whether the command line switch kEnableGLPathRendering is passed in.
+ bool enable_gl_path_rendering_switch_;
+
scoped_ptr<gfx::GLVersionInfo> gl_version_info_;
DISALLOW_COPY_AND_ASSIGN(FeatureInfo);
diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc
index fdff175..8321e68 100644
--- a/gpu/command_buffer/service/feature_info_unittest.cc
+++ b/gpu/command_buffer/service/feature_info_unittest.cc
@@ -8,6 +8,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "gpu/command_buffer/service/gpu_service_test.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/test_helper.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
@@ -77,6 +78,18 @@ class FeatureInfoTest
info_->Initialize();
}
+ void SetupInitExpectationsWithGLVersionAndCommandLine(
+ const char* extensions,
+ const char* renderer,
+ const char* version,
+ const base::CommandLine& command_line) {
+ GpuServiceTest::SetUpWithGLVersion(version, extensions);
+ TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(
+ gl_.get(), extensions, renderer, version);
+ info_ = new FeatureInfo(command_line);
+ info_->Initialize();
+ }
+
void SetupWithCommandLine(const base::CommandLine& command_line) {
GpuServiceTest::SetUp();
info_ = new FeatureInfo(command_line);
@@ -1191,31 +1204,49 @@ TEST_P(FeatureInfoTest, BlendEquationAdvancedDisabled) {
EXPECT_FALSE(info_->feature_flags().blend_equation_advanced_coherent);
}
-TEST_P(FeatureInfoTest, InitializeCHROMIUM_path_rendering) {
+TEST_P(FeatureInfoTest, InitializeCHROMIUM_path_rendering_no_cmdline_switch) {
SetupInitExpectationsWithGLVersion(
"GL_ARB_compatibility GL_NV_path_rendering GL_EXT_direct_state_access",
"", "4.3");
+ EXPECT_FALSE(info_->feature_flags().chromium_path_rendering);
+ EXPECT_THAT(info_->extensions(),
+ Not(HasSubstr("GL_CHROMIUM_path_rendering")));
+}
+
+TEST_P(FeatureInfoTest, InitializeCHROMIUM_path_rendering) {
+ base::CommandLine command_line(0, NULL);
+ command_line.AppendSwitch(switches::kEnableGLPathRendering);
+ SetupInitExpectationsWithGLVersionAndCommandLine(
+ "GL_ARB_compatibility GL_NV_path_rendering GL_EXT_direct_state_access",
+ "", "4.3", command_line);
EXPECT_TRUE(info_->feature_flags().chromium_path_rendering);
EXPECT_THAT(info_->extensions(), HasSubstr("GL_CHROMIUM_path_rendering"));
}
TEST_P(FeatureInfoTest, InitializeCHROMIUM_path_rendering2) {
- SetupInitExpectationsWithGLVersion(
- "GL_NV_path_rendering", "", "OpenGL ES 3.1");
+ base::CommandLine command_line(0, NULL);
+ command_line.AppendSwitch(switches::kEnableGLPathRendering);
+ SetupInitExpectationsWithGLVersionAndCommandLine(
+ "GL_NV_path_rendering", "", "OpenGL ES 3.1", command_line);
EXPECT_TRUE(info_->feature_flags().chromium_path_rendering);
EXPECT_THAT(info_->extensions(), HasSubstr("GL_CHROMIUM_path_rendering"));
}
TEST_P(FeatureInfoTest, InitializeNoCHROMIUM_path_rendering) {
- SetupInitExpectationsWithGLVersion("GL_ARB_compatibility", "", "4.3");
+ base::CommandLine command_line(0, NULL);
+ command_line.AppendSwitch(switches::kEnableGLPathRendering);
+ SetupInitExpectationsWithGLVersionAndCommandLine("GL_ARB_compatibility", "",
+ "4.3", command_line);
EXPECT_FALSE(info_->feature_flags().chromium_path_rendering);
EXPECT_THAT(info_->extensions(),
Not(HasSubstr("GL_CHROMIUM_path_rendering")));
}
TEST_P(FeatureInfoTest, InitializeNoCHROMIUM_path_rendering2) {
- SetupInitExpectationsWithGLVersion(
- "GL_ARB_compatibility GL_NV_path_rendering", "", "4.3");
+ base::CommandLine command_line(0, NULL);
+ command_line.AppendSwitch(switches::kEnableGLPathRendering);
+ SetupInitExpectationsWithGLVersionAndCommandLine(
+ "GL_ARB_compatibility GL_NV_path_rendering", "", "4.3", command_line);
EXPECT_FALSE(info_->feature_flags().chromium_path_rendering);
EXPECT_THAT(info_->extensions(),
Not(HasSubstr("GL_CHROMIUM_path_rendering")));
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 4e35d55..3f70846 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -47,6 +47,7 @@
#include "gpu/command_buffer/service/logger.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/memory_tracking.h"
+#include "gpu/command_buffer/service/path_manager.h"
#include "gpu/command_buffer/service/program_manager.h"
#include "gpu/command_buffer/service/query_manager.h"
#include "gpu/command_buffer/service/renderbuffer_manager.h"
@@ -791,6 +792,8 @@ class GLES2DecoderImpl : public GLES2Decoder,
void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
+ bool GenPathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
+ bool DeletePathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
// Helper for async upload token completion notification callback.
base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
@@ -823,6 +826,8 @@ class GLES2DecoderImpl : public GLES2Decoder,
return group_->valuebuffer_manager();
}
+ PathManager* path_manager() { return group_->path_manager(); }
+
ProgramManager* program_manager() {
return group_->program_manager();
}
@@ -1563,6 +1568,7 @@ class GLES2DecoderImpl : public GLES2Decoder,
bool DoIsShader(GLuint client_id);
bool DoIsTexture(GLuint client_id);
bool DoIsVertexArrayOES(GLuint client_id);
+ bool DoIsPathCHROMIUM(GLuint client_id);
// Wrapper for glLinkProgram
void DoLinkProgram(GLuint program);
@@ -3350,6 +3356,42 @@ bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
return true;
}
+bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id,
+ GLsizei range) {
+ GLuint last_client_id;
+ if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
+ return false;
+
+ if (path_manager()->HasPathsInRange(first_client_id, last_client_id))
+ return false;
+
+ GLuint first_service_id = glGenPathsNV(range);
+ if (first_service_id == 0) {
+ // We have to fail the connection here, because client has already
+ // succeeded in allocating the ids. This happens if we allocate
+ // the whole path id space (two allocations of 0x7FFFFFFF paths, for
+ // example).
+ return false;
+ }
+ // GenPathsNV does not wrap.
+ DCHECK(first_service_id + range - 1 >= first_service_id);
+
+ path_manager()->CreatePathRange(first_client_id, last_client_id,
+ first_service_id);
+
+ return true;
+}
+
+bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id,
+ GLsizei range) {
+ GLuint last_client_id;
+ if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
+ return false;
+
+ path_manager()->RemovePaths(first_client_id, last_client_id);
+ return true;
+}
+
void GLES2DecoderImpl::DeleteBuffersHelper(
GLsizei n, const GLuint* client_ids) {
for (GLsizei ii = 0; ii < n; ++ii) {
@@ -11748,6 +11790,12 @@ bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
return vao && vao->IsValid() && !vao->IsDeleted();
}
+bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id) {
+ GLuint service_id = 0;
+ return path_manager()->GetPath(client_id, &service_id) &&
+ glIsPathNV(service_id) == GL_TRUE;
+}
+
#if defined(OS_MACOSX)
void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
@@ -13833,6 +13881,455 @@ void GLES2DecoderImpl::OnOutOfMemoryError() {
}
}
+error::Error GLES2DecoderImpl::HandleGenPathsCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ static const char kFunctionName[] = "glGenPathsCHROMIUM";
+ const gles2::cmds::GenPathsCHROMIUM& c =
+ *static_cast<const gles2::cmds::GenPathsCHROMIUM*>(cmd_data);
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "function not available");
+ return error::kNoError;
+ }
+
+ GLsizei range = static_cast<GLsizei>(c.range);
+ if (range < 0) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
+ return error::kNoError;
+ }
+
+ GLuint first_client_id = static_cast<GLuint>(c.first_client_id);
+ if (first_client_id == 0)
+ return error::kInvalidArguments;
+
+ if (range == 0)
+ return error::kNoError;
+
+ if (!GenPathsCHROMIUMHelper(first_client_id, range))
+ return error::kInvalidArguments;
+
+ return error::kNoError;
+}
+error::Error GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
+ uint32_t immediate_data_size,
+ const void* cmd_data) {
+ static const char kFunctionName[] = "glDeletePathsCHROMIUM";
+ const gles2::cmds::DeletePathsCHROMIUM& c =
+ *static_cast<const gles2::cmds::DeletePathsCHROMIUM*>(cmd_data);
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "function not available");
+ return error::kNoError;
+ }
+
+ GLsizei range = static_cast<GLsizei>(c.range);
+ if (range < 0) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
+ return error::kNoError;
+ }
+
+ if (range == 0)
+ return error::kNoError;
+
+ GLuint first_client_id = c.first_client_id;
+ // first_client_id can be 0, because non-existing path ids are skipped.
+
+ if (!DeletePathsCHROMIUMHelper(first_client_id, range))
+ return error::kInvalidArguments;
+
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ static const char kFunctionName[] = "glPathCommandsCHROMIUM";
+ const gles2::cmds::PathCommandsCHROMIUM& c =
+ *static_cast<const gles2::cmds::PathCommandsCHROMIUM*>(cmd_data);
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "function not available");
+ return error::kNoError;
+ }
+
+ GLuint service_id = 0;
+ if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "invalid path name");
+ return error::kNoError;
+ }
+
+ GLsizei num_commands = static_cast<GLsizei>(c.numCommands);
+ if (num_commands < 0) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCommands < 0");
+ return error::kNoError;
+ }
+
+ GLsizei num_coords = static_cast<uint32>(c.numCoords);
+ if (num_coords < 0) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCoords < 0");
+ return error::kNoError;
+ }
+
+ GLenum coord_type = static_cast<uint32>(c.coordType);
+ if (!validators_->path_coord_type.IsValid(static_cast<GLint>(coord_type))) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid coordType");
+ return error::kNoError;
+ }
+
+ const GLubyte* commands = NULL;
+ base::CheckedNumeric<GLsizei> num_coords_expected = 0;
+
+ if (num_commands > 0) {
+ uint32 commands_shm_id = static_cast<uint32>(c.commands_shm_id);
+ uint32 commands_shm_offset = static_cast<uint32>(c.commands_shm_offset);
+ if (commands_shm_id != 0 || commands_shm_offset != 0)
+ commands = GetSharedMemoryAs<const GLubyte*>(
+ commands_shm_id, commands_shm_offset, num_commands);
+
+ if (!commands)
+ return error::kOutOfBounds;
+
+ for (GLsizei i = 0; i < num_commands; ++i) {
+ switch (commands[i]) {
+ case GL_CLOSE_PATH_CHROMIUM:
+ // Close has no coords.
+ break;
+ case GL_MOVE_TO_CHROMIUM:
+ // Fallthrough.
+ case GL_LINE_TO_CHROMIUM:
+ num_coords_expected += 2;
+ break;
+ case GL_QUADRATIC_CURVE_TO_CHROMIUM:
+ num_coords_expected += 4;
+ break;
+ case GL_CUBIC_CURVE_TO_CHROMIUM:
+ num_coords_expected += 6;
+ break;
+ case GL_CONIC_CURVE_TO_CHROMIUM:
+ num_coords_expected += 5;
+ break;
+ default:
+ LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid command");
+ return error::kNoError;
+ }
+ }
+ }
+
+ if (!num_coords_expected.IsValid() ||
+ num_coords != num_coords_expected.ValueOrDie()) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "numCoords does not match commands");
+ return error::kNoError;
+ }
+
+ const void* coords = NULL;
+
+ if (num_coords > 0) {
+ uint32 coords_size = 0;
+ uint32 coord_type_size =
+ GLES2Util::GetGLTypeSizeForPathCoordType(coord_type);
+ if (!SafeMultiplyUint32(num_coords, coord_type_size, &coords_size))
+ return error::kOutOfBounds;
+
+ uint32 coords_shm_id = static_cast<uint32>(c.coords_shm_id);
+ uint32 coords_shm_offset = static_cast<uint32>(c.coords_shm_offset);
+ if (coords_shm_id != 0 || coords_shm_offset != 0)
+ coords = GetSharedMemoryAs<const void*>(coords_shm_id, coords_shm_offset,
+ coords_size);
+
+ if (!coords)
+ return error::kOutOfBounds;
+ }
+
+ glPathCommandsNV(service_id, num_commands, commands, num_coords, coord_type,
+ coords);
+
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ static const char kFunctionName[] = "glPathParameterfCHROMIUM";
+ const gles2::cmds::PathParameterfCHROMIUM& c =
+ *static_cast<const gles2::cmds::PathParameterfCHROMIUM*>(cmd_data);
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "function not available");
+ return error::kNoError;
+ }
+ GLuint service_id = 0;
+ if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "invalid path name");
+ return error::kNoError;
+ }
+
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLfloat value = static_cast<GLfloat>(c.value);
+ bool hasValueError = false;
+
+ switch (pname) {
+ case GL_PATH_STROKE_WIDTH_CHROMIUM:
+ case GL_PATH_MITER_LIMIT_CHROMIUM:
+ hasValueError = std::isnan(value) || !std::isfinite(value) || value < 0;
+ break;
+ case GL_PATH_STROKE_BOUND_CHROMIUM:
+ value = std::max(std::min(1.0f, value), 0.0f);
+ break;
+ case GL_PATH_END_CAPS_CHROMIUM:
+ hasValueError = !validators_->path_parameter_cap_values.IsValid(
+ static_cast<GLint>(value));
+ break;
+ case GL_PATH_JOIN_STYLE_CHROMIUM:
+ hasValueError = !validators_->path_parameter_join_values.IsValid(
+ static_cast<GLint>(value));
+ break;
+ default:
+ DCHECK(!validators_->path_parameter.IsValid(pname));
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
+ return error::kNoError;
+ }
+ DCHECK(validators_->path_parameter.IsValid(pname));
+
+ if (hasValueError) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
+ return error::kNoError;
+ }
+
+ glPathParameterfNV(service_id, pname, value);
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ static const char kFunctionName[] = "glPathParameteriCHROMIUM";
+ const gles2::cmds::PathParameteriCHROMIUM& c =
+ *static_cast<const gles2::cmds::PathParameteriCHROMIUM*>(cmd_data);
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "function not available");
+ return error::kNoError;
+ }
+ GLuint service_id = 0;
+ if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "invalid path name");
+ return error::kNoError;
+ }
+
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLint value = static_cast<GLint>(c.value);
+ bool hasValueError = false;
+
+ switch (pname) {
+ case GL_PATH_STROKE_WIDTH_CHROMIUM:
+ case GL_PATH_MITER_LIMIT_CHROMIUM:
+ hasValueError = value < 0;
+ break;
+ case GL_PATH_STROKE_BOUND_CHROMIUM:
+ value = std::max(std::min(1, value), 0);
+ break;
+ case GL_PATH_END_CAPS_CHROMIUM:
+ hasValueError = !validators_->path_parameter_cap_values.IsValid(value);
+ break;
+ case GL_PATH_JOIN_STYLE_CHROMIUM:
+ hasValueError = !validators_->path_parameter_join_values.IsValid(value);
+ break;
+ default:
+ DCHECK(!validators_->path_parameter.IsValid(pname));
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
+ return error::kNoError;
+ }
+ DCHECK(validators_->path_parameter.IsValid(pname));
+
+ if (hasValueError) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
+ return error::kNoError;
+ }
+
+ glPathParameteriNV(service_id, pname, value);
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ static const char kFunctionName[] = "glStencilFillPathCHROMIUM";
+ const gles2::cmds::StencilFillPathCHROMIUM& c =
+ *static_cast<const gles2::cmds::StencilFillPathCHROMIUM*>(cmd_data);
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "function not available");
+ return error::kNoError;
+ }
+ GLenum fill_mode = static_cast<GLenum>(c.fillMode);
+ if (!validators_->path_fill_mode.IsValid(fill_mode)) {
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
+ return error::kNoError;
+ }
+ GLuint mask = static_cast<GLuint>(c.mask);
+ if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
+ fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
+ GLES2Util::IsNPOT(mask + 1)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
+ "mask + 1 is not power of two");
+ return error::kNoError;
+ }
+ GLuint service_id = 0;
+ if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
+ // "If /path/ does not name an existing path object, the command does
+ // nothing (and no error is generated)."
+ // This holds for other rendering functions, too.
+ return error::kNoError;
+ }
+ ApplyDirtyState();
+ glStencilFillPathNV(service_id, fill_mode, mask);
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ static const char kFunctionName[] = "glStencilStrokePathCHROMIUM";
+ const gles2::cmds::StencilStrokePathCHROMIUM& c =
+ *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM*>(cmd_data);
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "function not available");
+ return error::kNoError;
+ }
+ GLuint service_id = 0;
+ if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
+ return error::kNoError;
+ }
+ GLint reference = static_cast<GLint>(c.reference);
+ GLuint mask = static_cast<GLuint>(c.mask);
+ ApplyDirtyState();
+ glStencilStrokePathNV(service_id, reference, mask);
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ static const char kFunctionName[] = "glCoverFillPathCHROMIUM";
+ const gles2::cmds::CoverFillPathCHROMIUM& c =
+ *static_cast<const gles2::cmds::CoverFillPathCHROMIUM*>(cmd_data);
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "function not available");
+ return error::kNoError;
+ }
+ GLenum cover_mode = static_cast<GLenum>(c.coverMode);
+ if (!validators_->path_cover_mode.IsValid(cover_mode)) {
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
+ return error::kNoError;
+ }
+ GLuint service_id = 0;
+ if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
+ return error::kNoError;
+
+ ApplyDirtyState();
+ glCoverFillPathNV(service_id, cover_mode);
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ static const char kFunctionName[] = "glCoverStrokePathCHROMIUM";
+ const gles2::cmds::CoverStrokePathCHROMIUM& c =
+ *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM*>(cmd_data);
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "function not available");
+ return error::kNoError;
+ }
+ GLenum cover_mode = static_cast<GLenum>(c.coverMode);
+ if (!validators_->path_cover_mode.IsValid(cover_mode)) {
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
+ return error::kNoError;
+ }
+ GLuint service_id = 0;
+ if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
+ return error::kNoError;
+
+ ApplyDirtyState();
+ glCoverStrokePathNV(service_id, cover_mode);
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ static const char kFunctionName[] = "glStencilThenCoverFillPathCHROMIUM";
+ const gles2::cmds::StencilThenCoverFillPathCHROMIUM& c =
+ *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM*>(
+ cmd_data);
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "function not available");
+ return error::kNoError;
+ }
+ GLenum fill_mode = static_cast<GLenum>(c.fillMode);
+ if (!validators_->path_fill_mode.IsValid(fill_mode)) {
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
+ return error::kNoError;
+ }
+ GLuint mask = static_cast<GLuint>(c.mask);
+ if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
+ fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
+ GLES2Util::IsNPOT(mask + 1)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
+ "mask + 1 is not power of two");
+ return error::kNoError;
+ }
+ GLenum cover_mode = static_cast<GLenum>(c.coverMode);
+ if (!validators_->path_cover_mode.IsValid(cover_mode)) {
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
+ return error::kNoError;
+ }
+ GLuint service_id = 0;
+ if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
+ return error::kNoError;
+
+ ApplyDirtyState();
+ glStencilThenCoverFillPathNV(service_id, fill_mode, mask, cover_mode);
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ static const char kFunctionName[] = "glStencilThenCoverStrokePathCHROMIUM";
+ const gles2::cmds::StencilThenCoverStrokePathCHROMIUM& c =
+ *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM*>(
+ cmd_data);
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "function not available");
+ return error::kNoError;
+ }
+ GLenum cover_mode = static_cast<GLenum>(c.coverMode);
+ if (!validators_->path_cover_mode.IsValid(cover_mode)) {
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
+ return error::kNoError;
+ }
+ GLuint service_id = 0;
+ if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
+ return error::kNoError;
+
+ GLint reference = static_cast<GLint>(c.reference);
+ GLuint mask = static_cast<GLuint>(c.mask);
+ ApplyDirtyState();
+ glStencilThenCoverStrokePathNV(service_id, reference, mask, cover_mode);
+ return error::kNoError;
+}
+
// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 1314d0d..615d287 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -4946,6 +4946,58 @@ error::Error GLES2DecoderImpl::HandleMatrixLoadIdentityCHROMIUM(
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleIsPathCHROMIUM(
+ uint32_t immediate_data_size,
+ const void* cmd_data) {
+ const gles2::cmds::IsPathCHROMIUM& c =
+ *static_cast<const gles2::cmds::IsPathCHROMIUM*>(cmd_data);
+ (void)c;
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glIsPathCHROMIUM",
+ "function not available");
+ return error::kNoError;
+ }
+
+ GLuint path = c.path;
+ typedef cmds::IsPathCHROMIUM::Result Result;
+ Result* result_dst = GetSharedMemoryAs<Result*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+ if (!result_dst) {
+ return error::kOutOfBounds;
+ }
+ *result_dst = DoIsPathCHROMIUM(path);
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandlePathStencilFuncCHROMIUM(
+ uint32_t immediate_data_size,
+ const void* cmd_data) {
+ const gles2::cmds::PathStencilFuncCHROMIUM& c =
+ *static_cast<const gles2::cmds::PathStencilFuncCHROMIUM*>(cmd_data);
+ (void)c;
+ if (!features().chromium_path_rendering) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glPathStencilFuncCHROMIUM",
+ "function not available");
+ return error::kNoError;
+ }
+
+ GLenum func = static_cast<GLenum>(c.func);
+ GLint ref = static_cast<GLint>(c.ref);
+ GLuint mask = static_cast<GLuint>(c.mask);
+ if (!validators_->cmp_function.IsValid(func)) {
+ LOCAL_SET_GL_ERROR_INVALID_ENUM("glPathStencilFuncCHROMIUM", func, "func");
+ return error::kNoError;
+ }
+ if (state_.stencil_path_func != func || state_.stencil_path_ref != ref ||
+ state_.stencil_path_mask != mask) {
+ state_.stencil_path_func = func;
+ state_.stencil_path_ref = ref;
+ state_.stencil_path_mask = mask;
+ glPathStencilFuncNV(func, ref, mask);
+ }
+ return error::kNoError;
+}
+
error::Error GLES2DecoderImpl::HandleBlendBarrierKHR(
uint32_t immediate_data_size,
const void* cmd_data) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
index 1620423..dd11716 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
@@ -71,6 +71,11 @@ void GLES2DecoderTestBase::SetupInitStateExpectations() {
.Times(1)
.RetiresOnSaturation();
}
+ if (group_->feature_info()->feature_flags().chromium_path_rendering) {
+ EXPECT_CALL(*gl_, PathStencilFuncNV(GL_ALWAYS, 0, 0xFFFFFFFFU))
+ .Times(1)
+ .RetiresOnSaturation();
+ }
EXPECT_CALL(*gl_, PixelStorei(GL_PACK_ALIGNMENT, 4))
.Times(1)
.RetiresOnSaturation();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_4_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_4_autogen.h
new file mode 100644
index 0000000..9abba52
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_4_autogen.h
@@ -0,0 +1,15 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is auto-generated from
+// gpu/command_buffer/build_gles2_cmd_buffer.py
+// It's formatted by clang-format using chromium coding style:
+// clang-format -i -style=chromium filename
+// DO NOT EDIT!
+
+// It is included by gles2_cmd_decoder_unittest_4.cc
+#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_4_AUTOGEN_H_
+#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_4_AUTOGEN_H_
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_4_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
index f87a4bd..916f2aa 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
@@ -4,21 +4,134 @@
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "base/command_line.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_mock.h"
using ::gfx::MockGLInterface;
using ::testing::_;
+using ::testing::Return;
namespace gpu {
namespace gles2 {
+// Class to use to test that functions which need feature flags or
+// extensions always return INVALID_OPERATION if the feature flags is not
+// enabled or extension is not present.
+class GLES2DecoderTestDisabledExtensions : public GLES2DecoderTest {
+ public:
+ GLES2DecoderTestDisabledExtensions() {}
+};
+INSTANTIATE_TEST_CASE_P(Service,
+ GLES2DecoderTestDisabledExtensions,
+ ::testing::Bool());
+
+TEST_P(GLES2DecoderTestDisabledExtensions, CHROMIUMPathRenderingDisabled) {
+ const GLuint kClientPathId = 0;
+ {
+ cmds::MatrixLoadfCHROMIUMImmediate& cmd =
+ *GetImmediateAs<cmds::MatrixLoadfCHROMIUMImmediate>();
+ GLfloat temp[16] = {
+ 0,
+ };
+ cmd.Init(GL_PATH_MODELVIEW_CHROMIUM, temp);
+ EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::MatrixLoadIdentityCHROMIUM cmd;
+ cmd.Init(GL_PATH_PROJECTION_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::GenPathsCHROMIUM cmd;
+ cmd.Init(0, 0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::DeletePathsCHROMIUM cmd;
+ cmd.Init(0, 0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::IsPathCHROMIUM cmd;
+ cmd.Init(kClientPathId, shared_memory_id_, shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::PathCommandsCHROMIUM cmd;
+ cmd.Init(kClientPathId, 0, 0, 0, 0, GL_FLOAT, 0, 0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::PathParameterfCHROMIUM cmd;
+ cmd.Init(kClientPathId, GL_PATH_STROKE_WIDTH_CHROMIUM, 1.0f);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::PathParameteriCHROMIUM cmd;
+ cmd.Init(kClientPathId, GL_PATH_STROKE_WIDTH_CHROMIUM, 1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::PathStencilFuncCHROMIUM cmd;
+ cmd.Init(GL_NEVER, 2, 3);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::StencilFillPathCHROMIUM cmd;
+ cmd.Init(kClientPathId, GL_COUNT_UP_CHROMIUM, 1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::StencilStrokePathCHROMIUM cmd;
+ cmd.Init(kClientPathId, 1, 2);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::CoverFillPathCHROMIUM cmd;
+ cmd.Init(kClientPathId, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::CoverStrokePathCHROMIUM cmd;
+ cmd.Init(kClientPathId, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::StencilThenCoverFillPathCHROMIUM cmd;
+ cmd.Init(kClientPathId, GL_COUNT_UP_CHROMIUM, 1, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ cmds::StencilThenCoverStrokePathCHROMIUM cmd;
+ cmd.Init(kClientPathId, 1, 2, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+}
+
class GLES2DecoderTestWithCHROMIUMPathRendering : public GLES2DecoderTest {
public:
- GLES2DecoderTestWithCHROMIUMPathRendering() {}
+ GLES2DecoderTestWithCHROMIUMPathRendering() : client_path_id_(125) {}
+
void SetUp() override {
InitState init;
init.gl_version = "opengl es 3.1";
@@ -28,8 +141,24 @@ class GLES2DecoderTestWithCHROMIUMPathRendering : public GLES2DecoderTest {
init.request_depth = true;
init.bind_generates_resource = true;
init.extensions = "GL_NV_path_rendering";
- InitDecoder(init);
+ base::CommandLine command_line(0, NULL);
+ command_line.AppendSwitch(switches::kEnableGLPathRendering);
+ InitDecoderWithCommandLine(init, &command_line);
+
+ EXPECT_CALL(*gl_, GenPathsNV(1))
+ .WillOnce(Return(kServicePathId))
+ .RetiresOnSaturation();
+ cmds::GenPathsCHROMIUM cmd;
+ cmd.Init(client_path_id_, 1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
+
+ protected:
+ template <typename TypeParam>
+ void TestPathCommandsCHROMIUMCoordTypes();
+
+ GLuint client_path_id_;
+ static const GLuint kServicePathId = 311;
};
INSTANTIATE_TEST_CASE_P(Service,
@@ -56,6 +185,814 @@ INSTANTIATE_TEST_CASE_P(Service,
GLES2DecoderTestWithBlendEquationAdvanced,
::testing::Bool());
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, GenDeletePaths) {
+ static GLuint kFirstClientID = client_path_id_ + 88;
+ static GLsizei kPathCount = 58;
+ static GLuint kFirstCreatedServiceID = 8000;
+
+ // GenPaths range 0 causes no calls.
+ cmds::GenPathsCHROMIUM gen_cmd;
+ gen_cmd.Init(kFirstClientID, 0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // DeletePaths range 0 causes no calls.
+ cmds::DeletePathsCHROMIUM delete_cmd;
+ delete_cmd.Init(kFirstClientID, 0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // DeletePaths client 0 causes no calls and no errors.
+ delete_cmd.Init(0, 1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // DeletePaths with a big range should not cause any deletes.
+ delete_cmd.Init(client_path_id_ + 1,
+ std::numeric_limits<GLsizei>::max() - client_path_id_ - 1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ delete_cmd.Init(std::numeric_limits<GLsizei>::max() + 1,
+ std::numeric_limits<GLsizei>::max());
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Normal Gen and Delete should cause the normal calls.
+ EXPECT_CALL(*gl_, GenPathsNV(kPathCount))
+ .WillOnce(Return(kFirstCreatedServiceID))
+ .RetiresOnSaturation();
+
+ gen_cmd.Init(kFirstClientID, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, DeletePathsNV(kFirstCreatedServiceID, kPathCount))
+ .RetiresOnSaturation();
+
+ delete_cmd.Init(kFirstClientID, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, GenDeleteRanges) {
+ static GLuint kFirstClientID = client_path_id_ + 77;
+ static GLsizei kPathCount = 5800;
+ static GLuint kFirstCreatedServiceID = 8000;
+
+ // Create a range of path names, delete one in middle and then
+ // the rest. Expect 3 DeletePath calls.
+ EXPECT_CALL(*gl_, GenPathsNV(kPathCount))
+ .WillOnce(Return(kFirstCreatedServiceID))
+ .RetiresOnSaturation();
+ cmds::GenPathsCHROMIUM gen_cmd;
+ gen_cmd.Init(kFirstClientID, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, DeletePathsNV(kFirstCreatedServiceID + (kPathCount / 2), 1))
+ .RetiresOnSaturation();
+
+ cmds::DeletePathsCHROMIUM delete_cmd;
+ delete_cmd.Init(kFirstClientID + (kPathCount / 2), 1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, DeletePathsNV(kFirstCreatedServiceID, (kPathCount / 2)))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, DeletePathsNV(kFirstCreatedServiceID + (kPathCount / 2) + 1,
+ (kPathCount / 2) - 1)).RetiresOnSaturation();
+
+ delete_cmd.Init(kFirstClientID, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, GenDeleteManyPaths) {
+ static GLuint kFirstClientID = client_path_id_ + 1;
+ static GLsizei kPathCount = std::numeric_limits<GLsizei>::max();
+ static GLuint kFirstCreatedServiceID = 8000;
+
+ EXPECT_CALL(*gl_, GenPathsNV(kPathCount))
+ .WillOnce(Return(kFirstCreatedServiceID))
+ .RetiresOnSaturation();
+
+ // GenPaths with big range.
+ cmds::GenPathsCHROMIUM gen_cmd;
+ gen_cmd.Init(kFirstClientID, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Path range wraps, so we get connection error.
+ gen_cmd.Init(kFirstClientID + kPathCount, kPathCount);
+ EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, DeletePathsNV(kFirstCreatedServiceID, kPathCount))
+ .RetiresOnSaturation();
+
+ cmds::DeletePathsCHROMIUM delete_cmd;
+ delete_cmd.Init(kFirstClientID, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Delete every possible path.
+ // We run into the one created for client_path_id_.
+ EXPECT_CALL(*gl_, DeletePathsNV(kServicePathId, 1)).RetiresOnSaturation();
+
+ delete_cmd.Init(1u, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ delete_cmd.Init(static_cast<GLuint>(kPathCount) + 1u, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Allocate every possible path, delete few, allocate them back and
+ // expect minimum amount of calls.
+ EXPECT_CALL(*gl_, GenPathsNV(kPathCount))
+ .WillOnce(Return(static_cast<GLuint>(1u)))
+ .WillOnce(Return(static_cast<GLuint>(kPathCount) + 1u))
+ .RetiresOnSaturation();
+
+ gen_cmd.Init(1u, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ gen_cmd.Init(static_cast<GLuint>(kPathCount) + 1u, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ gen_cmd.Init(static_cast<GLuint>(kPathCount) * 2u + 2u, kPathCount);
+ EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, DeletePathsNV(kFirstClientID, 4)).RetiresOnSaturation();
+
+ delete_cmd.Init(kFirstClientID, 4);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, DeletePathsNV(kFirstClientID * 3, 1)).RetiresOnSaturation();
+
+ delete_cmd.Init(kFirstClientID * 3, 1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, GenPathsNV(1))
+ .WillOnce(Return(kFirstClientID))
+ .WillOnce(Return(kFirstClientID + 1))
+ .WillOnce(Return(kFirstClientID + 2))
+ .WillOnce(Return(kFirstClientID + 3))
+ .RetiresOnSaturation();
+
+ for (int i = 0; i < 4; ++i) {
+ gen_cmd.Init(kFirstClientID + i, 1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ }
+
+ EXPECT_CALL(*gl_, GenPathsNV(1))
+ .WillOnce(Return(kFirstClientID * 3))
+ .RetiresOnSaturation();
+ gen_cmd.Init(kFirstClientID * 3, 1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, DeletePathsNV(1u, kPathCount)).RetiresOnSaturation();
+ EXPECT_CALL(*gl_, DeletePathsNV(static_cast<GLuint>(kPathCount) + 1u,
+ kPathCount)).RetiresOnSaturation();
+
+ delete_cmd.Init(1u, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ delete_cmd.Init(static_cast<GLuint>(kPathCount) + 1u, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Cleanup: return the client_path_id_ as a path.
+ EXPECT_CALL(*gl_, GenPathsNV(1))
+ .WillOnce(Return(static_cast<GLuint>(kServicePathId)))
+ .RetiresOnSaturation();
+
+ gen_cmd.Init(client_path_id_, 1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
+ GenPathsCHROMIUMInvalidCalls) {
+ static GLuint kFirstClientID = client_path_id_ + 88;
+ static GLsizei kPathCount = 5800;
+ static GLuint kFirstCreatedServiceID = 8000;
+
+ // Range < 0 is causes gl error.
+ cmds::GenPathsCHROMIUM gen_cmd;
+ gen_cmd.Init(kFirstClientID, -1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+
+ // Path 0 is invalid client id, connection error.
+ gen_cmd.Init(0, kPathCount);
+ EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Too big range causes client id to wrap, connection error.
+ gen_cmd.Init(std::numeric_limits<GLsizei>::max() + 3,
+ std::numeric_limits<GLsizei>::max());
+ EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Creating duplicate client_ids cause connection error.
+ EXPECT_CALL(*gl_, GenPathsNV(kPathCount))
+ .WillOnce(Return(kFirstCreatedServiceID))
+ .RetiresOnSaturation();
+
+ gen_cmd.Init(kFirstClientID, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Create duplicate by executing the same cmd.
+ EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Create duplicate by creating a range that contains
+ // an already existing client path id.
+ gen_cmd.Init(kFirstClientID - 1, 2);
+ EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Cleanup.
+ EXPECT_CALL(*gl_, DeletePathsNV(kFirstCreatedServiceID, kPathCount))
+ .RetiresOnSaturation();
+ cmds::DeletePathsCHROMIUM delete_cmd;
+ delete_cmd.Init(kFirstClientID, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
+ DeletePathsCHROMIUMInvalidCalls) {
+ static GLuint kFirstClientID = client_path_id_ + 88;
+
+ // Range < 0 is causes gl error.
+ cmds::DeletePathsCHROMIUM delete_cmd;
+ delete_cmd.Init(kFirstClientID, -1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+
+ // Too big range causes client id to wrap, connection error.
+ delete_cmd.Init(std::numeric_limits<GLsizei>::max() + 3,
+ std::numeric_limits<GLsizei>::max());
+ EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
+ PathCommandsCHROMIUMInvalidCalls) {
+ static const GLsizei kCorrectCoordCount = 19;
+ static const GLsizei kCorrectCommandCount = 6;
+ static const GLenum kInvalidCoordType = GL_NONE;
+
+ GLfloat* coords = GetSharedMemoryAs<GLfloat*>();
+ unsigned commands_offset = sizeof(GLfloat) * kCorrectCoordCount;
+ GLubyte* commands = GetSharedMemoryAsWithOffset<GLubyte*>(commands_offset);
+ for (int i = 0; i < kCorrectCoordCount; ++i) {
+ coords[i] = 5.0f * i;
+ }
+ commands[0] = GL_MOVE_TO_CHROMIUM;
+ commands[1] = GL_CLOSE_PATH_CHROMIUM;
+ commands[2] = GL_LINE_TO_CHROMIUM;
+ commands[3] = GL_QUADRATIC_CURVE_TO_CHROMIUM;
+ commands[4] = GL_CUBIC_CURVE_TO_CHROMIUM;
+ commands[5] = GL_CONIC_CURVE_TO_CHROMIUM;
+
+ EXPECT_CALL(*gl_, PathCommandsNV(kServicePathId, kCorrectCommandCount,
+ commands, kCorrectCoordCount, GL_FLOAT,
+ coords)).RetiresOnSaturation();
+
+ cmds::PathCommandsCHROMIUM cmd;
+
+ // Reference call -- this succeeds.
+ cmd.Init(client_path_id_, kCorrectCommandCount, shared_memory_id_,
+ shared_memory_offset_ + commands_offset, kCorrectCoordCount,
+ GL_FLOAT, shared_memory_id_, shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, PathCommandsNV(_, _, _, _, _, _)).Times(0);
+
+ // Invalid client id fails.
+ cmd.Init(client_path_id_ - 1, kCorrectCommandCount, shared_memory_id_,
+ shared_memory_offset_, kCorrectCoordCount, GL_FLOAT,
+ shared_memory_id_, shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+
+ // The numCommands < 0.
+ cmd.Init(client_path_id_, -1, shared_memory_id_, shared_memory_offset_,
+ kCorrectCoordCount, GL_FLOAT, shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+
+ // The numCoords < 0.
+ cmd.Init(client_path_id_, kCorrectCommandCount, shared_memory_id_,
+ shared_memory_offset_, -1, GL_FLOAT, shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+
+ // Invalid coordType fails.
+ cmd.Init(client_path_id_, kCorrectCommandCount, shared_memory_id_,
+ shared_memory_offset_, kCorrectCoordCount, kInvalidCoordType,
+ shared_memory_id_, shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
+
+ // Big command counts.
+ cmd.Init(client_path_id_, std::numeric_limits<GLsizei>::max(),
+ shared_memory_id_, shared_memory_offset_ + commands_offset,
+ kCorrectCoordCount, GL_FLOAT, shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Invalid SHM cases.
+ cmd.Init(client_path_id_, kCorrectCommandCount, kInvalidSharedMemoryId,
+ shared_memory_offset_ + commands_offset, kCorrectCoordCount,
+ GL_FLOAT, shared_memory_id_, shared_memory_offset_);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ cmd.Init(client_path_id_, kCorrectCommandCount, shared_memory_id_,
+ kInvalidSharedMemoryOffset, kCorrectCoordCount, GL_FLOAT,
+ shared_memory_id_, shared_memory_offset_);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ cmd.Init(client_path_id_, kCorrectCommandCount, shared_memory_id_,
+ shared_memory_offset_ + commands_offset, kCorrectCoordCount,
+ GL_FLOAT, kInvalidSharedMemoryId, shared_memory_offset_);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ cmd.Init(client_path_id_, kCorrectCommandCount, shared_memory_id_,
+ shared_memory_offset_ + commands_offset, kCorrectCoordCount,
+ GL_FLOAT, shared_memory_id_, kInvalidSharedMemoryOffset);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // NULL shm command id with non-zero command count.
+ cmd.Init(client_path_id_, kCorrectCommandCount, 0, 0, kCorrectCoordCount,
+ GL_FLOAT, shared_memory_id_, shared_memory_offset_);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // NULL shm coord id with non-zero coord count.
+ cmd.Init(client_path_id_, kCorrectCommandCount, shared_memory_id_,
+ shared_memory_offset_ + commands_offset, kCorrectCoordCount,
+ GL_FLOAT, 0, 0);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // The coordCount not matching what is in commands.
+ // Expects kCorrectCoordCount+2 coords.
+ commands[1] = GL_MOVE_TO_CHROMIUM;
+ cmd.Init(client_path_id_, kCorrectCommandCount, shared_memory_id_,
+ shared_memory_offset_ + commands_offset, kCorrectCoordCount,
+ GL_FLOAT, shared_memory_id_, shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+
+ // The coordCount not matching what is in commands.
+ // Expects kCorrectCoordCount-2 coords.
+ commands[0] = GL_CLOSE_PATH_CHROMIUM;
+ commands[1] = GL_CLOSE_PATH_CHROMIUM;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+
+ // NULL shm coord ids. Currently causes gl error, though client should not let
+ // this through.
+ cmd.Init(client_path_id_, kCorrectCommandCount, shared_memory_id_,
+ shared_memory_offset_ + commands_offset, kCorrectCoordCount,
+ GL_FLOAT, 0, 0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
+ PathCommandsCHROMIUMEmptyCommands) {
+ EXPECT_CALL(*gl_, PathCommandsNV(kServicePathId, 0, NULL, 0, GL_FLOAT, NULL))
+ .RetiresOnSaturation();
+ cmds::PathCommandsCHROMIUM cmd;
+ cmd.Init(client_path_id_, 0, 0, 0, 0, GL_FLOAT, 0, 0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
+ PathCommandsCHROMIUMInvalidCommands) {
+ EXPECT_CALL(*gl_, PathCommandsNV(_, _, _, _, _, _)).Times(0);
+
+ cmds::PathCommandsCHROMIUM cmd;
+
+ {
+ const GLsizei kCoordCount = 2;
+ const GLsizei kCommandCount = 2;
+ GLfloat* coords = GetSharedMemoryAs<GLfloat*>();
+ unsigned commands_offset = sizeof(GLfloat) * kCoordCount;
+ GLubyte* commands = GetSharedMemoryAsWithOffset<GLubyte*>(commands_offset);
+
+ coords[0] = 5.0f;
+ coords[1] = 5.0f;
+ commands[0] = 0x3; // Token MOVE_TO_RELATIVE in NV_path_rendering.
+ commands[1] = GL_CLOSE_PATH_CHROMIUM;
+
+ cmd.Init(client_path_id_ - 1, kCommandCount, shared_memory_id_,
+ shared_memory_offset_, kCoordCount, GL_FLOAT, shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+ {
+ const GLsizei kCoordCount = 8;
+ const GLsizei kCommandCount = 4;
+ GLfloat* coords = GetSharedMemoryAs<GLfloat*>();
+ unsigned commands_offset = sizeof(GLfloat) * kCoordCount;
+ GLubyte* commands = GetSharedMemoryAsWithOffset<GLubyte*>(commands_offset);
+
+ for (int i = 0; i < kCoordCount; ++i) {
+ coords[i] = 5.0f * i;
+ }
+ commands[0] = GL_MOVE_TO_CHROMIUM;
+ commands[1] = GL_MOVE_TO_CHROMIUM;
+ commands[2] = 'M'; // Synonym to MOVE_TO in NV_path_rendering.
+ commands[3] = GL_MOVE_TO_CHROMIUM;
+
+ cmd.Init(client_path_id_ - 1, kCommandCount, shared_memory_id_,
+ shared_memory_offset_, kCoordCount, GL_FLOAT, shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, PathParameterXCHROMIUM) {
+ static GLuint kFirstClientID = client_path_id_ + 88;
+ static GLsizei kPathCount = 2;
+ static GLuint kFirstCreatedServiceID = 8000;
+
+ // Create a paths so that we do not modify client_path_id_
+ EXPECT_CALL(*gl_, GenPathsNV(kPathCount))
+ .WillOnce(Return(kFirstCreatedServiceID))
+ .RetiresOnSaturation();
+ cmds::GenPathsCHROMIUM gen_cmd;
+ gen_cmd.Init(kFirstClientID, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ cmds::PathParameterfCHROMIUM fcmd;
+ cmds::PathParameteriCHROMIUM icmd;
+ const struct {
+ GLenum pname;
+ GLfloat value;
+ GLfloat expected_value;
+ } kTestcases[] = {
+ {GL_PATH_STROKE_WIDTH_CHROMIUM, 1.0f, 1.0f},
+ {GL_PATH_STROKE_WIDTH_CHROMIUM, 0.0f, 0.0f},
+ {GL_PATH_MITER_LIMIT_CHROMIUM, 500.0f, 500.0f},
+ {GL_PATH_STROKE_BOUND_CHROMIUM, .80f, .80f},
+ {GL_PATH_STROKE_BOUND_CHROMIUM, 1.80f, 1.0f},
+ {GL_PATH_STROKE_BOUND_CHROMIUM, -1.0f, 0.0f},
+ {GL_PATH_END_CAPS_CHROMIUM, GL_FLAT_CHROMIUM, GL_FLAT_CHROMIUM},
+ {GL_PATH_END_CAPS_CHROMIUM, GL_SQUARE_CHROMIUM, GL_SQUARE_CHROMIUM},
+ {GL_PATH_JOIN_STYLE_CHROMIUM,
+ GL_MITER_REVERT_CHROMIUM,
+ GL_MITER_REVERT_CHROMIUM},
+ };
+
+ for (auto& testcase : kTestcases) {
+ EXPECT_CALL(*gl_, PathParameterfNV(kFirstCreatedServiceID, testcase.pname,
+ testcase.expected_value))
+ .Times(1)
+ .RetiresOnSaturation();
+ fcmd.Init(kFirstClientID, testcase.pname, testcase.value);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(fcmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_,
+ PathParameteriNV(kFirstCreatedServiceID + 1, testcase.pname,
+ static_cast<GLint>(testcase.expected_value)))
+ .Times(1)
+ .RetiresOnSaturation();
+ icmd.Init(kFirstClientID + 1, testcase.pname,
+ static_cast<GLint>(testcase.value));
+ EXPECT_EQ(error::kNoError, ExecuteCmd(icmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ }
+
+ // Cleanup.
+ EXPECT_CALL(*gl_, DeletePathsNV(kFirstCreatedServiceID, kPathCount))
+ .RetiresOnSaturation();
+
+ cmds::DeletePathsCHROMIUM delete_cmd;
+ delete_cmd.Init(kFirstClientID, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
+ PathParameterXCHROMIUMInvalidArgs) {
+ static GLuint kFirstClientID = client_path_id_ + 88;
+ static GLsizei kPathCount = 2;
+ static GLuint kFirstCreatedServiceID = 8000;
+
+ // Create a paths so that we do not modify client_path_id_
+ EXPECT_CALL(*gl_, GenPathsNV(kPathCount))
+ .WillOnce(Return(kFirstCreatedServiceID))
+ .RetiresOnSaturation();
+ cmds::GenPathsCHROMIUM gen_cmd;
+ gen_cmd.Init(kFirstClientID, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ cmds::PathParameterfCHROMIUM fcmd;
+ cmds::PathParameteriCHROMIUM icmd;
+ const struct {
+ GLenum pname;
+ GLfloat value;
+ bool try_int_version;
+ GLint error;
+ } kTestcases[] = {
+ {GL_PATH_STROKE_WIDTH_CHROMIUM, -1.0f, true, GL_INVALID_VALUE},
+ {GL_PATH_MITER_LIMIT_CHROMIUM,
+ std::numeric_limits<float>::infinity(),
+ false,
+ GL_INVALID_VALUE},
+ {GL_PATH_MITER_LIMIT_CHROMIUM,
+ std::numeric_limits<float>::quiet_NaN(),
+ false,
+ GL_INVALID_VALUE},
+ {GL_PATH_END_CAPS_CHROMIUM, 0x4, true, GL_INVALID_VALUE},
+ {GL_PATH_END_CAPS_CHROMIUM,
+ GL_MITER_REVERT_CHROMIUM,
+ true,
+ GL_INVALID_VALUE},
+ {GL_PATH_JOIN_STYLE_CHROMIUM, GL_FLAT_CHROMIUM, true, GL_INVALID_VALUE},
+ {GL_PATH_MODELVIEW_CHROMIUM, GL_FLAT_CHROMIUM, true, GL_INVALID_ENUM},
+ };
+
+ EXPECT_CALL(*gl_, PathParameterfNV(_, _, _)).Times(0);
+ EXPECT_CALL(*gl_, PathParameteriNV(_, _, _)).Times(0);
+
+ for (auto& testcase : kTestcases) {
+ fcmd.Init(kFirstClientID, testcase.pname, testcase.value);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(fcmd));
+ EXPECT_EQ(testcase.error, GetGLError());
+ if (!testcase.try_int_version)
+ continue;
+
+ icmd.Init(kFirstClientID + 1, testcase.pname,
+ static_cast<GLint>(testcase.value));
+ EXPECT_EQ(error::kNoError, ExecuteCmd(icmd));
+ EXPECT_EQ(testcase.error, GetGLError());
+ }
+
+ // Cleanup.
+ EXPECT_CALL(*gl_, DeletePathsNV(kFirstCreatedServiceID, kPathCount))
+ .RetiresOnSaturation();
+
+ cmds::DeletePathsCHROMIUM delete_cmd;
+ delete_cmd.Init(kFirstClientID, kPathCount);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, StencilFillPathCHROMIUM) {
+ SetupExpectationsForApplyingDefaultDirtyState();
+
+ cmds::StencilFillPathCHROMIUM cmd;
+ cmds::StencilThenCoverFillPathCHROMIUM tcmd;
+
+ static const GLenum kFillModes[] = {
+ GL_INVERT, GL_COUNT_UP_CHROMIUM, GL_COUNT_DOWN_CHROMIUM};
+ static const GLuint kMask = 0x7F;
+
+ for (auto& fill_mode : kFillModes) {
+ EXPECT_CALL(*gl_, StencilFillPathNV(kServicePathId, fill_mode, kMask))
+ .RetiresOnSaturation();
+ cmd.Init(client_path_id_, fill_mode, kMask);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, StencilThenCoverFillPathNV(kServicePathId, fill_mode,
+ kMask, GL_BOUNDING_BOX_NV))
+ .RetiresOnSaturation();
+ tcmd.Init(client_path_id_, fill_mode, kMask, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(tcmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ }
+
+ // Non-existent path: no error, no call.
+ cmd.Init(client_path_id_ - 1, GL_INVERT, 0x80);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ tcmd.Init(client_path_id_ - 1, GL_INVERT, 0x80, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(tcmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
+ StencilFillPathCHROMIUMInvalidArgs) {
+ EXPECT_CALL(*gl_, StencilFillPathNV(_, _, _)).Times(0);
+ EXPECT_CALL(*gl_, StencilThenCoverFillPathNV(_, _, _, GL_BOUNDING_BOX_NV))
+ .Times(0);
+
+ cmds::StencilFillPathCHROMIUM cmd;
+ cmds::StencilThenCoverFillPathCHROMIUM tcmd;
+
+ cmd.Init(client_path_id_, GL_INVERT - 1, 0x80);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
+
+ tcmd.Init(client_path_id_, GL_INVERT - 1, 0x80, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(tcmd));
+ EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
+
+ // The /mask/+1 is not power of two -> invalid value.
+ cmd.Init(client_path_id_, GL_COUNT_UP_CHROMIUM, 0x80);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+
+ tcmd.Init(client_path_id_, GL_COUNT_UP_CHROMIUM, 0x80,
+ GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(tcmd));
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+
+ cmd.Init(client_path_id_, GL_COUNT_DOWN_CHROMIUM, 5);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+
+ tcmd.Init(client_path_id_, GL_COUNT_DOWN_CHROMIUM, 5,
+ GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(tcmd));
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, StencilStrokePathCHROMIUM) {
+ SetupExpectationsForApplyingDefaultDirtyState();
+
+ EXPECT_CALL(*gl_, StencilStrokePathNV(kServicePathId, 1, 0x80))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, StencilThenCoverStrokePathNV(kServicePathId, 1, 0x80,
+ GL_BOUNDING_BOX_NV))
+ .RetiresOnSaturation();
+
+ cmds::StencilStrokePathCHROMIUM cmd;
+ cmds::StencilThenCoverStrokePathCHROMIUM tcmd;
+
+ cmd.Init(client_path_id_, 1, 0x80);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ tcmd.Init(client_path_id_, 1, 0x80, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(tcmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, StencilThenCoverStrokePathNV(kServicePathId, 1, 0x80,
+ GL_CONVEX_HULL_NV))
+ .RetiresOnSaturation();
+
+ tcmd.Init(client_path_id_, 1, 0x80, GL_CONVEX_HULL_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(tcmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Non-existent path: no error, no call.
+ cmd.Init(client_path_id_ - 1, 1, 0x80);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ tcmd.Init(client_path_id_ - 1, 1, 0x80, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(tcmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, CoverFillPathCHROMIUM) {
+ SetupExpectationsForApplyingDefaultDirtyState();
+
+ EXPECT_CALL(*gl_, CoverFillPathNV(kServicePathId, GL_BOUNDING_BOX_NV))
+ .RetiresOnSaturation();
+ cmds::CoverFillPathCHROMIUM cmd;
+ cmd.Init(client_path_id_, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, CoverFillPathNV(kServicePathId, GL_CONVEX_HULL_NV))
+ .RetiresOnSaturation();
+ cmd.Init(client_path_id_, GL_CONVEX_HULL_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Non-existent path: no error, no call.
+ cmd.Init(client_path_id_ - 1, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, CoverStrokePathCHROMIUM) {
+ SetupExpectationsForApplyingDefaultDirtyState();
+ EXPECT_CALL(*gl_, CoverStrokePathNV(kServicePathId, GL_BOUNDING_BOX_NV))
+ .RetiresOnSaturation();
+ cmds::CoverStrokePathCHROMIUM cmd;
+ cmd.Init(client_path_id_, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ EXPECT_CALL(*gl_, CoverStrokePathNV(kServicePathId, GL_CONVEX_HULL_NV))
+ .RetiresOnSaturation();
+ cmd.Init(client_path_id_, GL_CONVEX_HULL_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // Non-existent path: no error, no call.
+ cmd.Init(client_path_id_ - 1, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+namespace {
+template <typename T>
+struct gl_type_enum {};
+template <>
+struct gl_type_enum<GLbyte> {
+ enum { kGLType = GL_BYTE };
+};
+template <>
+struct gl_type_enum<GLubyte> {
+ enum { kGLType = GL_UNSIGNED_BYTE };
+};
+template <>
+struct gl_type_enum<GLshort> {
+ enum { kGLType = GL_SHORT };
+};
+template <>
+struct gl_type_enum<GLushort> {
+ enum { kGLType = GL_UNSIGNED_SHORT };
+};
+template <>
+struct gl_type_enum<GLfloat> {
+ enum { kGLType = GL_FLOAT };
+};
+}
+
+template <typename TypeParam>
+void GLES2DecoderTestWithCHROMIUMPathRendering::
+ TestPathCommandsCHROMIUMCoordTypes() {
+ static const GLsizei kCorrectCoordCount = 19;
+ static const GLsizei kCorrectCommandCount = 6;
+
+ TypeParam* coords = GetSharedMemoryAs<TypeParam*>();
+ unsigned commands_offset = sizeof(TypeParam) * kCorrectCoordCount;
+ GLubyte* commands = GetSharedMemoryAsWithOffset<GLubyte*>(commands_offset);
+ for (int i = 0; i < kCorrectCoordCount; ++i) {
+ coords[i] = static_cast<TypeParam>(5 * i);
+ }
+ commands[0] = GL_MOVE_TO_CHROMIUM;
+ commands[1] = GL_CLOSE_PATH_CHROMIUM;
+ commands[2] = GL_LINE_TO_CHROMIUM;
+ commands[3] = GL_QUADRATIC_CURVE_TO_CHROMIUM;
+ commands[4] = GL_CUBIC_CURVE_TO_CHROMIUM;
+ commands[5] = GL_CONIC_CURVE_TO_CHROMIUM;
+
+ EXPECT_CALL(*gl_, PathCommandsNV(kServicePathId, kCorrectCommandCount,
+ commands, kCorrectCoordCount,
+ gl_type_enum<TypeParam>::kGLType, coords))
+ .RetiresOnSaturation();
+
+ cmds::PathCommandsCHROMIUM cmd;
+
+ cmd.Init(client_path_id_, kCorrectCommandCount, shared_memory_id_,
+ shared_memory_offset_ + commands_offset, kCorrectCoordCount,
+ gl_type_enum<TypeParam>::kGLType, shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
+ PathCommandsCHROMIUMCoordTypes) {
+ // Not using a typed test case, because the base class is already parametrized
+ // test case and uses GetParam.
+ TestPathCommandsCHROMIUMCoordTypes<GLbyte>();
+ TestPathCommandsCHROMIUMCoordTypes<GLubyte>();
+ TestPathCommandsCHROMIUMCoordTypes<GLshort>();
+ TestPathCommandsCHROMIUMCoordTypes<GLushort>();
+ TestPathCommandsCHROMIUMCoordTypes<GLfloat>();
+}
+
#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h"
} // namespace gles2
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h
index 57db672..5c22b6c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h
@@ -44,6 +44,55 @@ TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
+// TODO(gman): GenPathsCHROMIUM
+
+// TODO(gman): DeletePathsCHROMIUM
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, IsPathCHROMIUMValidArgs) {
+ EXPECT_CALL(*gl_, IsPathNV(kServicePathId));
+ SpecializedSetup<cmds::IsPathCHROMIUM, 0>(true);
+ cmds::IsPathCHROMIUM cmd;
+ cmd.Init(client_path_id_, shared_memory_id_, shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
+ IsPathCHROMIUMInvalidArgsBadSharedMemoryId) {
+ EXPECT_CALL(*gl_, IsPathNV(kServicePathId)).Times(0);
+ SpecializedSetup<cmds::IsPathCHROMIUM, 0>(false);
+ cmds::IsPathCHROMIUM cmd;
+ cmd.Init(client_path_id_, kInvalidSharedMemoryId, shared_memory_offset_);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ cmd.Init(client_path_id_, shared_memory_id_, kInvalidSharedMemoryOffset);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+}
+// TODO(gman): PathCommandsCHROMIUM
+
+// TODO(gman): PathParameterfCHROMIUM
+
+// TODO(gman): PathParameteriCHROMIUM
+
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
+ PathStencilFuncCHROMIUMValidArgs) {
+ EXPECT_CALL(*gl_, PathStencilFuncNV(GL_NEVER, 2, 3));
+ SpecializedSetup<cmds::PathStencilFuncCHROMIUM, 0>(true);
+ cmds::PathStencilFuncCHROMIUM cmd;
+ cmd.Init(GL_NEVER, 2, 3);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+// TODO(gman): StencilFillPathCHROMIUM
+
+// TODO(gman): StencilStrokePathCHROMIUM
+
+// TODO(gman): CoverFillPathCHROMIUM
+
+// TODO(gman): CoverStrokePathCHROMIUM
+
+// TODO(gman): StencilThenCoverFillPathCHROMIUM
+
+// TODO(gman): StencilThenCoverStrokePathCHROMIUM
TEST_P(GLES2DecoderTestWithBlendEquationAdvanced, BlendBarrierKHRValidArgs) {
EXPECT_CALL(*gl_, BlendBarrierKHR());
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
index ec96c6b..ccaeb59 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
@@ -46,6 +46,12 @@ ValueValidator<GLenum> internal_format_parameter;
ValueValidator<GLenum> invalidate_frame_buffer_target;
ValueValidator<GLenum> map_buffer_access;
ValueValidator<GLenum> matrix_mode;
+ValueValidator<GLenum> path_coord_type;
+ValueValidator<GLenum> path_cover_mode;
+ValueValidator<GLenum> path_fill_mode;
+ValueValidator<GLenum> path_parameter;
+ValueValidator<GLint> path_parameter_cap_values;
+ValueValidator<GLint> path_parameter_join_values;
ValueValidator<GLenum> pixel_store;
ValueValidator<GLint> pixel_store_alignment;
ValueValidator<GLenum> pixel_type;
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
index 1c4cf97..5e23712 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
@@ -474,6 +474,45 @@ static const GLenum valid_matrix_mode_table[] = {
GL_PATH_MODELVIEW_CHROMIUM,
};
+static const GLenum valid_path_coord_type_table[] = {
+ GL_BYTE,
+ GL_UNSIGNED_BYTE,
+ GL_SHORT,
+ GL_UNSIGNED_SHORT,
+ GL_FLOAT,
+};
+
+static const GLenum valid_path_cover_mode_table[] = {
+ GL_CONVEX_HULL_CHROMIUM,
+ GL_BOUNDING_BOX_CHROMIUM,
+};
+
+static const GLenum valid_path_fill_mode_table[] = {
+ GL_INVERT,
+ GL_COUNT_UP_CHROMIUM,
+ GL_COUNT_DOWN_CHROMIUM,
+};
+
+static const GLenum valid_path_parameter_table[] = {
+ GL_PATH_STROKE_WIDTH_CHROMIUM,
+ GL_PATH_END_CAPS_CHROMIUM,
+ GL_PATH_JOIN_STYLE_CHROMIUM,
+ GL_PATH_MITER_LIMIT_CHROMIUM,
+ GL_PATH_STROKE_BOUND_CHROMIUM,
+};
+
+static const GLint valid_path_parameter_cap_values_table[] = {
+ GL_FLAT,
+ GL_SQUARE_CHROMIUM,
+ GL_ROUND_CHROMIUM,
+};
+
+static const GLint valid_path_parameter_join_values_table[] = {
+ GL_MITER_REVERT_CHROMIUM,
+ GL_BEVEL_CHROMIUM,
+ GL_ROUND_CHROMIUM,
+};
+
static const GLenum valid_pixel_store_table[] = {
GL_PACK_ALIGNMENT,
GL_UNPACK_ALIGNMENT,
@@ -1148,6 +1187,20 @@ Validators::Validators()
map_buffer_access(valid_map_buffer_access_table,
arraysize(valid_map_buffer_access_table)),
matrix_mode(valid_matrix_mode_table, arraysize(valid_matrix_mode_table)),
+ path_coord_type(valid_path_coord_type_table,
+ arraysize(valid_path_coord_type_table)),
+ path_cover_mode(valid_path_cover_mode_table,
+ arraysize(valid_path_cover_mode_table)),
+ path_fill_mode(valid_path_fill_mode_table,
+ arraysize(valid_path_fill_mode_table)),
+ path_parameter(valid_path_parameter_table,
+ arraysize(valid_path_parameter_table)),
+ path_parameter_cap_values(
+ valid_path_parameter_cap_values_table,
+ arraysize(valid_path_parameter_cap_values_table)),
+ path_parameter_join_values(
+ valid_path_parameter_join_values_table,
+ arraysize(valid_path_parameter_join_values_table)),
pixel_store(valid_pixel_store_table, arraysize(valid_pixel_store_table)),
pixel_store_alignment(valid_pixel_store_alignment_table,
arraysize(valid_pixel_store_alignment_table)),
diff --git a/gpu/command_buffer/service/gpu_switches.cc b/gpu/command_buffer/service/gpu_switches.cc
index d2ca490..171f543 100644
--- a/gpu/command_buffer/service/gpu_switches.cc
+++ b/gpu/command_buffer/service/gpu_switches.cc
@@ -71,25 +71,31 @@ const char kGLShaderIntermOutput[] = "gl-shader-interm-output";
// round intermediate values in ANGLE.
const char kEmulateShaderPrecision[] = "emulate-shader-precision";
+// Enables using path rendering implementation implemented currently
+// in NV_path_rendering OpenGL extension. Requires compatible hardware
+// and driver. This is used in GPU rasterization.
+const char kEnableGLPathRendering[] = "enable-gl-path-rendering";
+
const char* kGpuSwitches[] = {
- kCompileShaderAlwaysSucceeds,
- kDisableGLErrorLimit,
- kDisableGLSLTranslator,
- kDisableGpuDriverBugWorkarounds,
- kDisableShaderNameHashing,
- kEnableGPUCommandLogging,
- kEnableGPUDebugging,
- kEnableGPUServiceLoggingGPU,
- kDisableGpuProgramCache,
- kEnforceGLMinimums,
- kForceGpuMemAvailableMb,
- kGpuDriverBugWorkarounds,
- kGpuProgramCacheSizeKb,
- kDisableGpuShaderDiskCache,
- kEnableShareGroupAsyncTextureUpload,
- kEnableSubscribeUniformExtension,
- kGLShaderIntermOutput,
- kEmulateShaderPrecision,
+ kCompileShaderAlwaysSucceeds,
+ kDisableGLErrorLimit,
+ kDisableGLSLTranslator,
+ kDisableGpuDriverBugWorkarounds,
+ kDisableShaderNameHashing,
+ kEnableGPUCommandLogging,
+ kEnableGPUDebugging,
+ kEnableGPUServiceLoggingGPU,
+ kDisableGpuProgramCache,
+ kEnforceGLMinimums,
+ kForceGpuMemAvailableMb,
+ kGpuDriverBugWorkarounds,
+ kGpuProgramCacheSizeKb,
+ kDisableGpuShaderDiskCache,
+ kEnableShareGroupAsyncTextureUpload,
+ kEnableSubscribeUniformExtension,
+ kGLShaderIntermOutput,
+ kEmulateShaderPrecision,
+ kEnableGLPathRendering,
};
const int kNumGpuSwitches = arraysize(kGpuSwitches);
diff --git a/gpu/command_buffer/service/gpu_switches.h b/gpu/command_buffer/service/gpu_switches.h
index ac6883a..ac347e4 100644
--- a/gpu/command_buffer/service/gpu_switches.h
+++ b/gpu/command_buffer/service/gpu_switches.h
@@ -30,6 +30,7 @@ GPU_EXPORT extern const char kEnableSubscribeUniformExtension[];
GPU_EXPORT extern const char kEnableThreadedTextureMailboxes[];
GPU_EXPORT extern const char kGLShaderIntermOutput[];
GPU_EXPORT extern const char kEmulateShaderPrecision[];
+GPU_EXPORT extern const char kEnableGLPathRendering[];
GPU_EXPORT extern const char* kGpuSwitches[];
GPU_EXPORT extern const int kNumGpuSwitches;
diff --git a/gpu/command_buffer/service/path_manager.cc b/gpu/command_buffer/service/path_manager.cc
new file mode 100644
index 0000000..3e0d257
--- /dev/null
+++ b/gpu/command_buffer/service/path_manager.cc
@@ -0,0 +1,252 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/path_manager.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "ui/gl/gl_bindings.h"
+
+namespace gpu {
+namespace gles2 {
+
+namespace {
+void CallDeletePaths(GLuint first_id, GLuint range) {
+ while (range > 0) {
+ GLsizei irange;
+ if (range > static_cast<GLuint>(std::numeric_limits<GLsizei>::max()))
+ irange = std::numeric_limits<GLsizei>::max();
+ else
+ irange = static_cast<GLsizei>(range);
+
+ glDeletePathsNV(first_id, irange);
+ range -= irange;
+ first_id += irange;
+ }
+}
+
+template <typename RangeIterator>
+static GLuint RangeSize(const RangeIterator& it) {
+ return it->second.last_client_id - it->first + 1;
+}
+template <typename RangeIterator>
+static GLuint FirstClientId(const RangeIterator& it) {
+ return it->first;
+}
+template <typename RangeIterator>
+static GLuint FirstServiceId(const RangeIterator& it) {
+ return it->second.first_service_id;
+}
+template <typename RangeIterator>
+static GLuint LastServiceId(const RangeIterator& it) {
+ return FirstServiceId(it) + RangeSize(it) - 1;
+}
+static GLuint LastClientId(PathManager::PathRangeMap::const_iterator& it) {
+ return it->second.last_client_id;
+}
+// Note: this one can be assigned to.
+static GLuint& LastClientId(PathManager::PathRangeMap::iterator& it) {
+ return it->second.last_client_id;
+}
+
+template <typename T>
+struct IteratorSelector {
+ typedef typename T::iterator iterator;
+};
+template <typename T>
+struct IteratorSelector<const T> {
+ typedef typename T::const_iterator iterator;
+};
+
+// Returns the range position that contains |client_id| or
+// |PathRangeMap::iterator::end()| if |client_id| is not found.
+template <typename MapType>
+static typename IteratorSelector<MapType>::iterator GetContainingRange(
+ MapType& path_map,
+ GLuint client_id) {
+ auto it = path_map.lower_bound(client_id);
+ if (it != path_map.end() && FirstClientId(it) == client_id)
+ return it;
+ if (it != path_map.begin()) {
+ --it;
+ if (LastClientId(it) >= client_id)
+ return it;
+ }
+ return path_map.end();
+}
+
+// Returns the range position that contains |client_id|. If that is
+// not available, returns the range that has smallest
+// |first_client_id| that is bigger than |client_id|. Returns
+// |PathRangeMap::iterator::end()| if there is no such range.
+template <typename MapType>
+static typename IteratorSelector<MapType>::iterator GetContainingOrNextRange(
+ MapType& path_map,
+ GLuint client_id) {
+ auto it = path_map.lower_bound(client_id);
+ if (it != path_map.end() && FirstClientId(it) == client_id) {
+ return it;
+ }
+ if (it != path_map.begin()) {
+ --it;
+ if (LastClientId(it) >= client_id)
+ return it;
+ ++it;
+ }
+ return it;
+}
+
+} // anonymous namespace
+
+PathManager::PathManager() {
+}
+
+PathManager::~PathManager() {
+ DCHECK(path_map_.empty());
+}
+
+void PathManager::Destroy(bool have_context) {
+ if (have_context) {
+ for (PathRangeMap::const_iterator it = path_map_.begin();
+ it != path_map_.end(); ++it)
+ CallDeletePaths(FirstServiceId(it), RangeSize(it));
+ }
+ path_map_.clear();
+}
+
+void PathManager::CreatePathRange(GLuint first_client_id,
+ GLuint last_client_id,
+ GLuint first_service_id) {
+ DCHECK(first_service_id > 0u);
+ DCHECK(first_client_id > 0u);
+ DCHECK(!HasPathsInRange(first_client_id, last_client_id));
+ DCHECK(CheckConsistency());
+
+ PathRangeMap::iterator range =
+ GetContainingRange(path_map_, first_client_id - 1u);
+
+ if (range != path_map_.end() &&
+ LastServiceId(range) == first_service_id - 1u) {
+ DCHECK_EQ(LastClientId(range), first_client_id - 1u);
+ LastClientId(range) = last_client_id;
+ } else {
+ auto result = path_map_.insert(
+ std::make_pair(first_client_id,
+ PathRangeDescription(last_client_id, first_service_id)));
+ DCHECK(result.second);
+ range = result.first;
+ }
+
+ PathRangeMap::iterator next_range = range;
+ ++next_range;
+ if (next_range != path_map_.end()) {
+ if (LastClientId(range) == FirstClientId(next_range) - 1u &&
+ LastServiceId(range) == FirstServiceId(next_range) - 1u) {
+ LastClientId(range) = LastClientId(next_range);
+ path_map_.erase(next_range);
+ }
+ }
+ DCHECK(CheckConsistency());
+}
+
+bool PathManager::HasPathsInRange(GLuint first_client_id,
+ GLuint last_client_id) const {
+ PathRangeMap::const_iterator it =
+ GetContainingOrNextRange(path_map_, first_client_id);
+ if (it == path_map_.end())
+ return false;
+
+ return FirstClientId(it) <= last_client_id;
+}
+
+bool PathManager::GetPath(GLuint client_id, GLuint* service_id) const {
+ PathRangeMap::const_iterator range = GetContainingRange(path_map_, client_id);
+ if (range == path_map_.end())
+ return false;
+
+ *service_id = FirstServiceId(range) + client_id - FirstClientId(range);
+ return true;
+}
+
+void PathManager::RemovePaths(GLuint first_client_id, GLuint last_client_id) {
+ DCHECK(CheckConsistency());
+ PathRangeMap::iterator it =
+ GetContainingOrNextRange(path_map_, first_client_id);
+
+ while (it != path_map_.end() && FirstClientId(it) <= last_client_id) {
+ GLuint delete_first_client_id =
+ std::max(first_client_id, FirstClientId(it));
+ GLuint delete_last_client_id = std::min(last_client_id, LastClientId(it));
+ GLuint delete_first_service_id =
+ FirstServiceId(it) + delete_first_client_id - FirstClientId(it);
+ GLuint delete_range = delete_last_client_id - delete_first_client_id + 1u;
+
+ CallDeletePaths(delete_first_service_id, delete_range);
+
+ PathRangeMap::iterator current = it;
+ ++it;
+
+ GLuint current_last_client_id = LastClientId(current);
+
+ if (FirstClientId(current) < delete_first_client_id)
+ LastClientId(current) = delete_first_client_id - 1u;
+ else
+ path_map_.erase(current);
+
+ if (current_last_client_id > delete_last_client_id) {
+ path_map_.insert(std::make_pair(
+ delete_last_client_id + 1u,
+ PathRangeDescription(current_last_client_id,
+ delete_first_service_id + delete_range)));
+ DCHECK(delete_last_client_id == last_client_id);
+ // This is necessarily the last range to check. Return early due to
+ // consistency. Iterator increment would skip the inserted range. The
+ // algorithm would work ok, but it looks weird.
+ DCHECK(CheckConsistency());
+ return;
+ }
+ }
+ DCHECK(CheckConsistency());
+}
+
+bool PathManager::CheckConsistency() {
+ GLuint prev_first_client_id = 0u;
+ GLuint prev_last_client_id = 0u;
+ GLuint prev_first_service_id = 0u;
+ for (PathRangeMap::iterator range = path_map_.begin();
+ range != path_map_.end(); ++range) {
+ // Code relies on ranges not starting at 0. Also, the above initialization
+ // is only
+ // correct then.
+ if (FirstClientId(range) == 0u || FirstServiceId(range) == 0u)
+ return false;
+
+ // Each range is consistent.
+ if (FirstClientId(range) > LastClientId(range))
+ return false;
+
+ if (prev_first_client_id != 0u) {
+ // No overlapping ranges. (The iteration is sorted).
+ if (FirstClientId(range) <= prev_last_client_id)
+ return false;
+
+ // No mergeable ranges.
+ bool is_mergeable_client =
+ FirstClientId(range) - 1u == prev_last_client_id;
+ bool is_mergeable_service =
+ FirstServiceId(range) - 1u == prev_first_service_id;
+ if (is_mergeable_client && is_mergeable_service)
+ return false;
+ }
+ prev_first_client_id = FirstClientId(range);
+ prev_last_client_id = LastClientId(range);
+ prev_first_service_id = FirstServiceId(range);
+ }
+ return true;
+}
+
+} // namespace gles2
+} // namespace gpu
diff --git a/gpu/command_buffer/service/path_manager.h b/gpu/command_buffer/service/path_manager.h
new file mode 100644
index 0000000..78a53b7
--- /dev/null
+++ b/gpu/command_buffer/service/path_manager.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_PATH_MANAGER_H_
+#define GPU_COMMAND_BUFFER_SERVICE_PATH_MANAGER_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "gpu/command_buffer/service/gl_utils.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+namespace gles2 {
+
+// This class keeps track of paths and their client and service ids
+// so we can correctly clear them.
+class GPU_EXPORT PathManager {
+ public:
+ PathManager();
+ ~PathManager();
+
+ // Must call before destruction.
+ void Destroy(bool have_context);
+
+ // Creates a path mapping between closed intervals
+ // [first_client_id, last_client_id] -> [first_service_id, ...].
+ void CreatePathRange(GLuint first_client_id,
+ GLuint last_client_id,
+ GLuint first_service_id);
+
+ // Returns true if any path exists in the closed interval
+ // [first_client_id, last_client_id].
+ bool HasPathsInRange(GLuint first_client_id, GLuint last_client_id) const;
+
+ // Gets the path id corresponding the client path id.
+ // Returns false if no such service path id was not found.
+ bool GetPath(GLuint client_id, GLuint* service_id) const;
+
+ // Removes a closed interval of paths [first_client_id, last_client_id].
+ void RemovePaths(GLuint first_client_id, GLuint last_client_id);
+
+ // Mapping between client id and service id.
+ // Should be used only by the implementation.
+ struct PathRangeDescription {
+ PathRangeDescription(GLuint last_client, GLuint first_service)
+ : last_client_id(last_client), first_service_id(first_service) {}
+ GLuint last_client_id;
+ GLuint first_service_id;
+ typedef GLuint ServiceIdType;
+ };
+ typedef std::map<GLuint, PathRangeDescription> PathRangeMap;
+
+ private:
+ // Checks for consistency inside the book-keeping structures. Used as
+ // DCHECK pre/post condition in mutating functions.
+ bool CheckConsistency();
+
+ PathRangeMap path_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(PathManager);
+};
+
+} // namespace gles2
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_PATH_MANAGER_H_
diff --git a/gpu/command_buffer/service/path_manager_unittest.cc b/gpu/command_buffer/service/path_manager_unittest.cc
new file mode 100644
index 0000000..8a20db5
--- /dev/null
+++ b/gpu/command_buffer/service/path_manager_unittest.cc
@@ -0,0 +1,164 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/path_manager.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "gpu/command_buffer/service/gpu_service_test.h"
+#include "gpu/command_buffer/service/mocks.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gl/gl_mock.h"
+
+namespace gpu {
+namespace gles2 {
+
+class PathManagerTest : public GpuServiceTest {
+ public:
+ PathManagerTest() {}
+
+ protected:
+ void SetUp() override {
+ SetUpWithGLVersion("3.0", "GL_NV_path_rendering");
+ manager_.reset(new PathManager());
+ }
+
+ void TearDown() override {
+ manager_->Destroy(true);
+ manager_.reset();
+ GpuServiceTest::TearDown();
+ }
+
+ scoped_ptr<PathManager> manager_;
+};
+
+TEST_F(PathManagerTest, Basic) {
+ const GLuint kClient1Id = 1;
+ const GLuint kService1Id = 11;
+ const GLuint kClient2Id = 2;
+ GLuint service_id = 0;
+ manager_->CreatePathRange(kClient1Id, kClient1Id, kService1Id);
+ ASSERT_TRUE(manager_->HasPathsInRange(kClient1Id, kClient1Id));
+ EXPECT_TRUE(manager_->GetPath(kClient1Id, &service_id));
+ EXPECT_EQ(kService1Id, service_id);
+
+ // Check we get nothing for a non-existent path.
+ service_id = 123u;
+ ASSERT_FALSE(manager_->HasPathsInRange(kClient2Id, kClient2Id));
+ EXPECT_FALSE(manager_->GetPath(kClient2Id, &service_id));
+ EXPECT_EQ(123u, service_id);
+
+ // Check trying to remove non-existent paths does not crash.
+ manager_->RemovePaths(kClient2Id, kClient2Id);
+
+ // Check that it gets deleted when the last reference is released.
+ EXPECT_CALL(*gl_, DeletePathsNV(kService1Id, 1))
+ .Times(1)
+ .RetiresOnSaturation();
+
+ // Check we can't get the path after we remove it.
+ manager_->RemovePaths(kClient1Id, kClient1Id);
+ ASSERT_FALSE(manager_->HasPathsInRange(kClient1Id, kClient1Id));
+ EXPECT_FALSE(manager_->GetPath(kClient1Id, &service_id));
+}
+
+// Tests that path manager does not merge ranges that contain service ids that
+// prevent the merging. Path ranges A and B can be merged if
+// * client ids of B start immediately after the last client id of A
+// * service ids of B start immediately after the last service id of A
+// and similarly for the 'before' case.
+TEST_F(PathManagerTest, NonContiguousServiceIds) {
+ const GLuint kMergeCheckRange = 54;
+
+ const struct {
+ GLuint first_client_id;
+ GLuint last_client_id;
+ GLuint first_service_id;
+ } kIdRanges[] = {{500, 1000, 900}, {1001, 1155, 1}, {200, 499, 4888}};
+ for (auto& range : kIdRanges) {
+ manager_->CreatePathRange(range.first_client_id, range.last_client_id,
+ range.first_service_id);
+ ASSERT_TRUE(manager_->HasPathsInRange(range.first_client_id,
+ range.first_client_id));
+ ASSERT_TRUE(
+ manager_->HasPathsInRange(range.last_client_id, range.last_client_id));
+ ASSERT_TRUE(
+ manager_->HasPathsInRange(range.first_client_id, range.last_client_id));
+ GLuint service_id = 0u;
+ EXPECT_TRUE(manager_->GetPath(range.first_client_id + 5u, &service_id));
+ EXPECT_EQ(range.first_service_id + 5u, service_id);
+ }
+
+ // Insert a mergeable range last, to check that merges
+ // work. Otherwise the test could succeed because merges were not
+ // working.
+ auto& merge_candidate = kIdRanges[1];
+ GLuint merge_candidate_range =
+ merge_candidate.last_client_id - merge_candidate.first_client_id + 1;
+ manager_->CreatePathRange(
+ merge_candidate.last_client_id + 1,
+ merge_candidate.last_client_id + kMergeCheckRange,
+ merge_candidate.first_service_id + merge_candidate_range);
+
+ // We detect that ranges were not merged accidentally by detecting individual
+ // deletes.
+ for (auto& range : kIdRanges) {
+ if (&range == &merge_candidate)
+ continue;
+ GLsizei range_amount = range.last_client_id - range.first_client_id + 1;
+ EXPECT_CALL(*gl_, DeletePathsNV(range.first_service_id, range_amount))
+ .Times(1)
+ .RetiresOnSaturation();
+ }
+
+ // Just a check that merges work.
+ EXPECT_CALL(*gl_, DeletePathsNV(merge_candidate.first_service_id,
+ merge_candidate_range + kMergeCheckRange))
+ .Times(1)
+ .RetiresOnSaturation();
+
+ // Remove all ids. This should cause the expected amount of DeletePathsNV
+ // calls.
+ manager_->RemovePaths(1, std::numeric_limits<GLsizei>::max());
+
+ for (auto& range : kIdRanges) {
+ ASSERT_FALSE(
+ manager_->HasPathsInRange(range.first_client_id, range.last_client_id));
+ }
+}
+
+TEST_F(PathManagerTest, DeleteBigRange) {
+ // Allocates two ranges which in path manager end up merging as one
+ // big range. The range will be too big to fit in one DeletePaths
+ // call. Test that the range is deleted correctly with two calls.
+ const GLuint kFirstClientId1 = 1;
+ const GLsizei kRange1 = std::numeric_limits<GLsizei>::max() - 3;
+ const GLuint kLastClientId1 = kFirstClientId1 + kRange1 - 1;
+ const GLuint kFirstServiceId1 = 77;
+ const GLuint kLastServiceId1 = kFirstServiceId1 + kRange1 - 1;
+
+ const GLuint kFirstClientId2 = kLastClientId1 + 1;
+ const GLsizei kRange2 = 15;
+ const GLuint kLastClientId2 = kFirstClientId2 + kRange2 - 1;
+ const GLuint kFirstServiceId2 = kLastServiceId1 + 1;
+
+ const GLsizei kFirstDeleteRange = std::numeric_limits<GLsizei>::max();
+ const GLsizei kSecondDeleteRange = kRange2 - (kFirstDeleteRange - kRange1);
+ const GLuint kSecondDeleteFirstServiceId =
+ kFirstServiceId1 + kFirstDeleteRange;
+
+ EXPECT_CALL(*gl_, DeletePathsNV(kFirstServiceId1,
+ std::numeric_limits<GLsizei>::max()))
+ .RetiresOnSaturation();
+
+ EXPECT_CALL(*gl_, DeletePathsNV(kSecondDeleteFirstServiceId,
+ kSecondDeleteRange)).RetiresOnSaturation();
+
+ manager_->CreatePathRange(kFirstClientId1, kLastClientId1, kFirstServiceId1);
+ manager_->CreatePathRange(kFirstClientId2, kLastClientId2, kFirstServiceId2);
+ manager_->RemovePaths(0, std::numeric_limits<GLuint>::max());
+}
+
+} // namespace gles2
+
+} // namespace gpu
diff --git a/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc b/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc
index 0d17b7c..57f5dd0 100644
--- a/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc
+++ b/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc
@@ -7,11 +7,15 @@
#include <GLES2/gl2extchromium.h>
#include <cmath>
+#include "base/command_line.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/tests/gl_manager.h"
#include "gpu/command_buffer/tests/gl_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#define SHADER(Src) #Src
+
namespace gpu {
class CHROMIUMPathRenderingTest : public testing::Test {
@@ -22,7 +26,9 @@ class CHROMIUMPathRenderingTest : public testing::Test {
void SetUp() override {
GLManager::Options options;
options.size = gfx::Size(kResolution, kResolution);
- gl_.Initialize(options);
+ base::CommandLine command_line(*base::CommandLine::ForCurrentProcess());
+ command_line.AppendSwitch(switches::kEnableGLPathRendering);
+ gl_.InitializeWithCommandLine(options, &command_line);
}
void TearDown() override { gl_.Destroy(); }
@@ -37,13 +43,156 @@ class CHROMIUMPathRenderingTest : public testing::Test {
EXPECT_EQ(static_cast<GLint>(round(expected[i])), actual[i]);
}
}
+
+ void SetupStateForTestPattern() {
+ glViewport(0, 0, kResolution, kResolution);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glStencilMask(0xffffffff);
+ glClearStencil(0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ static const char* kVertexShaderSource =
+ SHADER(void main() { gl_Position = vec4(1); });
+ static const char* kFragmentShaderSource =
+ SHADER(precision mediump float; uniform vec4 color;
+ void main() { gl_FragColor = color; });
+
+ GLuint program =
+ GLTestHelper::LoadProgram(kVertexShaderSource, kFragmentShaderSource);
+ glUseProgram(program);
+ color_loc_ = glGetUniformLocation(program, "color");
+ glDeleteProgram(program);
+
+ // Set up orthogonal projection with near/far plane distance of 2.
+ static GLfloat matrix[16] = {2.0f / (kResolution - 1),
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 2.0f / (kResolution - 1),
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ -1.0f,
+ 0.0f,
+ -1.0f,
+ -1.0f,
+ 0.0f,
+ 1.0f};
+ glMatrixLoadfCHROMIUM(GL_PATH_PROJECTION_CHROMIUM, matrix);
+ glMatrixLoadIdentityCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM);
+
+ glEnable(GL_STENCIL_TEST);
+
+ GLTestHelper::CheckGLError("no errors at state setup", __LINE__);
+ }
+
+ void SetupPathStateForTestPattern(GLuint path) {
+ static const GLubyte kCommands[] = {GL_MOVE_TO_CHROMIUM,
+ GL_LINE_TO_CHROMIUM,
+ GL_QUADRATIC_CURVE_TO_CHROMIUM,
+ GL_CUBIC_CURVE_TO_CHROMIUM,
+ GL_CLOSE_PATH_CHROMIUM};
+
+ static const GLfloat kCoords[] = {50.0f,
+ 50.0f,
+ 75.0f,
+ 75.0f,
+ 100.0f,
+ 62.5f,
+ 50.0f,
+ 25.5f,
+ 0.0f,
+ 62.5f,
+ 50.0f,
+ 50.0f,
+ 25.0f,
+ 75.0f};
+
+ glPathCommandsCHROMIUM(path, arraysize(kCommands), kCommands,
+ arraysize(kCoords), GL_FLOAT, kCoords);
+
+ glPathParameterfCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM, 5.0f);
+ glPathParameterfCHROMIUM(path, GL_PATH_MITER_LIMIT_CHROMIUM, 1.0f);
+ glPathParameterfCHROMIUM(path, GL_PATH_STROKE_BOUND_CHROMIUM, .02f);
+ glPathParameteriCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM,
+ GL_ROUND_CHROMIUM);
+ glPathParameteriCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM,
+ GL_SQUARE_CHROMIUM);
+ }
+
+ void VerifyTestPatternFill(float x, float y) {
+ static const float kFillCoords[] = {
+ 55.0f, 55.0f, 50.0f, 28.0f, 66.0f, 63.0f};
+ static const uint8 kBlue[] = {0, 0, 255, 255};
+
+ for (size_t i = 0; i < arraysize(kFillCoords); i += 2) {
+ float fx = kFillCoords[i];
+ float fy = kFillCoords[i + 1];
+
+ EXPECT_TRUE(GLTestHelper::CheckPixels(x + fx, y + fy, 1, 1, 0, kBlue));
+ }
+ }
+
+ void VerifyTestPatternBg(float x, float y) {
+ const float kBackgroundCoords[] = {80.0f, 80.0f, 20.0f, 20.0f, 90.0f, 1.0f};
+ const uint8 kExpectedColor[] = {0, 0, 0, 0};
+
+ for (size_t i = 0; i < arraysize(kBackgroundCoords); i += 2) {
+ float bx = kBackgroundCoords[i];
+ float by = kBackgroundCoords[i + 1];
+
+ EXPECT_TRUE(
+ GLTestHelper::CheckPixels(x + bx, y + by, 1, 1, 0, kExpectedColor));
+ }
+ }
+
+ void VerifyTestPatternStroke(float x, float y) {
+ // Inside the stroke we should have green.
+ const uint8 kGreen[] = {0, 255, 0, 255};
+ EXPECT_TRUE(GLTestHelper::CheckPixels(x + 50, y + 53, 1, 1, 0, kGreen));
+ EXPECT_TRUE(GLTestHelper::CheckPixels(x + 26, y + 76, 1, 1, 0, kGreen));
+
+ // Outside the path we should have black.
+ const uint8 black[] = {0, 0, 0, 0};
+ EXPECT_TRUE(GLTestHelper::CheckPixels(x + 10, y + 10, 1, 1, 0, black));
+ EXPECT_TRUE(GLTestHelper::CheckPixels(x + 80, y + 80, 1, 1, 0, black));
+ }
+
+ void TryAllDrawFunctions(GLuint path, GLenum expected_error) {
+ glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F);
+ EXPECT_EQ(expected_error, glGetError());
+
+ glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F);
+ EXPECT_EQ(expected_error, glGetError());
+
+ glStencilStrokePathCHROMIUM(path, 0x80, 0x80);
+ EXPECT_EQ(expected_error, glGetError());
+
+ glCoverFillPathCHROMIUM(path, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(expected_error, glGetError());
+
+ glCoverStrokePathCHROMIUM(path, GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(expected_error, glGetError());
+
+ glStencilThenCoverStrokePathCHROMIUM(path, 0x80, 0x80,
+ GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(expected_error, glGetError());
+
+ glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F,
+ GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(expected_error, glGetError());
+ }
+
GLManager gl_;
+ GLint color_loc_;
};
TEST_F(CHROMIUMPathRenderingTest, TestMatrix) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering")) {
+ if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
return;
- }
+
static const GLfloat kIdentityMatrix[16] = {
1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
@@ -86,25 +235,388 @@ TEST_F(CHROMIUMPathRenderingTest, TestMatrix) {
}
TEST_F(CHROMIUMPathRenderingTest, TestMatrixErrors) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering")) {
+ if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
return;
- }
+
GLfloat mf[16];
memset(mf, 0, sizeof(mf));
- // This should fail.
+ glMatrixLoadfCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM, mf);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ glMatrixLoadIdentityCHROMIUM(GL_PATH_PROJECTION_CHROMIUM);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ // Test that invalid matrix targets fail.
glMatrixLoadfCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM - 1, mf);
EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
- glMatrixLoadfCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM, mf);
+ // Test that invalid matrix targets fail.
+ glMatrixLoadIdentityCHROMIUM(GL_PATH_PROJECTION_CHROMIUM + 1);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
+}
+
+TEST_F(CHROMIUMPathRenderingTest, TestSimpleCalls) {
+ if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ return;
+
+ // This is unspecified in NV_path_rendering.
+ EXPECT_EQ(0u, glGenPathsCHROMIUM(0));
+
+ GLuint path = glGenPathsCHROMIUM(1);
+ EXPECT_NE(path, 0u);
+ glDeletePathsCHROMIUM(path, 1);
EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
- // This should fail.
- glMatrixLoadIdentityCHROMIUM(GL_PATH_PROJECTION_CHROMIUM + 1);
+ GLuint first_path = glGenPathsCHROMIUM(5);
+ EXPECT_NE(first_path, 0u);
+ glDeletePathsCHROMIUM(first_path, 5);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ // Test deleting paths that are not actually allocated:
+ // "unused names in /paths/ are silently ignored".
+ first_path = glGenPathsCHROMIUM(5);
+ EXPECT_NE(first_path, 0u);
+ glDeletePathsCHROMIUM(first_path, 6);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ GLsizei big_range = 0xffff;
+ // Setting big_range = std::numeric_limits<GLsizei>::max() should go through
+ // too, as far as NV_path_rendering is concerned. Current chromium side id
+ // allocator will use too much memory.
+ first_path = glGenPathsCHROMIUM(big_range);
+ EXPECT_NE(first_path, 0u);
+ glDeletePathsCHROMIUM(first_path, big_range);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ // Test glIsPathCHROMIUM().
+ path = glGenPathsCHROMIUM(1);
+ EXPECT_FALSE(glIsPathCHROMIUM(path));
+ GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
+ GLfloat coords[] = {50.0f, 50.0f};
+ glPathCommandsCHROMIUM(path, arraysize(commands), commands, arraysize(coords),
+ GL_FLOAT, coords);
+ EXPECT_TRUE(glIsPathCHROMIUM(path));
+ glDeletePathsCHROMIUM(path, 1);
+ EXPECT_FALSE(glIsPathCHROMIUM(path));
+}
+
+TEST_F(CHROMIUMPathRenderingTest, TestGenDeleteErrors) {
+ if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ return;
+
+ // GenPaths / DeletePaths tests.
+ // std::numeric_limits<GLuint>::max() is wrong for GLsizei.
+ GLuint first_path = glGenPathsCHROMIUM(std::numeric_limits<GLuint>::max());
+ EXPECT_EQ(first_path, 0u);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+
+ first_path = glGenPathsCHROMIUM(-1);
+ EXPECT_EQ(first_path, 0u);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+
+ glDeletePathsCHROMIUM(1, -5);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+
+ first_path = glGenPathsCHROMIUM(-1);
+ EXPECT_EQ(first_path, 0u);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+
+ // Test that delete with first_id and range such that first_id + range
+ // overflows the GLuint. Example:
+ // Range is 0x7fffffff. First id is X. Last id will be X + 0x7ffffffe.
+ // X = 0x80000001 would succeed, where as X = 0x80000002 would fail.
+ // To get 0x80000002, we need to allocate first 0x7fffffff and then
+ // 3 (0x80000000, 0x80000001 and 0x80000002).
+ // While not guaranteed by the API, we expect the implementation
+ // hands us deterministic ids.
+ first_path = glGenPathsCHROMIUM(std::numeric_limits<GLsizei>::max());
+ EXPECT_EQ(first_path, 1u);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ GLuint additional_paths = glGenPathsCHROMIUM(3);
+ EXPECT_EQ(additional_paths,
+ static_cast<GLuint>(std::numeric_limits<GLsizei>::max()) + 1u);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ // Test that passing a range so big that it would overflow client_id
+ // + range - 1 check causes an error.
+ glDeletePathsCHROMIUM(additional_paths + 2u,
+ std::numeric_limits<GLsizei>::max());
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+
+ // Cleanup the above allocations. Also test that passing max value still
+ // works.
+ glDeletePathsCHROMIUM(1, std::numeric_limits<GLsizei>::max());
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ glDeletePathsCHROMIUM(std::numeric_limits<GLsizei>::max(),
+ std::numeric_limits<GLsizei>::max());
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+TEST_F(CHROMIUMPathRenderingTest, TestPathParameterErrors) {
+ if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ return;
+
+ GLuint path = glGenPathsCHROMIUM(1);
+ // PathParameter*: Wrong value for the pname should fail.
+ glPathParameteriCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM, GL_FLAT_CHROMIUM);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+ glPathParameterfCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM,
+ GL_MITER_REVERT_CHROMIUM);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+
+ // PathParameter*: Wrong floating-point value should fail.
+ glPathParameterfCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM, -0.1f);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+ glPathParameterfCHROMIUM(path, GL_PATH_MITER_LIMIT_CHROMIUM,
+ std::numeric_limits<float>::quiet_NaN());
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+ glPathParameterfCHROMIUM(path, GL_PATH_MITER_LIMIT_CHROMIUM,
+ std::numeric_limits<float>::infinity());
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+
+ // PathParameter*: Wrong pname should fail.
+ glPathParameteriCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM - 1, 5);
EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
+ glDeletePathsCHROMIUM(path, 1);
+}
- glMatrixLoadIdentityCHROMIUM(GL_PATH_PROJECTION_CHROMIUM);
+TEST_F(CHROMIUMPathRenderingTest, TestPathObjectState) {
+ if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ return;
+
+ glViewport(0, 0, kResolution, kResolution);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glStencilMask(0xffffffff);
+ glClearStencil(0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+
+ // Test that trying to draw non-existing paths does not produce errors or
+ // results.
+ GLuint non_existing_paths[] = {0, 55, 74744};
+ for (auto& p : non_existing_paths) {
+ EXPECT_FALSE(glIsPathCHROMIUM(p));
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ TryAllDrawFunctions(p, GL_NO_ERROR);
+ }
+
+ // Path name marked as used but without path object state causes
+ // a GL error upon any draw command.
+ GLuint path = glGenPathsCHROMIUM(1);
+ EXPECT_FALSE(glIsPathCHROMIUM(path));
+ TryAllDrawFunctions(path, GL_INVALID_OPERATION);
+ glDeletePathsCHROMIUM(path, 1);
+
+ // Document a bit of an inconsistency: path name marked as used but without
+ // path object state causes a GL error upon any draw command (tested above).
+ // Path name that had path object state, but then was "cleared", still has a
+ // path object state, even though the state is empty.
+ path = glGenPathsCHROMIUM(1);
+ EXPECT_FALSE(glIsPathCHROMIUM(path));
+ GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
+ GLfloat coords[] = {50.0f, 50.0f};
+ glPathCommandsCHROMIUM(path, arraysize(commands), commands, arraysize(coords),
+ GL_FLOAT, coords);
+ EXPECT_TRUE(glIsPathCHROMIUM(path));
+ glPathCommandsCHROMIUM(path, 0, NULL, 0, GL_FLOAT, NULL);
+ EXPECT_TRUE(glIsPathCHROMIUM(path)); // The surprise.
+ TryAllDrawFunctions(path, GL_NO_ERROR);
+ glDeletePathsCHROMIUM(path, 1);
+
+ // Document a bit of an inconsistency: "clearing" a used path name causes
+ // path to acquire state.
+ path = glGenPathsCHROMIUM(1);
+ EXPECT_FALSE(glIsPathCHROMIUM(path));
+ glPathCommandsCHROMIUM(path, 0, NULL, 0, GL_FLOAT, NULL);
+ EXPECT_TRUE(glIsPathCHROMIUM(path)); // The surprise.
+ glDeletePathsCHROMIUM(path, 1);
+
+ // Make sure nothing got drawn by the drawing commands that should not produce
+ // anything.
+ const uint8 black[] = {0, 0, 0, 0};
+ EXPECT_TRUE(
+ GLTestHelper::CheckPixels(0, 0, kResolution, kResolution, 0, black));
+}
+
+TEST_F(CHROMIUMPathRenderingTest, TestUnnamedPathsErrors) {
+ if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ return;
+
+ // Unnamed paths: Trying to create a path object with non-existing path name
+ // produces error. (Not a error in real NV_path_rendering).
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
+ GLfloat coords[] = {50.0f, 50.0f};
+ glPathCommandsCHROMIUM(555, arraysize(commands), commands, arraysize(coords),
+ GL_FLOAT, coords);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+
+ // PathParameter*: Using non-existing path object produces error.
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ glPathParameterfCHROMIUM(555, GL_PATH_STROKE_WIDTH_CHROMIUM, 5.0f);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ glPathParameteriCHROMIUM(555, GL_PATH_JOIN_STYLE_CHROMIUM, GL_ROUND_CHROMIUM);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+}
+
+TEST_F(CHROMIUMPathRenderingTest, TestPathCommandsErrors) {
+ if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ return;
+
+ static const GLenum kInvalidCoordType = GL_NONE;
+
+ GLuint path = glGenPathsCHROMIUM(1);
+ GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
+ GLfloat coords[] = {50.0f, 50.0f};
+
+ glPathCommandsCHROMIUM(path, arraysize(commands), commands, -4, GL_FLOAT,
+ coords);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+
+ glPathCommandsCHROMIUM(path, -1, commands, arraysize(coords), GL_FLOAT,
+ coords);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+
+ glPathCommandsCHROMIUM(path, arraysize(commands), commands, arraysize(coords),
+ kInvalidCoordType, coords);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
+
+ // These can not distinquish between the check that should fail them.
+ // This should fail due to coord count * float size overflow.
+ glPathCommandsCHROMIUM(path, arraysize(commands), commands,
+ std::numeric_limits<GLsizei>::max(), GL_FLOAT, coords);
+ // This should fail due to cmd count + coord count * short size.
+ glPathCommandsCHROMIUM(path, arraysize(commands), commands,
+ std::numeric_limits<GLsizei>::max(), GL_SHORT, coords);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+
+ glDeletePathsCHROMIUM(path, 1);
+}
+
+TEST_F(CHROMIUMPathRenderingTest, TestPathRenderingInvalidArgs) {
+ if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ return;
+
+ GLuint path = glGenPathsCHROMIUM(1);
+ glPathCommandsCHROMIUM(path, 0, NULL, 0, GL_FLOAT, NULL);
+
+ // Verify that normal calls work.
+ glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F);
EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F,
+ GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ // Using invalid fill mode causes INVALID_ENUM.
+ glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM - 1, 0x7F);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
+ glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM - 1, 0x7F,
+ GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
+
+ // Using invalid cover mode causes INVALID_ENUM.
+ glCoverFillPathCHROMIUM(path, GL_CONVEX_HULL_CHROMIUM - 1);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
+ glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F,
+ GL_BOUNDING_BOX_CHROMIUM + 1);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
+
+ // Using mask+1 not being power of two causes INVALID_VALUE with up/down fill
+ // mode.
+ glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x40);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+ glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_DOWN_CHROMIUM, 12,
+ GL_BOUNDING_BOX_CHROMIUM);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+
+ glDeletePathsCHROMIUM(path, 1);
+}
+
+// Tests that drawing with CHROMIUM_path_rendering functions work.
+TEST_F(CHROMIUMPathRenderingTest, TestPathRendering) {
+ if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ return;
+
+ static const float kBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
+ static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
+
+ SetupStateForTestPattern();
+
+ GLuint path = glGenPathsCHROMIUM(1);
+ SetupPathStateForTestPattern(path);
+
+ // Do the stencil fill, cover fill, stencil stroke, cover stroke
+ // in unconventional order:
+ // 1) stencil the stroke in stencil high bit
+ // 2) stencil the fill in low bits
+ // 3) cover the fill
+ // 4) cover the stroke
+ // This is done to check that glPathStencilFunc works, eg the mask
+ // goes through. Stencil func is not tested ATM, for simplicity.
+
+ glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
+ glStencilStrokePathCHROMIUM(path, 0x80, 0x80);
+
+ glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
+ glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F);
+
+ glStencilFunc(GL_LESS, 0, 0x7F);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+ glUniform4fv(color_loc_, 1, kBlue);
+ glCoverFillPathCHROMIUM(path, GL_BOUNDING_BOX_CHROMIUM);
+
+ glStencilFunc(GL_EQUAL, 0x80, 0x80);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+ glUniform4fv(color_loc_, 1, kGreen);
+ glCoverStrokePathCHROMIUM(path, GL_CONVEX_HULL_CHROMIUM);
+
+ glDeletePathsCHROMIUM(path, 1);
+
+ // Verify the image.
+ VerifyTestPatternFill(0.0f, 0.0f);
+ VerifyTestPatternBg(0.0f, 0.0f);
+ VerifyTestPatternStroke(0.0f, 0.0f);
+}
+
+// Tests that drawing with CHROMIUM_path_rendering
+// StencilThenCover{Stroke,Fill}Path functions work.
+TEST_F(CHROMIUMPathRenderingTest, TestPathRenderingThenFunctions) {
+ if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ return;
+
+ static float kBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
+ static float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
+
+ SetupStateForTestPattern();
+
+ GLuint path = glGenPathsCHROMIUM(1);
+ SetupPathStateForTestPattern(path);
+
+ glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
+ glStencilFunc(GL_EQUAL, 0x80, 0x80);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+ glUniform4fv(color_loc_, 1, kGreen);
+ glStencilThenCoverStrokePathCHROMIUM(path, 0x80, 0x80,
+ GL_BOUNDING_BOX_CHROMIUM);
+
+ glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
+ glStencilFunc(GL_LESS, 0, 0x7F);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+ glUniform4fv(color_loc_, 1, kBlue);
+ glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F,
+ GL_CONVEX_HULL_CHROMIUM);
+
+ glDeletePathsCHROMIUM(path, 1);
+
+ // Verify the image.
+ VerifyTestPatternFill(0.0f, 0.0f);
+ VerifyTestPatternBg(0.0f, 0.0f);
+ VerifyTestPatternStroke(0.0f, 0.0f);
}
} // namespace gpu