| Index: gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
|
| 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 dbb9100fa17425892ee6d543244ceb7b7cac4afe..4f1cca5ef4553c988b9c4d4a4700e8a302e3de14 100644
|
| --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
|
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
|
| @@ -111,6 +111,56 @@ TEST_P(GLES2DecoderTestDisabledExtensions, CHROMIUMPathRenderingDisabled) {
|
| cmd.Init(kClientPathId, 1, 2, GL_BOUNDING_BOX_CHROMIUM);
|
| EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
|
| }
|
| + {
|
| + cmds::StencilFillPathInstancedCHROMIUM cmd;
|
| + GLuint* paths = GetSharedMemoryAs<GLuint*>();
|
| + paths[0] = kClientPathId;
|
| + cmd.Init(1, GL_UNSIGNED_INT, shared_memory_id_, shared_memory_offset_, 0,
|
| + GL_COUNT_UP_CHROMIUM, 1, GL_NONE, 0, 0);
|
| + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
|
| + }
|
| + {
|
| + cmds::StencilStrokePathInstancedCHROMIUM cmd;
|
| + GLuint* paths = GetSharedMemoryAs<GLuint*>();
|
| + paths[0] = kClientPathId;
|
| + cmd.Init(1, GL_UNSIGNED_INT, shared_memory_id_, shared_memory_offset_, 0,
|
| + 0x80, 0x80, GL_NONE, 0, 0);
|
| + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
|
| + }
|
| + {
|
| + cmds::CoverFillPathInstancedCHROMIUM cmd;
|
| + GLuint* paths = GetSharedMemoryAs<GLuint*>();
|
| + paths[0] = kClientPathId;
|
| + cmd.Init(1, GL_UNSIGNED_INT, shared_memory_id_, shared_memory_offset_, 0,
|
| + GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM, GL_NONE, 0, 0);
|
| + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
|
| + }
|
| + {
|
| + cmds::CoverStrokePathInstancedCHROMIUM cmd;
|
| + GLuint* paths = GetSharedMemoryAs<GLuint*>();
|
| + paths[0] = kClientPathId;
|
| + cmd.Init(1, GL_UNSIGNED_INT, shared_memory_id_, shared_memory_offset_, 0,
|
| + GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM, GL_NONE, 0, 0);
|
| + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
|
| + }
|
| + {
|
| + cmds::StencilThenCoverFillPathInstancedCHROMIUM cmd;
|
| + GLuint* paths = GetSharedMemoryAs<GLuint*>();
|
| + paths[0] = kClientPathId;
|
| + cmd.Init(1, GL_UNSIGNED_INT, shared_memory_id_, shared_memory_offset_, 0,
|
| + GL_COUNT_UP_CHROMIUM, 1,
|
| + GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM, GL_NONE, 0, 0);
|
| + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
|
| + }
|
| + {
|
| + cmds::StencilThenCoverStrokePathInstancedCHROMIUM cmd;
|
| + GLuint* paths = GetSharedMemoryAs<GLuint*>();
|
| + paths[0] = kClientPathId;
|
| + cmd.Init(1, GL_UNSIGNED_INT, shared_memory_id_, shared_memory_offset_, 0,
|
| + 0x80, 0x80, GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM, GL_NONE, 0,
|
| + 0);
|
| + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
|
| + }
|
| }
|
|
|
| class GLES2DecoderTestWithCHROMIUMPathRendering : public GLES2DecoderTest {
|
| @@ -136,12 +186,273 @@ class GLES2DecoderTestWithCHROMIUMPathRendering : public GLES2DecoderTest {
|
| cmds::GenPathsCHROMIUM cmd;
|
| cmd.Init(client_path_id_, 1);
|
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| +
|
| + // The tests use client_path_id_ to test all sorts of drawing. The NVPR API
|
| + // behaves differently with a path name that is "used" but not which does
|
| + // not "allocate path object state" and a path name that is a name of a real
|
| + // path object. The drawing with former causes GL error while latter works
|
| + // ok, even if there is nothing in the actual path object. To remain
|
| + // compatible with the API, we allocate path object state even when using
|
| + // the mock API.
|
| + EXPECT_CALL(*gl_,
|
| + PathCommandsNV(kServicePathId, 0, NULL, 0, GL_FLOAT, NULL))
|
| + .RetiresOnSaturation();
|
| + cmds::PathCommandsCHROMIUM pcmd;
|
| + pcmd.Init(client_path_id_, 0, 0, 0, 0, GL_FLOAT, 0, 0);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(pcmd));
|
| }
|
|
|
| protected:
|
| template <typename TypeParam>
|
| void TestPathCommandsCHROMIUMCoordTypes();
|
|
|
| + struct InstancedTestcase {
|
| + GLsizei num_paths;
|
| + const GLuint* paths;
|
| + GLuint path_base;
|
| + GLenum fill_mode;
|
| + GLuint reference;
|
| + GLuint mask;
|
| + GLenum transform_type;
|
| + const GLfloat* transform_values;
|
| + size_t sizeof_paths; // Used for copying to shm buffer.
|
| + size_t sizeof_transform_values; // Used for copying to shm buffer.
|
| + error::Error expected_error;
|
| + GLint expected_gl_error;
|
| + bool expect_gl_call;
|
| + };
|
| +
|
| + void CallAllInstancedCommands(const InstancedTestcase& testcase) {
|
| + // Note: for testcases that expect a call, We do not compare the 'paths'
|
| + // array during EXPECT_CALL due to it being void*. Instead, we rely on the
|
| + // fact that if the path base was not added correctly, the paths wouldn't
|
| + // exists and the call wouldn't come through.
|
| +
|
| + bool copy_paths = false; // Paths are copied for each call that has paths,
|
| + // since the implementation modifies the memory
|
| + // area.
|
| + GLuint* paths = NULL;
|
| + uint32 paths_shm_id = 0;
|
| + uint32 paths_shm_offset = 0;
|
| + GLfloat* transforms = NULL;
|
| + uint32 transforms_shm_id = 0;
|
| + uint32 transforms_shm_offset = 0;
|
| +
|
| + if (testcase.transform_values) {
|
| + transforms = GetSharedMemoryAs<GLfloat*>();
|
| + transforms_shm_id = shared_memory_id_;
|
| + transforms_shm_offset = shared_memory_offset_;
|
| + memcpy(transforms, testcase.transform_values,
|
| + testcase.sizeof_transform_values);
|
| + } else {
|
| + DCHECK(testcase.sizeof_transform_values == 0);
|
| + }
|
| + if (testcase.paths) {
|
| + paths = GetSharedMemoryAsWithOffset<GLuint*>(
|
| + testcase.sizeof_transform_values);
|
| + paths_shm_id = shared_memory_id_;
|
| + paths_shm_offset =
|
| + shared_memory_offset_ + testcase.sizeof_transform_values;
|
| + copy_paths = true;
|
| + } else {
|
| + DCHECK(testcase.sizeof_paths == 0);
|
| + }
|
| +
|
| + if (testcase.expect_gl_call) {
|
| + EXPECT_CALL(*gl_, StencilFillPathInstancedNV(
|
| + testcase.num_paths, GL_UNSIGNED_INT, paths, 0,
|
| + testcase.fill_mode, testcase.mask,
|
| + testcase.transform_type, transforms))
|
| + .RetiresOnSaturation();
|
| + }
|
| + if (copy_paths) {
|
| + memcpy(paths, testcase.paths, testcase.sizeof_paths);
|
| + }
|
| + {
|
| + cmds::StencilFillPathInstancedCHROMIUM sfi_cmd;
|
| + sfi_cmd.Init(testcase.num_paths, GL_UNSIGNED_INT, paths_shm_id,
|
| + paths_shm_offset, testcase.path_base, testcase.fill_mode,
|
| + testcase.mask, testcase.transform_type, transforms_shm_id,
|
| + transforms_shm_offset);
|
| + EXPECT_EQ(testcase.expected_error, ExecuteCmd(sfi_cmd));
|
| + EXPECT_EQ(testcase.expected_gl_error, GetGLError());
|
| + }
|
| +
|
| + if (testcase.expect_gl_call) {
|
| + EXPECT_CALL(*gl_, StencilStrokePathInstancedNV(
|
| + testcase.num_paths, GL_UNSIGNED_INT, paths, 0,
|
| + testcase.reference, testcase.mask,
|
| + testcase.transform_type, transforms))
|
| + .RetiresOnSaturation();
|
| + }
|
| + if (copy_paths) {
|
| + memcpy(paths, testcase.paths, testcase.sizeof_paths);
|
| + }
|
| + {
|
| + cmds::StencilStrokePathInstancedCHROMIUM ssi_cmd;
|
| + ssi_cmd.Init(testcase.num_paths, GL_UNSIGNED_INT, paths_shm_id,
|
| + paths_shm_offset, testcase.path_base, testcase.reference,
|
| + testcase.mask, testcase.transform_type, transforms_shm_id,
|
| + transforms_shm_offset);
|
| + EXPECT_EQ(testcase.expected_error, ExecuteCmd(ssi_cmd));
|
| + EXPECT_EQ(testcase.expected_gl_error, GetGLError());
|
| + }
|
| +
|
| + if (testcase.expect_gl_call) {
|
| + EXPECT_CALL(*gl_, CoverFillPathInstancedNV(
|
| + testcase.num_paths, GL_UNSIGNED_INT, paths, 0,
|
| + GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV,
|
| + testcase.transform_type, transforms))
|
| + .RetiresOnSaturation();
|
| + }
|
| + if (copy_paths) {
|
| + memcpy(paths, testcase.paths, testcase.sizeof_paths);
|
| + }
|
| + {
|
| + cmds::CoverFillPathInstancedCHROMIUM cfi_cmd;
|
| + cfi_cmd.Init(
|
| + testcase.num_paths, GL_UNSIGNED_INT, paths_shm_id, paths_shm_offset,
|
| + testcase.path_base, GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM,
|
| + testcase.transform_type, transforms_shm_id, transforms_shm_offset);
|
| + EXPECT_EQ(testcase.expected_error, ExecuteCmd(cfi_cmd));
|
| + EXPECT_EQ(testcase.expected_gl_error, GetGLError());
|
| + }
|
| + if (testcase.expect_gl_call) {
|
| + EXPECT_CALL(*gl_, CoverStrokePathInstancedNV(
|
| + testcase.num_paths, GL_UNSIGNED_INT, paths, 0,
|
| + GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV,
|
| + testcase.transform_type, transforms))
|
| + .RetiresOnSaturation();
|
| + }
|
| + if (copy_paths) {
|
| + memcpy(paths, testcase.paths, testcase.sizeof_paths);
|
| + }
|
| +
|
| + {
|
| + cmds::CoverStrokePathInstancedCHROMIUM csi_cmd;
|
| + csi_cmd.Init(
|
| + testcase.num_paths, GL_UNSIGNED_INT, paths_shm_id, paths_shm_offset,
|
| + testcase.path_base, GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM,
|
| + testcase.transform_type, transforms_shm_id, transforms_shm_offset);
|
| + EXPECT_EQ(testcase.expected_error, ExecuteCmd(csi_cmd));
|
| + EXPECT_EQ(testcase.expected_gl_error, GetGLError());
|
| + }
|
| +
|
| + if (testcase.expect_gl_call) {
|
| + EXPECT_CALL(*gl_, StencilThenCoverFillPathInstancedNV(
|
| + testcase.num_paths, GL_UNSIGNED_INT, paths, 0,
|
| + testcase.fill_mode, testcase.mask,
|
| + GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV,
|
| + testcase.transform_type, transforms))
|
| + .RetiresOnSaturation();
|
| + }
|
| + if (copy_paths) {
|
| + memcpy(paths, testcase.paths, testcase.sizeof_paths);
|
| + }
|
| + {
|
| + cmds::StencilThenCoverFillPathInstancedCHROMIUM stcfi_cmd;
|
| + stcfi_cmd.Init(testcase.num_paths, GL_UNSIGNED_INT, paths_shm_id,
|
| + paths_shm_offset, testcase.path_base, testcase.fill_mode,
|
| + testcase.mask, GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM,
|
| + testcase.transform_type, transforms_shm_id,
|
| + transforms_shm_offset);
|
| + EXPECT_EQ(testcase.expected_error, ExecuteCmd(stcfi_cmd));
|
| + EXPECT_EQ(testcase.expected_gl_error, GetGLError());
|
| + }
|
| +
|
| + if (testcase.expect_gl_call) {
|
| + EXPECT_CALL(*gl_, StencilThenCoverStrokePathInstancedNV(
|
| + testcase.num_paths, GL_UNSIGNED_INT, paths, 0,
|
| + testcase.reference, testcase.mask,
|
| + GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV,
|
| + testcase.transform_type, transforms))
|
| + .RetiresOnSaturation();
|
| + }
|
| + if (copy_paths) {
|
| + memcpy(paths, testcase.paths, testcase.sizeof_paths);
|
| + }
|
| + {
|
| + cmds::StencilThenCoverStrokePathInstancedCHROMIUM stcsi_cmd;
|
| + stcsi_cmd.Init(testcase.num_paths, GL_UNSIGNED_INT, paths_shm_id,
|
| + paths_shm_offset, testcase.path_base, testcase.reference,
|
| + testcase.mask, GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM,
|
| + testcase.transform_type, transforms_shm_id,
|
| + transforms_shm_offset);
|
| + EXPECT_EQ(testcase.expected_error, ExecuteCmd(stcsi_cmd));
|
| + EXPECT_EQ(testcase.expected_gl_error, GetGLError());
|
| + }
|
| + }
|
| +
|
| + void CallAllInstancedCommandsWithInvalidSHM(GLsizei num_paths,
|
| + const GLuint* paths,
|
| + GLuint* paths_shm,
|
| + uint32 paths_shm_id,
|
| + uint32 paths_shm_offset,
|
| + uint32 transforms_shm_id,
|
| + uint32 transforms_shm_offset) {
|
| + const GLuint kPathBase = 0;
|
| + const GLenum kFillMode = GL_INVERT;
|
| + const GLuint kMask = 0x80;
|
| + const GLuint kReference = 0xFF;
|
| + const GLuint kTransformType = GL_AFFINE_3D_CHROMIUM;
|
| + memcpy(paths_shm, paths, sizeof(GLuint) * num_paths);
|
| + {
|
| + cmds::StencilFillPathInstancedCHROMIUM sfi_cmd;
|
| + sfi_cmd.Init(num_paths, GL_UNSIGNED_INT, paths_shm_id, paths_shm_offset,
|
| + kPathBase, kFillMode, kMask, kTransformType,
|
| + transforms_shm_id, transforms_shm_offset);
|
| + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(sfi_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + }
|
| + memcpy(paths_shm, paths, sizeof(GLuint) * num_paths);
|
| + {
|
| + cmds::StencilStrokePathInstancedCHROMIUM ssi_cmd;
|
| + ssi_cmd.Init(num_paths, GL_UNSIGNED_INT, paths_shm_id, paths_shm_offset,
|
| + kPathBase, kReference, kMask, kTransformType,
|
| + transforms_shm_id, transforms_shm_offset);
|
| + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(ssi_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + }
|
| + memcpy(paths_shm, paths, sizeof(GLuint) * num_paths);
|
| + {
|
| + cmds::CoverFillPathInstancedCHROMIUM cfi_cmd;
|
| + cfi_cmd.Init(num_paths, GL_UNSIGNED_INT, paths_shm_id, paths_shm_offset,
|
| + kPathBase, GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM,
|
| + kTransformType, transforms_shm_id, transforms_shm_offset);
|
| + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cfi_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + }
|
| + memcpy(paths_shm, paths, sizeof(GLuint) * num_paths);
|
| + {
|
| + cmds::CoverStrokePathInstancedCHROMIUM csi_cmd;
|
| + csi_cmd.Init(num_paths, GL_UNSIGNED_INT, paths_shm_id, paths_shm_offset,
|
| + kPathBase, GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM,
|
| + kTransformType, transforms_shm_id, transforms_shm_offset);
|
| + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(csi_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + }
|
| + memcpy(paths_shm, paths, sizeof(GLuint) * num_paths);
|
| + {
|
| + cmds::StencilThenCoverFillPathInstancedCHROMIUM stcfi_cmd;
|
| + stcfi_cmd.Init(num_paths, GL_UNSIGNED_INT, paths_shm_id, paths_shm_offset,
|
| + kPathBase, kFillMode, kMask,
|
| + GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM, kTransformType,
|
| + transforms_shm_id, transforms_shm_offset);
|
| + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(stcfi_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + }
|
| + memcpy(paths_shm, paths, sizeof(GLuint) * num_paths);
|
| + {
|
| + cmds::StencilThenCoverStrokePathInstancedCHROMIUM stcsi_cmd;
|
| + stcsi_cmd.Init(num_paths, GL_UNSIGNED_INT, paths_shm_id, paths_shm_offset,
|
| + kPathBase, kReference, kMask,
|
| + GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM, kTransformType,
|
| + transforms_shm_id, transforms_shm_offset);
|
| + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(stcsi_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + }
|
| + }
|
| +
|
| GLuint client_path_id_;
|
| static const GLuint kServicePathId = 311;
|
| };
|
| @@ -187,7 +498,7 @@ TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, GenDeletePaths) {
|
| EXPECT_EQ(error::kNoError, ExecuteCmd(delete_cmd));
|
| EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
|
|
| - // DeletePaths client 0 causes no calls and no errors.
|
| + // DeletePaths client id 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());
|
| @@ -978,6 +1289,283 @@ TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
|
| TestPathCommandsCHROMIUMCoordTypes<GLfloat>();
|
| }
|
|
|
| +TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
|
| + StencilXFillPathInstancedCHROMIUMInvalidArgs) {
|
| + cmds::StencilFillPathInstancedCHROMIUM sfi_cmd;
|
| + cmds::StencilThenCoverFillPathInstancedCHROMIUM stcfi_cmd;
|
| +
|
| + const GLuint kPaths[] = {client_path_id_, client_path_id_ + 5,
|
| + client_path_id_, client_path_id_ + 18};
|
| + const GLsizei kPathCount = arraysize(kPaths);
|
| +
|
| + struct {
|
| + GLenum fill_mode;
|
| + GLuint mask;
|
| + GLint expected_error;
|
| + } testcases[] = {
|
| + // Using invalid fill mode produces invalid enum.
|
| + {GL_COUNT_UP_CHROMIUM - 1, 0x7F, GL_INVALID_ENUM},
|
| + {GL_COUNT_DOWN_CHROMIUM + 1, 0x7F, GL_INVALID_ENUM},
|
| + // Using /mask/+1 which is not power of two produces invalid value.
|
| + {GL_COUNT_UP_CHROMIUM, 0x80, GL_INVALID_VALUE},
|
| + {GL_COUNT_DOWN_CHROMIUM, 4, GL_INVALID_VALUE}};
|
| +
|
| + GLuint* paths = GetSharedMemoryAs<GLuint*>();
|
| +
|
| + for (size_t i = 0; i < arraysize(testcases); ++i) {
|
| + memcpy(paths, kPaths, sizeof(kPaths));
|
| + sfi_cmd.Init(kPathCount, GL_UNSIGNED_INT, shared_memory_id_,
|
| + shared_memory_offset_, 0, testcases[i].fill_mode,
|
| + testcases[i].mask, GL_NONE, 0, 0);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(sfi_cmd));
|
| + EXPECT_EQ(testcases[i].expected_error, GetGLError());
|
| +
|
| + memcpy(paths, kPaths, sizeof(kPaths));
|
| + stcfi_cmd.Init(kPathCount, GL_UNSIGNED_INT, shared_memory_id_,
|
| + shared_memory_offset_, 0, testcases[i].fill_mode,
|
| + testcases[i].mask,
|
| + GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM, GL_NONE, 0, 0);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(stcfi_cmd));
|
| + EXPECT_EQ(testcases[i].expected_error, GetGLError());
|
| + }
|
| +}
|
| +
|
| +TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
|
| + StencilXFillPathInstancedCHROMIUMFillMode) {
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| +
|
| + // Test different fill modes.
|
| + cmds::StencilFillPathInstancedCHROMIUM sfi_cmd;
|
| + cmds::StencilThenCoverFillPathInstancedCHROMIUM stcfi_cmd;
|
| +
|
| + const GLuint kPaths[] = {client_path_id_, client_path_id_ + 5,
|
| + client_path_id_, client_path_id_ + 18};
|
| + const GLsizei kPathCount = arraysize(kPaths);
|
| +
|
| + static const GLenum kFillModes[] = {GL_INVERT, GL_COUNT_UP_CHROMIUM,
|
| + GL_COUNT_DOWN_CHROMIUM};
|
| + const GLuint kMask = 0x7F;
|
| +
|
| + GLuint* paths = GetSharedMemoryAs<GLuint*>();
|
| +
|
| + for (size_t i = 0; i < arraysize(kFillModes); ++i) {
|
| + memcpy(paths, kPaths, sizeof(kPaths));
|
| + EXPECT_CALL(
|
| + *gl_, StencilFillPathInstancedNV(kPathCount, GL_UNSIGNED_INT, paths, 0,
|
| + kFillModes[i], kMask, GL_NONE, NULL))
|
| + .RetiresOnSaturation();
|
| + sfi_cmd.Init(kPathCount, GL_UNSIGNED_INT, shared_memory_id_,
|
| + shared_memory_offset_, 0, kFillModes[i], kMask, GL_NONE, 0, 0);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(sfi_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + memcpy(paths, kPaths, sizeof(kPaths));
|
| + EXPECT_CALL(*gl_,
|
| + StencilThenCoverFillPathInstancedNV(
|
| + kPathCount, GL_UNSIGNED_INT, paths, 0, kFillModes[i], kMask,
|
| + GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV, GL_NONE, NULL))
|
| + .RetiresOnSaturation();
|
| + stcfi_cmd.Init(kPathCount, GL_UNSIGNED_INT, shared_memory_id_,
|
| + shared_memory_offset_, 0, kFillModes[i], kMask,
|
| + GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM, GL_NONE, 0, 0);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(stcfi_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + }
|
| +}
|
| +
|
| +TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, InstancedCalls) {
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| +
|
| + const GLuint kPaths[] = {0, client_path_id_, 15, client_path_id_};
|
| + const GLsizei kPathCount = arraysize(kPaths);
|
| +
|
| + // The path base will be client_path_id_, and so 0 is a
|
| + // valid path.
|
| + const GLuint kPathBase = client_path_id_;
|
| + const GLuint kPathsWithBase[] = {0, 5, 0, 18};
|
| +
|
| + const GLenum kFillMode = GL_INVERT;
|
| + const GLuint kMask = 0x80;
|
| + const GLuint kReference = 0xFF;
|
| +
|
| + GLfloat transform_values[12 * kPathCount];
|
| + for (GLsizei i = 0; i < kPathCount; ++i) {
|
| + for (int j = 0; j < 12; ++j) {
|
| + transform_values[i * 12 + j] = 0.1f * j + i;
|
| + }
|
| + }
|
| +
|
| + InstancedTestcase testcases[] = {
|
| + // Test a normal call.
|
| + {kPathCount, kPaths, 0, kFillMode, kReference, kMask, GL_NONE, NULL,
|
| + sizeof(kPaths), 0, error::kNoError, GL_NO_ERROR, true},
|
| + // Test that the path base is applied correctly for each instanced call.
|
| + {kPathCount, kPathsWithBase, kPathBase, kFillMode, kReference, kMask,
|
| + GL_NONE, NULL, sizeof(kPaths), 0, error::kNoError, GL_NO_ERROR, true},
|
| + {kPathCount, kPathsWithBase, kPathBase, kFillMode, kReference, kMask,
|
| +
|
| + // Test all possible transform types. The float array is big enough for
|
| + // all the variants. The contents of the array in call is not checked,
|
| + // though.
|
| + GL_TRANSLATE_X_CHROMIUM, transform_values, sizeof(kPaths),
|
| + sizeof(transform_values), error::kNoError, GL_NO_ERROR, true},
|
| + {kPathCount, kPathsWithBase, kPathBase, kFillMode, kReference, kMask,
|
| + GL_TRANSLATE_Y_CHROMIUM, transform_values, sizeof(kPaths),
|
| + sizeof(transform_values), error::kNoError, GL_NO_ERROR, true},
|
| + {kPathCount, kPathsWithBase, kPathBase, kFillMode, kReference, kMask,
|
| + GL_TRANSLATE_2D_CHROMIUM, transform_values, sizeof(kPaths),
|
| + sizeof(transform_values), error::kNoError, GL_NO_ERROR, true},
|
| + {kPathCount, kPathsWithBase, kPathBase, kFillMode, kReference, kMask,
|
| + GL_TRANSLATE_3D_CHROMIUM, transform_values, sizeof(kPaths),
|
| + sizeof(transform_values), error::kNoError, GL_NO_ERROR, true},
|
| + {kPathCount, kPathsWithBase, kPathBase, kFillMode, kReference, kMask,
|
| + GL_AFFINE_2D_CHROMIUM, transform_values, sizeof(kPaths),
|
| + sizeof(transform_values), error::kNoError, GL_NO_ERROR, true},
|
| + {kPathCount, kPathsWithBase, kPathBase, kFillMode, kReference, kMask,
|
| + GL_AFFINE_3D_CHROMIUM, transform_values, sizeof(kPaths),
|
| + sizeof(transform_values), error::kNoError, GL_NO_ERROR, true},
|
| + {kPathCount, kPathsWithBase, kPathBase, kFillMode, kReference, kMask,
|
| + GL_TRANSPOSE_AFFINE_2D_CHROMIUM, transform_values, sizeof(kPaths),
|
| + sizeof(transform_values), error::kNoError, GL_NO_ERROR, true},
|
| + {kPathCount, kPathsWithBase, kPathBase, kFillMode, kReference, kMask,
|
| + GL_TRANSPOSE_AFFINE_3D_CHROMIUM, transform_values, sizeof(kPaths),
|
| + sizeof(transform_values), error::kNoError, GL_NO_ERROR, true}};
|
| +
|
| + for (size_t i = 0; i < arraysize(testcases); ++i) {
|
| + SCOPED_TRACE(testing::Message() << "InstancedCalls testcase " << i);
|
| + CallAllInstancedCommands(testcases[i]);
|
| + }
|
| +}
|
| +
|
| +TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, InstancedNoCalls) {
|
| + const GLuint kPaths[] = {1, client_path_id_, 5, client_path_id_};
|
| + const GLsizei kPathCount = arraysize(kPaths);
|
| +
|
| + const GLenum kFillMode = GL_INVERT;
|
| + const GLuint kMask = 0x80;
|
| + const GLuint kReference = 0xFF;
|
| + GLfloat transform_values[12 * kPathCount];
|
| + for (GLsizei i = 0; i < kPathCount; ++i) {
|
| + for (int j = 0; j < 12; ++j) {
|
| + transform_values[i * 12 + j] = 0.1f * j + i;
|
| + }
|
| + }
|
| +
|
| + // The path base will be client_path_id_, and so 0 is a valid path and others
|
| + // should be invalid.
|
| + const GLuint kInvalidPathBase = client_path_id_;
|
| + const GLuint kInvalidPathsWithBase[] = {1, client_path_id_, 5, 18};
|
| +
|
| + const GLuint kBigInvalidPathBase = std::numeric_limits<GLuint>::max() - 5;
|
| +
|
| + InstancedTestcase testcases[] = {
|
| + // Zero path count produces no error, no call.
|
| + {0, NULL, 0, kFillMode, kReference, kMask, GL_NONE, NULL, 0, 0,
|
| + error::kNoError, GL_NO_ERROR, false},
|
| +
|
| + // Zero path count, even with path data, produces no error, no call.
|
| + {0, kPaths, 0, kFillMode, kReference, kMask, GL_TRANSLATE_X_CHROMIUM,
|
| + transform_values, sizeof(kPaths), sizeof(transform_values),
|
| + error::kNoError, GL_NO_ERROR, false},
|
| +
|
| + // Negative path count produces error.
|
| + {-1, kPaths, 0, kFillMode, kReference, kMask, GL_TRANSLATE_X_CHROMIUM,
|
| + transform_values, sizeof(kPaths), sizeof(transform_values),
|
| + error::kNoError, GL_INVALID_VALUE, false},
|
| +
|
| + // Passing paths count but not having the shm data is a connection error.
|
| + {kPathCount, NULL, 0, kFillMode, kReference, kMask,
|
| + GL_TRANSLATE_X_CHROMIUM, transform_values, 0, sizeof(transform_values),
|
| + error::kOutOfBounds, GL_NO_ERROR, false},
|
| +
|
| + // Huge path count would cause huge transfer buffer, it does not go
|
| + // through.
|
| + {std::numeric_limits<GLsizei>::max() - 3, kPaths, 0, kFillMode,
|
| + kReference, kMask, GL_TRANSLATE_X_CHROMIUM, transform_values,
|
| + sizeof(kPaths), sizeof(transform_values), error::kOutOfBounds,
|
| + GL_NO_ERROR, false},
|
| +
|
| + // Test that the path base is applied correctly for each instanced call.
|
| + // In this case no path is marked as used, and so no GL function should be
|
| + // called and no error should be generated.
|
| + {kPathCount, kInvalidPathsWithBase, kInvalidPathBase, kFillMode,
|
| + kReference, kMask, GL_TRANSLATE_X_CHROMIUM, transform_values,
|
| + sizeof(kInvalidPathsWithBase), sizeof(transform_values), error::kNoError,
|
| + GL_NO_ERROR, false},
|
| +
|
| + // Test that if using path base causes path id to overflow, we get gl
|
| + // invalid operation error.
|
| + {kPathCount, kInvalidPathsWithBase, kBigInvalidPathBase, kFillMode,
|
| + kReference, kMask, GL_TRANSLATE_X_CHROMIUM, transform_values,
|
| + sizeof(kInvalidPathsWithBase), sizeof(transform_values), error::kNoError,
|
| + GL_INVALID_OPERATION, false},
|
| +
|
| + // Test that using correct paths but invalid transform type produces
|
| + // invalid enum.
|
| + {kPathCount, kPaths, 0, kFillMode, kReference, kMask,
|
| + GL_TRANSLATE_X_CHROMIUM - 1, transform_values, sizeof(kPaths),
|
| + sizeof(transform_values), error::kNoError, GL_INVALID_ENUM, false},
|
| +
|
| + // Test that if we have transform, not having the shm data is a connection
|
| + // error.
|
| + {kPathCount, kPaths, 0, kFillMode, kReference, kMask,
|
| + GL_TRANSLATE_X_CHROMIUM, NULL, sizeof(kPaths), 0, error::kOutOfBounds,
|
| + GL_NO_ERROR, false}};
|
| + for (size_t i = 0; i < arraysize(testcases); ++i) {
|
| + SCOPED_TRACE(testing::Message() << "InstancedNoCalls testcase " << i);
|
| + CallAllInstancedCommands(testcases[i]);
|
| + }
|
| +}
|
| +
|
| +TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, InstancedInvalidSHMValues) {
|
| + const GLuint kPaths[] = {1, client_path_id_, 5, client_path_id_};
|
| + const GLsizei kPathCount = arraysize(kPaths);
|
| + GLfloat transform_values[12 * kPathCount];
|
| + for (GLsizei i = 0; i < kPathCount; ++i) {
|
| + for (int j = 0; j < 12; ++j) {
|
| + transform_values[i * 12 + j] = 0.1f * j + i;
|
| + }
|
| + }
|
| + enum {
|
| + kPathsSHMIdInvalid = 1,
|
| + kPathsSHMOffsetInvalid = 1 << 1,
|
| + kTransformsHMIdInvalid = 1 << 2,
|
| + kTransformsHMOffsetInvalid = 1 << 3,
|
| + kFirstTestcase = kPathsSHMIdInvalid,
|
| + kLastTestcase = kTransformsHMOffsetInvalid
|
| + };
|
| +
|
| + for (int testcase = kFirstTestcase; testcase <= kLastTestcase; ++testcase) {
|
| + GLfloat* transforms = GetSharedMemoryAs<GLfloat*>();
|
| + uint32 transforms_shm_id = shared_memory_id_;
|
| + uint32 transforms_shm_offset = shared_memory_offset_;
|
| + memcpy(transforms, transform_values, sizeof(transform_values));
|
| +
|
| + GLuint* paths =
|
| + GetSharedMemoryAsWithOffset<GLuint*>(sizeof(transform_values));
|
| + uint32 paths_shm_id = shared_memory_id_;
|
| + uint32 paths_shm_offset = shared_memory_offset_ + sizeof(transform_values);
|
| +
|
| + if (testcase & kPathsSHMIdInvalid) {
|
| + paths_shm_id = kInvalidSharedMemoryId;
|
| + }
|
| + if (testcase & kPathsSHMOffsetInvalid) {
|
| + paths_shm_offset = kInvalidSharedMemoryOffset;
|
| + }
|
| + if (testcase & kTransformsHMIdInvalid) {
|
| + transforms_shm_id = kInvalidSharedMemoryId;
|
| + }
|
| + if (testcase & kTransformsHMOffsetInvalid) {
|
| + transforms_shm_offset = kInvalidSharedMemoryOffset;
|
| + }
|
| + SCOPED_TRACE(testing::Message() << "InstancedInvalidSHMValues testcase "
|
| + << testcase);
|
| + CallAllInstancedCommandsWithInvalidSHM(
|
| + kPathCount, kPaths, paths, paths_shm_id, paths_shm_offset,
|
| + transforms_shm_id, transforms_shm_offset);
|
| + }
|
| +}
|
| +
|
| #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h"
|
|
|
| } // namespace gles2
|
|
|