summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkkinnunen <kkinnunen@nvidia.com>2015-11-01 23:57:51 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-02 07:58:41 +0000
commitc8b449e1586d545db9f6692efa0aa4f990bc9658 (patch)
treeb3476907ba1385152760ca374e40dad008ebe9da
parentb907c9c34c99ed5445d2f94a8ef4a2fbc85808f6 (diff)
downloadchromium_src-c8b449e1586d545db9f6692efa0aa4f990bc9658.zip
chromium_src-c8b449e1586d545db9f6692efa0aa4f990bc9658.tar.gz
chromium_src-c8b449e1586d545db9f6692efa0aa4f990bc9658.tar.bz2
command_buffer: Support textured path rendering for CHROMIUM_path_rendering
Implement support textured path rendering in gpu command buffer for CHROMIUM_path_rendering. Add the concept of "fragment input" to the system: a fragment input is a fragment shader varying in the case the fragment shader of a shader program is used without the vertex shader. A fragment input can be referenced by the varying name in the shader code. As the vertex shader is skipped during path rendering, the fragment inputs will be populated with the functions added in this commit. Add following functions to the command buffer: BindFragmentInputLocationCHROMIUM ProgramPathFragmentInputGenCHROMIUM BindFragmentInputLocationCHROMIUM will bind a fragment input to a location supplied by the caller. The fragment input is identified by the varying name. The semantics of the call are similar to BindUniformLocationCHROMIUM, but of course the location bound with BindFragmentInputLocationCHROMIUM is part of fragment input location range. Concretely, BindFragmentInputLocationCHROMIUM is used to obtain a location to pass to ProgramPathFragmentInputGenCHROMIUM. ProgramPathFragmentInputGenCHROMIUM sets the "path fragment input generator" property of the fragment input identified by the location passed by the caller. This property, together with global path modelview transform and global path projection transform is used to generate the value of the fragment input. Concretely, ProgramPathFragmentInputGenCHROMIUM is used to obtain a value in the fragment input that is somehow relative to the fragment position in on the path coverage. When drawing normal vertex-based primitives, shading is done by setting the vertex position with an attribute or an uniform, the transform with an attribute or an uniform, transforming the position with the transform in vertex shader and interpolating the values for fragment varying. When drawing a path, the path position is set with projection and modelview matrix, transform is set with ProgramPathFragmentInputGenCHROMIUM and the system will then fill the fragment input based on the location of the fragment in the area covered by the path and the input generator mode (eye space or model space). Implement the BindFragmentInputLocationCHROMIUM by the means of program interface query API, which is part of OpenGL 4.3 and OpenGL ES 3.1. Alternatively, OpenGL pre 4.3 can have the functionality through ARB_program_interface_query. glGetProgramInterfaceiv, glGetProgramResourceiv, glGetProgramResourceName and glGetProgramResourceLocation are used to query the program for its fragment inputs after successful link. This list is then used to map caller-bound locations to actual locations. This is similar to existing logic for bound uniform and attribute locations. Note: this patch does not provide getter for fragment input location, so unbound fragment und locations to actual locations. This is similar to existing logic for bound uniform and attribute locations. Note: this patch does not provide getter for fragment input location, so unbound fragment inputs can not be used by the caller. Providing this would require implementation of the interface query API, which is too elaborate to be implemented without proper consumers. Note: as the query API is not available for the client, the fragment input information is not serialized between client and the service. Implement the ProgramPathFragmentInputGenCHROMIUM by means of NV_path_rendering ProgramPathFragmentInputGenNV. This is part of NV_path_rendering spec version 1.3. Changes gpu::gles2::ProgramManager to reference FeatureInfo of the ContextGroup, because the queries for the fragment input is only done if path rendering is enabled. Changes program_manager_unittests to have a common test base class. Remove some client/service program id constants from test functions that shadow ProgramManagerWithShader constants. Instead, use the common constants defined in the test class. Re-organizes the test classes to be able to use common ProgramManager from the test base class. Initialize the ProgramManager in SetUp phase. This is done to be able to provide custom FeatureInfo objects to the ProgramManager. This is done in order to test the code that is run only if path rendering is enabled. Changes NV_path_rendering to be enabled only for ES 3.1 contexts. The extension spec does not spec the full needed program_interface_query functionality. Thus the location info is only obtainable from 3.1 contexts. Sets the driver version needed for the feature as 346. The 346.35 driver is the version in which glGetProgramInterfaceiv(.._, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES, ..) works. BUG=344330 Review URL: https://codereview.chromium.org/527233002 Cr-Commit-Position: refs/heads/master@{#357321}
-rw-r--r--gpu/GLES2/extensions/CHROMIUM/CHROMIUM_path_rendering.txt260
-rw-r--r--gpu/GLES2/gl2chromium_autogen.h4
-rw-r--r--gpu/GLES2/gl2extchromium.h30
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py23
-rw-r--r--gpu/command_buffer/client/gles2_c_lib_autogen.h25
-rw-r--r--gpu/command_buffer/client/gles2_cmd_helper_autogen.h24
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc57
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h10
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest_autogen.h7
-rw-r--r--gpu/command_buffer/client/gles2_interface_autogen.h8
-rw-r--r--gpu/command_buffer/client/gles2_interface_stub_autogen.h8
-rw-r--r--gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h10
-rw-r--r--gpu/command_buffer/client/gles2_trace_implementation_autogen.h8
-rw-r--r--gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h21
-rw-r--r--gpu/command_buffer/client/program_info_manager.cc19
-rw-r--r--gpu/command_buffer/cmd_buffer_functions.txt3
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_autogen.h123
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_test_autogen.h35
-rw-r--r--gpu/command_buffer/common/gles2_cmd_ids_autogen.h6
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.cc68
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.h40
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_autogen.h1
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h20
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_unittest.cc73
-rw-r--r--gpu/command_buffer/service/context_group.cc2
-rw-r--r--gpu/command_buffer/service/feature_info.cc25
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc178
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.h3
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_mock.h1
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc50
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h12
-rw-r--r--gpu/command_buffer/service/gles2_cmd_validation_autogen.h1
-rw-r--r--gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h8
-rw-r--r--gpu/command_buffer/service/program_manager.cc212
-rw-r--r--gpu/command_buffer/service/program_manager.h40
-rw-r--r--gpu/command_buffer/service/program_manager_unittest.cc561
-rw-r--r--gpu/command_buffer/service/test_helper.cc95
-rw-r--r--gpu/command_buffer/service/test_helper.h40
-rw-r--r--gpu/command_buffer/tests/gl_bind_uniform_location_unittest.cc17
-rw-r--r--gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc1049
-rw-r--r--gpu/command_buffer/tests/gl_manager.cc7
-rw-r--r--gpu/command_buffer/tests/gl_manager.h2
-rw-r--r--gpu/config/gpu_driver_bug_list_json.cc6
-rw-r--r--gpu/skia_bindings/gl_bindings_skia_cmd_buffer.cc3
-rw-r--r--mojo/gpu/mojo_gles2_impl_autogen.cc15
-rw-r--r--mojo/gpu/mojo_gles2_impl_autogen.h8
-rw-r--r--third_party/mojo/src/mojo/public/c/gles2/gles2_call_visitor_chromium_extension_autogen.h12
-rwxr-xr-xui/gl/generate_bindings.py21
-rw-r--r--ui/gl/gl_bindings.h12
-rw-r--r--ui/gl/gl_bindings_api_autogen_gl.h23
-rw-r--r--ui/gl/gl_bindings_autogen_gl.cc248
-rw-r--r--ui/gl/gl_bindings_autogen_gl.h63
-rw-r--r--ui/gl/gl_bindings_autogen_mock.cc54
-rw-r--r--ui/gl/gl_bindings_autogen_mock.h26
-rw-r--r--ui/gl/gl_enums_implementation_autogen.h9
-rw-r--r--ui/gl/gl_mock_autogen_gl.h25
57 files changed, 3227 insertions, 490 deletions
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_path_rendering.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_path_rendering.txt
index 026ac11..a8af396 100644
--- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_path_rendering.txt
+++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_path_rendering.txt
@@ -73,6 +73,11 @@ New Tokens
BOUNDING_BOX_CHROMIUM see above
BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM 0x909C
+ Accepted by the <genMode> parameter of ProgramPathFragmentInputGen:
+ EYE_LINEAR_CHROMIUM 0x2400
+ OBJECT_LINEAR_CHROMIUM 0x2401
+ CONSTANT_CHROMIUM 0x8576
+
Accepted by the <transformType> parameter of
StencilFillPathInstancedCHROMIUM, StencilStrokePathInstancedCHROMIUM,
CoverFillPathInstancedCHROMIUM, CoverStrokePathInstancedCHROMIUM,
@@ -992,6 +997,261 @@ New Procedures and Functions
unless either command would generate an error; for any such error
other than OUT_OF_MEMORY, only that error is generated.
+ void BindFragmentInputLocationCHROMIUM(uint program, int location,
+ const char* name);
+
+ The call specifes that the fragment shader input varying named
+ /name/ in program /program/ should be bound to uniform location
+ /location/ when the program is next linked. If /name/ was bound
+ previously, its assigned binding is replaced with /location/. The
+ /name/ must be a null terminated string. The error INVALID_VALUE
+ is generated if /location/ is equal or greater than
+
+ MAX_VARYING_VECTORS * 4
+
+ or less than 0. BindFragmentInputLocation has no effect until the
+ program is linked. In particular, it doesn't modify the bindings of active
+ uniforms variables in a program that has already been linked.
+
+ The error INVALID_OPERATION is generated if /program/ is not name for a
+ program object.
+
+ The error INVALID_OPERATION is generated if name starts with the reserved
+ "gl_" prefix.
+
+ When a program is linked, any active uniforms without a binding specified
+ through BindFragmentInputLocation will be automatically be bound to
+ locations by the GL. Such bindings can not be queried.
+
+ BindFragmentInputLocation may be issued before any shader objects are
+ attached to a program object. Hence it is allowed to bind any name (except
+ a name starting with "gl_") to an index, including a name that is never used
+ as a varying in the fragment shader object. Assigned bindings for varying
+ variables that do not exist or are not active are ignored.
+
+ It is possible for an application to bind more than one fragment
+ input name to the same location. This is referred to as aliasing.
+ This will only work if only one of the aliased fragment inputs is
+ active in the executable program, or if no path through the shader
+ consumes more than one fragment input of a set of fragment inputs
+ aliased to the same location. If two statically used fragment
+ inputs in a program are bound to the name location, link must
+ fail.
+
+ void ProgramPathFragmentInputGenCHROMIUM(uint program,
+ int location,
+ enum genMode,
+ int components,
+ const float *coeffs);
+
+ The command controls how a user-defined (non-built-in) fragment input of
+ a GLSL program object is computed for fragment shading operations that occur
+ as a result of CoverFillPathCHROMIUM or CoverStrokePathCHROMIUM.
+
+ /program/ names a GLSL program object. If /program/ has not been
+ successfully linked, the error INVALID_OPERATION is generated.
+
+ The given fragment input generation state is loaded into the fragment
+ input variable location identified by /location/. This location
+ is a value bound with BindFragmentInputLocation.
+
+ If the value of location is -1, the ProgramPathFragmentInputGenCHROMIUM
+ command will silently ignore the command, and the program's path fragment
+ input generation state will not be changed.
+
+ If any of the following conditions occur, an INVALID_OPERATION error is
+ generated by the ProgramPathFragmentInputGenCHROMIUM, and no state is
+ changed:
+
+ * if the size indicated in the /components/ of the
+ ProgramPathFragmentInputGenCHROMIUM command used does not match the
+ size of the fragment input scalar or vector declared in the
+ shader,
+
+ * if the fragment input declared in the shader is not
+ single-precision floating-point scalar or vector, or
+
+ * if no fragment input variable with a location of /location/
+ exists in the program object named by /program/ and location
+ is not -1, or
+
+ * if the fragment input declared in the shader is a built-in
+ variables (i.e. prefixed by "gl_").
+
+ When covering paths, fragment input variables are interpolated at
+ each shaded fragment based on the corresponding fragment input
+ generation state specified by ProgramPathFragmentInputGenCHROMIUM for
+ each respective fragment input.
+
+ The /genMode/, /components/, and /coeffs/ parameters are used to
+ generate the fragment input variable values. This is described in
+ subsection FRAGMENT INPUT GENERATION FOR PATH COVER COMMANDS.
+
+ When covering paths, if a fragment input variable has not had its
+ path fragment input generation state successfully generated, it as
+ if the values of this variable are always initialized to zero when
+ the fragment shader is executing.
+
+ FRAGMENT INPUT GENERATION FOR PATH COVER COMMANDS
+
+ The /genMode/, /components/, and /coeffs/ parameters of
+ ProgramPathFragmentInputGenCHROMIUM control how fragment inputs are computed
+ for fragment shading operations that occur as a result of
+ CoverFillPathCHROMIUM and CoverStrokePathCHROMIUM and their StencilThenCover
+ and instanced variants.
+
+ /genMode/ must be one of NONE, OBJECT_LINEAR_CHROMIUM, EYE_LINEAR_CHROMIUM
+ or CONSTANT_CHROMIUM; otherwise INVALID_ENUM is generated.
+
+ NONE means that the fragment input is not generated. OBJECT_LINEAR_CHROMIUM
+ means that the specified input is generated from a linear combination of the
+ 2D path coordinates (x,y). EYE_LINEAR_CHROMIUM means the specified input is
+ generated from a linear combination of path's 2D coordinates transformed in
+ eye space, with (xe, ye, ze, we) calculated as in section 2.12
+ ("Fixed-Function Vertex Transformation") of OpenGL 3.2 (unabridged)
+ Specification (Special Functions). CONSTANT_CHROMIUM means that the
+ specified input is set to corresponding constant value.
+
+ /components/ must be 0 if /genMode/ is NONE or for other allowed /genMode/
+ values must be one of 1, 2, 3, or 4; otherwise INVALID_VALUE is generated.
+ /components/ determines how many fragment input components, how many
+ coefficients read from the /coeffs/ array, and the linear equations used to
+ generate the s, t, r, and q coordinates of the fragment input specified by
+ /location/.
+
+ In the following equations, coeffs[i] is the /i/th element (base zero) of
+ the /coeffs/ array; x, y, z, and w are determined by the /genMode/.
+
+ When /genMode/ is EYE_LINEAR_CHROMIUM, xcoeffs[i] is the /i/th element (base
+ zero) of a /xcoeffs/ array generated by multiplying each respective vector
+ of four elements of coeffs by the current inverse modelview matrix when
+ ProgramPathFragmentInputGen is called.
+
+ xcoeffs[0..3] = coeffs[0..3] * MV^-1
+ xcoeffs[4..7] = coeffs[4..7] * MV^-1
+ xcoeffs[8..11] = coeffs[8..11] * MV^-1
+ xcoeffs[12..15] = coeffs[12..12] * MV^-1
+
+ [[ NOTATION:
+
+ xxx[0..3] is a vector form from xxx[0], xxx[1], xxx[2], and xxx[3]
+
+ MV^-1 is the inverse of the current PATH_MODELVIEW_CHROMIUM matrix when
+ ProgramPathFragmentInputGenCHROMIUM happens.
+
+ ]]
+
+ If the /components/ is 0, no values from the /coeffs/ array are
+ accessed and the s, t, r, and q coordinates of a covered fragment's
+ fragment input for /location/ are computed:
+
+ s = 0
+ t = 0
+ r = 0
+ q = 0
+
+ If the /components/ is 1 and /genMode/ is OBJECT_LINEAR_CHROMIUM
+ 3 values from the /coeffs/ array are
+ accessed and the s, t, r, and q coordinates of a covered fragment's
+ fragment input for /location/ are computed:
+
+ s = coeffs[0] * x + coeffs[1] * y + coeffs[2]
+ t = 0
+ r = 0
+ q = 0
+
+ Alternatively if the /genMode/ is EYE_LINEAR_CHROMIUM, then 4 values are
+ accessed and the fragment input for /location/ are
+ computed:
+
+ s = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we
+ t = 0
+ r = 0
+ q = 0
+
+ Alternatively if the /genMode/ is CONSTANT_CHROMIUM, then:
+
+ s = xcoeffs[0]
+ t = 0
+ r = 0
+ q = 0
+
+ If the /components/ is 2 and /genMode/ is OBJECT_LINEAR_CHROMIUM,
+ 6 values from the /coeffs/ array are accessed and the
+ s, t, r, and q coordinates of a covered fragment's fragment input
+ coordinates are computed:
+
+ s = coeffs[0] * x + coeffs[1] * y + coeffs[2]
+ t = coeffs[3] * x + coeffs[4] * y + coeffs[5]
+ r = 0
+ q = 0
+
+ Alternatively if the /genMode/ is EYE_LINEAR_CHROMIUM, then 8 values are
+ accessed and the fragment input coordinates are computed:
+
+ s = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we
+ t = xcoeffs[4] * xe + xcoeffs[5] * ye + xcoeffs[6] * ze + xcoeffs[7] * we
+ r = 0
+ q = 0
+
+ Alternatively if the /genMode/ is CONSTANT_CHROMIUM, then:
+
+ s = xcoeffs[0]
+ t = xcoeffs[1]
+ r = 0
+ q = 0
+
+ If the /components/ is 3 and /genMode/ is OBJECT_LINEAR_CHROMIUM 9 values
+ from the /coeffs/ array are accessed and the s, t, r, and q coordinates of a
+ covered fragment's fragment input coordinates for /location/ are computed:
+
+ s = coeffs[0] * x + coeffs[1] * y + coeffs[2]
+ t = coeffs[3] * x + coeffs[4] * y + coeffs[5]
+ r = coeffs[6] * x + coeffs[7] * y + coeffs[8]
+ q = 0
+
+ Alternatively if the /genMode/ is CONSTANT_CHROMIUM, then:
+
+ s = xcoeffs[0]
+ t = xcoeffs[1]
+ r = xcoeffs[2]
+ q = 0
+
+ Alternatively if the /genMode/ is EYE_LINEAR_CHROMIUM, then 12 values are
+ accessed and the fragment input coodinates for /location/ are computed:
+
+ s = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we
+ t = xcoeffs[4] * xe + xcoeffs[5] * ye + xcoeffs[6] * ze + xcoeffs[7] * we
+ r = xcoeffs[8] * xe + xcoeffs[9] * ye + xcoeffs[10] * ze + xcoeffs[11] * we
+ q = 0
+
+ If the /components/ is 4 and /genMode/ is OBJECT_LINEAR_CHROMIUM,
+ 12 values from the /coeffs/ array are accessed and the
+ s, t, r, and q coordinates of a covered fragment's fragment input
+ coordinates for /location/ are computed:
+
+ s = coeffs[0] * x + coeffs[1] * y + coeffs[2]
+ t = coeffs[3] * x + coeffs[4] * y + coeffs[5]
+ r = coeffs[6] * x + coeffs[7] * y + coeffs[8]
+ q = coeffs[9] * x + coeffs[10] * y + coeffs[11]
+
+ Alternatively if the /genMode/ is EYE_LINEAR_CHROMIUM, then 16 values are
+ accessed and the fragment input coordinates for /location/ are
+ computed:
+
+ s = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we
+ t = xcoeffs[4] * xe + xcoeffs[5] * ye + xcoeffs[6] * ze + xcoeffs[7] * we
+ r = xcoeffs[8] * xe + xcoeffs[9] * ye + xcoeffs[10] * ze + xcoeffs[11] * we
+ q = xcoeffs[12] * xe + xcoeffs[13] * ye + xcoeffs[14] * ze + xcoeffs[15] * we
+
+ Alternatively if the /genMode/ is CONSTANT_CHROMIUM, then:
+
+ s = xcoeffs[0]
+ t = xcoeffs[1]
+ r = xcoeffs[2]
+ q = xcoeffs[3]
+
+ The initial mode is NONE and the coefficients are all initially zero.
PATH COVERING RASTERIZATION DETAILS
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h
index ee4a8fc..67b07de 100644
--- a/gpu/GLES2/gl2chromium_autogen.h
+++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -367,6 +367,10 @@
GLES2_GET_FUN(StencilThenCoverFillPathInstancedCHROMIUM)
#define glStencilThenCoverStrokePathInstancedCHROMIUM \
GLES2_GET_FUN(StencilThenCoverStrokePathInstancedCHROMIUM)
+#define glBindFragmentInputLocationCHROMIUM \
+ GLES2_GET_FUN(BindFragmentInputLocationCHROMIUM)
+#define glProgramPathFragmentInputGenCHROMIUM \
+ GLES2_GET_FUN(ProgramPathFragmentInputGenCHROMIUM)
#define glGetGraphicsResetStatusKHR GLES2_GET_FUN(GetGraphicsResetStatusKHR)
#define glBlendBarrierKHR GLES2_GET_FUN(BlendBarrierKHR)
#define glApplyScreenSpaceAntialiasingCHROMIUM \
diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h
index ccbe6f2..9e15249 100644
--- a/gpu/GLES2/gl2extchromium.h
+++ b/gpu/GLES2/gl2extchromium.h
@@ -899,6 +899,17 @@ glStencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
GLenum coverMode,
GLenum transformType,
const GLfloat* transformValues);
+GL_APICALL void GL_APIENTRY
+glBindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const char* name);
+GL_APICALL void GL_APIENTRY
+glProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs);
+
#endif
typedef void(GL_APIENTRYP PFNGLMATRIXLOADFCHROMIUMPROC)(GLenum matrixMode,
@@ -1000,6 +1011,16 @@ typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDCHROMIUMPROC)(
GLenum coverMode,
GLenum transformType,
const GLfloat* transformValues);
+typedef void(GL_APIENTRYP PFNGLBINDFRAGMENTINPUTLOCATIONCHROMIUMPROC)(
+ GLuint program,
+ GLint location,
+ const char* name);
+typedef void(GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENCHROMIUMPROC)(
+ GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs);
#ifndef GL_CLOSE_PATH_CHROMIUM
#define GL_CLOSE_PATH_CHROMIUM 0x00
@@ -1034,6 +1055,15 @@ typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDCHROMIUMPROC)(
#ifndef GL_FLAT_CHROMIUM
#define GL_FLAT_CHROMIUM 0x1D00
#endif
+#ifndef GL_EYE_LINEAR_CHROMIUM
+#define GL_EYE_LINEAR_CHROMIUM 0x2400
+#endif
+#ifndef GL_OBJECT_LINEAR_CHROMIUM
+#define GL_OBJECT_LINEAR_CHROMIUM 0x2401
+#endif
+#ifndef GL_CONSTANT_CHROMIUM
+#define GL_CONSTANT_CHROMIUM 0x8576
+#endif
#ifndef GL_PATH_STROKE_WIDTH_CHROMIUM
#define GL_PATH_STROKE_WIDTH_CHROMIUM 0x9075
#endif
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 5af1c7f..8be8c4b 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1621,6 +1621,15 @@ _NAMED_TYPE_INFO = {
'GL_TRANSPOSE_AFFINE_3D_CHROMIUM',
],
},
+ 'PathFragmentInputGenMode': {
+ 'type': 'GLenum',
+ 'valid': [
+ 'GL_NONE',
+ 'GL_EYE_LINEAR_CHROMIUM',
+ 'GL_OBJECT_LINEAR_CHROMIUM',
+ 'GL_CONSTANT_CHROMIUM',
+ ],
+ },
'ReadPixelType': {
'type': 'GLenum',
'valid': [
@@ -4299,6 +4308,20 @@ _FUNCTION_INFO = {
'extension': 'CHROMIUM_path_rendering',
'extension_flag': 'chromium_path_rendering',
},
+ 'BindFragmentInputLocationCHROMIUM': {
+ 'type': 'GLchar',
+ 'data_transfer_methods': ['bucket'],
+ 'needs_size': True,
+ 'gl_test_func': 'DoBindFragmentInputLocationCHROMIUM',
+ 'extension': 'CHROMIUM_path_rendering',
+ 'extension_flag': 'chromium_path_rendering',
+ },
+ 'ProgramPathFragmentInputGenCHROMIUM': {
+ 'type': 'Custom',
+ 'data_transfer_methods': ['shm'],
+ 'extension': 'CHROMIUM_path_rendering',
+ 'extension_flag': 'chromium_path_rendering',
+ },
}
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 36210ff..1e70766 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -1669,6 +1669,21 @@ void GL_APIENTRY GLES2StencilThenCoverStrokePathInstancedCHROMIUM(
numPaths, pathNameType, paths, pathBase, reference, mask, coverMode,
transformType, transformValues);
}
+void GL_APIENTRY GLES2BindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const char* name) {
+ gles2::GetGLContext()->BindFragmentInputLocationCHROMIUM(program, location,
+ name);
+}
+void GL_APIENTRY
+GLES2ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) {
+ gles2::GetGLContext()->ProgramPathFragmentInputGenCHROMIUM(
+ program, location, genMode, components, coeffs);
+}
GLenum GL_APIENTRY GLES2GetGraphicsResetStatusKHR() {
return gles2::GetGLContext()->GetGraphicsResetStatusKHR();
}
@@ -2941,6 +2956,16 @@ extern const NameToFunc g_gles2_function_table[] = {
glStencilThenCoverStrokePathInstancedCHROMIUM),
},
{
+ "glBindFragmentInputLocationCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(
+ glBindFragmentInputLocationCHROMIUM),
+ },
+ {
+ "glProgramPathFragmentInputGenCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(
+ glProgramPathFragmentInputGenCHROMIUM),
+ },
+ {
"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 10358c8..601266d 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -3102,6 +3102,30 @@ void StencilThenCoverStrokePathInstancedCHROMIUM(
}
}
+void BindFragmentInputLocationCHROMIUMBucket(GLuint program,
+ GLint location,
+ uint32_t name_bucket_id) {
+ gles2::cmds::BindFragmentInputLocationCHROMIUMBucket* c =
+ GetCmdSpace<gles2::cmds::BindFragmentInputLocationCHROMIUMBucket>();
+ if (c) {
+ c->Init(program, location, name_bucket_id);
+ }
+}
+
+void ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ uint32_t coeffs_shm_id,
+ uint32_t coeffs_shm_offset) {
+ gles2::cmds::ProgramPathFragmentInputGenCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::ProgramPathFragmentInputGenCHROMIUM>();
+ if (c) {
+ c->Init(program, location, genMode, components, coeffs_shm_id,
+ coeffs_shm_offset);
+ }
+}
+
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 7c994d9..45b52d9 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -6290,6 +6290,63 @@ void GLES2Implementation::StencilThenCoverStrokePathInstancedCHROMIUM(
CheckGLError();
}
+void GLES2Implementation::BindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const char* name) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix()
+ << "] glBindFragmentInputLocationCHROMIUM(" << program
+ << ", " << location << ", " << name << ")");
+ SetBucketAsString(kResultBucketId, name);
+ helper_->BindFragmentInputLocationCHROMIUMBucket(program, location,
+ kResultBucketId);
+ helper_->SetBucketSize(kResultBucketId, 0);
+ CheckGLError();
+}
+
+void GLES2Implementation::ProgramPathFragmentInputGenCHROMIUM(
+ GLuint program,
+ GLint location,
+ GLenum gen_mode,
+ GLint components,
+ const GLfloat* coeffs) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix()
+ << "] glProgramPathFragmentInputGenCHROMIUM(" << program
+ << ", " << gen_mode << ", " << components << ", " << coeffs
+ << ")");
+
+ uint32 coeffs_per_component =
+ GLES2Util::GetCoefficientCountForGLPathFragmentInputGenMode(gen_mode);
+
+ if (components <= 0 || components > 4 || gen_mode == GL_NONE ||
+ coeffs_per_component == 0 || location == -1) {
+ helper_->ProgramPathFragmentInputGenCHROMIUM(program, location, gen_mode,
+ components, 0, 0);
+ } else {
+ // The multiplication below will not overflow.
+ DCHECK(coeffs_per_component > 0 && coeffs_per_component <= 4);
+ DCHECK(components > 0 && components <= 4);
+ uint32 coeffs_size = sizeof(GLfloat) * coeffs_per_component * components;
+
+ ScopedTransferBufferPtr buffer(coeffs_size, helper_, transfer_buffer_);
+ if (!buffer.valid() || buffer.size() < coeffs_size) {
+ SetGLError(GL_OUT_OF_MEMORY, "glProgramPathFragmentInputGenCHROMIUM",
+ "no room in transfer buffer");
+ return;
+ }
+
+ DCHECK(coeffs_size > 0);
+ unsigned char* addr = static_cast<unsigned char*>(buffer.address());
+ memcpy(addr, coeffs, coeffs_size);
+
+ helper_->ProgramPathFragmentInputGenCHROMIUM(program, location, gen_mode,
+ components, buffer.shm_id(),
+ buffer.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_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 880c6fa..2cf5ba1 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -1158,6 +1158,16 @@ void StencilThenCoverStrokePathInstancedCHROMIUM(
GLenum transformType,
const GLfloat* transformValues) override;
+void BindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const char* name) override;
+
+void ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) override;
+
GLenum GetGraphicsResetStatusKHR() override;
void BlendBarrierKHR() override;
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
index 37d601d..ed37383 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -3251,11 +3251,4 @@ TEST_F(GLES2ImplementationTest, StencilThenCoverStrokePathCHROMIUM) {
gl_->StencilThenCoverStrokePathCHROMIUM(1, 2, 3, GL_CONVEX_HULL_CHROMIUM);
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
}
-// TODO(zmo): Implement unit test for StencilFillPathInstancedCHROMIUM
-// TODO(zmo): Implement unit test for StencilStrokePathInstancedCHROMIUM
-// TODO(zmo): Implement unit test for CoverFillPathInstancedCHROMIUM
-// TODO(zmo): Implement unit test for CoverStrokePathInstancedCHROMIUM
-// TODO(zmo): Implement unit test for StencilThenCoverFillPathInstancedCHROMIUM
-// TODO(zmo): Implement unit test for
-// StencilThenCoverStrokePathInstancedCHROMIUM
#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 1b10663..4bed4f1 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -867,6 +867,14 @@ virtual void StencilThenCoverStrokePathInstancedCHROMIUM(
GLenum coverMode,
GLenum transformType,
const GLfloat* transformValues) = 0;
+virtual void BindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const char* name) = 0;
+virtual void ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) = 0;
virtual GLenum GetGraphicsResetStatusKHR() = 0;
virtual void BlendBarrierKHR() = 0;
virtual void ApplyScreenSpaceAntialiasingCHROMIUM() = 0;
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index 70402d2..580dc9d 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -839,6 +839,14 @@ void StencilThenCoverStrokePathInstancedCHROMIUM(
GLenum coverMode,
GLenum transformType,
const GLfloat* transformValues) override;
+void BindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const char* name) override;
+void ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) override;
GLenum GetGraphicsResetStatusKHR() override;
void BlendBarrierKHR() override;
void ApplyScreenSpaceAntialiasingCHROMIUM() override;
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 9eb4c9c..fa729d2 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -1138,6 +1138,16 @@ void GLES2InterfaceStub::StencilThenCoverStrokePathInstancedCHROMIUM(
GLenum /* coverMode */,
GLenum /* transformType */,
const GLfloat* /* transformValues */) {}
+void GLES2InterfaceStub::BindFragmentInputLocationCHROMIUM(
+ GLuint /* program */,
+ GLint /* location */,
+ const char* /* name */) {}
+void GLES2InterfaceStub::ProgramPathFragmentInputGenCHROMIUM(
+ GLuint /* program */,
+ GLint /* location */,
+ GLenum /* genMode */,
+ GLint /* components */,
+ const GLfloat* /* coeffs */) {}
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 60b742c..82587a2 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -839,6 +839,14 @@ void StencilThenCoverStrokePathInstancedCHROMIUM(
GLenum coverMode,
GLenum transformType,
const GLfloat* transformValues) override;
+void BindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const char* name) override;
+void ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) override;
GLenum GetGraphicsResetStatusKHR() override;
void BlendBarrierKHR() override;
void ApplyScreenSpaceAntialiasingCHROMIUM() override;
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 baeeb13..0e2e7e7 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -2425,6 +2425,27 @@ void GLES2TraceImplementation::StencilThenCoverStrokePathInstancedCHROMIUM(
transformType, transformValues);
}
+void GLES2TraceImplementation::BindFragmentInputLocationCHROMIUM(
+ GLuint program,
+ GLint location,
+ const char* name) {
+ TRACE_EVENT_BINARY_EFFICIENT0(
+ "gpu", "GLES2Trace::BindFragmentInputLocationCHROMIUM");
+ gl_->BindFragmentInputLocationCHROMIUM(program, location, name);
+}
+
+void GLES2TraceImplementation::ProgramPathFragmentInputGenCHROMIUM(
+ GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) {
+ TRACE_EVENT_BINARY_EFFICIENT0(
+ "gpu", "GLES2Trace::ProgramPathFragmentInputGenCHROMIUM");
+ gl_->ProgramPathFragmentInputGenCHROMIUM(program, location, genMode,
+ components, coeffs);
+}
+
GLenum GLES2TraceImplementation::GetGraphicsResetStatusKHR() {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetGraphicsResetStatusKHR");
return gl_->GetGraphicsResetStatusKHR();
diff --git a/gpu/command_buffer/client/program_info_manager.cc b/gpu/command_buffer/client/program_info_manager.cc
index 2eb2b1f..939473a 100644
--- a/gpu/command_buffer/client/program_info_manager.cc
+++ b/gpu/command_buffer/client/program_info_manager.cc
@@ -122,25 +122,20 @@ ProgramInfoManager::Program::GetUniformBlock(GLuint index) const {
GLint ProgramInfoManager::Program::GetUniformLocation(
const std::string& name) const {
- bool getting_array_location = false;
- size_t open_pos = std::string::npos;
- int index = 0;
- if (!GLES2Util::ParseUniformName(
- name, &open_pos, &index, &getting_array_location)) {
- return -1;
- }
+ GLSLArrayName parsed_name(name);
+
for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
const UniformInfo& info = uniform_infos_[ii];
if (info.name == name ||
(info.is_array &&
info.name.compare(0, info.name.size() - 3, name) == 0)) {
return info.element_locations[0];
- } else if (getting_array_location && info.is_array) {
+ } else if (parsed_name.IsArrayName() && info.is_array) {
// Look for an array specification.
- size_t open_pos_2 = info.name.find_last_of('[');
- if (open_pos_2 == open_pos &&
- name.compare(0, open_pos, info.name, 0, open_pos) == 0) {
- if (index >= 0 && index < info.size) {
+ size_t open_pos = info.name.find_last_of('[');
+ if (info.name.compare(0, open_pos, parsed_name.base_name()) == 0) {
+ int index = parsed_name.element_index();
+ if (index < info.size) {
return info.element_locations[index];
}
}
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index bbfeff7..bc26f11 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -339,6 +339,9 @@ GL_APICALL void GL_APIENTRY glCoverFillPathInstancedCHROMIUM (GLsizei nu
GL_APICALL void GL_APIENTRY glCoverStrokePathInstancedCHROMIUM (GLsizei numPaths, GLenum pathNameType, const GLvoid* paths, GLuint pathBase, GLenumPathInstancedCoverMode coverMode, GLenumPathTransformType transformType, const GLfloat* transformValues);
GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathInstancedCHROMIUM (GLsizei numPaths, GLenum pathNameType, const GLvoid* paths, GLuint pathBase, GLenumPathFillMode fillMode, GLuint mask, GLenumPathInstancedCoverMode coverMode, GLenumPathTransformType transformType, const GLfloat* transformValues);
GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathInstancedCHROMIUM (GLsizei numPaths, GLenum pathNameType, const GLvoid* paths, GLuint pathBase, GLint reference, GLuint mask, GLenumPathInstancedCoverMode coverMode, GLenumPathTransformType transformType, const GLfloat* transformValues);
+GL_APICALL void GL_APIENTRY glBindFragmentInputLocationCHROMIUM (GLidProgram program, GLint location, const char* name);
+GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenCHROMIUM (GLidProgram program, GLint location, GLenumPathFragmentInputGenMode genMode, GLint components, const GLfloat* coeffs);
+
// Extension KHR_robustness
GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void);
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index e601bd9..480abf2 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -15146,6 +15146,129 @@ static_assert(offsetof(StencilThenCoverStrokePathInstancedCHROMIUM,
"offset of StencilThenCoverStrokePathInstancedCHROMIUM "
"transformValues_shm_offset should be 44");
+struct BindFragmentInputLocationCHROMIUMBucket {
+ typedef BindFragmentInputLocationCHROMIUMBucket ValueType;
+ static const CommandId kCmdId = kBindFragmentInputLocationCHROMIUMBucket;
+ 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 _program, GLint _location, uint32_t _name_bucket_id) {
+ SetHeader();
+ program = _program;
+ location = _location;
+ name_bucket_id = _name_bucket_id;
+ }
+
+ void* Set(void* cmd,
+ GLuint _program,
+ GLint _location,
+ uint32_t _name_bucket_id) {
+ static_cast<ValueType*>(cmd)->Init(_program, _location, _name_bucket_id);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t program;
+ int32_t location;
+ uint32_t name_bucket_id;
+};
+
+static_assert(sizeof(BindFragmentInputLocationCHROMIUMBucket) == 16,
+ "size of BindFragmentInputLocationCHROMIUMBucket should be 16");
+static_assert(
+ offsetof(BindFragmentInputLocationCHROMIUMBucket, header) == 0,
+ "offset of BindFragmentInputLocationCHROMIUMBucket header should be 0");
+static_assert(
+ offsetof(BindFragmentInputLocationCHROMIUMBucket, program) == 4,
+ "offset of BindFragmentInputLocationCHROMIUMBucket program should be 4");
+static_assert(
+ offsetof(BindFragmentInputLocationCHROMIUMBucket, location) == 8,
+ "offset of BindFragmentInputLocationCHROMIUMBucket location should be 8");
+static_assert(offsetof(BindFragmentInputLocationCHROMIUMBucket,
+ name_bucket_id) == 12,
+ "offset of BindFragmentInputLocationCHROMIUMBucket "
+ "name_bucket_id should be 12");
+
+struct ProgramPathFragmentInputGenCHROMIUM {
+ typedef ProgramPathFragmentInputGenCHROMIUM ValueType;
+ static const CommandId kCmdId = kProgramPathFragmentInputGenCHROMIUM;
+ 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 _program,
+ GLint _location,
+ GLenum _genMode,
+ GLint _components,
+ uint32_t _coeffs_shm_id,
+ uint32_t _coeffs_shm_offset) {
+ SetHeader();
+ program = _program;
+ location = _location;
+ genMode = _genMode;
+ components = _components;
+ coeffs_shm_id = _coeffs_shm_id;
+ coeffs_shm_offset = _coeffs_shm_offset;
+ }
+
+ void* Set(void* cmd,
+ GLuint _program,
+ GLint _location,
+ GLenum _genMode,
+ GLint _components,
+ uint32_t _coeffs_shm_id,
+ uint32_t _coeffs_shm_offset) {
+ static_cast<ValueType*>(cmd)->Init(_program, _location, _genMode,
+ _components, _coeffs_shm_id,
+ _coeffs_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t program;
+ int32_t location;
+ uint32_t genMode;
+ int32_t components;
+ uint32_t coeffs_shm_id;
+ uint32_t coeffs_shm_offset;
+};
+
+static_assert(sizeof(ProgramPathFragmentInputGenCHROMIUM) == 28,
+ "size of ProgramPathFragmentInputGenCHROMIUM should be 28");
+static_assert(
+ offsetof(ProgramPathFragmentInputGenCHROMIUM, header) == 0,
+ "offset of ProgramPathFragmentInputGenCHROMIUM header should be 0");
+static_assert(
+ offsetof(ProgramPathFragmentInputGenCHROMIUM, program) == 4,
+ "offset of ProgramPathFragmentInputGenCHROMIUM program should be 4");
+static_assert(
+ offsetof(ProgramPathFragmentInputGenCHROMIUM, location) == 8,
+ "offset of ProgramPathFragmentInputGenCHROMIUM location should be 8");
+static_assert(
+ offsetof(ProgramPathFragmentInputGenCHROMIUM, genMode) == 12,
+ "offset of ProgramPathFragmentInputGenCHROMIUM genMode should be 12");
+static_assert(
+ offsetof(ProgramPathFragmentInputGenCHROMIUM, components) == 16,
+ "offset of ProgramPathFragmentInputGenCHROMIUM components should be 16");
+static_assert(
+ offsetof(ProgramPathFragmentInputGenCHROMIUM, coeffs_shm_id) == 20,
+ "offset of ProgramPathFragmentInputGenCHROMIUM coeffs_shm_id should be 20");
+static_assert(offsetof(ProgramPathFragmentInputGenCHROMIUM,
+ coeffs_shm_offset) == 24,
+ "offset of ProgramPathFragmentInputGenCHROMIUM coeffs_shm_offset "
+ "should be 24");
+
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 fbbd95c..0b02f87 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -5211,6 +5211,41 @@ TEST_F(GLES2FormatTest, StencilThenCoverStrokePathInstancedCHROMIUM) {
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, BindFragmentInputLocationCHROMIUMBucket) {
+ cmds::BindFragmentInputLocationCHROMIUMBucket& cmd =
+ *GetBufferAs<cmds::BindFragmentInputLocationCHROMIUMBucket>();
+ void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11),
+ static_cast<GLint>(12), static_cast<uint32_t>(13));
+ EXPECT_EQ(static_cast<uint32_t>(
+ cmds::BindFragmentInputLocationCHROMIUMBucket::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+ EXPECT_EQ(static_cast<GLint>(12), cmd.location);
+ EXPECT_EQ(static_cast<uint32_t>(13), cmd.name_bucket_id);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, ProgramPathFragmentInputGenCHROMIUM) {
+ cmds::ProgramPathFragmentInputGenCHROMIUM& cmd =
+ *GetBufferAs<cmds::ProgramPathFragmentInputGenCHROMIUM>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLint>(12),
+ static_cast<GLenum>(13), static_cast<GLint>(14),
+ static_cast<uint32_t>(15), static_cast<uint32_t>(16));
+ EXPECT_EQ(
+ static_cast<uint32_t>(cmds::ProgramPathFragmentInputGenCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+ EXPECT_EQ(static_cast<GLint>(12), cmd.location);
+ EXPECT_EQ(static_cast<GLenum>(13), cmd.genMode);
+ EXPECT_EQ(static_cast<GLint>(14), cmd.components);
+ EXPECT_EQ(static_cast<uint32_t>(15), cmd.coeffs_shm_id);
+ EXPECT_EQ(static_cast<uint32_t>(16), cmd.coeffs_shm_offset);
+ 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 cf20fab..9c381c1 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -326,8 +326,10 @@
OP(CoverStrokePathInstancedCHROMIUM) /* 567 */ \
OP(StencilThenCoverFillPathInstancedCHROMIUM) /* 568 */ \
OP(StencilThenCoverStrokePathInstancedCHROMIUM) /* 569 */ \
- OP(BlendBarrierKHR) /* 570 */ \
- OP(ApplyScreenSpaceAntialiasingCHROMIUM) /* 571 */
+ OP(BindFragmentInputLocationCHROMIUMBucket) /* 570 */ \
+ OP(ProgramPathFragmentInputGenCHROMIUM) /* 571 */ \
+ OP(BlendBarrierKHR) /* 572 */ \
+ OP(ApplyScreenSpaceAntialiasingCHROMIUM) /* 573 */
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 0376425..8b547fa 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -758,6 +758,20 @@ size_t GLES2Util::GetComponentCountForGLTransformType(uint32 type) {
return 0;
}
}
+size_t GLES2Util::GetCoefficientCountForGLPathFragmentInputGenMode(
+ uint32_t gen_mode) {
+ switch (gen_mode) {
+ case GL_EYE_LINEAR_CHROMIUM:
+ return 4;
+ case GL_OBJECT_LINEAR_CHROMIUM:
+ return 3;
+ case GL_CONSTANT_CHROMIUM:
+ return 1;
+ case GL_NONE:
+ default:
+ return 0;
+ }
+}
size_t GLES2Util::GetGLTypeSizeForPathCoordType(uint32 type) {
switch (type) {
@@ -1116,42 +1130,28 @@ std::string GLES2Util::GetQualifiedEnumString(
return GetStringEnum(value);
}
-bool GLES2Util::ParseUniformName(
- const std::string& name,
- size_t* array_pos,
- int* element_index,
- bool* getting_array) {
- if (name.empty())
- return false;
- bool getting_array_location = false;
- size_t open_pos = std::string::npos;
+GLSLArrayName::GLSLArrayName(const std::string& name) : element_index_(-1) {
+ if (name.size() < 4)
+ return;
+ if (name[name.size() - 1] != ']')
+ return;
+
+ size_t open_pos = name.find_last_of('[');
+ if (open_pos >= name.size() - 2)
+ return;
+
base::CheckedNumeric<int> index = 0;
- if (name[name.size() - 1] == ']') {
- if (name.size() < 3) {
- return false;
- }
- open_pos = name.find_last_of('[');
- if (open_pos == std::string::npos ||
- open_pos >= name.size() - 2) {
- return false;
- }
- size_t last = name.size() - 1;
- for (size_t pos = open_pos + 1; pos < last; ++pos) {
- int8 digit = name[pos] - '0';
- if (digit < 0 || digit > 9) {
- return false;
- }
- index = index * 10 + digit;
- }
- if (!index.IsValid()) {
- return false;
- }
- getting_array_location = true;
+ size_t last = name.size() - 1;
+ for (size_t pos = open_pos + 1; pos < last; ++pos) {
+ int8 digit = name[pos] - '0';
+ if (digit < 0 || digit > 9)
+ return;
+ index = index * 10 + digit;
}
- *getting_array = getting_array_location;
- *element_index = index.ValueOrDie();
- *array_pos = open_pos;
- return true;
+ if (!index.IsValid())
+ return;
+ element_index_ = index.ValueOrDie();
+ base_name_ = name.substr(0, open_pos);
}
size_t GLES2Util::CalcClearBufferivDataCount(int buffer) {
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
index d5790a2..3aa0299 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -14,6 +14,7 @@
#include <string>
#include <vector>
+#include "base/macros.h"
#include "base/numerics/safe_math.h"
#include "gpu/command_buffer/common/gles2_utils_export.h"
@@ -134,6 +135,9 @@ class GLES2_UTILS_EXPORT GLES2Util {
static size_t GetComponentCountForGLTransformType(uint32_t type);
static size_t GetGLTypeSizeForGLPathNameType(uint32_t type);
+ static size_t GetCoefficientCountForGLPathFragmentInputGenMode(
+ uint32_t gen_mode);
+
static uint32_t GLErrorBitToGLError(uint32_t error_bit);
static uint32_t IndexToGLFaceTarget(int index);
@@ -168,19 +172,6 @@ class GLES2_UTILS_EXPORT GLES2Util {
static std::string GetStringBool(uint32_t value);
static std::string GetStringError(uint32_t value);
- // Parses a uniform name.
- // array_pos: the position of the last '[' character in name.
- // element_index: the index of the array element specifed in the name.
- // getting_array: True if name refers to array.
- // returns true of parsing was successful. Returing true does NOT mean
- // it's a valid uniform name. On the otherhand, returning false does mean
- // it's an invalid uniform name.
- static bool ParseUniformName(
- const std::string& name,
- size_t* array_pos,
- int* element_index,
- bool* getting_array);
-
static size_t CalcClearBufferivDataCount(int buffer);
static size_t CalcClearBufferfvDataCount(int buffer);
@@ -208,6 +199,29 @@ class GLES2_UTILS_EXPORT GLES2Util {
int num_shader_binary_formats_;
};
+class GLES2_UTILS_EXPORT GLSLArrayName {
+ public:
+ explicit GLSLArrayName(const std::string& name);
+
+ // Returns true if the string is an array reference.
+ bool IsArrayName() const { return element_index_ >= 0; }
+ // Returns the name with the possible last array index specifier removed.
+ std::string base_name() const {
+ DCHECK(IsArrayName());
+ return base_name_;
+ }
+ // Returns the element index of a name which references an array element.
+ int element_index() const {
+ DCHECK(IsArrayName());
+ return element_index_;
+ }
+
+ private:
+ std::string base_name_;
+ int element_index_;
+ DISALLOW_COPY_AND_ASSIGN(GLSLArrayName);
+};
+
enum ContextType {
CONTEXT_TYPE_WEBGL1,
CONTEXT_TYPE_WEBGL2,
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
index a6460fd..e37d8c5 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
@@ -50,6 +50,7 @@ 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 GetStringPathFragmentInputGenMode(uint32_t value);
static std::string GetStringPathInstancedCoverMode(uint32_t value);
static std::string GetStringPathNameType(uint32_t value);
static std::string GetStringPathParameter(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 78453ec..f234c3f 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -454,6 +454,9 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
0x300E, "GL_CONTEXT_LOST",
},
{
+ 0x2400, "GL_EYE_LINEAR_CHROMIUM",
+ },
+ {
0x90a3, "GL_SQUARE_CHROMIUM",
},
{
@@ -1318,6 +1321,9 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
0x8A39, "GL_UNIFORM_NAME_LENGTH",
},
{
+ 0x8576, "GL_CONSTANT_CHROMIUM",
+ },
+ {
0x8E2C, "GL_DEPTH_COMPONENT16_NONLINEAR_NV",
},
{
@@ -2911,6 +2917,9 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
0x00008000, "GL_COVERAGE_BUFFER_BIT_NV",
},
{
+ 0x2401, "GL_OBJECT_LINEAR_CHROMIUM",
+ },
+ {
0x1506, "GL_XOR_NV",
},
{
@@ -4057,6 +4066,17 @@ std::string GLES2Util::GetStringPathFillMode(uint32_t value) {
arraysize(string_table), value);
}
+std::string GLES2Util::GetStringPathFragmentInputGenMode(uint32_t value) {
+ static const EnumToString string_table[] = {
+ {GL_NONE, "GL_NONE"},
+ {GL_EYE_LINEAR_CHROMIUM, "GL_EYE_LINEAR_CHROMIUM"},
+ {GL_OBJECT_LINEAR_CHROMIUM, "GL_OBJECT_LINEAR_CHROMIUM"},
+ {GL_CONSTANT_CHROMIUM, "GL_CONSTANT_CHROMIUM"},
+ };
+ return GLES2Util::GetQualifiedEnumString(string_table,
+ arraysize(string_table), value);
+}
+
std::string GLES2Util::GetStringPathInstancedCoverMode(uint32_t value) {
static const EnumToString string_table[] = {
{GL_CONVEX_HULL_CHROMIUM, "GL_CONVEX_HULL_CHROMIUM"},
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc b/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc
index 54ad3b5..3eb2a38 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc
@@ -362,47 +362,44 @@ TEST_F(GLES2UtilTest, GetChannelsForCompressedFormat) {
GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG));
}
-namespace {
-
-void CheckParseUniformName(
- const char* name,
- bool expected_success,
- size_t expected_array_pos,
- int expected_index,
- bool expected_getting_array) {
- int index = 1234;
- size_t array_pos = 1244;
- bool getting_array = false;
- bool success = GLES2Util::ParseUniformName(
- name, &array_pos, &index, &getting_array);
- EXPECT_EQ(expected_success, success);
- if (success) {
- EXPECT_EQ(expected_array_pos, array_pos);
- EXPECT_EQ(expected_index, index);
- EXPECT_EQ(expected_getting_array, getting_array);
+TEST_F(GLES2UtilTest, GLSLArrayNameParsingNotArray) {
+ const char* kNotArrayNames[] = {
+ "u_name", "u_name[]", "u_name]", "u_name[0a]",
+ "u_name[a0]", "u_name[0a0]", "[3]", ""};
+ for (auto name : kNotArrayNames) {
+ GLSLArrayName parsed_name(name);
+ EXPECT_FALSE(parsed_name.IsArrayName());
}
}
-} // anonymous namespace
-
-TEST_F(GLES2UtilTest, ParseUniformName) {
- CheckParseUniformName("u_name", true, std::string::npos, 0, false);
- CheckParseUniformName("u_name[]", false, std::string::npos, 0, false);
- CheckParseUniformName("u_name]", false, std::string::npos, 0, false);
- CheckParseUniformName("u_name[0a]", false, std::string::npos, 0, false);
- CheckParseUniformName("u_name[a0]", false, std::string::npos, 0, false);
- CheckParseUniformName("u_name[0a0]", false, std::string::npos, 0, false);
- CheckParseUniformName("u_name[0]", true, 6u, 0, true);
- CheckParseUniformName("u_name[2]", true, 6u, 2, true);
- CheckParseUniformName("u_name[02]", true, 6u, 2, true);
- CheckParseUniformName("u_name[20]", true, 6u, 20, true);
- CheckParseUniformName("u_name[020]", true, 6u, 20, true);
- CheckParseUniformName("u_name[0][0]", true, 9u, 0, true);
- CheckParseUniformName("u_name[3][2]", true, 9u, 2, true);
- CheckParseUniformName("u_name[03][02]", true, 10u, 2, true);
- CheckParseUniformName("u_name[30][20]", true, 10u, 20, true);
- CheckParseUniformName("u_name[030][020]", true, 11u, 20, true);
- CheckParseUniformName("", false, std::string::npos, 0, false);
+TEST_F(GLES2UtilTest, GLSLArrayNameParsing) {
+ struct {
+ const char* name;
+ const char* base_name;
+ int element_index;
+ } testcases[] = {{"u_name[0]", "u_name", 0},
+ {"u_name[2]", "u_name", 2},
+ {
+ "u_name[02]", "u_name", 2,
+ },
+ {
+ "u_name[20]", "u_name", 20,
+ },
+ {"u_name[020]", "u_name", 20},
+ {"u_name[0][0]", "u_name[0]", 0},
+ {"u_name[3][2]", "u_name[3]", 2},
+ {"u_name[03][02]", "u_name[03]", 2},
+ {"u_name[30][20]", "u_name[30]", 20},
+ {"u_name[030][020]", "u_name[030]", 20}};
+ for (auto& testcase : testcases) {
+ GLSLArrayName parsed_name(testcase.name);
+ EXPECT_TRUE(parsed_name.IsArrayName());
+ if (!parsed_name.IsArrayName()) {
+ continue;
+ }
+ EXPECT_EQ(testcase.base_name, parsed_name.base_name());
+ EXPECT_EQ(testcase.element_index, parsed_name.element_index());
+ }
}
} // namespace gles2
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index e22459a..aeae5c6 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -286,7 +286,7 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder,
path_manager_.reset(new PathManager());
program_manager_.reset(new ProgramManager(
- program_cache_, max_varying_vectors_));
+ program_cache_, max_varying_vectors_, feature_info_.get()));
if (!texture_manager_->Initialize()) {
LOG(ERROR) << "Context::Group::Initialize failed because texture manager "
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index b2ccbd4..9e6d4ada 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -1085,16 +1085,21 @@ void FeatureInfo::InitializeFeatures() {
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);
+ extensions.Contains("GL_NV_path_rendering")) {
+ bool has_dsa = gl_version_info_->IsAtLeastGL(4, 5) ||
+ extensions.Contains("GL_EXT_direct_state_access");
+ bool has_piq = gl_version_info_->IsAtLeastGL(4, 3) ||
+ extensions.Contains("GL_ARB_program_interface_query");
+ if (gl_version_info_->IsAtLeastGLES(3, 1) ||
+ (gl_version_info_->IsAtLeastGL(3, 2) && has_dsa && has_piq)) {
+ 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/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index f90615a..39e0a29 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -892,6 +892,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
void SetWaitFenceSyncCallback(const WaitFenceSyncCallback& callback) override;
void SetIgnoreCachedStateForTest(bool ignore) override;
+ void SetForceShaderNameHashingForTest(bool force) override;
void ProcessFinishedAsyncTransfers();
bool GetServiceTextureId(uint32 client_texture_id,
@@ -1287,8 +1288,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
// Creates a Program for the given program.
- Program* CreateProgram(
- GLuint client_id, GLuint service_id) {
+ Program* CreateProgram(GLuint client_id, GLuint service_id) {
return program_manager()->CreateProgram(client_id, service_id);
}
@@ -2113,6 +2113,9 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
void ProcessPendingReadPixels(bool did_finish);
void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
+ void DoBindFragmentInputLocationCHROMIUM(GLuint program_id,
+ GLint location,
+ const char* name);
// Generate a member function prototype for each command in an automated and
// typesafe way.
#define GLES2_CMD_OP(name) \
@@ -2307,6 +2310,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
// A table of CommandInfo for all the commands.
static const CommandInfo command_info[kNumCommands - kStartPoint];
+ bool force_shader_name_hashing_for_test;
+
DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
};
@@ -2800,7 +2805,8 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
gpu_debug_commands_(false),
validation_texture_(0),
validation_fbo_multisample_(0),
- validation_fbo_(0) {
+ validation_fbo_(0),
+ force_shader_name_hashing_for_test(false) {
DCHECK(group);
}
@@ -3469,8 +3475,9 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() {
break;
}
- if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
- features().enable_shader_name_hashing)
+ if (((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
+ features().enable_shader_name_hashing) ||
+ force_shader_name_hashing_for_test)
resources.HashFunction = &CityHash64;
else
resources.HashFunction = NULL;
@@ -4925,6 +4932,10 @@ void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
state_.SetIgnoreCachedStateForTest(ignore);
}
+void GLES2DecoderImpl::SetForceShaderNameHashingForTest(bool force) {
+ force_shader_name_hashing_for_test = force;
+}
+
void GLES2DecoderImpl::OnFboChanged() const {
if (workarounds().restore_scissor_on_fbo_change)
state_.fbo_binding_for_scissor_workaround_dirty = true;
@@ -15432,6 +15443,163 @@ GLES2DecoderImpl::HandleStencilThenCoverStrokePathInstancedCHROMIUM(
return error::kNoError;
}
+void GLES2DecoderImpl::DoBindFragmentInputLocationCHROMIUM(GLuint program_id,
+ GLint location,
+ const char* name) {
+ static const char kFunctionName[] = "glBindFragmentInputLocationCHROMIUM";
+ Program* program = GetProgram(program_id);
+ if (!program || program->IsDeleted()) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "invalid program");
+ return;
+ }
+ if (!StringIsValidForGLES(name)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "invalid character");
+ return;
+ }
+ if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "reserved prefix");
+ return;
+ }
+ if (location < 0 ||
+ static_cast<uint32>(location) >= group_->max_varying_vectors() * 4) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
+ "location out of range");
+ return;
+ }
+
+ program->SetFragmentInputLocationBinding(name, location);
+}
+
+error::Error GLES2DecoderImpl::HandleBindFragmentInputLocationCHROMIUMBucket(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ const gles2::cmds::BindFragmentInputLocationCHROMIUMBucket& c =
+ *static_cast<const gles2::cmds::BindFragmentInputLocationCHROMIUMBucket*>(
+ cmd_data);
+ if (!features().chromium_path_rendering) {
+ return error::kUnknownCommand;
+ }
+
+ GLuint program = static_cast<GLuint>(c.program);
+ GLint location = static_cast<GLint>(c.location);
+ Bucket* bucket = GetBucket(c.name_bucket_id);
+ if (!bucket || bucket->size() == 0) {
+ return error::kInvalidArguments;
+ }
+ std::string name_str;
+ if (!bucket->GetAsString(&name_str)) {
+ return error::kInvalidArguments;
+ }
+ DoBindFragmentInputLocationCHROMIUM(program, location, name_str.c_str());
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleProgramPathFragmentInputGenCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ static const char kFunctionName[] = "glProgramPathFragmentInputGenCHROMIUM";
+ const gles2::cmds::ProgramPathFragmentInputGenCHROMIUM& c =
+ *static_cast<const gles2::cmds::ProgramPathFragmentInputGenCHROMIUM*>(
+ cmd_data);
+ if (!features().chromium_path_rendering) {
+ return error::kUnknownCommand;
+ }
+
+ GLint program_id = static_cast<GLint>(c.program);
+
+ Program* program = GetProgram(program_id);
+ if (!program || !program->IsValid() || program->IsDeleted()) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "invalid program");
+ return error::kNoError;
+ }
+
+ GLenum gen_mode = static_cast<GLint>(c.genMode);
+ if (!validators_->path_fragment_input_gen_mode.IsValid(gen_mode)) {
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, gen_mode, "genMode");
+ return error::kNoError;
+ }
+
+ GLint components = static_cast<GLint>(c.components);
+ if (components < 0 || components > 4) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
+ "components out of range");
+ return error::kNoError;
+ }
+
+ if ((components != 0 && gen_mode == GL_NONE) ||
+ (components == 0 && gen_mode != GL_NONE)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
+ "components and genMode do not match");
+ return error::kNoError;
+ }
+
+ GLint location = static_cast<GLint>(c.location);
+ if (location == -1) {
+ return error::kNoError;
+ }
+
+ const Program::FragmentInputInfo* fragment_input_info =
+ program->GetFragmentInputInfoByFakeLocation(location);
+ if (!fragment_input_info) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "unknown location");
+ return error::kNoError;
+ }
+ GLint real_location = fragment_input_info->location;
+
+ const GLfloat* coeffs = NULL;
+
+ if (components > 0) {
+ GLint components_needed = -1;
+
+ switch (fragment_input_info->type) {
+ case GL_FLOAT:
+ components_needed = 1;
+ break;
+ case GL_FLOAT_VEC2:
+ components_needed = 2;
+ break;
+ case GL_FLOAT_VEC3:
+ components_needed = 3;
+ break;
+ case GL_FLOAT_VEC4:
+ components_needed = 4;
+ break;
+ default:
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "fragment input type is not single-precision "
+ "floating-point scalar or vector");
+ return error::kNoError;
+ }
+
+ if (components_needed != components) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
+ "components does not match fragment input type");
+ return error::kNoError;
+ }
+ uint32 coeffs_per_component =
+ GLES2Util::GetCoefficientCountForGLPathFragmentInputGenMode(gen_mode);
+ // The multiplication below will not overflow.
+ DCHECK(coeffs_per_component > 0 && coeffs_per_component <= 4);
+ DCHECK(components > 0 && components <= 4);
+ uint32 coeffs_size = sizeof(GLfloat) * coeffs_per_component * components;
+
+ uint32 coeffs_shm_id = static_cast<uint32>(c.coeffs_shm_id);
+ uint32 coeffs_shm_offset = static_cast<uint32>(c.coeffs_shm_offset);
+
+ if (coeffs_shm_id != 0 || coeffs_shm_offset != 0) {
+ coeffs = GetSharedMemoryAs<const GLfloat*>(
+ coeffs_shm_id, coeffs_shm_offset, coeffs_size);
+ }
+
+ if (!coeffs) {
+ return error::kOutOfBounds;
+ }
+ }
+ glProgramPathFragmentInputGenNV(program->service_id(), real_location,
+ gen_mode, components, coeffs);
+ 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.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index ec870bf..6e1cff5 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -178,6 +178,7 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>,
virtual void RestoreAllAttributes() const = 0;
virtual void SetIgnoreCachedStateForTest(bool ignore) = 0;
+ virtual void SetForceShaderNameHashingForTest(bool force) = 0;
// Gets the QueryManager for this context.
virtual QueryManager* GetQueryManager() = 0;
@@ -271,7 +272,7 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>,
bool debug_;
bool log_commands_;
bool unsafe_es3_apis_enabled_;
-
+ bool force_shader_name_hashing_for_test_;
DISALLOW_COPY_AND_ASSIGN(GLES2Decoder);
};
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index 590c27a..7bf1c69 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -85,6 +85,7 @@ class MockGLES2Decoder : public GLES2Decoder {
MOCK_METHOD1(
SetResizeCallback, void(const base::Callback<void(gfx::Size, float)>&));
MOCK_METHOD1(SetIgnoreCachedStateForTest, void(bool ignore));
+ MOCK_METHOD1(SetForceShaderNameHashingForTest, void(bool force));
MOCK_METHOD1(SetAllowExit, void(bool allow));
MOCK_METHOD3(DoCommand, error::Error(unsigned int command,
unsigned int arg_count,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index d4ca3bc..579688c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -1665,9 +1665,9 @@ void GLES2DecoderTestBase::SetupShader(
AttachShader(program_service_id, fragment_shader_service_id))
.Times(1)
.RetiresOnSaturation();
- TestHelper::SetupShader(
- gl_.get(), attribs, num_attribs, uniforms, num_uniforms,
- program_service_id);
+ TestHelper::SetupShaderExpectations(gl_.get(), group_->feature_info(),
+ attribs, num_attribs, uniforms,
+ num_uniforms, program_service_id);
}
DoCreateShader(
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 0a2843e..b726ade4 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
@@ -161,6 +161,21 @@ TEST_P(GLES2DecoderTestDisabledExtensions, CHROMIUMPathRenderingDisabled) {
0);
EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
}
+ {
+ cmds::BindFragmentInputLocationCHROMIUMBucket cmd;
+ const uint32 kBucketId = 123;
+ const GLint kLocation = 2;
+ const char* kName = "testing";
+ SetBucketAsCString(kBucketId, kName);
+ cmd.Init(client_program_id_, kLocation, kBucketId);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+ }
+ {
+ cmds::ProgramPathFragmentInputGenCHROMIUM cmd;
+ const GLint kLocation = 2;
+ cmd.Init(client_program_id_, kLocation, 0, GL_NONE, 0, 0);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+ }
}
class GLES2DecoderTestWithCHROMIUMPathRendering : public GLES2DecoderTest {
@@ -1611,6 +1626,41 @@ TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, InstancedInvalidSHMValues) {
}
}
+TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
+ BindFragmentInputLocationCHROMIUM) {
+ const uint32 kBucketId = 123;
+ const GLint kLocation = 2;
+ const char* kName = "testing";
+ const char* kBadName1 = "gl_testing";
+
+ SetBucketAsCString(kBucketId, kName);
+ cmds::BindFragmentInputLocationCHROMIUMBucket cmd;
+ cmd.Init(client_program_id_, kLocation, kBucketId);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ // Check negative location.
+ SetBucketAsCString(kBucketId, kName);
+ cmd.Init(client_program_id_, -1, kBucketId);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+ // Check the highest location.
+ SetBucketAsCString(kBucketId, kName);
+ const GLint kMaxLocation = kMaxVaryingVectors * 4 - 1;
+ cmd.Init(client_program_id_, kMaxLocation, kBucketId);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ // Check too high location.
+ SetBucketAsCString(kBucketId, kName);
+ cmd.Init(client_program_id_, kMaxLocation + 1, kBucketId);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+ // Check bad name "gl_...".
+ SetBucketAsCString(kBucketId, kBadName1);
+ cmd.Init(client_program_id_, kLocation, kBucketId);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
#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 aa7a954..cf42d07 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
@@ -69,18 +69,6 @@ TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
-// TODO(gman): StencilFillPathInstancedCHROMIUM
-
-// TODO(gman): StencilStrokePathInstancedCHROMIUM
-
-// TODO(gman): CoverFillPathInstancedCHROMIUM
-
-// TODO(gman): CoverStrokePathInstancedCHROMIUM
-
-// TODO(gman): StencilThenCoverFillPathInstancedCHROMIUM
-
-// TODO(gman): StencilThenCoverStrokePathInstancedCHROMIUM
-
TEST_P(GLES2DecoderTestWithBlendEquationAdvanced, BlendBarrierKHRValidArgs) {
EXPECT_CALL(*gl_, BlendBarrierKHR());
SpecializedSetup<cmds::BlendBarrierKHR, 0>(true);
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
index 1d7ec78..ac58e82 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
@@ -50,6 +50,7 @@ ValueValidator<GLenum> matrix_mode;
ValueValidator<GLenum> path_coord_type;
ValueValidator<GLenum> path_cover_mode;
ValueValidator<GLenum> path_fill_mode;
+ValueValidator<GLenum> path_fragment_input_gen_mode;
ValueValidator<GLenum> path_instanced_cover_mode;
ValueValidator<GLenum> path_name_type;
ValueValidator<GLenum> path_parameter;
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 76258af..867e194 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
@@ -424,6 +424,11 @@ static const GLenum valid_path_fill_mode_table[] = {
GL_INVERT, GL_COUNT_UP_CHROMIUM, GL_COUNT_DOWN_CHROMIUM,
};
+static const GLenum valid_path_fragment_input_gen_mode_table[] = {
+ GL_NONE, GL_EYE_LINEAR_CHROMIUM, GL_OBJECT_LINEAR_CHROMIUM,
+ GL_CONSTANT_CHROMIUM,
+};
+
static const GLenum valid_path_instanced_cover_mode_table[] = {
GL_CONVEX_HULL_CHROMIUM, GL_BOUNDING_BOX_CHROMIUM,
GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM,
@@ -1032,6 +1037,9 @@ Validators::Validators()
arraysize(valid_path_cover_mode_table)),
path_fill_mode(valid_path_fill_mode_table,
arraysize(valid_path_fill_mode_table)),
+ path_fragment_input_gen_mode(
+ valid_path_fragment_input_gen_mode_table,
+ arraysize(valid_path_fragment_input_gen_mode_table)),
path_instanced_cover_mode(
valid_path_instanced_cover_mode_table,
arraysize(valid_path_instanced_cover_mode_table)),
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index b9a3835..94e7bde 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -20,6 +20,7 @@
#include "base/time/time.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/program_cache.h"
@@ -268,6 +269,7 @@ void Program::Reset() {
max_attrib_name_length_ = 0;
attrib_infos_.clear();
uniform_infos_.clear();
+ fragment_input_infos_.clear();
sampler_indices_.clear();
attrib_location_to_index_map_.clear();
}
@@ -454,12 +456,6 @@ struct UniformData {
bool added;
};
-struct UniformDataComparer {
- bool operator()(const UniformData& lhs, const UniformData& rhs) const {
- return lhs.queried_name < rhs.queried_name;
- }
-};
-
} // anonymous namespace
void Program::Update() {
@@ -522,6 +518,7 @@ void Program::Update() {
GLint num_uniforms = 0;
glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms);
glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len);
+ DCHECK(num_uniforms <= 0 || max_len > 0);
name_buffer.reset(new char[max_len]);
// Reads all the names.
@@ -532,7 +529,7 @@ void Program::Update() {
glGetActiveUniform(
service_id_, ii, max_len, &length,
&data.size, &data.type, name_buffer.get());
- DCHECK(max_len == 0 || length < max_len);
+ DCHECK(length < max_len);
DCHECK(length == 0 || name_buffer[length] == '\0');
data.queried_name = std::string(name_buffer.get());
GetCorrectedUniformData(data.queried_name, &data.corrected_name,
@@ -563,7 +560,7 @@ void Program::Update() {
// remove "[0]"
std::string short_name;
int element_index = 0;
- bool good = GetUniformNameSansElement(data.queried_name, &element_index,
+ bool good = GetUniformNameSansElement(data.original_name, &element_index,
&short_name);
DCHECK(good);
LocationMap::const_iterator it = bind_uniform_location_map_.find(
@@ -602,9 +599,124 @@ void Program::Update() {
}
#endif
+ UpdateFragmentInputs();
+
valid_ = true;
}
+void Program::UpdateFragmentInputs() {
+ if (!feature_info().feature_flags().chromium_path_rendering)
+ return;
+ GLint num_fragment_inputs = 0;
+ glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV,
+ GL_ACTIVE_RESOURCES, &num_fragment_inputs);
+ if (num_fragment_inputs <= 0)
+ return;
+ GLint max_len = 0;
+ glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
+ &max_len);
+ DCHECK(max_len > 0);
+
+ scoped_ptr<char[]> name_buffer(new char[max_len]);
+
+ Shader* fragment_shader =
+ attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get();
+
+ const GLenum kQueryProperties[] = {GL_LOCATION, GL_TYPE, GL_ARRAY_SIZE};
+
+ for (GLint ii = 0; ii < num_fragment_inputs; ++ii) {
+ GLsizei name_length = 0;
+ glGetProgramResourceName(service_id_, GL_FRAGMENT_INPUT_NV, ii, max_len,
+ &name_length, name_buffer.get());
+ DCHECK(name_length < max_len);
+ DCHECK(name_length == 0 || name_buffer[name_length] == '\0');
+ // A fragment shader can have gl_FragCoord, gl_FrontFacing or gl_PointCoord
+ // built-ins as its input, as well as custom varyings. We are interested in
+ // custom varyings, client is allowed to bind only them.
+ if (ProgramManager::IsInvalidPrefix(name_buffer.get(), name_length))
+ continue;
+ std::string service_name(name_buffer.get(), name_length);
+ // Unlike when binding uniforms, we expect the driver to give correct
+ // names: "name" for simple variable, "name[0]" for an array.
+ GLsizei query_length = 0;
+ GLint query_results[arraysize(kQueryProperties)] = {
+ 0,
+ };
+ glGetProgramResourceiv(service_id_, GL_FRAGMENT_INPUT_NV, ii,
+ arraysize(kQueryProperties), kQueryProperties,
+ arraysize(query_results), &query_length,
+ query_results);
+ DCHECK(query_length == arraysize(kQueryProperties));
+
+ GLenum type = static_cast<GLenum>(query_results[1]);
+ GLsizei size = static_cast<GLsizei>(query_results[2]);
+ std::string client_name;
+
+ const sh::Varying* varying = fragment_shader->GetVaryingInfo(service_name);
+ const sh::ShaderVariable* info = nullptr;
+ if (varying &&
+ varying->findInfoByMappedName(service_name, &info, &client_name)) {
+ type = info->type;
+ size = std::max(1u, info->arraySize);
+ } else {
+ // Should only happen if there are major bugs in the driver, ANGLE or if
+ // the shader translator is disabled.
+ DCHECK(feature_info().disable_shader_translator());
+ client_name = service_name;
+ if (size <= 0)
+ continue;
+ }
+
+ auto it = bind_fragment_input_location_map_.find(client_name);
+ if (it != bind_fragment_input_location_map_.end() && it->second >= 0 &&
+ query_results[0] >= 0) {
+ size_t client_location = static_cast<size_t>(it->second);
+ GLuint service_location = static_cast<GLuint>(query_results[0]);
+
+ if (fragment_input_infos_.size() <= client_location)
+ fragment_input_infos_.resize(client_location + 1);
+ DCHECK(!fragment_input_infos_[client_location].IsValid());
+ fragment_input_infos_[client_location] =
+ FragmentInputInfo(type, service_location);
+ }
+
+ if (size <= 1)
+ continue;
+ GLSLArrayName parsed_client_name(client_name);
+ GLSLArrayName parsed_service_name(service_name);
+ if (!parsed_client_name.IsArrayName() ||
+ parsed_client_name.element_index() != 0 ||
+ !parsed_service_name.IsArrayName() ||
+ parsed_service_name.element_index() != 0) {
+ NOTREACHED() << "GLSL array variable names should end with \"[0]\". "
+ "Likely driver or ANGLE error.";
+ continue;
+ }
+
+ for (GLsizei jj = 1; jj < size; ++jj) {
+ std::string array_spec(std::string("[") + base::IntToString(jj) + "]");
+ std::string client_element_name =
+ parsed_client_name.base_name() + array_spec;
+
+ auto it = bind_fragment_input_location_map_.find(client_element_name);
+ if (it != bind_fragment_input_location_map_.end() && it->second >= 0) {
+ size_t client_location = static_cast<size_t>(it->second);
+ std::string service_element_name =
+ parsed_service_name.base_name() + array_spec;
+ GLint service_location = glGetProgramResourceLocation(
+ service_id_, GL_FRAGMENT_INPUT_NV, service_element_name.c_str());
+ if (service_location >= 0) {
+ if (fragment_input_infos_.size() <= client_location)
+ fragment_input_infos_.resize(client_location + 1);
+ DCHECK(!fragment_input_infos_[client_location].IsValid());
+ fragment_input_infos_[client_location] =
+ FragmentInputInfo(type, static_cast<GLuint>(service_location));
+ }
+ }
+ }
+ }
+}
+
void Program::ExecuteBindAttribLocationCalls() {
for (const auto& key_value : bind_attrib_location_map_) {
const std::string* mapped_name = GetAttribMappedName(key_value.first);
@@ -718,6 +830,10 @@ bool Program::Link(ShaderManager* manager,
set_log_info(ProcessLogInfo(info_log).c_str());
return false;
}
+ if (DetectFragmentInputLocationBindingConflicts()) {
+ set_log_info("glBindFragmentInputLocationCHROMIUM() conflicts");
+ return false;
+ }
if (DetectBuiltInInvariantConflicts()) {
set_log_info("Invariant settings for certain built-in varyings "
"have to match");
@@ -796,13 +912,8 @@ void Program::Validate() {
GLint Program::GetUniformFakeLocation(
const std::string& name) const {
- bool getting_array_location = false;
- size_t open_pos = std::string::npos;
- int index = 0;
- if (!GLES2Util::ParseUniformName(
- name, &open_pos, &index, &getting_array_location)) {
- return -1;
- }
+ GLSLArrayName parsed_name(name);
+
for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
const UniformInfo& info = uniform_infos_[ii];
if (!info.IsValid()) {
@@ -812,12 +923,13 @@ GLint Program::GetUniformFakeLocation(
(info.is_array &&
info.name.compare(0, info.name.size() - 3, name) == 0)) {
return info.fake_location_base;
- } else if (getting_array_location && info.is_array) {
+ } else if (parsed_name.IsArrayName() && info.is_array) {
// Look for an array specification.
- size_t open_pos_2 = info.name.find_last_of('[');
- if (open_pos_2 == open_pos &&
- name.compare(0, open_pos, info.name, 0, open_pos) == 0) {
- if (index >= 0 && index < info.size) {
+ size_t open_pos = info.name.find_last_of('[');
+ if (info.name.compare(0, open_pos, parsed_name.base_name()) == 0) {
+ int index = parsed_name.element_index();
+ DCHECK(index >= 0);
+ if (index < info.size) {
DCHECK_GT(static_cast<int>(info.element_locations.size()), index);
if (info.element_locations[index] == -1)
return -1;
@@ -906,6 +1018,17 @@ const std::string* Program::GetOriginalNameFromHashedName(
return nullptr;
}
+const Program::FragmentInputInfo* Program::GetFragmentInputInfoByFakeLocation(
+ GLint fake_location) const {
+ if (fake_location < 0 ||
+ static_cast<size_t>(fake_location) >= fragment_input_infos_.size())
+ return nullptr;
+ const FragmentInputInfo* info = &fragment_input_infos_[fake_location];
+ if (!info->IsValid())
+ return nullptr;
+ return info;
+}
+
bool Program::SetUniformLocationBinding(
const std::string& name, GLint location) {
std::string short_name;
@@ -918,6 +1041,21 @@ bool Program::SetUniformLocationBinding(
return true;
}
+void Program::SetFragmentInputLocationBinding(const std::string& name,
+ GLint location) {
+ // The client wants to bind either "name" or "name[0]".
+ // GL ES 3.1 spec refers to active array names with language such as:
+ // "if the string identifies the base name of an active array, where the
+ // string would exactly match the name of the variable if the suffix "[0]"
+ // were appended to the string".
+
+ // At this point we can not know if the string identifies a simple variable,
+ // a base name of an array, or nothing. Store both, so if user overwrites
+ // either, both still work correctly.
+ bind_fragment_input_location_map_[name] = location;
+ bind_fragment_input_location_map_[name + "[0]"] = location;
+}
+
// Note: This is only valid to call right after a program has been linked
// successfully.
void Program::GetCorrectedUniformData(
@@ -997,7 +1135,7 @@ void Program::AddUniformInfo(
UniformInfo& info = uniform_infos_[uniform_index];
info.element_locations.resize(size);
info.element_locations[0] = location;
- DCHECK_GE(size, 0);
+ DCHECK_LE(0, size);
size_t num_texture_units = info.IsSampler() ? static_cast<size_t>(size) : 0u;
info.texture_units.clear();
info.texture_units.resize(num_texture_units, 0);
@@ -1328,6 +1466,28 @@ bool Program::DetectVaryingsMismatch(std::string* conflicting_name) const {
return false;
}
+bool Program::DetectFragmentInputLocationBindingConflicts() const {
+ auto shader = attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get();
+ if (!shader || !shader->valid())
+ return false;
+
+ std::set<GLint> location_binding_used;
+ for (auto it : bind_fragment_input_location_map_) {
+ // Find out if an fragment input is statically used in this program's
+ // shaders.
+ const std::string* mapped_name = shader->GetVaryingMappedName(it.first);
+ if (!mapped_name)
+ continue;
+ const sh::Varying* fragment_input = shader->GetVaryingInfo(*mapped_name);
+ if (fragment_input && fragment_input->staticUse) {
+ auto result = location_binding_used.insert(it.second);
+ if (!result.second)
+ return true;
+ }
+ }
+ return false;
+}
+
bool Program::DetectBuiltInInvariantConflicts() const {
DCHECK(attached_shaders_[0].get() &&
attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
@@ -1498,6 +1658,9 @@ void Program::GetProgramInfo(
}
}
+ // NOTE: currently we do not pass fragment input infos through the program
+ // info call, because they are not exposed through any getter function.
+
DCHECK_EQ(ComputeOffset(header, strings), size);
}
@@ -1826,13 +1989,14 @@ Program::~Program() {
}
}
-
ProgramManager::ProgramManager(ProgramCache* program_cache,
- uint32 max_varying_vectors)
+ uint32 max_varying_vectors,
+ FeatureInfo* feature_info)
: program_count_(0),
have_context_(true),
program_cache_(program_cache),
- max_varying_vectors_(max_varying_vectors) { }
+ max_varying_vectors_(max_varying_vectors),
+ feature_info_(feature_info) {}
ProgramManager::~ProgramManager() {
DCHECK(programs_.empty());
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h
index 1df6519..bf02f80 100644
--- a/gpu/command_buffer/service/program_manager.h
+++ b/gpu/command_buffer/service/program_manager.h
@@ -24,6 +24,7 @@ class ProgramCache;
class ProgramManager;
class Shader;
class ShaderManager;
+class FeatureInfo;
// This is used to track which attributes a particular program needs
// so we can verify at glDrawXXX time that every attribute is either disabled
@@ -61,6 +62,14 @@ class GPU_EXPORT Program : public base::RefCounted<Program> {
kUniformMatrix4x2f = 1 << 19,
kUniformMatrix4x3f = 1 << 20,
};
+ struct FragmentInputInfo {
+ FragmentInputInfo(GLenum _type, GLuint _location)
+ : type(_type), location(_location) {}
+ FragmentInputInfo() : type(GL_NONE), location(0) {}
+ bool IsValid() const { return type != GL_NONE; }
+ GLenum type;
+ GLuint location;
+ };
struct UniformInfo {
UniformInfo();
@@ -103,6 +112,7 @@ class GPU_EXPORT Program : public base::RefCounted<Program> {
typedef std::vector<UniformInfo> UniformInfoVector;
typedef std::vector<VertexAttrib> AttribInfoVector;
+ typedef std::vector<FragmentInputInfo> FragmentInputInfoVector;
typedef std::vector<int> SamplerIndices;
typedef std::map<std::string, GLint> LocationMap;
typedef std::vector<std::string> StringVector;
@@ -152,6 +162,9 @@ class GPU_EXPORT Program : public base::RefCounted<Program> {
const std::string* GetOriginalNameFromHashedName(
const std::string& hashed_name) const;
+ const FragmentInputInfo* GetFragmentInputInfoByFakeLocation(
+ GLint fake_location) const;
+
// Gets the fake location of a uniform by name.
GLint GetUniformFakeLocation(const std::string& name) const;
@@ -231,6 +244,10 @@ class GPU_EXPORT Program : public base::RefCounted<Program> {
// Detects if the shader version combination is not valid.
bool DetectShaderVersionMismatch() const;
+ // Sets fragment input-location binding from a
+ // glBindFragmentInputLocationCHROMIUM() call.
+ void SetFragmentInputLocationBinding(const std::string& name, GLint location);
+
// Detects if there are attribute location conflicts from
// glBindAttribLocation() calls.
// We only consider the declared attributes in the program.
@@ -251,6 +268,11 @@ class GPU_EXPORT Program : public base::RefCounted<Program> {
// is not declared in vertex shader.
bool DetectVaryingsMismatch(std::string* conflicting_name) const;
+ // Detects if there are fragment input location conflicts from
+ // glBindFragmentInputLocationCHROMIUM() calls.
+ // We only consider the statically used fragment inputs in the program.
+ bool DetectFragmentInputLocationBindingConflicts() const;
+
// Return true if any built-in invariant matching rules are broken as in
// GLSL ES spec 1.00.17, section 4.6.4, Invariance and Linkage.
bool DetectBuiltInInvariantConflicts() const;
@@ -311,6 +333,7 @@ class GPU_EXPORT Program : public base::RefCounted<Program> {
// Updates the program info after a successful link.
void Update();
+ void UpdateFragmentInputs();
// Process the program log, replacing the hashed names with original names.
std::string ProcessLogInfo(const std::string& log);
@@ -361,6 +384,8 @@ class GPU_EXPORT Program : public base::RefCounted<Program> {
return (fake_location >> 16) & 0xFFFF;
}
+ const FeatureInfo& feature_info() const;
+
ProgramManager* manager_;
int use_count_;
@@ -381,6 +406,8 @@ class GPU_EXPORT Program : public base::RefCounted<Program> {
// The indices of the uniforms that are samplers.
SamplerIndices sampler_indices_;
+ FragmentInputInfoVector fragment_input_infos_;
+
// The program this Program is tracking.
GLuint service_id_;
@@ -416,6 +443,10 @@ class GPU_EXPORT Program : public base::RefCounted<Program> {
std::vector<std::string> transform_feedback_varyings_;
GLenum transform_feedback_buffer_mode_;
+
+ // Fragment input-location binding map from
+ // glBindFragmentInputLocationCHROMIUM() calls.
+ LocationMap bind_fragment_input_location_map_;
};
// Tracks the Programs.
@@ -425,7 +456,8 @@ class GPU_EXPORT Program : public base::RefCounted<Program> {
class GPU_EXPORT ProgramManager {
public:
explicit ProgramManager(ProgramCache* program_cache,
- uint32 max_varying_vectors);
+ uint32 max_varying_vectors,
+ FeatureInfo* feature_info);
~ProgramManager();
// Must call before destruction.
@@ -494,9 +526,15 @@ class GPU_EXPORT ProgramManager {
uint32 max_varying_vectors_;
+ scoped_refptr<FeatureInfo> feature_info_;
+
DISALLOW_COPY_AND_ASSIGN(ProgramManager);
};
+inline const FeatureInfo& Program::feature_info() const {
+ return *manager_->feature_info_.get();
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc
index edbdbf1..fe1835e 100644
--- a/gpu/command_buffer/service/program_manager_unittest.cc
+++ b/gpu/command_buffer/service/program_manager_unittest.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -14,6 +15,7 @@
#include "gpu/command_buffer/service/common_decoder.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gpu_service_test.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/mocks.h"
#include "gpu/command_buffer/service/shader_manager.h"
#include "gpu/command_buffer/service/test_helper.h"
@@ -46,46 +48,72 @@ uint32 ComputeOffset(const void* start, const void* position) {
} // namespace anonymous
-class ProgramManagerTest : public GpuServiceTest {
- public:
- ProgramManagerTest() : manager_(NULL, kMaxVaryingVectors) { }
- ~ProgramManagerTest() override { manager_.Destroy(false); }
-
+class ProgramManagerTestBase : public GpuServiceTest {
protected:
- ProgramManager manager_;
+ virtual void SetupProgramManager() {
+ manager_.reset(
+ new ProgramManager(NULL, kMaxVaryingVectors, feature_info_.get()));
+ }
+ void SetUpBase(const char* gl_version,
+ const char* gl_extensions,
+ FeatureInfo* feature_info = NULL) {
+ GpuServiceTest::SetUpWithGLVersion(gl_version, gl_extensions);
+ TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(
+ gl_.get(), gl_extensions, "", gl_version);
+ if (!feature_info)
+ feature_info = new FeatureInfo();
+ feature_info->InitializeForTesting();
+ feature_info_ = feature_info;
+ SetupProgramManager();
+ }
+ void SetUp() override {
+ // Parameters same as GpuServiceTest::SetUp
+ SetUpBase("2.0", "GL_EXT_framebuffer_object");
+ }
+ void TearDown() override {
+ manager_->Destroy(false);
+ manager_.reset();
+ feature_info_ = nullptr;
+ GpuServiceTest::TearDown();
+ }
+
+ scoped_ptr<ProgramManager> manager_;
+ scoped_refptr<FeatureInfo> feature_info_;
};
+class ProgramManagerTest : public ProgramManagerTestBase {};
+
TEST_F(ProgramManagerTest, Basic) {
const GLuint kClient1Id = 1;
const GLuint kService1Id = 11;
const GLuint kClient2Id = 2;
// Check we can create program.
- manager_.CreateProgram(kClient1Id, kService1Id);
+ manager_->CreateProgram(kClient1Id, kService1Id);
// Check program got created.
- Program* program1 = manager_.GetProgram(kClient1Id);
+ Program* program1 = manager_->GetProgram(kClient1Id);
ASSERT_TRUE(program1 != NULL);
GLuint client_id = 0;
- EXPECT_TRUE(manager_.GetClientId(program1->service_id(), &client_id));
+ EXPECT_TRUE(manager_->GetClientId(program1->service_id(), &client_id));
EXPECT_EQ(kClient1Id, client_id);
// Check we get nothing for a non-existent program.
- EXPECT_TRUE(manager_.GetProgram(kClient2Id) == NULL);
+ EXPECT_TRUE(manager_->GetProgram(kClient2Id) == NULL);
}
TEST_F(ProgramManagerTest, Destroy) {
const GLuint kClient1Id = 1;
const GLuint kService1Id = 11;
// Check we can create program.
- Program* program0 = manager_.CreateProgram(kClient1Id, kService1Id);
+ Program* program0 = manager_->CreateProgram(kClient1Id, kService1Id);
ASSERT_TRUE(program0 != NULL);
// Check program got created.
- Program* program1 = manager_.GetProgram(kClient1Id);
+ Program* program1 = manager_->GetProgram(kClient1Id);
ASSERT_EQ(program0, program1);
EXPECT_CALL(*gl_, DeleteProgram(kService1Id))
.Times(1)
.RetiresOnSaturation();
- manager_.Destroy(true);
+ manager_->Destroy(true);
// Check the resources were released.
- program1 = manager_.GetProgram(kClient1Id);
+ program1 = manager_->GetProgram(kClient1Id);
ASSERT_TRUE(program1 == NULL);
}
@@ -97,29 +125,28 @@ TEST_F(ProgramManagerTest, DeleteBug) {
const GLuint kService2Id = 12;
// Check we can create program.
scoped_refptr<Program> program1(
- manager_.CreateProgram(kClient1Id, kService1Id));
+ manager_->CreateProgram(kClient1Id, kService1Id));
scoped_refptr<Program> program2(
- manager_.CreateProgram(kClient2Id, kService2Id));
+ manager_->CreateProgram(kClient2Id, kService2Id));
// Check program got created.
ASSERT_TRUE(program1.get());
ASSERT_TRUE(program2.get());
- manager_.UseProgram(program1.get());
- manager_.MarkAsDeleted(&shader_manager, program1.get());
+ manager_->UseProgram(program1.get());
+ manager_->MarkAsDeleted(&shader_manager, program1.get());
// Program will be deleted when last ref is released.
EXPECT_CALL(*gl_, DeleteProgram(kService2Id))
.Times(1)
.RetiresOnSaturation();
- manager_.MarkAsDeleted(&shader_manager, program2.get());
- EXPECT_TRUE(manager_.IsOwned(program1.get()));
- EXPECT_FALSE(manager_.IsOwned(program2.get()));
+ manager_->MarkAsDeleted(&shader_manager, program2.get());
+ EXPECT_TRUE(manager_->IsOwned(program1.get()));
+ EXPECT_FALSE(manager_->IsOwned(program2.get()));
}
TEST_F(ProgramManagerTest, Program) {
const GLuint kClient1Id = 1;
const GLuint kService1Id = 11;
// Check we can create program.
- Program* program1 = manager_.CreateProgram(
- kClient1Id, kService1Id);
+ Program* program1 = manager_->CreateProgram(kClient1Id, kService1Id);
ASSERT_TRUE(program1);
EXPECT_EQ(kService1Id, program1->service_id());
EXPECT_FALSE(program1->InUse());
@@ -129,17 +156,8 @@ TEST_F(ProgramManagerTest, Program) {
EXPECT_TRUE(program1->log_info() == NULL);
}
-class ProgramManagerWithShaderTest : public GpuServiceTest {
+class ProgramManagerWithShaderTest : public ProgramManagerTestBase {
public:
- ProgramManagerWithShaderTest()
- : manager_(NULL, kMaxVaryingVectors), program_(NULL) {
- }
-
- ~ProgramManagerWithShaderTest() override {
- manager_.Destroy(false);
- shader_manager_.Destroy(false);
- }
-
static const GLint kNumVertexAttribs = 16;
static const GLuint kClientProgramId = 123;
@@ -221,9 +239,12 @@ class ProgramManagerWithShaderTest : public GpuServiceTest {
void SetUp() override {
// Need to be at leat 3.1 for UniformBlock related GL APIs.
- GpuServiceTest::SetUpWithGLVersion("3.1", NULL);
+ SetUpBase("3.1", "");
+ }
- SetupDefaultShaderExpectations();
+ Program* SetupDefaultProgram() {
+ SetupShaderExpectations(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
+ kServiceProgramId);
Shader* vertex_shader = shader_manager_.CreateShader(
kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
@@ -231,31 +252,30 @@ class ProgramManagerWithShaderTest : public GpuServiceTest {
shader_manager_.CreateShader(
kFragmentShaderClientId, kFragmentShaderServiceId,
GL_FRAGMENT_SHADER);
- ASSERT_TRUE(vertex_shader != NULL);
- ASSERT_TRUE(fragment_shader != NULL);
+ EXPECT_TRUE(vertex_shader != NULL);
+ EXPECT_TRUE(fragment_shader != NULL);
TestHelper::SetShaderStates(gl_.get(), vertex_shader, true);
TestHelper::SetShaderStates(gl_.get(), fragment_shader, true);
- program_ = manager_.CreateProgram(
- kClientProgramId, kServiceProgramId);
- ASSERT_TRUE(program_ != NULL);
-
- program_->AttachShader(&shader_manager_, vertex_shader);
- program_->AttachShader(&shader_manager_, fragment_shader);
- program_->Link(NULL, Program::kCountOnlyStaticallyUsed,
- base::Bind(&ShaderCacheCb));
- }
+ Program* program =
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
+ EXPECT_TRUE(program != NULL);
- void SetupShader(AttribInfo* attribs, size_t num_attribs,
- UniformInfo* uniforms, size_t num_uniforms,
- GLuint service_id) {
- TestHelper::SetupShader(
- gl_.get(), attribs, num_attribs, uniforms, num_uniforms, service_id);
+ program->AttachShader(&shader_manager_, vertex_shader);
+ program->AttachShader(&shader_manager_, fragment_shader);
+ program->Link(NULL, Program::kCountOnlyStaticallyUsed,
+ base::Bind(&ShaderCacheCb));
+ return program;
}
- void SetupDefaultShaderExpectations() {
- SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
- kServiceProgramId);
+ void SetupShaderExpectations(AttribInfo* attribs,
+ size_t num_attribs,
+ UniformInfo* uniforms,
+ size_t num_uniforms,
+ GLuint service_id) {
+ TestHelper::SetupShaderExpectations(gl_.get(), feature_info_.get(), attribs,
+ num_attribs, uniforms, num_uniforms,
+ service_id);
}
void SetupExpectationsForClearingUniforms(
@@ -269,8 +289,8 @@ class ProgramManagerWithShaderTest : public GpuServiceTest {
bool expected_link_status) {
GLuint service_id = program->service_id();
if (expected_link_status) {
- SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
- service_id);
+ SetupShaderExpectations(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
+ service_id);
}
program->Link(NULL, Program::kCountOnlyStaticallyUsed,
base::Bind(&ShaderCacheCb));
@@ -284,11 +304,6 @@ class ProgramManagerWithShaderTest : public GpuServiceTest {
const VarInfo* fragment_variables,
size_t fragment_variable_size) {
// Set up shader
- const GLuint kVShaderClientId = 1;
- const GLuint kVShaderServiceId = 11;
- const GLuint kFShaderClientId = 2;
- const GLuint kFShaderServiceId = 12;
-
AttributeMap vertex_attrib_map;
UniformMap vertex_uniform_map;
VaryingMap vertex_varying_map;
@@ -365,9 +380,9 @@ class ProgramManagerWithShaderTest : public GpuServiceTest {
// Check we can create shader.
Shader* vshader = shader_manager_.CreateShader(
- kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
Shader* fshader = shader_manager_.CreateShader(
- kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
// Check shader got created.
EXPECT_TRUE(vshader != NULL && fshader != NULL);
// Set Status
@@ -379,21 +394,21 @@ class ProgramManagerWithShaderTest : public GpuServiceTest {
&frag_attrib_map, &frag_uniform_map, &frag_varying_map, NULL);
// Set up program
- const GLuint kClientProgramId = 6666;
- const GLuint kServiceProgramId = 8888;
Program* program =
- manager_.CreateProgram(kClientProgramId, kServiceProgramId);
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
EXPECT_TRUE(program != NULL);
EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
return program;
}
+ void TearDown() override {
+ shader_manager_.Destroy(false);
+ ProgramManagerTestBase::TearDown();
+ }
+
static AttribInfo kAttribs[];
static UniformInfo kUniforms[];
-
- ProgramManager manager_;
- Program* program_;
ShaderManager shader_manager_;
};
@@ -489,7 +504,7 @@ const char* ProgramManagerWithShaderTest::kUniform3NameWithArrayIndex =
"uniform3[0]";
TEST_F(ProgramManagerWithShaderTest, GetAttribInfos) {
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
const Program::AttribInfoVector& infos =
program->GetAttribInfos();
@@ -507,7 +522,7 @@ TEST_F(ProgramManagerWithShaderTest, GetAttribInfos) {
TEST_F(ProgramManagerWithShaderTest, GetAttribInfo) {
const GLint kValidIndex = 1;
const GLint kInvalidIndex = 1000;
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
const Program::VertexAttrib* info =
program->GetAttribInfo(kValidIndex);
@@ -521,7 +536,7 @@ TEST_F(ProgramManagerWithShaderTest, GetAttribInfo) {
TEST_F(ProgramManagerWithShaderTest, GetAttribLocation) {
const char* kInvalidName = "foo";
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
EXPECT_EQ(kAttrib2Location, program->GetAttribLocation(kAttrib2Name));
EXPECT_EQ(-1, program->GetAttribLocation(kInvalidName));
@@ -529,7 +544,7 @@ TEST_F(ProgramManagerWithShaderTest, GetAttribLocation) {
TEST_F(ProgramManagerWithShaderTest, GetUniformInfo) {
const GLint kInvalidIndex = 1000;
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
const Program::UniformInfo* info =
program->GetUniformInfo(0);
@@ -556,22 +571,16 @@ TEST_F(ProgramManagerWithShaderTest, GetUniformInfo) {
}
TEST_F(ProgramManagerWithShaderTest, AttachDetachShader) {
- static const GLuint kClientProgramId = 124;
- static const GLuint kServiceProgramId = 457;
- Program* program = manager_.CreateProgram(
- kClientProgramId, kServiceProgramId);
+ Program* program =
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
ASSERT_TRUE(program != NULL);
EXPECT_FALSE(program->CanLink());
- const GLuint kVShaderClientId = 2001;
- const GLuint kFShaderClientId = 2002;
- const GLuint kVShaderServiceId = 3001;
- const GLuint kFShaderServiceId = 3002;
Shader* vshader = shader_manager_.CreateShader(
- kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
ASSERT_TRUE(vshader != NULL);
TestHelper::SetShaderStates(gl_.get(), vshader, true);
Shader* fshader = shader_manager_.CreateShader(
- kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
ASSERT_TRUE(fshader != NULL);
TestHelper::SetShaderStates(gl_.get(), fshader, true);
EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
@@ -601,7 +610,7 @@ TEST_F(ProgramManagerWithShaderTest, AttachDetachShader) {
}
TEST_F(ProgramManagerWithShaderTest, GetUniformFakeLocation) {
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
// Emulate the situation that uniform3[1] isn't used and optimized out by
// a driver, so it's location is -1.
@@ -637,7 +646,7 @@ TEST_F(ProgramManagerWithShaderTest, GetUniformFakeLocation) {
TEST_F(ProgramManagerWithShaderTest, GetUniformInfoByFakeLocation) {
const GLint kInvalidLocation = 1234;
const Program::UniformInfo* info;
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
GLint real_location = -1;
GLint array_index = -1;
ASSERT_TRUE(program != NULL);
@@ -696,24 +705,18 @@ TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsGLUnderscoreUniform) {
},
};
const size_t kNumUniforms = arraysize(kUniforms);
- static const GLuint kClientProgramId = 1234;
- static const GLuint kServiceProgramId = 5679;
- const GLuint kVShaderClientId = 2001;
- const GLuint kFShaderClientId = 2002;
- const GLuint kVShaderServiceId = 3001;
- const GLuint kFShaderServiceId = 3002;
- SetupShader(
- kAttribs, kNumAttribs, kUniforms, kNumUniforms, kServiceProgramId);
+ SetupShaderExpectations(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
+ kServiceProgramId);
Shader* vshader = shader_manager_.CreateShader(
- kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
ASSERT_TRUE(vshader != NULL);
TestHelper::SetShaderStates(gl_.get(), vshader, true);
Shader* fshader = shader_manager_.CreateShader(
- kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
ASSERT_TRUE(fshader != NULL);
TestHelper::SetShaderStates(gl_.get(), fshader, true);
Program* program =
- manager_.CreateProgram(kClientProgramId, kServiceProgramId);
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
ASSERT_TRUE(program != NULL);
EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
@@ -767,24 +770,18 @@ TEST_F(ProgramManagerWithShaderTest, SimilarArrayNames) {
},
};
const size_t kNumUniforms = arraysize(kUniforms);
- static const GLuint kClientProgramId = 1234;
- static const GLuint kServiceProgramId = 5679;
- const GLuint kVShaderClientId = 2001;
- const GLuint kFShaderClientId = 2002;
- const GLuint kVShaderServiceId = 3001;
- const GLuint kFShaderServiceId = 3002;
- SetupShader(
- kAttribs, kNumAttribs, kUniforms, kNumUniforms, kServiceProgramId);
+ SetupShaderExpectations(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
+ kServiceProgramId);
Shader* vshader = shader_manager_.CreateShader(
- kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
ASSERT_TRUE(vshader != NULL);
TestHelper::SetShaderStates(gl_.get(), vshader, true);
Shader* fshader = shader_manager_.CreateShader(
- kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
ASSERT_TRUE(fshader != NULL);
TestHelper::SetShaderStates(gl_.get(), fshader, true);
Program* program =
- manager_.CreateProgram(kClientProgramId, kServiceProgramId);
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
ASSERT_TRUE(program != NULL);
EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
@@ -826,18 +823,14 @@ TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsWrongTypeInfo) {
uniform_map[kUniform3Name] = TestHelper::ConstructUniform(
kUniform3Type, kUniform3Size, kUniform3Precision,
kUniform3StaticUse, kUniform3Name);
- const GLuint kVShaderClientId = 2001;
- const GLuint kFShaderClientId = 2002;
- const GLuint kVShaderServiceId = 3001;
- const GLuint kFShaderServiceId = 3002;
Shader* vshader = shader_manager_.CreateShader(
- kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
ASSERT_TRUE(vshader != NULL);
TestHelper::SetShaderStates(
gl_.get(), vshader, true, NULL, NULL, NULL,
&attrib_map, &uniform_map, &varying_map, NULL);
Shader* fshader = shader_manager_.CreateShader(
- kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
ASSERT_TRUE(fshader != NULL);
TestHelper::SetShaderStates(
gl_.get(), fshader, true, NULL, NULL, NULL,
@@ -875,12 +868,10 @@ TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsWrongTypeInfo) {
};
const size_t kNumAttribs= arraysize(kAttribs);
const size_t kNumUniforms = arraysize(kUniforms);
- static const GLuint kClientProgramId = 1234;
- static const GLuint kServiceProgramId = 5679;
- SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
- kServiceProgramId);
- Program* program = manager_.CreateProgram(
- kClientProgramId, kServiceProgramId);
+ SetupShaderExpectations(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
+ kServiceProgramId);
+ Program* program =
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
ASSERT_TRUE(program!= NULL);
EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
@@ -931,22 +922,16 @@ TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsWrongTypeInfo) {
}
TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount) {
- static const GLuint kClientProgramId = 124;
- static const GLuint kServiceProgramId = 457;
- Program* program = manager_.CreateProgram(
- kClientProgramId, kServiceProgramId);
+ Program* program =
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
ASSERT_TRUE(program != NULL);
EXPECT_FALSE(program->CanLink());
- const GLuint kVShaderClientId = 2001;
- const GLuint kFShaderClientId = 2002;
- const GLuint kVShaderServiceId = 3001;
- const GLuint kFShaderServiceId = 3002;
Shader* vshader = shader_manager_.CreateShader(
- kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
ASSERT_TRUE(vshader != NULL);
TestHelper::SetShaderStates(gl_.get(), vshader, true);
Shader* fshader = shader_manager_.CreateShader(
- kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
ASSERT_TRUE(fshader != NULL);
TestHelper::SetShaderStates(gl_.get(), fshader, true);
EXPECT_FALSE(vshader->InUse());
@@ -958,44 +943,38 @@ TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount) {
EXPECT_TRUE(program->CanLink());
EXPECT_FALSE(program->InUse());
EXPECT_FALSE(program->IsDeleted());
- manager_.UseProgram(program);
+ manager_->UseProgram(program);
EXPECT_TRUE(program->InUse());
- manager_.UseProgram(program);
+ manager_->UseProgram(program);
EXPECT_TRUE(program->InUse());
- manager_.MarkAsDeleted(&shader_manager_, program);
+ manager_->MarkAsDeleted(&shader_manager_, program);
EXPECT_TRUE(program->IsDeleted());
- Program* info2 = manager_.GetProgram(kClientProgramId);
+ Program* info2 = manager_->GetProgram(kClientProgramId);
EXPECT_EQ(program, info2);
- manager_.UnuseProgram(&shader_manager_, program);
+ manager_->UnuseProgram(&shader_manager_, program);
EXPECT_TRUE(program->InUse());
// this should delete the info.
EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId))
.Times(1)
.RetiresOnSaturation();
- manager_.UnuseProgram(&shader_manager_, program);
- info2 = manager_.GetProgram(kClientProgramId);
+ manager_->UnuseProgram(&shader_manager_, program);
+ info2 = manager_->GetProgram(kClientProgramId);
EXPECT_TRUE(info2 == NULL);
EXPECT_FALSE(vshader->InUse());
EXPECT_FALSE(fshader->InUse());
}
TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount2) {
- static const GLuint kClientProgramId = 124;
- static const GLuint kServiceProgramId = 457;
- Program* program = manager_.CreateProgram(
- kClientProgramId, kServiceProgramId);
+ Program* program =
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
ASSERT_TRUE(program != NULL);
EXPECT_FALSE(program->CanLink());
- const GLuint kVShaderClientId = 2001;
- const GLuint kFShaderClientId = 2002;
- const GLuint kVShaderServiceId = 3001;
- const GLuint kFShaderServiceId = 3002;
Shader* vshader = shader_manager_.CreateShader(
- kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
ASSERT_TRUE(vshader != NULL);
TestHelper::SetShaderStates(gl_.get(), vshader, true);
Shader* fshader = shader_manager_.CreateShader(
- kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
ASSERT_TRUE(fshader != NULL);
TestHelper::SetShaderStates(gl_.get(), fshader, true);
EXPECT_FALSE(vshader->InUse());
@@ -1007,22 +986,22 @@ TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount2) {
EXPECT_TRUE(program->CanLink());
EXPECT_FALSE(program->InUse());
EXPECT_FALSE(program->IsDeleted());
- manager_.UseProgram(program);
+ manager_->UseProgram(program);
EXPECT_TRUE(program->InUse());
- manager_.UseProgram(program);
+ manager_->UseProgram(program);
EXPECT_TRUE(program->InUse());
- manager_.UnuseProgram(&shader_manager_, program);
+ manager_->UnuseProgram(&shader_manager_, program);
EXPECT_TRUE(program->InUse());
- manager_.UnuseProgram(&shader_manager_, program);
+ manager_->UnuseProgram(&shader_manager_, program);
EXPECT_FALSE(program->InUse());
- Program* info2 = manager_.GetProgram(kClientProgramId);
+ Program* info2 = manager_->GetProgram(kClientProgramId);
EXPECT_EQ(program, info2);
// this should delete the program.
EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId))
.Times(1)
.RetiresOnSaturation();
- manager_.MarkAsDeleted(&shader_manager_, program);
- info2 = manager_.GetProgram(kClientProgramId);
+ manager_->MarkAsDeleted(&shader_manager_, program);
+ info2 = manager_->GetProgram(kClientProgramId);
EXPECT_TRUE(info2 == NULL);
EXPECT_FALSE(vshader->InUse());
EXPECT_FALSE(fshader->InUse());
@@ -1030,9 +1009,9 @@ TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount2) {
TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetProgramInfo) {
CommonDecoder::Bucket bucket;
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
- program->GetProgramInfo(&manager_, &bucket);
+ program->GetProgramInfo(manager_.get(), &bucket);
ProgramInfoHeader* header =
bucket.GetDataAs<ProgramInfoHeader*>(0, sizeof(ProgramInfoHeader));
ASSERT_TRUE(header != NULL);
@@ -1086,7 +1065,7 @@ TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetProgramInfo) {
TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformBlocksNone) {
CommonDecoder::Bucket bucket;
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
// The program's previous link failed.
EXPECT_CALL(*(gl_.get()),
@@ -1118,7 +1097,7 @@ TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformBlocksNone) {
TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformBlocksValid) {
CommonDecoder::Bucket bucket;
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
struct Data {
UniformBlocksHeader header;
@@ -1234,7 +1213,7 @@ TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformBlocksValid) {
TEST_F(ProgramManagerWithShaderTest,
ProgramInfoGetTransformFeedbackVaryingsNone) {
CommonDecoder::Bucket bucket;
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
// The program's previous link failed.
EXPECT_CALL(*(gl_.get()),
@@ -1285,7 +1264,7 @@ TEST_F(ProgramManagerWithShaderTest,
TEST_F(ProgramManagerWithShaderTest,
ProgramInfoGetTransformFeedbackVaryingsValid) {
CommonDecoder::Bucket bucket;
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
struct Data {
TransformFeedbackVaryingsHeader header;
@@ -1354,7 +1333,7 @@ TEST_F(ProgramManagerWithShaderTest,
TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformsES3None) {
CommonDecoder::Bucket bucket;
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
// The program's previous link failed.
EXPECT_CALL(*(gl_.get()),
@@ -1386,7 +1365,7 @@ TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformsES3None) {
TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformsES3Valid) {
CommonDecoder::Bucket bucket;
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
struct Data {
UniformsES3Header header;
@@ -1452,7 +1431,7 @@ TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformsES3Valid) {
// location would be -1.
TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) {
CommonDecoder::Bucket bucket;
- const Program* program = manager_.GetProgram(kClientProgramId);
+ const Program* program = SetupDefaultProgram();
ASSERT_TRUE(program != NULL);
// Emulate the situation that only the first element has a valid location.
// TODO(zmo): Don't assume these are in order.
@@ -1465,7 +1444,7 @@ TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) {
for (GLsizei jj = 1; jj < uniform->size; ++jj)
uniform->element_locations[jj] = -1;
}
- program->GetProgramInfo(&manager_, &bucket);
+ program->GetProgramInfo(manager_.get(), &bucket);
ProgramInfoHeader* header =
bucket.GetDataAs<ProgramInfoHeader*>(0, sizeof(ProgramInfoHeader));
ASSERT_TRUE(header != NULL);
@@ -1494,10 +1473,6 @@ TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) {
TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) {
// Set up shader
- const GLuint kVShaderClientId = 1;
- const GLuint kVShaderServiceId = 11;
- const GLuint kFShaderClientId = 2;
- const GLuint kFShaderServiceId = 12;
AttributeMap attrib_map;
for (uint32 ii = 0; ii < kNumAttribs; ++ii) {
attrib_map[kAttribs[ii].name] = TestHelper::ConstructAttribute(
@@ -1516,9 +1491,9 @@ TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) {
kAttribMatName);
// Check we can create shader.
Shader* vshader = shader_manager_.CreateShader(
- kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
Shader* fshader = shader_manager_.CreateShader(
- kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
// Check shader got created.
ASSERT_TRUE(vshader != NULL && fshader != NULL);
// Set Status
@@ -1542,10 +1517,8 @@ TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) {
NULL);
// Set up program
- const GLuint kClientProgramId = 6666;
- const GLuint kServiceProgramId = 8888;
Program* program =
- manager_.CreateProgram(kClientProgramId, kServiceProgramId);
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
ASSERT_TRUE(program != NULL);
EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
@@ -1593,11 +1566,6 @@ TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) {
TEST_F(ProgramManagerWithShaderTest, UniformsPrecisionMismatch) {
// Set up shader
- const GLuint kVShaderClientId = 1;
- const GLuint kVShaderServiceId = 11;
- const GLuint kFShaderClientId = 2;
- const GLuint kFShaderServiceId = 12;
-
UniformMap vertex_uniform_map;
vertex_uniform_map["a"] = TestHelper::ConstructUniform(
GL_FLOAT, 3, GL_MEDIUM_FLOAT, true, "a");
@@ -1607,9 +1575,9 @@ TEST_F(ProgramManagerWithShaderTest, UniformsPrecisionMismatch) {
// Check we can create shader.
Shader* vshader = shader_manager_.CreateShader(
- kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
Shader* fshader = shader_manager_.CreateShader(
- kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
// Check shader got created.
ASSERT_TRUE(vshader != NULL && fshader != NULL);
// Set Status
@@ -1621,10 +1589,8 @@ TEST_F(ProgramManagerWithShaderTest, UniformsPrecisionMismatch) {
&frag_uniform_map, NULL, NULL);
// Set up program
- const GLuint kClientProgramId = 6666;
- const GLuint kServiceProgramId = 8888;
Program* program =
- manager_.CreateProgram(kClientProgramId, kServiceProgramId);
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
ASSERT_TRUE(program != NULL);
EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
@@ -1790,22 +1756,16 @@ TEST_F(ProgramManagerWithShaderTest, CountAllVaryingsInPacking) {
}
TEST_F(ProgramManagerWithShaderTest, ClearWithSamplerTypes) {
- const GLuint kVShaderClientId = 2001;
- const GLuint kFShaderClientId = 2002;
- const GLuint kVShaderServiceId = 3001;
- const GLuint kFShaderServiceId = 3002;
Shader* vshader = shader_manager_.CreateShader(
- kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
ASSERT_TRUE(vshader != NULL);
TestHelper::SetShaderStates(gl_.get(), vshader, true);
Shader* fshader = shader_manager_.CreateShader(
- kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
ASSERT_TRUE(fshader != NULL);
TestHelper::SetShaderStates(gl_.get(), fshader, true);
- static const GLuint kClientProgramId = 1234;
- static const GLuint kServiceProgramId = 5679;
- Program* program = manager_.CreateProgram(
- kClientProgramId, kServiceProgramId);
+ Program* program =
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
ASSERT_TRUE(program != NULL);
EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
@@ -1852,37 +1812,30 @@ TEST_F(ProgramManagerWithShaderTest, ClearWithSamplerTypes) {
};
const size_t kNumAttribs = arraysize(kAttribs);
const size_t kNumUniforms = arraysize(kUniforms);
- SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
- kServiceProgramId);
+ SetupShaderExpectations(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
+ kServiceProgramId);
program->Link(NULL, Program::kCountOnlyStaticallyUsed,
base::Bind(&ShaderCacheCb));
SetupExpectationsForClearingUniforms(kUniforms, kNumUniforms);
- manager_.ClearUniforms(program);
+ manager_->ClearUniforms(program);
}
}
TEST_F(ProgramManagerWithShaderTest, BindUniformLocation) {
- const GLuint kVShaderClientId = 2001;
- const GLuint kFShaderClientId = 2002;
- const GLuint kVShaderServiceId = 3001;
- const GLuint kFShaderServiceId = 3002;
-
const GLint kUniform1DesiredLocation = 10;
const GLint kUniform2DesiredLocation = -1;
const GLint kUniform3DesiredLocation = 5;
Shader* vshader = shader_manager_.CreateShader(
- kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
ASSERT_TRUE(vshader != NULL);
TestHelper::SetShaderStates(gl_.get(), vshader, true);
Shader* fshader = shader_manager_.CreateShader(
- kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
ASSERT_TRUE(fshader != NULL);
TestHelper::SetShaderStates(gl_.get(), fshader, true);
- static const GLuint kClientProgramId = 1234;
- static const GLuint kServiceProgramId = 5679;
- Program* program = manager_.CreateProgram(
- kClientProgramId, kServiceProgramId);
+ Program* program =
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
ASSERT_TRUE(program != NULL);
EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
@@ -1925,8 +1878,8 @@ TEST_F(ProgramManagerWithShaderTest, BindUniformLocation) {
const size_t kNumAttribs = arraysize(kAttribs);
const size_t kNumUniforms = arraysize(kUniforms);
- SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
- kServiceProgramId);
+ SetupShaderExpectations(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
+ kServiceProgramId);
program->Link(NULL, Program::kCountOnlyStaticallyUsed,
base::Bind(&ShaderCacheCb));
@@ -1938,7 +1891,7 @@ TEST_F(ProgramManagerWithShaderTest, BindUniformLocation) {
program->GetUniformFakeLocation(kUniform3NameWithArrayIndex));
}
-class ProgramManagerWithCacheTest : public GpuServiceTest {
+class ProgramManagerWithCacheTest : public ProgramManagerTestBase {
public:
static const GLuint kClientProgramId = 1;
static const GLuint kServiceProgramId = 10;
@@ -1949,19 +1902,19 @@ class ProgramManagerWithCacheTest : public GpuServiceTest {
ProgramManagerWithCacheTest()
: cache_(new MockProgramCache()),
- manager_(cache_.get(), kMaxVaryingVectors),
vertex_shader_(NULL),
fragment_shader_(NULL),
program_(NULL) {
}
- ~ProgramManagerWithCacheTest() override {
- manager_.Destroy(false);
- shader_manager_.Destroy(false);
- }
protected:
+ void SetupProgramManager() override {
+ manager_.reset(new ProgramManager(cache_.get(), kMaxVaryingVectors,
+ feature_info_.get()));
+ }
+
void SetUp() override {
- GpuServiceTest::SetUp();
+ ProgramManagerTestBase::SetUp();
vertex_shader_ = shader_manager_.CreateShader(
kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
@@ -1972,14 +1925,16 @@ class ProgramManagerWithCacheTest : public GpuServiceTest {
vertex_shader_->set_source("lka asjf bjajsdfj");
fragment_shader_->set_source("lka asjf a fasgag 3rdsf3 bjajsdfj");
- program_ = manager_.CreateProgram(
- kClientProgramId, kServiceProgramId);
+ program_ = manager_->CreateProgram(kClientProgramId, kServiceProgramId);
ASSERT_TRUE(program_ != NULL);
program_->AttachShader(&shader_manager_, vertex_shader_);
program_->AttachShader(&shader_manager_, fragment_shader_);
}
-
+ void TearDown() override {
+ shader_manager_.Destroy(false);
+ ProgramManagerTestBase::TearDown();
+ }
void SetShadersCompiled() {
TestHelper::SetShaderStates(gl_.get(), vertex_shader_, true);
TestHelper::SetShaderStates(gl_.get(), fragment_shader_, true);
@@ -2064,12 +2019,9 @@ class ProgramManagerWithCacheTest : public GpuServiceTest {
}
void SetExpectationsForProgramLoadSuccess(GLuint service_program_id) {
- TestHelper::SetupProgramSuccessExpectations(gl_.get(),
- NULL,
- 0,
- NULL,
- 0,
- service_program_id);
+ TestHelper::SetupProgramSuccessExpectations(gl_.get(), feature_info_.get(),
+ nullptr, 0, nullptr, 0, nullptr,
+ 0, service_program_id);
}
void SetExpectationsForProgramLink() {
@@ -2077,7 +2029,8 @@ class ProgramManagerWithCacheTest : public GpuServiceTest {
}
void SetExpectationsForProgramLink(GLuint service_program_id) {
- TestHelper::SetupShader(gl_.get(), NULL, 0, NULL, 0, service_program_id);
+ TestHelper::SetupShaderExpectations(gl_.get(), feature_info_.get(), nullptr,
+ 0, nullptr, 0, service_program_id);
if (gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) {
EXPECT_CALL(*gl_.get(),
ProgramParameteri(service_program_id,
@@ -2122,7 +2075,6 @@ class ProgramManagerWithCacheTest : public GpuServiceTest {
}
scoped_ptr<MockProgramCache> cache_;
- ProgramManager manager_;
Shader* vertex_shader_;
Shader* fragment_shader_;
@@ -2162,5 +2114,162 @@ TEST_F(ProgramManagerWithCacheTest, LoadProgramOnProgramCacheHit) {
base::Bind(&ShaderCacheCb)));
}
+class ProgramManagerWithPathRenderingTest
+ : public ProgramManagerWithShaderTest,
+ public testing::WithParamInterface<
+ testing::tuple<const char*, const char*>> {
+ protected:
+ void SetUp() override {
+ base::CommandLine command_line(*base::CommandLine::ForCurrentProcess());
+ command_line.AppendSwitch(switches::kEnableGLPathRendering);
+ FeatureInfo* feature_info = new FeatureInfo(command_line);
+ SetUpBase(testing::get<0>(GetParam()), testing::get<1>(GetParam()),
+ feature_info);
+ }
+ static const char* kFragmentInput1Name;
+ static const char* kFragmentInput2Name;
+ // Name that GL reports for input 2. Needed because input 2 is an
+ // array.
+ static const char* kFragmentInput2GLName;
+ static const char* kFragmentInput3Name;
+ static const char* kFragmentInput3GLName;
+ static const GLint kFragmentInput1Size = 1;
+ static const GLint kFragmentInput2Size = 3;
+ static const GLint kFragmentInput3Size = 2;
+ static const int kFragmentInput1Precision = GL_LOW_FLOAT;
+ static const int kFragmentInput2Precision = GL_MEDIUM_INT;
+ static const int kFragmentInput3Precision = GL_HIGH_FLOAT;
+ static const int kFragmentInput1StaticUse = 1;
+ static const int kFragmentInput2StaticUse = 1;
+ static const int kFragmentInput3StaticUse = 1;
+ static const GLint kFragmentInput1FakeLocation = 0;
+ static const GLint kFragmentInput2FakeLocation = 1;
+ static const GLint kFragmentInput3FakeLocation = 2;
+ static const GLint kFragmentInput1RealLocation = 11;
+ static const GLint kFragmentInput2RealLocation = 22;
+ static const GLint kFragmentInput3RealLocation = 33;
+ static const GLenum kFragmentInput1Type = GL_FLOAT_VEC4;
+ static const GLenum kFragmentInput2Type = GL_INT_VEC2;
+ static const GLenum kFragmentInput3Type = GL_FLOAT_VEC3;
+};
+#ifndef COMPILER_MSVC
+const GLint ProgramManagerWithPathRenderingTest::kFragmentInput1Size;
+const GLint ProgramManagerWithPathRenderingTest::kFragmentInput2Size;
+const GLint ProgramManagerWithPathRenderingTest::kFragmentInput3Size;
+const int ProgramManagerWithPathRenderingTest::kFragmentInput1Precision;
+const int ProgramManagerWithPathRenderingTest::kFragmentInput2Precision;
+const int ProgramManagerWithPathRenderingTest::kFragmentInput3Precision;
+const int ProgramManagerWithPathRenderingTest::kFragmentInput1StaticUse;
+const int ProgramManagerWithPathRenderingTest::kFragmentInput2StaticUse;
+const int ProgramManagerWithPathRenderingTest::kFragmentInput3StaticUse;
+const GLint ProgramManagerWithPathRenderingTest::kFragmentInput1FakeLocation;
+const GLint ProgramManagerWithPathRenderingTest::kFragmentInput2FakeLocation;
+const GLint ProgramManagerWithPathRenderingTest::kFragmentInput3FakeLocation;
+const GLint ProgramManagerWithPathRenderingTest::kFragmentInput1RealLocation;
+const GLint ProgramManagerWithPathRenderingTest::kFragmentInput2RealLocation;
+const GLint ProgramManagerWithPathRenderingTest::kFragmentInput3RealLocation;
+const GLenum ProgramManagerWithPathRenderingTest::kFragmentInput1Type;
+const GLenum ProgramManagerWithPathRenderingTest::kFragmentInput2Type;
+const GLenum ProgramManagerWithPathRenderingTest::kFragmentInput3Type;
+#endif
+
+const char* ProgramManagerWithPathRenderingTest::kFragmentInput1Name = "color1";
+const char* ProgramManagerWithPathRenderingTest::kFragmentInput2Name = "color2";
+const char* ProgramManagerWithPathRenderingTest::kFragmentInput2GLName =
+ "color2[0]";
+
+const char* ProgramManagerWithPathRenderingTest::kFragmentInput3Name = "color3";
+const char* ProgramManagerWithPathRenderingTest::kFragmentInput3GLName =
+ "color3[0]";
+
+TEST_P(ProgramManagerWithPathRenderingTest, BindFragmentInputLocation) {
+ const GLint kFragmentInput1DesiredLocation = 10;
+ const GLint kFragmentInput2DesiredLocation = -1;
+ const GLint kFragmentInput3DesiredLocation = 5;
+
+ Shader* vshader = shader_manager_.CreateShader(
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
+ ASSERT_TRUE(vshader != NULL);
+ Shader* fshader = shader_manager_.CreateShader(
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
+ ASSERT_TRUE(fshader != NULL);
+ VaryingMap varying_map;
+ varying_map[kFragmentInput1Name] = TestHelper::ConstructVarying(
+ kFragmentInput1Type, kFragmentInput1Size, kFragmentInput1Precision,
+ kFragmentInput1StaticUse, kFragmentInput1Name);
+ varying_map[kFragmentInput2Name] = TestHelper::ConstructVarying(
+ kFragmentInput2Type, kFragmentInput2Size, kFragmentInput2Precision,
+ kFragmentInput2StaticUse, kFragmentInput2Name);
+ varying_map[kFragmentInput3Name] = TestHelper::ConstructVarying(
+ kFragmentInput3Type, kFragmentInput3Size, kFragmentInput3Precision,
+ kFragmentInput3StaticUse, kFragmentInput3Name);
+ TestHelper::SetShaderStates(gl_.get(), vshader, true, nullptr, nullptr,
+ nullptr, nullptr, nullptr, &varying_map, nullptr);
+ TestHelper::SetShaderStates(gl_.get(), fshader, true, nullptr, nullptr,
+ nullptr, nullptr, nullptr, &varying_map, nullptr);
+ Program* program =
+ manager_->CreateProgram(kClientProgramId, kServiceProgramId);
+ ASSERT_TRUE(program != NULL);
+ EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
+ EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
+ program->SetFragmentInputLocationBinding(kFragmentInput1Name,
+ kFragmentInput1DesiredLocation);
+ program->SetFragmentInputLocationBinding(kFragmentInput3Name,
+ kFragmentInput3DesiredLocation);
+ TestHelper::VaryingInfo kFragmentInputExpectationInfos[] = {
+ {
+ kFragmentInput1Name, kFragmentInput1Size, kFragmentInput1Type,
+ kFragmentInput1FakeLocation, kFragmentInput1RealLocation,
+ kFragmentInput1DesiredLocation,
+ },
+ {
+ kFragmentInput2GLName, kFragmentInput2Size, kFragmentInput2Type,
+ kFragmentInput2FakeLocation, kFragmentInput2RealLocation,
+ kFragmentInput2DesiredLocation,
+ },
+ {
+ kFragmentInput3GLName, kFragmentInput3Size, kFragmentInput3Type,
+ kFragmentInput3FakeLocation, kFragmentInput3RealLocation,
+ kFragmentInput3DesiredLocation,
+ },
+ };
+ TestHelper::SetupShaderExpectationsWithVaryings(
+ gl_.get(), feature_info_.get(), nullptr, 0, nullptr, 0,
+ kFragmentInputExpectationInfos, arraysize(kFragmentInputExpectationInfos),
+ kServiceProgramId);
+ program->Link(NULL, Program::kCountOnlyStaticallyUsed,
+ base::Bind(&ShaderCacheCb));
+ const Program::FragmentInputInfo* info1 =
+ program->GetFragmentInputInfoByFakeLocation(
+ kFragmentInput1DesiredLocation);
+ ASSERT_NE(info1, nullptr);
+ EXPECT_EQ(kFragmentInput1RealLocation, static_cast<GLint>(info1->location));
+ const Program::FragmentInputInfo* info3 =
+ program->GetFragmentInputInfoByFakeLocation(
+ kFragmentInput3DesiredLocation);
+ ASSERT_NE(info3, nullptr);
+ EXPECT_EQ(kFragmentInput3RealLocation, static_cast<GLint>(info3->location));
+}
+
+// For some compilers, using make_tuple("a", "bb") would end up
+// instantiating make_tuple<char[1], char[2]>. This does not work.
+namespace {
+testing::tuple<const char*, const char*> make_gl_ext_tuple(
+ const char* gl_version,
+ const char* gl_extensions) {
+ return testing::make_tuple(gl_version, gl_extensions);
+}
+}
+
+INSTANTIATE_TEST_CASE_P(
+ SupportedContexts,
+ ProgramManagerWithPathRenderingTest,
+ testing::Values(
+ make_gl_ext_tuple("3.2",
+ "GL_ARB_program_interface_query "
+ "GL_EXT_direct_state_access GL_NV_path_rendering"),
+ make_gl_ext_tuple("4.5", "GL_NV_path_rendering"),
+ make_gl_ext_tuple("opengl es 3.1", "GL_NV_path_rendering")));
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/test_helper.cc b/gpu/command_buffer/service/test_helper.cc
index edc6662..066e38a 100644
--- a/gpu/command_buffer/service/test_helper.cc
+++ b/gpu/command_buffer/service/test_helper.cc
@@ -12,6 +12,7 @@
#include "base/strings/string_tokenizer.h"
#include "gpu/command_buffer/service/buffer_manager.h"
#include "gpu/command_buffer/service/error_state_mock.h"
+#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/mocks.h"
@@ -441,7 +442,8 @@ void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(
.WillOnce(Return(reinterpret_cast<const uint8*>(gl_renderer)))
.RetiresOnSaturation();
- if (strstr(extensions, "GL_ARB_texture_float") ||
+ if ((strstr(extensions, "GL_ARB_texture_float") ||
+ gl_info.is_desktop_core_profile) ||
(gl_info.is_es3 && strstr(extensions, "GL_EXT_color_buffer_float"))) {
static const GLuint tx_ids[] = {101, 102};
static const GLuint fb_ids[] = {103, 104};
@@ -513,7 +515,8 @@ void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(
if (strstr(extensions, "GL_EXT_draw_buffers") ||
strstr(extensions, "GL_ARB_draw_buffers") ||
- (gl_info.is_es3 && strstr(extensions, "GL_NV_draw_buffers"))) {
+ (gl_info.is_es3 && strstr(extensions, "GL_NV_draw_buffers")) ||
+ gl_info.is_desktop_core_profile) {
EXPECT_CALL(*gl, GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, _))
.WillOnce(SetArgumentPointee<1>(8))
.RetiresOnSaturation();
@@ -522,7 +525,8 @@ void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(
.RetiresOnSaturation();
}
- if (gl_info.is_es3 || strstr(extensions, "GL_EXT_texture_rg") ||
+ if (gl_info.is_es3 || gl_info.is_desktop_core_profile ||
+ strstr(extensions, "GL_EXT_texture_rg") ||
(strstr(extensions, "GL_ARB_texture_rg"))) {
static const GLuint tx_ids[] = {101, 102};
static const GLuint fb_ids[] = {103, 104};
@@ -678,8 +682,13 @@ void TestHelper::SetupExpectationsForClearingUniforms(
void TestHelper::SetupProgramSuccessExpectations(
::gfx::MockGLInterface* gl,
- AttribInfo* attribs, size_t num_attribs,
- UniformInfo* uniforms, size_t num_uniforms,
+ const FeatureInfo* feature_info,
+ AttribInfo* attribs,
+ size_t num_attribs,
+ UniformInfo* uniforms,
+ size_t num_uniforms,
+ VaryingInfo* varyings,
+ size_t num_varyings,
GLuint service_id) {
EXPECT_CALL(*gl,
GetProgramiv(service_id, GL_LINK_STATUS, _))
@@ -777,12 +786,77 @@ void TestHelper::SetupProgramSuccessExpectations(
}
}
}
+
+ if (feature_info->feature_flags().chromium_path_rendering) {
+ EXPECT_CALL(*gl, GetProgramInterfaceiv(service_id, GL_FRAGMENT_INPUT_NV,
+ GL_ACTIVE_RESOURCES, _))
+ .WillOnce(SetArgumentPointee<3>(int(num_varyings)))
+ .RetiresOnSaturation();
+ size_t max_varying_len = 0;
+ for (size_t ii = 0; ii < num_varyings; ++ii) {
+ size_t len = strlen(varyings[ii].name) + 1;
+ max_varying_len = std::max(max_varying_len, len);
+ }
+ EXPECT_CALL(*gl, GetProgramInterfaceiv(service_id, GL_FRAGMENT_INPUT_NV,
+ GL_MAX_NAME_LENGTH, _))
+ .WillOnce(SetArgumentPointee<3>(int(max_varying_len)))
+ .RetiresOnSaturation();
+ for (size_t ii = 0; ii < num_varyings; ++ii) {
+ VaryingInfo& info = varyings[ii];
+ EXPECT_CALL(*gl, GetProgramResourceName(service_id, GL_FRAGMENT_INPUT_NV,
+ ii, max_varying_len, _, _))
+ .WillOnce(DoAll(SetArgumentPointee<4>(strlen(info.name)),
+ SetArrayArgument<5>(
+ info.name, info.name + strlen(info.name) + 1)))
+ .RetiresOnSaturation();
+ if (!ProgramManager::IsInvalidPrefix(info.name, strlen(info.name))) {
+ static const GLenum kPropsArray[] = {GL_LOCATION, GL_TYPE,
+ GL_ARRAY_SIZE};
+ static const size_t kPropsSize = arraysize(kPropsArray);
+ EXPECT_CALL(
+ *gl, GetProgramResourceiv(
+ service_id, GL_FRAGMENT_INPUT_NV, ii, kPropsSize,
+ _ /*testing::ElementsAreArray(kPropsArray, kPropsSize)*/,
+ kPropsSize, _, _))
+ .WillOnce(testing::Invoke([info](GLuint, GLenum, GLuint, GLsizei,
+ const GLenum*, GLsizei,
+ GLsizei* length, GLint* params) {
+ *length = kPropsSize;
+ params[0] = info.real_location;
+ params[1] = info.type;
+ params[2] = info.size;
+ }))
+ .RetiresOnSaturation();
+ }
+ }
+ }
+}
+
+void TestHelper::SetupShaderExpectations(::gfx::MockGLInterface* gl,
+ const FeatureInfo* feature_info,
+ AttribInfo* attribs,
+ size_t num_attribs,
+ UniformInfo* uniforms,
+ size_t num_uniforms,
+ GLuint service_id) {
+ InSequence s;
+
+ EXPECT_CALL(*gl, LinkProgram(service_id)).Times(1).RetiresOnSaturation();
+
+ SetupProgramSuccessExpectations(gl, feature_info, attribs, num_attribs,
+ uniforms, num_uniforms, nullptr, 0,
+ service_id);
}
-void TestHelper::SetupShader(
+void TestHelper::SetupShaderExpectationsWithVaryings(
::gfx::MockGLInterface* gl,
- AttribInfo* attribs, size_t num_attribs,
- UniformInfo* uniforms, size_t num_uniforms,
+ const FeatureInfo* feature_info,
+ AttribInfo* attribs,
+ size_t num_attribs,
+ UniformInfo* uniforms,
+ size_t num_uniforms,
+ VaryingInfo* varyings,
+ size_t num_varyings,
GLuint service_id) {
InSequence s;
@@ -791,8 +865,9 @@ void TestHelper::SetupShader(
.Times(1)
.RetiresOnSaturation();
- SetupProgramSuccessExpectations(
- gl, attribs, num_attribs, uniforms, num_uniforms, service_id);
+ SetupProgramSuccessExpectations(gl, feature_info, attribs, num_attribs,
+ uniforms, num_uniforms, varyings,
+ num_varyings, service_id);
}
void TestHelper::DoBufferData(
diff --git a/gpu/command_buffer/service/test_helper.h b/gpu/command_buffer/service/test_helper.h
index 5998915b..45297ee 100644
--- a/gpu/command_buffer/service/test_helper.h
+++ b/gpu/command_buffer/service/test_helper.h
@@ -18,6 +18,7 @@ namespace gles2 {
struct DisallowedFeatures;
class Buffer;
class BufferManager;
+class FeatureInfo;
class MockErrorState;
class Shader;
class TextureRef;
@@ -73,6 +74,15 @@ class TestHelper {
const char* good_name;
};
+ struct VaryingInfo {
+ const char* name;
+ GLint size;
+ GLenum type;
+ GLint fake_location;
+ GLint real_location;
+ GLint desired_location;
+ };
+
static void SetupContextGroupInitExpectations(
::gfx::MockGLInterface* gl,
const DisallowedFeatures& disallowed_features,
@@ -99,16 +109,34 @@ class TestHelper {
static void SetupExpectationsForClearingUniforms(
::gfx::MockGLInterface* gl, UniformInfo* uniforms, size_t num_uniforms);
- static void SetupShader(
+ static void SetupShaderExpectations(::gfx::MockGLInterface* gl,
+ const FeatureInfo* feature_info,
+ AttribInfo* attribs,
+ size_t num_attribs,
+ UniformInfo* uniforms,
+ size_t num_uniforms,
+ GLuint service_id);
+
+ static void SetupShaderExpectationsWithVaryings(
::gfx::MockGLInterface* gl,
- AttribInfo* attribs, size_t num_attribs,
- UniformInfo* uniforms, size_t num_uniforms,
+ const FeatureInfo* feature_info,
+ AttribInfo* attribs,
+ size_t num_attribs,
+ UniformInfo* uniforms,
+ size_t num_uniforms,
+ VaryingInfo* varyings,
+ size_t num_varyings,
GLuint service_id);
static void SetupProgramSuccessExpectations(::gfx::MockGLInterface* gl,
- AttribInfo* attribs, size_t num_attribs,
- UniformInfo* uniforms, size_t num_uniforms,
- GLuint service_id);
+ const FeatureInfo* feature_info,
+ AttribInfo* attribs,
+ size_t num_attribs,
+ UniformInfo* uniforms,
+ size_t num_uniforms,
+ VaryingInfo* varyings,
+ size_t num_varyings,
+ GLuint service_id);
static void DoBufferData(
::gfx::MockGLInterface* gl, MockErrorState* error_state,
diff --git a/gpu/command_buffer/tests/gl_bind_uniform_location_unittest.cc b/gpu/command_buffer/tests/gl_bind_uniform_location_unittest.cc
index 0285542..d688c69 100644
--- a/gpu/command_buffer/tests/gl_bind_uniform_location_unittest.cc
+++ b/gpu/command_buffer/tests/gl_bind_uniform_location_unittest.cc
@@ -15,12 +15,13 @@
namespace gpu {
-class BindUniformLocationTest : public testing::Test {
+class BindUniformLocationTest : public testing::TestWithParam<bool> {
protected:
static const GLsizei kResolution = 4;
void SetUp() override {
GLManager::Options options;
options.size = gfx::Size(kResolution, kResolution);
+ options.force_shader_name_hashing = GetParam();
gl_.Initialize(options);
}
@@ -29,7 +30,7 @@ class BindUniformLocationTest : public testing::Test {
GLManager gl_;
};
-TEST_F(BindUniformLocationTest, Basic) {
+TEST_P(BindUniformLocationTest, Basic) {
ASSERT_TRUE(
GLTestHelper::HasExtension("GL_CHROMIUM_bind_uniform_location"));
@@ -99,7 +100,7 @@ TEST_F(BindUniformLocationTest, Basic) {
GLTestHelper::CheckGLError("no errors", __LINE__);
}
-TEST_F(BindUniformLocationTest, ConflictsDetection) {
+TEST_P(BindUniformLocationTest, ConflictsDetection) {
ASSERT_TRUE(
GLTestHelper::HasExtension("GL_CHROMIUM_bind_uniform_location"));
@@ -140,7 +141,7 @@ TEST_F(BindUniformLocationTest, ConflictsDetection) {
glGetProgramiv(program, GL_LINK_STATUS, &linked);
EXPECT_EQ(0, linked);
- // Bind u_colorB to location a, no conflicts, link should succeed.
+ // Bind u_colorB to location b, no conflicts, link should succeed.
glBindUniformLocationCHROMIUM(program, color_b_location, "u_colorB");
glLinkProgram(program);
linked = 0;
@@ -150,7 +151,7 @@ TEST_F(BindUniformLocationTest, ConflictsDetection) {
GLTestHelper::CheckGLError("no errors", __LINE__);
}
-TEST_F(BindUniformLocationTest, Compositor) {
+TEST_P(BindUniformLocationTest, Compositor) {
ASSERT_TRUE(
GLTestHelper::HasExtension("GL_CHROMIUM_bind_uniform_location"));
@@ -193,7 +194,7 @@ TEST_F(BindUniformLocationTest, Compositor) {
}
);
- int counter = 0;
+ int counter = 6;
int matrix_location = counter++;
int color_a_location = counter++;
int color_b_location = counter++;
@@ -267,6 +268,10 @@ TEST_F(BindUniformLocationTest, Compositor) {
}
+INSTANTIATE_TEST_CASE_P(WithAndWithoutShaderNameMapping,
+ BindUniformLocationTest,
+ ::testing::Bool());
+
} // 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 d634449..478f487 100644
--- a/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc
+++ b/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc
@@ -16,34 +16,72 @@
#define SHADER(Src) #Src
+namespace {
+void ExpectEqualMatrix(const GLfloat* expected, const GLfloat* actual) {
+ for (size_t i = 0; i < 16; ++i) {
+ EXPECT_EQ(expected[i], actual[i]);
+ }
+}
+void ExpectEqualMatrix(const GLfloat* expected, const GLint* actual) {
+ for (size_t i = 0; i < 16; ++i) {
+ EXPECT_EQ(static_cast<GLint>(roundf(expected[i])), actual[i]);
+ }
+}
+}
namespace gpu {
class CHROMIUMPathRenderingTest : public testing::Test {
- public:
+ protected:
static const GLsizei kResolution = 300;
- protected:
void SetUp() override {
GLManager::Options options;
- options.size = gfx::Size(kResolution, kResolution);
base::CommandLine command_line(*base::CommandLine::ForCurrentProcess());
command_line.AppendSwitch(switches::kEnableGLPathRendering);
+ InitializeContextFeatures(&options);
gl_.InitializeWithCommandLine(options, &command_line);
}
+ virtual void InitializeContextFeatures(GLManager::Options* options) {
+ options->size = gfx::Size(kResolution, kResolution);
+ }
+
void TearDown() override { gl_.Destroy(); }
- void ExpectEqualMatrix(const GLfloat* expected, const GLfloat* actual) {
- for (size_t i = 0; i < 16; ++i) {
- EXPECT_EQ(expected[i], actual[i]);
- }
+ bool IsApplicable() const {
+ return GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering");
}
- void ExpectEqualMatrix(const GLfloat* expected, const GLint* actual) {
- for (size_t i = 0; i < 16; ++i) {
- EXPECT_EQ(static_cast<GLint>(round(expected[i])), actual[i]);
- }
+
+ 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_;
+};
+
+class CHROMIUMPathRenderingDrawTest : public CHROMIUMPathRenderingTest {
+ protected:
void SetupStateForTestPattern() {
glViewport(0, 0, kResolution, kResolution);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -64,23 +102,7 @@ class CHROMIUMPathRenderingTest : public testing::Test {
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);
+ glMatrixLoadfCHROMIUM(GL_PATH_PROJECTION_CHROMIUM, kProjectionMatrix);
glMatrixLoadIdentityCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM);
glEnable(GL_STENCIL_TEST);
@@ -163,38 +185,30 @@ class CHROMIUMPathRenderingTest : public testing::Test {
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_;
+ static const GLfloat kProjectionMatrix[16];
GLint color_loc_;
};
+const GLfloat CHROMIUMPathRenderingDrawTest::kProjectionMatrix[16] = {
+ 2.0f / (CHROMIUMPathRenderingTest::kResolution - 1),
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 2.0f / (CHROMIUMPathRenderingTest::kResolution - 1),
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ -1.0f,
+ 0.0f,
+ -1.0f,
+ -1.0f,
+ 0.0f,
+ 1.0f};
+
TEST_F(CHROMIUMPathRenderingTest, TestMatrix) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ if (!IsApplicable())
return;
static const GLfloat kIdentityMatrix[16] = {
@@ -239,7 +253,7 @@ TEST_F(CHROMIUMPathRenderingTest, TestMatrix) {
}
TEST_F(CHROMIUMPathRenderingTest, TestMatrixErrors) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ if (!IsApplicable())
return;
GLfloat mf[16];
@@ -261,7 +275,7 @@ TEST_F(CHROMIUMPathRenderingTest, TestMatrixErrors) {
}
TEST_F(CHROMIUMPathRenderingTest, TestSimpleCalls) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ if (!IsApplicable())
return;
// This is unspecified in NV_path_rendering.
@@ -306,7 +320,7 @@ TEST_F(CHROMIUMPathRenderingTest, TestSimpleCalls) {
}
TEST_F(CHROMIUMPathRenderingTest, TestGenDeleteErrors) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ if (!IsApplicable())
return;
// GenPaths / DeletePaths tests.
@@ -359,7 +373,7 @@ TEST_F(CHROMIUMPathRenderingTest, TestGenDeleteErrors) {
}
TEST_F(CHROMIUMPathRenderingTest, TestPathParameterErrors) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ if (!IsApplicable())
return;
GLuint path = glGenPathsCHROMIUM(1);
@@ -387,7 +401,7 @@ TEST_F(CHROMIUMPathRenderingTest, TestPathParameterErrors) {
}
TEST_F(CHROMIUMPathRenderingTest, TestPathObjectState) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ if (!IsApplicable())
return;
glViewport(0, 0, kResolution, kResolution);
@@ -446,7 +460,7 @@ TEST_F(CHROMIUMPathRenderingTest, TestPathObjectState) {
}
TEST_F(CHROMIUMPathRenderingTest, TestUnnamedPathsErrors) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ if (!IsApplicable())
return;
// Unnamed paths: Trying to create a path object with non-existing path name
@@ -469,7 +483,7 @@ TEST_F(CHROMIUMPathRenderingTest, TestUnnamedPathsErrors) {
}
TEST_F(CHROMIUMPathRenderingTest, TestPathCommandsErrors) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ if (!IsApplicable())
return;
static const GLenum kInvalidCoordType = GL_NONE;
@@ -503,7 +517,7 @@ TEST_F(CHROMIUMPathRenderingTest, TestPathCommandsErrors) {
}
TEST_F(CHROMIUMPathRenderingTest, TestPathRenderingInvalidArgs) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+ if (!IsApplicable())
return;
GLuint path = glGenPathsCHROMIUM(1);
@@ -570,8 +584,8 @@ TEST_F(CHROMIUMPathRenderingTest, TestPathRenderingInvalidArgs) {
}
// Tests that drawing with CHROMIUM_path_rendering functions work.
-TEST_F(CHROMIUMPathRenderingTest, TestPathRendering) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+TEST_F(CHROMIUMPathRenderingDrawTest, TestPathRendering) {
+ if (!IsApplicable())
return;
static const float kBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
@@ -617,8 +631,8 @@ TEST_F(CHROMIUMPathRenderingTest, TestPathRendering) {
// Tests that drawing with CHROMIUM_path_rendering
// StencilThenCover{Stroke,Fill}Path functions work.
-TEST_F(CHROMIUMPathRenderingTest, TestPathRenderingThenFunctions) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering"))
+TEST_F(CHROMIUMPathRenderingDrawTest, TestPathRenderingThenFunctions) {
+ if (!IsApplicable())
return;
static float kBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
@@ -652,10 +666,10 @@ TEST_F(CHROMIUMPathRenderingTest, TestPathRenderingThenFunctions) {
}
// Tests that drawing with *Instanced functions work.
-TEST_F(CHROMIUMPathRenderingTest, TestPathRenderingInstanced) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering")) {
+TEST_F(CHROMIUMPathRenderingDrawTest, TestPathRenderingInstanced) {
+ if (!IsApplicable())
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};
@@ -729,10 +743,10 @@ TEST_F(CHROMIUMPathRenderingTest, TestPathRenderingInstanced) {
VerifyTestPatternStroke(kShapeSize, kShapeSize);
}
-TEST_F(CHROMIUMPathRenderingTest, TestPathRenderingThenFunctionsInstanced) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_path_rendering")) {
+TEST_F(CHROMIUMPathRenderingDrawTest, TestPathRenderingThenFunctionsInstanced) {
+ if (!IsApplicable())
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};
@@ -791,4 +805,891 @@ TEST_F(CHROMIUMPathRenderingTest, TestPathRenderingThenFunctionsInstanced) {
VerifyTestPatternStroke(kShapeSize, kShapeSize);
}
+// This class implements a test that draws a grid of v-shapes. The grid is
+// drawn so that even rows (from the bottom) are drawn with DrawArrays and odd
+// rows are drawn with path rendering. It can be used to test various texturing
+// modes, comparing how the fill would work in normal GL rendering and how to
+// setup same sort of fill with path rendering.
+// The texturing test is parametrized to run the test with and without
+// ANGLE name hashing.
+class CHROMIUMPathRenderingWithTexturingTest
+ : public CHROMIUMPathRenderingTest,
+ public ::testing::WithParamInterface<bool> {
+ protected:
+ void InitializeContextFeatures(GLManager::Options* options) override {
+ CHROMIUMPathRenderingTest::InitializeContextFeatures(options);
+ options->force_shader_name_hashing = GetParam();
+ }
+
+ /** Sets up the GL program state for the test.
+ Vertex shader needs at least following variables:
+ uniform mat4 view_matrix;
+ uniform mat? color_matrix; (accessible with kColorMatrixLocation)
+ uniform vec2 model_translate;
+ attribute vec2 position;
+ varying vec4 color;
+
+ Fragment shader needs at least following variables:
+ varying vec4 color;
+
+ (? can be anything)
+ */
+ void SetupProgramForTestPattern(const char* vertex_shader_source,
+ const char* fragment_shader_source) {
+ 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);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ GLuint vs =
+ GLTestHelper::LoadShader(GL_VERTEX_SHADER, vertex_shader_source);
+ GLuint fs =
+ GLTestHelper::LoadShader(GL_FRAGMENT_SHADER, fragment_shader_source);
+
+ program_ = glCreateProgram();
+ glBindAttribLocation(program_, kPositionLocation, "position");
+ glBindUniformLocationCHROMIUM(program_, kViewMatrixLocation, "view_matrix");
+ glBindUniformLocationCHROMIUM(program_, kColorMatrixLocation,
+ "color_matrix");
+ glBindUniformLocationCHROMIUM(program_, kModelTranslateLocation,
+ "model_translate");
+ glBindFragmentInputLocationCHROMIUM(program_, kColorFragmentInputLocation,
+ "color");
+ glAttachShader(program_, fs);
+ glAttachShader(program_, vs);
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+ }
+
+ void LinkProgramForTestPattern() {
+ glLinkProgram(program_);
+ GLint linked = 0;
+ glGetProgramiv(program_, GL_LINK_STATUS, &linked);
+ EXPECT_TRUE(linked == GL_TRUE);
+ glUseProgram(program_);
+
+ glUniformMatrix4fv(kViewMatrixLocation, 1, GL_FALSE, kProjectionMatrix);
+ }
+
+ void DrawTestPattern() {
+ // Setup state for drawing the shape with DrawArrays.
+
+ // This v-shape is used both for DrawArrays and path rendering.
+ static const GLfloat kVertices[] = {75.0f, 75.0f, 50.0f, 25.5f,
+ 50.0f, 50.0f, 25.0f, 75.0f};
+
+ GLuint vbo = 0;
+ glGenBuffers(1, &vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(kPositionLocation);
+ glVertexAttribPointer(kPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+ // Setup state for drawing the shape with path rendering.
+ glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
+ glStencilFunc(GL_LESS, 0, 0x7F);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+ glMatrixLoadfCHROMIUM(GL_PATH_PROJECTION_CHROMIUM, kProjectionMatrix);
+ glMatrixLoadIdentityCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM);
+
+ static const GLubyte kCommands[] = {
+ GL_MOVE_TO_CHROMIUM, GL_LINE_TO_CHROMIUM, GL_LINE_TO_CHROMIUM,
+ GL_LINE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
+
+ static const GLfloat kCoords[] = {
+ kVertices[0], kVertices[1], kVertices[2], kVertices[3],
+ kVertices[6], kVertices[7], kVertices[4], kVertices[5],
+ };
+
+ GLuint path = glGenPathsCHROMIUM(1);
+ glPathCommandsCHROMIUM(path, arraysize(kCommands), kCommands,
+ arraysize(kCoords), GL_FLOAT, kCoords);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ GLfloat path_model_translate[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,
+ };
+
+ // Draws the shapes. Every even row from the bottom is drawn with
+ // DrawArrays, odd row with path rendering. The shader program is
+ // the same for the both draws.
+ for (int j = 0; j < kTestRows; ++j) {
+ for (int i = 0; i < kTestColumns; ++i) {
+ if (j % 2 == 0) {
+ glDisable(GL_STENCIL_TEST);
+ glUniform2f(kModelTranslateLocation, i * kShapeWidth,
+ j * kShapeHeight);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ } else {
+ glEnable(GL_STENCIL_TEST);
+ path_model_translate[12] = i * kShapeWidth;
+ path_model_translate[13] = j * kShapeHeight;
+ glMatrixLoadfCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM,
+ path_model_translate);
+ glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F,
+ GL_BOUNDING_BOX_CHROMIUM);
+ }
+ }
+ }
+
+ glDisableVertexAttribArray(kPositionLocation);
+ glDeleteBuffers(1, &vbo);
+ glDeletePathsCHROMIUM(path, 1);
+ }
+
+ void TeardownStateForTestPattern() { glDeleteProgram(program_); }
+
+ static const GLfloat kProjectionMatrix[16];
+
+ // This uniform be can set by the test. It should be used to set the color for
+ // drawing with DrawArrays.
+ static const GLint kColorMatrixLocation = 4;
+
+ // This fragment input can be set by the test. It should be used to set the
+ // color for drawing with path rendering.
+ static const GLint kColorFragmentInputLocation = 7;
+
+ enum {
+ kShapeWidth = 75,
+ kShapeHeight = 75,
+ kTestRows = kResolution / kShapeHeight,
+ kTestColumns = kResolution / kShapeWidth,
+ };
+
+ // These coordinates are inside the shape fill. This can be used to verífy
+ // fill color.
+ static const float kFillCoords[6];
+
+ GLint program_;
+
+ static const GLint kModelTranslateLocation = 3;
+ static const GLint kPositionLocation = 0;
+ static const GLint kViewMatrixLocation = 7;
+};
+
+const GLfloat CHROMIUMPathRenderingWithTexturingTest::kProjectionMatrix[16] = {
+ 2.0f / (CHROMIUMPathRenderingWithTexturingTest::kResolution - 1),
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 2.0f / (CHROMIUMPathRenderingWithTexturingTest::kResolution - 1),
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ -1.0f,
+ 0.0f,
+ -1.0f,
+ -1.0f,
+ 0.0f,
+ 1.0f};
+
+const GLfloat CHROMIUMPathRenderingWithTexturingTest::kFillCoords[6] = {
+ 59.0f, 50.0f, 50.0f, 28.0f, 66.0f, 63.0f};
+
+// This test tests ProgramPathFragmentInputGenCHROMIUM and
+// BindFragmentInputLocationCHROMIUM. The test draws a shape multiple times as a
+// grid. Each shape is filled with a color pattern that has projection-space
+// gradient of the fragment coordinates in r and g components of the color. The
+// color slides as function of coordinates: x=0..kResolution --> r=0..1,
+// y=0..kResolution --> g=0..1
+TEST_P(CHROMIUMPathRenderingWithTexturingTest,
+ TestProgramPathFragmentInputGenCHROMIUM_EYE) {
+ if (!IsApplicable())
+ return;
+
+ // clang-format off
+ static const char* kVertexShaderSource = SHADER(
+ uniform mat4 view_matrix;
+ uniform mat4 color_matrix;
+ uniform vec2 model_translate;
+ attribute vec2 position;
+ varying vec3 color;
+ void main() {
+ vec4 p = vec4(model_translate + position, 1, 1);
+ color = (color_matrix * p).rgb;
+ gl_Position = view_matrix * p;
+ }
+ );
+
+ static const char* kFragmentShaderSource = SHADER(
+ precision mediump float;
+ varying vec3 color;
+ void main() {
+ gl_FragColor = vec4(color, 1.0);
+ }
+ );
+ // clang-format on
+
+ SetupProgramForTestPattern(kVertexShaderSource, kFragmentShaderSource);
+ LinkProgramForTestPattern();
+ static const GLfloat kColorMatrix[16] = {
+ 1.0f / kResolution,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 1.0f / kResolution,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ };
+ glUniformMatrix4fv(kColorMatrixLocation, 1, GL_FALSE, kColorMatrix);
+ // This is the functionality we are testing: ProgramPathFragmentInputGen
+ // does the same work as the color transform in vertex shader.
+ static const GLfloat kColorCoefficients[12] = {1.0f / kResolution,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 1.0f / kResolution,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f};
+ glProgramPathFragmentInputGenCHROMIUM(program_, kColorFragmentInputLocation,
+ GL_EYE_LINEAR_CHROMIUM, 3,
+ kColorCoefficients);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ DrawTestPattern();
+
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ for (int j = 0; j < kTestRows; ++j) {
+ for (int i = 0; i < kTestColumns; ++i) {
+ for (size_t k = 0; k < arraysize(kFillCoords); k += 2) {
+ SCOPED_TRACE(testing::Message() << "Verifying fill for shape " << i
+ << ", " << j << " coord " << k);
+ float fx = kFillCoords[k];
+ float fy = kFillCoords[k + 1];
+ float px = i * kShapeWidth;
+ float py = j * kShapeHeight;
+
+ uint8 color[4];
+ color[0] = roundf((px + fx) / kResolution * 255.0f);
+ color[1] = roundf((py + fy) / kResolution * 255.0f);
+ color[2] = 0;
+ color[3] = 255;
+
+ EXPECT_TRUE(
+ GLTestHelper::CheckPixels(px + fx, py + fy, 1, 1, 2, color));
+ }
+ }
+ }
+
+ TeardownStateForTestPattern();
+
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+// This test tests ProgramPathFragmentInputGenCHROMIUM and
+// BindFragmentInputLocationCHROMIUM, same as above test.
+// Each shape is filled with a color pattern that has object-space
+// gradient of the fragment coordinates in r and g components of the color. The
+// color slides as function of object coordinates: x=0..kShapeWidth --> r=0..1,
+// y=0..kShapeWidth --> g=0..1
+TEST_P(CHROMIUMPathRenderingWithTexturingTest,
+ TestProgramPathFragmentInputGenCHROMIUM_OBJECT) {
+ if (!IsApplicable())
+ return;
+
+ // clang-format off
+ static const char* kVertexShaderSource = SHADER(
+ uniform mat4 view_matrix;
+ uniform mat4 color_matrix;
+ uniform vec2 model_translate;
+ attribute vec2 position;
+ varying vec3 color;
+ void main() {
+ color = (color_matrix * vec4(position, 1, 1)).rgb;
+ vec4 p = vec4(model_translate + position, 1, 1);
+ gl_Position = view_matrix * p;
+ }
+ );
+
+ static const char* kFragmentShaderSource = SHADER(
+ precision mediump float;
+ varying vec3 color;
+ void main() {
+ gl_FragColor = vec4(color.rgb, 1.0);
+ }
+ );
+ // clang-format on
+
+ SetupProgramForTestPattern(kVertexShaderSource, kFragmentShaderSource);
+ LinkProgramForTestPattern();
+ static const GLfloat kColorMatrix[16] = {1.0f / kShapeWidth,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 1.0f / kShapeHeight,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f};
+ glUniformMatrix4fv(kColorMatrixLocation, 1, GL_FALSE, kColorMatrix);
+
+ // This is the functionality we are testing: ProgramPathFragmentInputGen
+ // does the same work as the color transform in vertex shader.
+ static const GLfloat kColorCoefficients[9] = {1.0f / kShapeWidth,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 1.0f / kShapeHeight,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f};
+ glProgramPathFragmentInputGenCHROMIUM(program_, kColorFragmentInputLocation,
+ GL_OBJECT_LINEAR_CHROMIUM, 3,
+ kColorCoefficients);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ DrawTestPattern();
+
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ for (int j = 0; j < kTestRows; ++j) {
+ for (int i = 0; i < kTestColumns; ++i) {
+ for (size_t k = 0; k < arraysize(kFillCoords); k += 2) {
+ SCOPED_TRACE(testing::Message() << "Verifying fill for shape " << i
+ << ", " << j << " coord " << k);
+ float fx = kFillCoords[k];
+ float fy = kFillCoords[k + 1];
+ float px = i * kShapeWidth;
+ float py = j * kShapeHeight;
+
+ uint8 color[4];
+ color[0] = roundf(fx / kShapeWidth * 255.0f);
+ color[1] = roundf(fy / kShapeHeight * 255.0f);
+ color[2] = 0;
+ color[3] = 255;
+
+ EXPECT_TRUE(
+ GLTestHelper::CheckPixels(px + fx, py + fy, 1, 1, 2, color));
+ }
+ }
+ }
+
+ TeardownStateForTestPattern();
+
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+TEST_P(CHROMIUMPathRenderingWithTexturingTest,
+ TestProgramPathFragmentInputGenArgs) {
+ if (!IsApplicable())
+ return;
+
+ // clang-format off
+ static const char* kVertexShaderSource = SHADER(
+ varying vec2 vec2_var; varying vec3 vec3_var; varying vec4 vec4_var;
+ varying float float_var; varying mat2 mat2_var; varying mat3 mat3_var;
+ varying mat4 mat4_var; attribute float avoid_opt; void main() {
+ vec2_var = vec2(1.0, 2.0 + avoid_opt);
+ vec3_var = vec3(1.0, 2.0, 3.0 + avoid_opt);
+ vec4_var = vec4(1.0, 2.0, 3.0, 4.0 + avoid_opt);
+ float_var = 5.0 + avoid_opt;
+ mat2_var = mat2(2.0 + avoid_opt);
+ mat3_var = mat3(3.0 + avoid_opt);
+ mat4_var = mat4(4.0 + avoid_opt);
+ gl_Position = vec4(1.0);
+ }
+ );
+
+ static const char* kFragmentShaderSource = SHADER(
+ precision mediump float; varying vec2 vec2_var; varying vec3 vec3_var;
+ varying vec4 vec4_var; varying float float_var; varying mat2 mat2_var;
+ varying mat3 mat3_var; varying mat4 mat4_var; void main() {
+ gl_FragColor = vec4(vec2_var, 0, 0) + vec4(vec3_var, 0) + vec4_var +
+ vec4(float_var) +
+ vec4(mat2_var[0][0], mat3_var[1][1], mat4_var[2][2], 1);
+ }
+ );
+ // clang-format on
+ GLuint vs = GLTestHelper::LoadShader(GL_VERTEX_SHADER, kVertexShaderSource);
+ GLuint fs =
+ GLTestHelper::LoadShader(GL_FRAGMENT_SHADER, kFragmentShaderSource);
+ enum {
+ kVec2Location = 0,
+ kVec3Location,
+ kVec4Location,
+ kFloatLocation,
+ kMat2Location,
+ kMat3Location,
+ kMat4Location,
+ };
+ struct {
+ GLint location;
+ const char* name;
+ GLint components;
+ } variables[] = {
+ {kVec2Location, "vec2_var", 2},
+ {kVec3Location, "vec3_var", 3},
+ {kVec4Location, "vec4_var", 4},
+ {kFloatLocation, "float_var", 1},
+ // If a varying is not single-precision floating-point scalar or
+ // vector, it always causes an invalid operation.
+ {kMat2Location, "mat2_var", -1},
+ {kMat3Location, "mat3_var", -1},
+ {kMat4Location, "mat4_var", -1},
+ };
+
+ GLint program = glCreateProgram();
+ for (size_t i = 0; i < sizeof(variables) / sizeof(variables[0]); ++i) {
+ glBindFragmentInputLocationCHROMIUM(program, variables[i].location,
+ variables[i].name);
+ }
+ glAttachShader(program, fs);
+ glAttachShader(program, vs);
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+
+ // Test that using invalid (not linked) program is an invalid operation.
+ // See similar calls at the end of the test for discussion about the
+ // arguments.
+ glProgramPathFragmentInputGenCHROMIUM(program, -1, GL_NONE, 0, NULL);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+
+ glLinkProgram(program);
+
+ GLint linked = 0;
+ glGetProgramiv(program, GL_LINK_STATUS, &linked);
+ EXPECT_TRUE(linked == GL_TRUE);
+ glUseProgram(program);
+
+ const GLfloat kCoefficients16[] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f,
+ 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f,
+ 13.0f, 14.0f, 15.0f, 16.0f};
+ const GLenum kGenModes[] = {GL_NONE, GL_EYE_LINEAR_CHROMIUM,
+ GL_OBJECT_LINEAR_CHROMIUM, GL_CONSTANT_CHROMIUM};
+
+ for (size_t ii = 0; ii < sizeof(variables) / sizeof(variables[0]); ++ii) {
+ for (GLint components = 0; components <= 4; ++components) {
+ for (size_t jj = 0; jj < arraysize(kGenModes); ++jj) {
+ GLenum gen_mode = kGenModes[jj];
+ SCOPED_TRACE(testing::Message()
+ << "Testing glProgramPathFragmentInputGenCHROMIUM "
+ << "for fragment input '" << variables[ii].name
+ << "' with " << variables[ii].components << " components "
+ << " using genMode " << gen_mode << " and components "
+ << components);
+
+ glProgramPathFragmentInputGenCHROMIUM(program, variables[ii].location,
+ gen_mode, components,
+ kCoefficients16);
+
+ if (components == 0 && gen_mode == GL_NONE) {
+ if (variables[ii].components == -1) {
+ // Clearing a fragment input that is not single-precision floating
+ // point scalar or vector is an invalid operation.
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+ } else {
+ // Clearing a valid fragment input is ok.
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ }
+ } else if (components == 0 || gen_mode == GL_NONE) {
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+ } else {
+ if (components == variables[ii].components) {
+ // Setting a generator for a single-precision floating point
+ // scalar or vector fragment input is ok.
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ } else {
+ // Setting a generator when components do not match is an invalid
+ // operation.
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+ }
+ }
+ }
+ }
+ }
+
+ // The location == -1 would mean fragment input was optimized away. At the
+ // time of writing, -1 can not happen because the only way to obtain the
+ // location numbers is through bind. Test just to be consistent.
+
+ enum {
+ kValidGenMode = GL_CONSTANT_CHROMIUM,
+ kValidComponents = 3,
+ kInvalidGenMode = 0xAB,
+ kInvalidComponents = 5,
+ };
+
+ glProgramPathFragmentInputGenCHROMIUM(program, -1, kValidGenMode,
+ kValidComponents, kCoefficients16);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ // Test that even though the spec says location == -1 causes the operation to
+ // be skipped, the verification of other parameters is still done. This is a
+ // GL policy.
+ glProgramPathFragmentInputGenCHROMIUM(program, -1, kInvalidGenMode,
+ kValidComponents, kCoefficients16);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
+ glProgramPathFragmentInputGenCHROMIUM(program, -1, kInvalidGenMode,
+ kInvalidComponents, kCoefficients16);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
+ glProgramPathFragmentInputGenCHROMIUM(program, -1, kValidGenMode,
+ kInvalidComponents, kCoefficients16);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), glGetError());
+
+ EXPECT_TRUE(glIsProgram(program));
+
+ glDeleteProgram(program);
+
+ EXPECT_FALSE(glIsProgram(program));
+
+ // Test that using invalid (deleted) program is an invalid operation.
+ glProgramPathFragmentInputGenCHROMIUM(program, -1, kValidGenMode,
+ kValidComponents, kCoefficients16);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+ glProgramPathFragmentInputGenCHROMIUM(program, -1, kInvalidGenMode,
+ kValidComponents, kCoefficients16);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+ glProgramPathFragmentInputGenCHROMIUM(program, -1, kInvalidGenMode,
+ kInvalidComponents, kCoefficients16);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+ glProgramPathFragmentInputGenCHROMIUM(program, -1, kValidGenMode,
+ kInvalidComponents, kCoefficients16);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+}
+
+// This test uses gl_FragCoord in a fragment shader. It is used to ensure
+// that the internal implementation runs codepaths related to built-ins.
+TEST_P(CHROMIUMPathRenderingWithTexturingTest,
+ TestProgramPathFragmentInputGenBuiltinInFragShader) {
+ if (!IsApplicable())
+ return;
+
+ static const int kColorLocation = 5;
+ static const int kFragColorLocation = 6;
+
+ // clang-format off
+ static const char* kVertexShaderSource = SHADER(
+ varying vec4 color;
+ void main() {
+ color = vec4(1.0);
+ gl_Position = vec4(1.0);
+ }
+ );
+
+ static const char* kFragmentShaderSource = SHADER(
+ precision mediump float;
+ varying vec4 color;
+ void main() {
+ gl_FragColor = gl_FragCoord + color;
+ }
+ );
+ // clang-format on
+
+ GLuint vs = GLTestHelper::LoadShader(GL_VERTEX_SHADER, kVertexShaderSource);
+ GLuint fs =
+ GLTestHelper::LoadShader(GL_FRAGMENT_SHADER, kFragmentShaderSource);
+
+ GLint program = glCreateProgram();
+ glBindFragmentInputLocationCHROMIUM(program, kColorLocation, "color");
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ glBindFragmentInputLocationCHROMIUM(program, kFragColorLocation,
+ "gl_FragColor");
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+
+ glAttachShader(program, fs);
+ glAttachShader(program, vs);
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+
+ glLinkProgram(program);
+
+ GLint linked = 0;
+ glGetProgramiv(program, GL_LINK_STATUS, &linked);
+ if (linked == 0) {
+ char buffer[1024];
+ GLsizei length = 0;
+ glGetProgramInfoLog(program, sizeof(buffer), &length, buffer);
+ std::string log(buffer, length);
+ EXPECT_EQ(1, linked) << "Error linking program: " << log;
+ glDeleteProgram(program);
+ program = 0;
+ }
+ ASSERT_EQ(GL_TRUE, linked);
+
+ glUseProgram(program);
+
+ const GLfloat kCoefficients16[] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f,
+ 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f,
+ 13.0f, 14.0f, 15.0f, 16.0f};
+
+ glProgramPathFragmentInputGenCHROMIUM(
+ program, kColorLocation, GL_EYE_LINEAR_CHROMIUM, 4, kCoefficients16);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ glProgramPathFragmentInputGenCHROMIUM(
+ program, kFragColorLocation, GL_EYE_LINEAR_CHROMIUM, 4, kCoefficients16);
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+}
+
+TEST_P(CHROMIUMPathRenderingWithTexturingTest,
+ BindFragmentInputConflictsDetection) {
+ if (!IsApplicable())
+ return;
+
+ // clang-format off
+ static const char* kVertexShaderSource = SHADER(
+ attribute vec4 position;
+ varying vec4 colorA;
+ varying vec4 colorB;
+ void main()
+ {
+ gl_Position = position;
+ colorA = position + vec4(1);
+ colorB = position + vec4(2);
+ }
+ );
+ static const char* kFragmentShaderSource = SHADER(
+ precision mediump float;
+ varying vec4 colorA;
+ varying vec4 colorB;
+ void main()
+ {
+ gl_FragColor = colorA + colorB;
+ }
+ );
+ // clang-format on
+ const GLint kColorALocation = 3;
+ const GLint kColorBLocation = 4;
+
+ GLuint vertex_shader =
+ GLTestHelper::LoadShader(GL_VERTEX_SHADER, kVertexShaderSource);
+ GLuint fragment_shader =
+ GLTestHelper::LoadShader(GL_FRAGMENT_SHADER, kFragmentShaderSource);
+
+ GLuint program = glCreateProgram();
+ glAttachShader(program, vertex_shader);
+ glAttachShader(program, fragment_shader);
+
+ glBindFragmentInputLocationCHROMIUM(program, kColorALocation, "colorA");
+ // Bind colorB to location a, causing conflicts, link should fail.
+ glBindFragmentInputLocationCHROMIUM(program, kColorALocation, "colorB");
+ glLinkProgram(program);
+ GLint linked = 0;
+ glGetProgramiv(program, GL_LINK_STATUS, &linked);
+ EXPECT_EQ(0, linked);
+
+ // Bind colorB to location b, no conflicts, link should succeed.
+ glBindFragmentInputLocationCHROMIUM(program, kColorBLocation, "colorB");
+ glLinkProgram(program);
+ linked = 0;
+ glGetProgramiv(program, GL_LINK_STATUS, &linked);
+ EXPECT_EQ(1, linked);
+
+ GLTestHelper::CheckGLError("no errors", __LINE__);
+}
+
+// Test binding with array variables, using zero indices. Tests that
+// binding colorA[0] with explicit "colorA[0]" as well as "colorA" produces
+// a correct location that can be used with PathProgramFragmentInputGen.
+// For path rendering, colorA[0] is bound to a location. The input generator for
+// the location is set to produce vec4(0, 0.1, 0, 0.1).
+// The default varying, color, is bound to a location and its generator
+// will produce vec4(10.0). The shader program produces green pixels.
+// For vertex-based rendering, the vertex shader produces the same effect as
+// the input generator for path rendering.
+TEST_P(CHROMIUMPathRenderingWithTexturingTest,
+ BindFragmentInputSimpleArrayHandling) {
+ if (!IsApplicable())
+ return;
+
+ // clang-format off
+ static const char* kVertexShaderSource = SHADER(
+ uniform mat4 view_matrix;
+ uniform mat4 color_matrix;
+ uniform vec2 model_translate;
+ attribute vec2 position;
+ varying vec4 color;
+
+ varying vec4 colorA[4];
+ void main()
+ {
+ vec4 p = vec4(model_translate + position, 1, 1);
+ gl_Position = view_matrix * p;
+ colorA[0] = vec4(0.0, 0.1, 0, 0.1);
+ colorA[1] = vec4(0.2);
+ colorA[2] = vec4(0.3);
+ colorA[3] = vec4(0.4);
+ color = vec4(10.0);
+ }
+ );
+ static const char* kFragmentShaderSource = SHADER(
+ precision mediump float;
+ varying vec4 color;
+
+ varying vec4 colorA[4];
+ void main()
+ {
+ gl_FragColor = colorA[0] * color;
+ }
+ );
+ // clang-format on
+ const GLint kColorA0Location = 4;
+ const GLint kUnusedLocation = 5;
+ const GLfloat kColorA0[] = {0.0f, 0.1f, 0.0f, 0.1f};
+ const GLfloat kColor[] = {10.0f, 10.0f, 10.0f, 10.0f};
+
+ for (int pass = 0; pass < 2; ++pass) {
+ SetupProgramForTestPattern(kVertexShaderSource, kFragmentShaderSource);
+ if (pass == 0) {
+ glBindFragmentInputLocationCHROMIUM(program_, kUnusedLocation,
+ "colorA[0]");
+ glBindFragmentInputLocationCHROMIUM(program_, kColorA0Location, "colorA");
+ } else {
+ glBindFragmentInputLocationCHROMIUM(program_, kUnusedLocation, "colorA");
+ glBindFragmentInputLocationCHROMIUM(program_, kColorA0Location,
+ "colorA[0]");
+ }
+ LinkProgramForTestPattern();
+ glProgramPathFragmentInputGenCHROMIUM(program_, kColorA0Location,
+ GL_CONSTANT_CHROMIUM, 4, kColorA0);
+ glProgramPathFragmentInputGenCHROMIUM(program_, kColorFragmentInputLocation,
+ GL_CONSTANT_CHROMIUM, 4, kColor);
+
+ DrawTestPattern();
+ for (int j = 0; j < kTestRows; ++j) {
+ for (int i = 0; i < kTestColumns; ++i) {
+ for (size_t k = 0; k < arraysize(kFillCoords); k += 2) {
+ SCOPED_TRACE(testing::Message() << "Verifying fill for shape " << i
+ << ", " << j << " coord " << k);
+ float fx = kFillCoords[k];
+ float fy = kFillCoords[k + 1];
+ float px = i * kShapeWidth;
+ float py = j * kShapeHeight;
+
+ uint8 color[4] = {0, 255, 0, 255};
+
+ EXPECT_TRUE(
+ GLTestHelper::CheckPixels(px + fx, py + fy, 1, 1, 2, color));
+ }
+ }
+ }
+ TeardownStateForTestPattern();
+ }
+
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+// Test binding with non-zero indices.
+// Currently this is disabled, as the drivers seem to have a bug with the
+// behavior.
+TEST_P(CHROMIUMPathRenderingWithTexturingTest,
+ DISABLED_BindFragmentInputArrayHandling) {
+ if (!IsApplicable())
+ return;
+
+ // clang-format off
+ static const char* kVertexShaderSource = SHADER(
+ uniform mat4 view_matrix;
+ uniform mat4 color_matrix;
+ uniform vec2 model_translate;
+ attribute vec2 position;
+ varying vec4 color;
+
+ varying vec4 colorA[4];
+ void main()
+ {
+ vec4 p = vec4(model_translate + position, 1, 1);
+ gl_Position = view_matrix * p;
+
+ colorA[0] = vec4(0, 0.1, 0, 0.1);
+ colorA[1] = vec4(0, 1, 0, 1);
+ colorA[2] = vec4(0, 0.8, 0, 0.8);
+ colorA[3] = vec4(0, 0.5, 0, 0.5);
+ color = vec4(0.2);
+ }
+ );
+ static const char* kFragmentShaderSource = SHADER(
+ precision mediump float;
+ varying vec4 colorA[4];
+ varying vec4 color;
+ void main()
+ {
+ gl_FragColor = (colorA[0] * colorA[1]) +
+ colorA[2] + (colorA[3] * color);
+ }
+ );
+ // clang-format on
+ const GLint kColorA0Location = 4;
+ const GLint kColorA1Location = 1;
+ const GLint kColorA2Location = 2;
+ const GLint kColorA3Location = 3;
+ const GLint kUnusedLocation = 5;
+ const GLfloat kColorA0[] = {0.0f, 0.1f, 0.0f, 0.1f};
+ const GLfloat kColorA1[] = {0.0f, 1.0f, 0.0f, 1.0f};
+ const GLfloat kColorA2[] = {0.0f, 0.8f, 0.0f, 0.8f};
+ const GLfloat kColorA3[] = {0.0f, 0.5f, 0.0f, 0.5f};
+ const GLfloat kColor[] = {0.2f, 0.2f, 0.2f, 0.2f};
+
+ SetupProgramForTestPattern(kVertexShaderSource, kFragmentShaderSource);
+ glBindFragmentInputLocationCHROMIUM(program_, kUnusedLocation, "colorA[0]");
+ glBindFragmentInputLocationCHROMIUM(program_, kColorA1Location, "colorA[1]");
+ glBindFragmentInputLocationCHROMIUM(program_, kColorA2Location, "colorA[2]");
+ glBindFragmentInputLocationCHROMIUM(program_, kColorA3Location, "colorA[3]");
+ glBindFragmentInputLocationCHROMIUM(program_, kColorA0Location, "colorA");
+ LinkProgramForTestPattern();
+
+ glProgramPathFragmentInputGenCHROMIUM(program_, kColorA0Location,
+ GL_CONSTANT_CHROMIUM, 4, kColorA0);
+ glProgramPathFragmentInputGenCHROMIUM(program_, kColorA1Location,
+ GL_CONSTANT_CHROMIUM, 4, kColorA1);
+ glProgramPathFragmentInputGenCHROMIUM(program_, kColorA2Location,
+ GL_CONSTANT_CHROMIUM, 4, kColorA2);
+ glProgramPathFragmentInputGenCHROMIUM(program_, kColorA3Location,
+ GL_CONSTANT_CHROMIUM, 4, kColorA3);
+ glProgramPathFragmentInputGenCHROMIUM(program_, kColorFragmentInputLocation,
+ GL_CONSTANT_CHROMIUM, 4, kColor);
+ DrawTestPattern();
+
+ for (int j = 0; j < kTestRows; ++j) {
+ for (int i = 0; i < kTestColumns; ++i) {
+ for (size_t k = 0; k < arraysize(kFillCoords); k += 2) {
+ SCOPED_TRACE(testing::Message() << "Verifying fill for shape " << i
+ << ", " << j << " coord " << k);
+ float fx = kFillCoords[k];
+ float fy = kFillCoords[k + 1];
+ float px = i * kShapeWidth;
+ float py = j * kShapeHeight;
+
+ uint8 color[4] = {0, 255, 0, 255};
+
+ EXPECT_TRUE(
+ GLTestHelper::CheckPixels(px + fx, py + fy, 1, 1, 2, color));
+ }
+ }
+ }
+
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ TeardownStateForTestPattern();
+}
+
+INSTANTIATE_TEST_CASE_P(WithAndWithoutShaderNameMapping,
+ CHROMIUMPathRenderingWithTexturingTest,
+ ::testing::Bool());
+
} // namespace gpu
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index 4daa466..821f95b 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -114,7 +114,8 @@ GLManager::Options::Options()
bind_generates_resource(false),
lose_context_when_out_of_memory(false),
context_lost_allowed(false),
- context_type(gles2::CONTEXT_TYPE_OPENGLES2) {}
+ context_type(gles2::CONTEXT_TYPE_OPENGLES2),
+ force_shader_name_hashing(false) {}
GLManager::GLManager()
: sync_point_manager_(nullptr),
@@ -222,7 +223,9 @@ void GLManager::InitializeWithCommandLine(const GLManager::Options& options,
}
decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group));
-
+ if (options.force_shader_name_hashing) {
+ decoder_->SetForceShaderNameHashingForTest(true);
+ }
command_buffer_.reset(new CommandBufferService(
decoder_->GetContextGroup()->transfer_buffer_manager()));
ASSERT_TRUE(command_buffer_->Initialize())
diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h
index e2074c2..19c066a 100644
--- a/gpu/command_buffer/tests/gl_manager.h
+++ b/gpu/command_buffer/tests/gl_manager.h
@@ -68,6 +68,8 @@ class GLManager : private GpuControl {
// Whether or not it's ok to lose the context.
bool context_lost_allowed;
gles2::ContextType context_type;
+ // Force shader name hashing for all context types.
+ bool force_shader_name_hashing;
};
GLManager();
~GLManager() override;
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index 81ac1d8..e1a4d3c 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST(
{
"name": "gpu driver bug list",
// Please update the version number whenever you change this file.
- "version": "8.29",
+ "version": "8.30",
"entries": [
{
"id": 1,
@@ -1430,14 +1430,14 @@ LONG_STRING_CONST(
{
"id": 123,
"cr_bugs": [344330],
- "description": "NVIDIA drivers before 337 lack features in NV_path_rendering and related extensions to implement driver level path rendering.",
+ "description": "NVIDIA drivers before 346 lack features in NV_path_rendering and related extensions to implement driver level path rendering.",
"vendor_id": "0x10de",
"os": {
"type": "linux"
},
"driver_version": {
"op": "<",
- "value": "337"
+ "value": "346"
},
"features": [
"disable_gl_path_rendering"
diff --git a/gpu/skia_bindings/gl_bindings_skia_cmd_buffer.cc b/gpu/skia_bindings/gl_bindings_skia_cmd_buffer.cc
index c92cb22..dc4b236 100644
--- a/gpu/skia_bindings/gl_bindings_skia_cmd_buffer.cc
+++ b/gpu/skia_bindings/gl_bindings_skia_cmd_buffer.cc
@@ -176,6 +176,9 @@ GrGLInterface* CreateCommandBufferSkiaGLBinding() {
glStencilThenCoverFillPathInstancedCHROMIUM;
functions->fStencilThenCoverStrokePathInstanced =
glStencilThenCoverStrokePathInstancedCHROMIUM;
+ functions->fProgramPathFragmentInputGen =
+ glProgramPathFragmentInputGenCHROMIUM;
+ functions->fBindFragmentInputLocation = glBindFragmentInputLocationCHROMIUM;
}
return interface;
diff --git a/mojo/gpu/mojo_gles2_impl_autogen.cc b/mojo/gpu/mojo_gles2_impl_autogen.cc
index 9fbe344..6e4fb9b 100644
--- a/mojo/gpu/mojo_gles2_impl_autogen.cc
+++ b/mojo/gpu/mojo_gles2_impl_autogen.cc
@@ -1871,6 +1871,21 @@ void MojoGLES2Impl::StencilThenCoverStrokePathInstancedCHROMIUM(
numPaths, pathNameType, paths, pathBase, reference, mask, coverMode,
transformType, transformValues);
}
+void MojoGLES2Impl::BindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const char* name) {
+ MojoGLES2MakeCurrent(context_);
+ glBindFragmentInputLocationCHROMIUM(program, location, name);
+}
+void MojoGLES2Impl::ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) {
+ MojoGLES2MakeCurrent(context_);
+ glProgramPathFragmentInputGenCHROMIUM(program, location, genMode, components,
+ coeffs);
+}
GLenum MojoGLES2Impl::GetGraphicsResetStatusKHR() {
MojoGLES2MakeCurrent(context_);
return glGetGraphicsResetStatusKHR();
diff --git a/mojo/gpu/mojo_gles2_impl_autogen.h b/mojo/gpu/mojo_gles2_impl_autogen.h
index 184766b..43f1c9c 100644
--- a/mojo/gpu/mojo_gles2_impl_autogen.h
+++ b/mojo/gpu/mojo_gles2_impl_autogen.h
@@ -870,6 +870,14 @@ class MojoGLES2Impl : public gpu::gles2::GLES2Interface {
GLenum coverMode,
GLenum transformType,
const GLfloat* transformValues) override;
+ void BindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const char* name) override;
+ void ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) override;
GLenum GetGraphicsResetStatusKHR() override;
void BlendBarrierKHR() override;
void ApplyScreenSpaceAntialiasingCHROMIUM() override;
diff --git a/third_party/mojo/src/mojo/public/c/gles2/gles2_call_visitor_chromium_extension_autogen.h b/third_party/mojo/src/mojo/public/c/gles2/gles2_call_visitor_chromium_extension_autogen.h
index 0bd4028..610292b 100644
--- a/third_party/mojo/src/mojo/public/c/gles2/gles2_call_visitor_chromium_extension_autogen.h
+++ b/third_party/mojo/src/mojo/public/c/gles2/gles2_call_visitor_chromium_extension_autogen.h
@@ -538,6 +538,18 @@ VISIT_GL_CALL(StencilThenCoverStrokePathInstancedCHROMIUM,
coverMode,
transformType,
transformValues))
+VISIT_GL_CALL(BindFragmentInputLocationCHROMIUM,
+ void,
+ (GLuint program, GLint location, const char* name),
+ (program, location, name))
+VISIT_GL_CALL(ProgramPathFragmentInputGenCHROMIUM,
+ void,
+ (GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs),
+ (program, location, genMode, components, coeffs))
VISIT_GL_CALL(GetGraphicsResetStatusKHR, GLenum, (), ())
VISIT_GL_CALL(BlendBarrierKHR, void, (), ())
VISIT_GL_CALL(ApplyScreenSpaceAntialiasingCHROMIUM, void, (), ())
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py
index 72ee92d..d5019b8 100755
--- a/ui/gl/generate_bindings.py
+++ b/ui/gl/generate_bindings.py
@@ -584,12 +584,28 @@ GL_FUNCTIONS = [
'arguments':
'GLuint program, GLsizei bufsize, GLsizei* length, char* infolog', },
{ 'return_type': 'void',
+ 'versions': [{'name': 'glGetProgramInterfaceiv',
+ 'extensions': ['GL_ARB_program_interface_query']}],
+ 'arguments': 'GLuint program, GLenum programInterface, GLenum pname, '
+ 'GLint* params'},
+{ 'return_type': 'void',
'names': ['glGetProgramiv'],
'arguments': 'GLuint program, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+ 'versions': [{'name': 'glGetProgramResourceiv',
+ 'extensions': ['GL_ARB_program_interface_query']}],
+ 'arguments': 'GLuint program, GLenum programInterface, GLuint index, '
+ 'GLsizei propCount, const GLenum* props, GLsizei bufSize, '
+ 'GLsizei* length, GLint* params'},
{ 'return_type': 'GLint',
'names': ['glGetProgramResourceLocation'],
'arguments': 'GLuint program, GLenum programInterface, const char* name', },
{ 'return_type': 'void',
+ 'versions': [{'name': 'glGetProgramResourceName',
+ 'extensions': ['GL_ARB_program_interface_query']}],
+ 'arguments': 'GLuint program, GLenum programInterface, GLuint index, '
+ 'GLsizei bufSize, GLsizei* length, GLchar* name'},
+{ 'return_type': 'void',
'versions': [{ 'name': 'glGetQueryiv' },
{ 'name': 'glGetQueryivARB' },
{ 'name': 'glGetQueryivEXT',
@@ -844,6 +860,11 @@ GL_FUNCTIONS = [
'extensions': ['GL_ARB_get_program_binary'] }],
'arguments': 'GLuint program, GLenum pname, GLint value' },
{ 'return_type': 'void',
+ 'names': ['glProgramPathFragmentInputGenNV'],
+ 'arguments': 'GLuint program, GLint location, GLenum genMode, '
+ 'GLint components, const GLfloat* coeffs',
+ 'is_optional': True, },
+{ 'return_type': 'void',
'names': ['glPushGroupMarkerEXT'],
'arguments': 'GLsizei length, const char* marker', },
{ 'return_type': 'void',
diff --git a/ui/gl/gl_bindings.h b/ui/gl/gl_bindings.h
index 0214be1..453437a 100644
--- a/ui/gl/gl_bindings.h
+++ b/ui/gl/gl_bindings.h
@@ -234,6 +234,9 @@
#define GL_QUADRATIC_CURVE_TO_CHROMIUM 0x0A
#define GL_CUBIC_CURVE_TO_CHROMIUM 0x0C
#define GL_CONIC_CURVE_TO_CHROMIUM 0x1A
+#define GL_EYE_LINEAR_CHROMIUM 0x2400
+#define GL_OBJECT_LINEAR_CHROMIUM 0x2401
+#define GL_CONSTANT_CHROMIUM 0x8576
#define GL_PATH_STROKE_WIDTH_CHROMIUM 0x9075
#define GL_PATH_END_CAPS_CHROMIUM 0x9076
#define GL_PATH_JOIN_STYLE_CHROMIUM 0x9079
@@ -313,6 +316,15 @@
#define GL_RG8_EXT 0x822B
#endif /* GL_EXT_texture_rg */
+// This is from NV_path_rendering, but the Mesa GL header is not up-to-date with
+// the most recent
+// version of the extension. This definition could be removed once glext.h
+// r27498 or later is
+// imported.
+#ifndef GL_FRAGMENT_INPUT_NV
+#define GL_FRAGMENT_INPUT_NV 0x936D
+#endif
+
#define GL_GLEXT_PROTOTYPES 1
#if defined(OS_WIN)
diff --git a/ui/gl/gl_bindings_api_autogen_gl.h b/ui/gl/gl_bindings_api_autogen_gl.h
index 35ccc96..4d86720 100644
--- a/ui/gl/gl_bindings_api_autogen_gl.h
+++ b/ui/gl/gl_bindings_api_autogen_gl.h
@@ -368,10 +368,28 @@ void glGetProgramInfoLogFn(GLuint program,
GLsizei bufsize,
GLsizei* length,
char* infolog) override;
+void glGetProgramInterfaceivFn(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint* params) override;
void glGetProgramivFn(GLuint program, GLenum pname, GLint* params) override;
+void glGetProgramResourceivFn(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum* props,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLint* params) override;
GLint glGetProgramResourceLocationFn(GLuint program,
GLenum programInterface,
const char* name) override;
+void glGetProgramResourceNameFn(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLchar* name) override;
void glGetQueryivFn(GLenum target, GLenum pname, GLint* params) override;
void glGetQueryObjecti64vFn(GLuint id, GLenum pname, GLint64* params) override;
void glGetQueryObjectivFn(GLuint id, GLenum pname, GLint* params) override;
@@ -503,6 +521,11 @@ void glProgramBinaryFn(GLuint program,
const GLvoid* binary,
GLsizei length) override;
void glProgramParameteriFn(GLuint program, GLenum pname, GLint value) override;
+void glProgramPathFragmentInputGenNVFn(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) override;
void glPushGroupMarkerEXTFn(GLsizei length, const char* marker) override;
void glQueryCounterFn(GLuint id, GLenum target) override;
void glReadBufferFn(GLenum src) override;
diff --git a/ui/gl/gl_bindings_autogen_gl.cc b/ui/gl/gl_bindings_autogen_gl.cc
index 7639a28..e7482d7 100644
--- a/ui/gl/gl_bindings_autogen_gl.cc
+++ b/ui/gl/gl_bindings_autogen_gl.cc
@@ -214,9 +214,12 @@ void DriverGL::InitializeStaticBindings() {
fn.glGetProgramBinaryFn = 0;
fn.glGetProgramInfoLogFn = reinterpret_cast<glGetProgramInfoLogProc>(
GetGLProcAddress("glGetProgramInfoLog"));
+ fn.glGetProgramInterfaceivFn = 0;
fn.glGetProgramivFn =
reinterpret_cast<glGetProgramivProc>(GetGLProcAddress("glGetProgramiv"));
+ fn.glGetProgramResourceivFn = 0;
fn.glGetProgramResourceLocationFn = 0;
+ fn.glGetProgramResourceNameFn = 0;
fn.glGetQueryivFn = 0;
fn.glGetQueryObjecti64vFn = 0;
fn.glGetQueryObjectivFn = 0;
@@ -306,6 +309,7 @@ void DriverGL::InitializeStaticBindings() {
fn.glPopGroupMarkerEXTFn = 0;
fn.glProgramBinaryFn = 0;
fn.glProgramParameteriFn = 0;
+ fn.glProgramPathFragmentInputGenNVFn = 0;
fn.glPushGroupMarkerEXTFn = 0;
fn.glQueryCounterFn = 0;
fn.glReadBufferFn = 0;
@@ -489,6 +493,8 @@ void DriverGL::InitializeDynamicBindings(GLContext* context) {
extensions.find("GL_ARB_map_buffer_range ") != std::string::npos;
ext.b_GL_ARB_occlusion_query =
extensions.find("GL_ARB_occlusion_query ") != std::string::npos;
+ ext.b_GL_ARB_program_interface_query =
+ extensions.find("GL_ARB_program_interface_query ") != std::string::npos;
ext.b_GL_ARB_robustness =
extensions.find("GL_ARB_robustness ") != std::string::npos;
ext.b_GL_ARB_sync = extensions.find("GL_ARB_sync ") != std::string::npos;
@@ -1221,6 +1227,21 @@ void DriverGL::InitializeDynamicBindings(GLContext* context) {
GetGLProcAddress("glGetProgramBinaryOES"));
}
+ debug_fn.glGetProgramInterfaceivFn = 0;
+ if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u) ||
+ ext.b_GL_ARB_program_interface_query) {
+ fn.glGetProgramInterfaceivFn =
+ reinterpret_cast<glGetProgramInterfaceivProc>(
+ GetGLProcAddress("glGetProgramInterfaceiv"));
+ }
+
+ debug_fn.glGetProgramResourceivFn = 0;
+ if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u) ||
+ ext.b_GL_ARB_program_interface_query) {
+ fn.glGetProgramResourceivFn = reinterpret_cast<glGetProgramResourceivProc>(
+ GetGLProcAddress("glGetProgramResourceiv"));
+ }
+
debug_fn.glGetProgramResourceLocationFn = 0;
if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u)) {
fn.glGetProgramResourceLocationFn =
@@ -1228,6 +1249,14 @@ void DriverGL::InitializeDynamicBindings(GLContext* context) {
GetGLProcAddress("glGetProgramResourceLocation"));
}
+ debug_fn.glGetProgramResourceNameFn = 0;
+ if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u) ||
+ ext.b_GL_ARB_program_interface_query) {
+ fn.glGetProgramResourceNameFn =
+ reinterpret_cast<glGetProgramResourceNameProc>(
+ GetGLProcAddress("glGetProgramResourceName"));
+ }
+
debug_fn.glGetQueryivFn = 0;
if (!ver->is_es || ver->IsAtLeastGLES(3u, 0u)) {
fn.glGetQueryivFn =
@@ -1562,6 +1591,13 @@ void DriverGL::InitializeDynamicBindings(GLContext* context) {
GetGLProcAddress("glProgramParameteri"));
}
+ debug_fn.glProgramPathFragmentInputGenNVFn = 0;
+ if (ext.b_GL_NV_path_rendering) {
+ fn.glProgramPathFragmentInputGenNVFn =
+ reinterpret_cast<glProgramPathFragmentInputGenNVProc>(
+ GetGLProcAddress("glProgramPathFragmentInputGenNV"));
+ }
+
debug_fn.glPushGroupMarkerEXTFn = 0;
if (ext.b_GL_EXT_debug_marker) {
fn.glPushGroupMarkerEXTFn = reinterpret_cast<glPushGroupMarkerEXTProc>(
@@ -3256,6 +3292,20 @@ static void GL_BINDING_CALL Debug_glGetProgramInfoLog(GLuint program,
g_driver_gl.debug_fn.glGetProgramInfoLogFn(program, bufsize, length, infolog);
}
+static void GL_BINDING_CALL
+Debug_glGetProgramInterfaceiv(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint* params) {
+ GL_SERVICE_LOG("glGetProgramInterfaceiv"
+ << "(" << program << ", "
+ << GLEnums::GetStringEnum(programInterface) << ", "
+ << GLEnums::GetStringEnum(pname) << ", "
+ << static_cast<const void*>(params) << ")");
+ g_driver_gl.debug_fn.glGetProgramInterfaceivFn(program, programInterface,
+ pname, params);
+}
+
static void GL_BINDING_CALL Debug_glGetProgramiv(GLuint program,
GLenum pname,
GLint* params) {
@@ -3265,6 +3315,26 @@ static void GL_BINDING_CALL Debug_glGetProgramiv(GLuint program,
g_driver_gl.debug_fn.glGetProgramivFn(program, pname, params);
}
+static void GL_BINDING_CALL
+Debug_glGetProgramResourceiv(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum* props,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLint* params) {
+ GL_SERVICE_LOG("glGetProgramResourceiv"
+ << "(" << program << ", "
+ << GLEnums::GetStringEnum(programInterface) << ", " << index
+ << ", " << propCount << ", " << static_cast<const void*>(props)
+ << ", " << bufSize << ", " << static_cast<const void*>(length)
+ << ", " << static_cast<const void*>(params) << ")");
+ g_driver_gl.debug_fn.glGetProgramResourceivFn(program, programInterface,
+ index, propCount, props,
+ bufSize, length, params);
+}
+
static GLint GL_BINDING_CALL
Debug_glGetProgramResourceLocation(GLuint program,
GLenum programInterface,
@@ -3279,6 +3349,22 @@ Debug_glGetProgramResourceLocation(GLuint program,
return result;
}
+static void GL_BINDING_CALL
+Debug_glGetProgramResourceName(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLchar* name) {
+ GL_SERVICE_LOG("glGetProgramResourceName"
+ << "(" << program << ", "
+ << GLEnums::GetStringEnum(programInterface) << ", " << index
+ << ", " << bufSize << ", " << static_cast<const void*>(length)
+ << ", " << static_cast<const void*>(name) << ")");
+ g_driver_gl.debug_fn.glGetProgramResourceNameFn(program, programInterface,
+ index, bufSize, length, name);
+}
+
static void GL_BINDING_CALL Debug_glGetQueryiv(GLenum target,
GLenum pname,
GLint* params) {
@@ -3896,6 +3982,20 @@ static void GL_BINDING_CALL Debug_glProgramParameteri(GLuint program,
g_driver_gl.debug_fn.glProgramParameteriFn(program, pname, value);
}
+static void GL_BINDING_CALL
+Debug_glProgramPathFragmentInputGenNV(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) {
+ GL_SERVICE_LOG("glProgramPathFragmentInputGenNV"
+ << "(" << program << ", " << location << ", "
+ << GLEnums::GetStringEnum(genMode) << ", " << components
+ << ", " << static_cast<const void*>(coeffs) << ")");
+ g_driver_gl.debug_fn.glProgramPathFragmentInputGenNVFn(
+ program, location, genMode, components, coeffs);
+}
+
static void GL_BINDING_CALL Debug_glPushGroupMarkerEXT(GLsizei length,
const char* marker) {
GL_SERVICE_LOG("glPushGroupMarkerEXT"
@@ -5533,14 +5633,26 @@ void DriverGL::InitializeDebugBindings() {
debug_fn.glGetProgramInfoLogFn = fn.glGetProgramInfoLogFn;
fn.glGetProgramInfoLogFn = Debug_glGetProgramInfoLog;
}
+ if (!debug_fn.glGetProgramInterfaceivFn) {
+ debug_fn.glGetProgramInterfaceivFn = fn.glGetProgramInterfaceivFn;
+ fn.glGetProgramInterfaceivFn = Debug_glGetProgramInterfaceiv;
+ }
if (!debug_fn.glGetProgramivFn) {
debug_fn.glGetProgramivFn = fn.glGetProgramivFn;
fn.glGetProgramivFn = Debug_glGetProgramiv;
}
+ if (!debug_fn.glGetProgramResourceivFn) {
+ debug_fn.glGetProgramResourceivFn = fn.glGetProgramResourceivFn;
+ fn.glGetProgramResourceivFn = Debug_glGetProgramResourceiv;
+ }
if (!debug_fn.glGetProgramResourceLocationFn) {
debug_fn.glGetProgramResourceLocationFn = fn.glGetProgramResourceLocationFn;
fn.glGetProgramResourceLocationFn = Debug_glGetProgramResourceLocation;
}
+ if (!debug_fn.glGetProgramResourceNameFn) {
+ debug_fn.glGetProgramResourceNameFn = fn.glGetProgramResourceNameFn;
+ fn.glGetProgramResourceNameFn = Debug_glGetProgramResourceName;
+ }
if (!debug_fn.glGetQueryivFn) {
debug_fn.glGetQueryivFn = fn.glGetQueryivFn;
fn.glGetQueryivFn = Debug_glGetQueryiv;
@@ -5810,6 +5922,12 @@ void DriverGL::InitializeDebugBindings() {
debug_fn.glProgramParameteriFn = fn.glProgramParameteriFn;
fn.glProgramParameteriFn = Debug_glProgramParameteri;
}
+ if (!debug_fn.glProgramPathFragmentInputGenNVFn) {
+ debug_fn.glProgramPathFragmentInputGenNVFn =
+ fn.glProgramPathFragmentInputGenNVFn;
+ fn.glProgramPathFragmentInputGenNVFn =
+ Debug_glProgramPathFragmentInputGenNV;
+ }
if (!debug_fn.glPushGroupMarkerEXTFn) {
debug_fn.glPushGroupMarkerEXTFn = fn.glPushGroupMarkerEXTFn;
fn.glPushGroupMarkerEXTFn = Debug_glPushGroupMarkerEXT;
@@ -7044,10 +7162,31 @@ void GLApiBase::glGetProgramInfoLogFn(GLuint program,
driver_->fn.glGetProgramInfoLogFn(program, bufsize, length, infolog);
}
+void GLApiBase::glGetProgramInterfaceivFn(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint* params) {
+ driver_->fn.glGetProgramInterfaceivFn(program, programInterface, pname,
+ params);
+}
+
void GLApiBase::glGetProgramivFn(GLuint program, GLenum pname, GLint* params) {
driver_->fn.glGetProgramivFn(program, pname, params);
}
+void GLApiBase::glGetProgramResourceivFn(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum* props,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLint* params) {
+ driver_->fn.glGetProgramResourceivFn(program, programInterface, index,
+ propCount, props, bufSize, length,
+ params);
+}
+
GLint GLApiBase::glGetProgramResourceLocationFn(GLuint program,
GLenum programInterface,
const char* name) {
@@ -7055,6 +7194,16 @@ GLint GLApiBase::glGetProgramResourceLocationFn(GLuint program,
name);
}
+void GLApiBase::glGetProgramResourceNameFn(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLchar* name) {
+ driver_->fn.glGetProgramResourceNameFn(program, programInterface, index,
+ bufSize, length, name);
+}
+
void GLApiBase::glGetQueryivFn(GLenum target, GLenum pname, GLint* params) {
driver_->fn.glGetQueryivFn(target, pname, params);
}
@@ -7404,6 +7553,15 @@ void GLApiBase::glProgramParameteriFn(GLuint program,
driver_->fn.glProgramParameteriFn(program, pname, value);
}
+void GLApiBase::glProgramPathFragmentInputGenNVFn(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) {
+ driver_->fn.glProgramPathFragmentInputGenNVFn(program, location, genMode,
+ components, coeffs);
+}
+
void GLApiBase::glPushGroupMarkerEXTFn(GLsizei length, const char* marker) {
driver_->fn.glPushGroupMarkerEXTFn(length, marker);
}
@@ -9016,11 +9174,32 @@ void TraceGLApi::glGetProgramInfoLogFn(GLuint program,
gl_api_->glGetProgramInfoLogFn(program, bufsize, length, infolog);
}
+void TraceGLApi::glGetProgramInterfaceivFn(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint* params) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glGetProgramInterfaceiv")
+ gl_api_->glGetProgramInterfaceivFn(program, programInterface, pname, params);
+}
+
void TraceGLApi::glGetProgramivFn(GLuint program, GLenum pname, GLint* params) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glGetProgramiv")
gl_api_->glGetProgramivFn(program, pname, params);
}
+void TraceGLApi::glGetProgramResourceivFn(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum* props,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLint* params) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glGetProgramResourceiv")
+ gl_api_->glGetProgramResourceivFn(program, programInterface, index, propCount,
+ props, bufSize, length, params);
+}
+
GLint TraceGLApi::glGetProgramResourceLocationFn(GLuint program,
GLenum programInterface,
const char* name) {
@@ -9030,6 +9209,17 @@ GLint TraceGLApi::glGetProgramResourceLocationFn(GLuint program,
name);
}
+void TraceGLApi::glGetProgramResourceNameFn(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLchar* name) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glGetProgramResourceName")
+ gl_api_->glGetProgramResourceNameFn(program, programInterface, index, bufSize,
+ length, name);
+}
+
void TraceGLApi::glGetQueryivFn(GLenum target, GLenum pname, GLint* params) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glGetQueryiv")
gl_api_->glGetQueryivFn(target, pname, params);
@@ -9451,6 +9641,17 @@ void TraceGLApi::glProgramParameteriFn(GLuint program,
gl_api_->glProgramParameteriFn(program, pname, value);
}
+void TraceGLApi::glProgramPathFragmentInputGenNVFn(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+ "TraceGLAPI::glProgramPathFragmentInputGenNV")
+ gl_api_->glProgramPathFragmentInputGenNVFn(program, location, genMode,
+ components, coeffs);
+}
+
void TraceGLApi::glPushGroupMarkerEXTFn(GLsizei length, const char* marker) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glPushGroupMarkerEXT")
gl_api_->glPushGroupMarkerEXTFn(length, marker);
@@ -11299,6 +11500,16 @@ void NoContextGLApi::glGetProgramInfoLogFn(GLuint program,
<< "Trying to call glGetProgramInfoLog() without current GL context";
}
+void NoContextGLApi::glGetProgramInterfaceivFn(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint* params) {
+ NOTREACHED()
+ << "Trying to call glGetProgramInterfaceiv() without current GL context";
+ LOG(ERROR)
+ << "Trying to call glGetProgramInterfaceiv() without current GL context";
+}
+
void NoContextGLApi::glGetProgramivFn(GLuint program,
GLenum pname,
GLint* params) {
@@ -11306,6 +11517,20 @@ void NoContextGLApi::glGetProgramivFn(GLuint program,
LOG(ERROR) << "Trying to call glGetProgramiv() without current GL context";
}
+void NoContextGLApi::glGetProgramResourceivFn(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum* props,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLint* params) {
+ NOTREACHED()
+ << "Trying to call glGetProgramResourceiv() without current GL context";
+ LOG(ERROR)
+ << "Trying to call glGetProgramResourceiv() without current GL context";
+}
+
GLint NoContextGLApi::glGetProgramResourceLocationFn(GLuint program,
GLenum programInterface,
const char* name) {
@@ -11316,6 +11541,18 @@ GLint NoContextGLApi::glGetProgramResourceLocationFn(GLuint program,
return 0;
}
+void NoContextGLApi::glGetProgramResourceNameFn(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLchar* name) {
+ NOTREACHED()
+ << "Trying to call glGetProgramResourceName() without current GL context";
+ LOG(ERROR)
+ << "Trying to call glGetProgramResourceName() without current GL context";
+}
+
void NoContextGLApi::glGetQueryivFn(GLenum target,
GLenum pname,
GLint* params) {
@@ -11836,6 +12073,17 @@ void NoContextGLApi::glProgramParameteriFn(GLuint program,
<< "Trying to call glProgramParameteri() without current GL context";
}
+void NoContextGLApi::glProgramPathFragmentInputGenNVFn(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) {
+ NOTREACHED() << "Trying to call glProgramPathFragmentInputGenNV() without "
+ "current GL context";
+ LOG(ERROR) << "Trying to call glProgramPathFragmentInputGenNV() without "
+ "current GL context";
+}
+
void NoContextGLApi::glPushGroupMarkerEXTFn(GLsizei length,
const char* marker) {
NOTREACHED()
diff --git a/ui/gl/gl_bindings_autogen_gl.h b/ui/gl/gl_bindings_autogen_gl.h
index 4ecd4cb..457c5e4 100644
--- a/ui/gl/gl_bindings_autogen_gl.h
+++ b/ui/gl/gl_bindings_autogen_gl.h
@@ -432,13 +432,34 @@ typedef void(GL_BINDING_CALL* glGetProgramInfoLogProc)(GLuint program,
GLsizei bufsize,
GLsizei* length,
char* infolog);
+typedef void(GL_BINDING_CALL* glGetProgramInterfaceivProc)(
+ GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint* params);
typedef void(GL_BINDING_CALL* glGetProgramivProc)(GLuint program,
GLenum pname,
GLint* params);
+typedef void(GL_BINDING_CALL* glGetProgramResourceivProc)(
+ GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum* props,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLint* params);
typedef GLint(GL_BINDING_CALL* glGetProgramResourceLocationProc)(
GLuint program,
GLenum programInterface,
const char* name);
+typedef void(GL_BINDING_CALL* glGetProgramResourceNameProc)(
+ GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLchar* name);
typedef void(GL_BINDING_CALL* glGetQueryivProc)(GLenum target,
GLenum pname,
GLint* params);
@@ -612,6 +633,12 @@ typedef void(GL_BINDING_CALL* glProgramBinaryProc)(GLuint program,
typedef void(GL_BINDING_CALL* glProgramParameteriProc)(GLuint program,
GLenum pname,
GLint value);
+typedef void(GL_BINDING_CALL* glProgramPathFragmentInputGenNVProc)(
+ GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs);
typedef void(GL_BINDING_CALL* glPushGroupMarkerEXTProc)(GLsizei length,
const char* marker);
typedef void(GL_BINDING_CALL* glQueryCounterProc)(GLuint id, GLenum target);
@@ -1010,6 +1037,7 @@ struct ExtensionsGL {
bool b_GL_ARB_instanced_arrays;
bool b_GL_ARB_map_buffer_range;
bool b_GL_ARB_occlusion_query;
+ bool b_GL_ARB_program_interface_query;
bool b_GL_ARB_robustness;
bool b_GL_ARB_sync;
bool b_GL_ARB_texture_storage;
@@ -1187,8 +1215,11 @@ struct ProcsGL {
glGetInternalformativProc glGetInternalformativFn;
glGetProgramBinaryProc glGetProgramBinaryFn;
glGetProgramInfoLogProc glGetProgramInfoLogFn;
+ glGetProgramInterfaceivProc glGetProgramInterfaceivFn;
glGetProgramivProc glGetProgramivFn;
+ glGetProgramResourceivProc glGetProgramResourceivFn;
glGetProgramResourceLocationProc glGetProgramResourceLocationFn;
+ glGetProgramResourceNameProc glGetProgramResourceNameFn;
glGetQueryivProc glGetQueryivFn;
glGetQueryObjecti64vProc glGetQueryObjecti64vFn;
glGetQueryObjectivProc glGetQueryObjectivFn;
@@ -1255,6 +1286,7 @@ struct ProcsGL {
glPopGroupMarkerEXTProc glPopGroupMarkerEXTFn;
glProgramBinaryProc glProgramBinaryFn;
glProgramParameteriProc glProgramParameteriFn;
+ glProgramPathFragmentInputGenNVProc glProgramPathFragmentInputGenNVFn;
glPushGroupMarkerEXTProc glPushGroupMarkerEXTFn;
glQueryCounterProc glQueryCounterFn;
glReadBufferProc glReadBufferFn;
@@ -1734,12 +1766,30 @@ class GL_EXPORT GLApi {
GLsizei bufsize,
GLsizei* length,
char* infolog) = 0;
+ virtual void glGetProgramInterfaceivFn(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint* params) = 0;
virtual void glGetProgramivFn(GLuint program,
GLenum pname,
GLint* params) = 0;
+ virtual void glGetProgramResourceivFn(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum* props,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLint* params) = 0;
virtual GLint glGetProgramResourceLocationFn(GLuint program,
GLenum programInterface,
const char* name) = 0;
+ virtual void glGetProgramResourceNameFn(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLchar* name) = 0;
virtual void glGetQueryivFn(GLenum target, GLenum pname, GLint* params) = 0;
virtual void glGetQueryObjecti64vFn(GLuint id,
GLenum pname,
@@ -1889,6 +1939,11 @@ class GL_EXPORT GLApi {
virtual void glProgramParameteriFn(GLuint program,
GLenum pname,
GLint value) = 0;
+ virtual void glProgramPathFragmentInputGenNVFn(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) = 0;
virtual void glPushGroupMarkerEXTFn(GLsizei length, const char* marker) = 0;
virtual void glQueryCounterFn(GLuint id, GLenum target) = 0;
virtual void glReadBufferFn(GLenum src) = 0;
@@ -2418,9 +2473,15 @@ class GL_EXPORT GLApi {
::gfx::g_current_gl_context->glGetInternalformativFn
#define glGetProgramBinary ::gfx::g_current_gl_context->glGetProgramBinaryFn
#define glGetProgramInfoLog ::gfx::g_current_gl_context->glGetProgramInfoLogFn
+#define glGetProgramInterfaceiv \
+ ::gfx::g_current_gl_context->glGetProgramInterfaceivFn
#define glGetProgramiv ::gfx::g_current_gl_context->glGetProgramivFn
+#define glGetProgramResourceiv \
+ ::gfx::g_current_gl_context->glGetProgramResourceivFn
#define glGetProgramResourceLocation \
::gfx::g_current_gl_context->glGetProgramResourceLocationFn
+#define glGetProgramResourceName \
+ ::gfx::g_current_gl_context->glGetProgramResourceNameFn
#define glGetQueryiv ::gfx::g_current_gl_context->glGetQueryivFn
#define glGetQueryObjecti64v ::gfx::g_current_gl_context->glGetQueryObjecti64vFn
#define glGetQueryObjectiv ::gfx::g_current_gl_context->glGetQueryObjectivFn
@@ -2504,6 +2565,8 @@ class GL_EXPORT GLApi {
#define glPopGroupMarkerEXT ::gfx::g_current_gl_context->glPopGroupMarkerEXTFn
#define glProgramBinary ::gfx::g_current_gl_context->glProgramBinaryFn
#define glProgramParameteri ::gfx::g_current_gl_context->glProgramParameteriFn
+#define glProgramPathFragmentInputGenNV \
+ ::gfx::g_current_gl_context->glProgramPathFragmentInputGenNVFn
#define glPushGroupMarkerEXT ::gfx::g_current_gl_context->glPushGroupMarkerEXTFn
#define glQueryCounter ::gfx::g_current_gl_context->glQueryCounterFn
#define glReadBuffer ::gfx::g_current_gl_context->glReadBufferFn
diff --git a/ui/gl/gl_bindings_autogen_mock.cc b/ui/gl/gl_bindings_autogen_mock.cc
index ebc5271..b356561 100644
--- a/ui/gl/gl_bindings_autogen_mock.cc
+++ b/ui/gl/gl_bindings_autogen_mock.cc
@@ -1299,6 +1299,15 @@ void GL_BINDING_CALL MockGLInterface::Mock_glGetProgramInfoLog(GLuint program,
interface_->GetProgramInfoLog(program, bufsize, length, infolog);
}
+void GL_BINDING_CALL
+MockGLInterface::Mock_glGetProgramInterfaceiv(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint* params) {
+ MakeFunctionUnique("glGetProgramInterfaceiv");
+ interface_->GetProgramInterfaceiv(program, programInterface, pname, params);
+}
+
GLint GL_BINDING_CALL
MockGLInterface::Mock_glGetProgramResourceLocation(GLuint program,
GLenum programInterface,
@@ -1308,6 +1317,32 @@ MockGLInterface::Mock_glGetProgramResourceLocation(GLuint program,
name);
}
+void GL_BINDING_CALL
+MockGLInterface::Mock_glGetProgramResourceName(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLchar* name) {
+ MakeFunctionUnique("glGetProgramResourceName");
+ interface_->GetProgramResourceName(program, programInterface, index, bufSize,
+ length, name);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glGetProgramResourceiv(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum* props,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLint* params) {
+ MakeFunctionUnique("glGetProgramResourceiv");
+ interface_->GetProgramResourceiv(program, programInterface, index, propCount,
+ props, bufSize, length, params);
+}
+
void GL_BINDING_CALL MockGLInterface::Mock_glGetProgramiv(GLuint program,
GLenum pname,
GLint* params) {
@@ -1904,6 +1939,17 @@ void GL_BINDING_CALL MockGLInterface::Mock_glProgramParameteri(GLuint program,
}
void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramPathFragmentInputGenNV(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs) {
+ MakeFunctionUnique("glProgramPathFragmentInputGenNV");
+ interface_->ProgramPathFragmentInputGenNV(program, location, genMode,
+ components, coeffs);
+}
+
+void GL_BINDING_CALL
MockGLInterface::Mock_glPushGroupMarkerEXT(GLsizei length, const char* marker) {
MakeFunctionUnique("glPushGroupMarkerEXT");
interface_->PushGroupMarkerEXT(length, marker);
@@ -3134,8 +3180,14 @@ void* GL_BINDING_CALL MockGLInterface::GetGLProcAddress(const char* name) {
return reinterpret_cast<void*>(Mock_glGetProgramBinaryOES);
if (strcmp(name, "glGetProgramInfoLog") == 0)
return reinterpret_cast<void*>(Mock_glGetProgramInfoLog);
+ if (strcmp(name, "glGetProgramInterfaceiv") == 0)
+ return reinterpret_cast<void*>(Mock_glGetProgramInterfaceiv);
if (strcmp(name, "glGetProgramResourceLocation") == 0)
return reinterpret_cast<void*>(Mock_glGetProgramResourceLocation);
+ if (strcmp(name, "glGetProgramResourceName") == 0)
+ return reinterpret_cast<void*>(Mock_glGetProgramResourceName);
+ if (strcmp(name, "glGetProgramResourceiv") == 0)
+ return reinterpret_cast<void*>(Mock_glGetProgramResourceiv);
if (strcmp(name, "glGetProgramiv") == 0)
return reinterpret_cast<void*>(Mock_glGetProgramiv);
if (strcmp(name, "glGetQueryObjecti64v") == 0)
@@ -3306,6 +3358,8 @@ void* GL_BINDING_CALL MockGLInterface::GetGLProcAddress(const char* name) {
return reinterpret_cast<void*>(Mock_glProgramBinaryOES);
if (strcmp(name, "glProgramParameteri") == 0)
return reinterpret_cast<void*>(Mock_glProgramParameteri);
+ if (strcmp(name, "glProgramPathFragmentInputGenNV") == 0)
+ return reinterpret_cast<void*>(Mock_glProgramPathFragmentInputGenNV);
if (strcmp(name, "glPushGroupMarkerEXT") == 0)
return reinterpret_cast<void*>(Mock_glPushGroupMarkerEXT);
if (strcmp(name, "glQueryCounter") == 0)
diff --git a/ui/gl/gl_bindings_autogen_mock.h b/ui/gl/gl_bindings_autogen_mock.h
index f89ab41..f97521e 100644
--- a/ui/gl/gl_bindings_autogen_mock.h
+++ b/ui/gl/gl_bindings_autogen_mock.h
@@ -490,10 +490,30 @@ static void GL_BINDING_CALL Mock_glGetProgramInfoLog(GLuint program,
GLsizei bufsize,
GLsizei* length,
char* infolog);
+static void GL_BINDING_CALL
+Mock_glGetProgramInterfaceiv(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint* params);
static GLint GL_BINDING_CALL
Mock_glGetProgramResourceLocation(GLuint program,
GLenum programInterface,
const char* name);
+static void GL_BINDING_CALL
+Mock_glGetProgramResourceName(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLchar* name);
+static void GL_BINDING_CALL Mock_glGetProgramResourceiv(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum* props,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLint* params);
static void GL_BINDING_CALL Mock_glGetProgramiv(GLuint program,
GLenum pname,
GLint* params);
@@ -707,6 +727,12 @@ static void GL_BINDING_CALL Mock_glProgramBinaryOES(GLuint program,
static void GL_BINDING_CALL Mock_glProgramParameteri(GLuint program,
GLenum pname,
GLint value);
+static void GL_BINDING_CALL
+Mock_glProgramPathFragmentInputGenNV(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs);
static void GL_BINDING_CALL Mock_glPushGroupMarkerEXT(GLsizei length,
const char* marker);
static void GL_BINDING_CALL Mock_glQueryCounter(GLuint id, GLenum target);
diff --git a/ui/gl/gl_enums_implementation_autogen.h b/ui/gl/gl_enums_implementation_autogen.h
index a240285..967f67a 100644
--- a/ui/gl/gl_enums_implementation_autogen.h
+++ b/ui/gl/gl_enums_implementation_autogen.h
@@ -454,6 +454,9 @@ static const GLEnums::EnumToString enum_to_string_table[] = {
0x300E, "GL_CONTEXT_LOST",
},
{
+ 0x2400, "GL_EYE_LINEAR_CHROMIUM",
+ },
+ {
0x90a3, "GL_SQUARE_CHROMIUM",
},
{
@@ -1321,6 +1324,9 @@ static const GLEnums::EnumToString enum_to_string_table[] = {
0x8A39, "GL_UNIFORM_NAME_LENGTH",
},
{
+ 0x8576, "GL_CONSTANT_CHROMIUM",
+ },
+ {
0x8E2C, "GL_DEPTH_COMPONENT16_NONLINEAR_NV",
},
{
@@ -2914,6 +2920,9 @@ static const GLEnums::EnumToString enum_to_string_table[] = {
0x00008000, "GL_COVERAGE_BUFFER_BIT_NV",
},
{
+ 0x2401, "GL_OBJECT_LINEAR_CHROMIUM",
+ },
+ {
0x1506, "GL_XOR_NV",
},
{
diff --git a/ui/gl/gl_mock_autogen_gl.h b/ui/gl/gl_mock_autogen_gl.h
index 7f782f3..2a34acd 100644
--- a/ui/gl/gl_mock_autogen_gl.h
+++ b/ui/gl/gl_mock_autogen_gl.h
@@ -364,9 +364,28 @@ MOCK_METHOD5(GetProgramBinary,
MOCK_METHOD4(
GetProgramInfoLog,
void(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog));
+MOCK_METHOD4(
+ GetProgramInterfaceiv,
+ void(GLuint program, GLenum programInterface, GLenum pname, GLint* params));
MOCK_METHOD3(GetProgramiv, void(GLuint program, GLenum pname, GLint* params));
+MOCK_METHOD8(GetProgramResourceiv,
+ void(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum* props,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLint* params));
MOCK_METHOD3(GetProgramResourceLocation,
GLint(GLuint program, GLenum programInterface, const char* name));
+MOCK_METHOD6(GetProgramResourceName,
+ void(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLchar* name));
MOCK_METHOD3(GetQueryiv, void(GLenum target, GLenum pname, GLint* params));
MOCK_METHOD3(GetQueryObjecti64v,
void(GLuint id, GLenum pname, GLint64* params));
@@ -499,6 +518,12 @@ MOCK_METHOD4(ProgramBinary,
GLsizei length));
MOCK_METHOD3(ProgramParameteri,
void(GLuint program, GLenum pname, GLint value));
+MOCK_METHOD5(ProgramPathFragmentInputGenNV,
+ void(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat* coeffs));
MOCK_METHOD2(PushGroupMarkerEXT, void(GLsizei length, const char* marker));
MOCK_METHOD2(QueryCounter, void(GLuint id, GLenum target));
MOCK_METHOD1(ReadBuffer, void(GLenum src));