diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-08-14 11:38:45 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-08-14 17:16:47 +0000 |
commit | 3a97ca8dd9b96b599ae2d33e40df0dd2f7ea5859 (patch) | |
tree | 43cc572ba067417c7341db81f71ae7cc6e0fcc3e /chromium/gpu | |
parent | f61ab1ac7f855cd281809255c0aedbb1895e1823 (diff) | |
download | qtwebengine-chromium-3a97ca8dd9b96b599ae2d33e40df0dd2f7ea5859.tar.gz |
BASELINE: Update chromium to 45.0.2454.40
Change-Id: Id2121d9f11a8fc633677236c65a3e41feef589e4
Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
Diffstat (limited to 'chromium/gpu')
155 files changed, 7113 insertions, 4068 deletions
diff --git a/chromium/gpu/BUILD.gn b/chromium/gpu/BUILD.gn index f9b7300bc8a..dd737e7ce4f 100644 --- a/chromium/gpu/BUILD.gn +++ b/chromium/gpu/BUILD.gn @@ -76,6 +76,7 @@ test("gl_tests") { "command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc", "command_buffer/tests/gl_chromium_path_rendering_unittest.cc", "command_buffer/tests/gl_clear_framebuffer_unittest.cc", + "command_buffer/tests/gl_compressed_copy_texture_CHROMIUM_unittest.cc", "command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc", "command_buffer/tests/gl_depth_texture_unittest.cc", "command_buffer/tests/gl_gpu_memory_buffer_unittest.cc", diff --git a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_compressed_copy_texture.txt b/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_compressed_copy_texture.txt new file mode 100644 index 00000000000..c236ce3835b --- /dev/null +++ b/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_compressed_copy_texture.txt @@ -0,0 +1,88 @@ +Name + + CHROMIUM_copy_compressed_texture + +Name Strings + + GL_CHROMIUM_copy_compressed_texture + +Version + + Last Modifed Date: Jun 15, 2015 + +Dependencies + + OpenGL ES 2.0 is required. + + GL_AMD_compressed_ATC_texture, GL_ATI_texture_compression_atitc, + GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt5, + GL_EXT_texture_compression_s3tc and GL_OES_compressed_ETC1_RGB8_texture + affects the definition of this extension. + +Overview + + This extension provides functionality for copying compressed textures. It + adds a new function glCompressedCopyTextureCHROMIUM that works similarily + to glCopyTextureCHROMIUM, but for compressed textures. + + Which compressed texture formats that this extension supports depends on + the supported texture compression formats of the host GPU. + +Issues + + glCompressedCopyTextureCHROMIUM will first try to copy into a compressed + texture of the same format as the source texture. If unsucessful, the + destination texture format will be changed to GL_RGBA and the texture will + be stored uncompressed. + +New Procedures and Functions + + The command + + void glCompressedCopyTextureCHROMIUM (GLenum target, GLenum source_id, + GLenum dest_id) + + Copies the contents of a compressed texture referred to by <source_id> to + <dest_id> texture. + + Texture level 0 is copied from the source image to level 0 of the + destination texture. + + The internal format of the source texture must be one of the following + symbolic constants: GL_ATC_RGB_AMD, GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD, + GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, + GL_ETC1_RGB8_OES + + The destination texture will be created or replaced with the same internal + format as the source texture. + + <target> uses the same parameters as TexImage2D. + + INVALID_OPERATION is generated if internal format of source texture is not + one of the valid formats described above. + + INVALID_OPERATION is generated if destination texture is immutable. + + INVALID_VALUE is generated if <source_id> or <dest_id> are not valid texture + objects. + + INVALID_VALUE is generated if textures corresponding to <dest_id> have not + been bound as GL_TEXTURE_2D object. + + INVALID_VALUE is generated if level 0 of the source texture is not defined. + +Errors + + None. + +New Tokens + + None. + +New State + + None. + +Revision History + + 15/6/2015 Documented the extension. diff --git a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt b/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt index 68459918548..be60af22dbb 100644 --- a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt +++ b/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt @@ -14,21 +14,15 @@ Dependencies OpenGL ES 2.0 is required. - CHROMIUM_flipy affects the definition of this extension. EXT_texture_format_BGRA8888 affects the definition of this extension. + ARB_texture_rg affects the definition of this extension. Overview This extension expands on the functionality provided by the glCopyTexImage2D command. A new function is exported, glCopyTextureCHROMIUM, that performs the same copy operation as - glCopyTexImage2D, while respecting the pixel-storage modifiers - UNPACK_FLIP_Y_CHROMIUM, GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM and - GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM. - - If GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM and - GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM are enabled. Then no alpha - processing occurs. This is the equivalent of having neither flag set. + glCopyTexImage2D. The extension also supports copying BGRA textures and copying EXTERNAL_OES texture to BGRA texture, which is not explicitly @@ -40,7 +34,10 @@ New Procedures and Functions void glCopyTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id, - GLint internal_format, GLenum dest_type) + GLint internal_format, GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) Copies the contents of texture referred to by <source_id> to <dest_id> texture. If <source_id> texture is not defined or has different dimension @@ -53,14 +50,15 @@ New Procedures and Functions specified by <internal_format>. Must be one of the following symbolic constants: GL_RGB, GL_RGBA The internal format of <source_id> texture must be one of the following - symbolic constants: GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, - GL_RGBA, GL_BGRA_EXT + symbolic constants: GL_R8, GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, + GL_RGB, GL_RGBA, GL_BGRA_EXT When <source_id> texture doens't contain a superset of the component required by <internal_format>, fill the components by following rules. source format color components ================================================= GL_ALPHA (0, 0, 0, A) + GL_R8 (R, 0, 0, 1) GL_LUMINANCE (L, L, L, 1) GL_LUMINANCE_ALPHA (L, L, L, A) GL_RGB (R, G, B, 1) @@ -72,6 +70,12 @@ New Procedures and Functions <target> uses the same parameters as TexImage2D. + If <flip_y> is true, vertically flip texture image data. + + If <unpack_premultiply_alpha> and <unpack_unmultiply_alpha> are true, + no alpha processing occurs. This is the equivalent of having neither flag + set. + INVALID_OPERATION is generated if <internal_format> is not one of the valid formats described above. @@ -96,16 +100,29 @@ New Procedures and Functions void glCopySubTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id, - GLint xoffset, GLint yoffset) + GLint xoffset, GLint yoffset, + GLint x, GLint y, + GLsizei width, GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) Copies the sub contents of texture referred to by <source_id> to <dest_id> texture without redefining <dest_id> texture. - See CopyTextureCHROMIUM for the interpretation of the <target> arguments. + See CopyTextureCHROMIUM for the interpretation of the <target>, <flip_y>, + <premultiply_alpha>, and <unmultiply_alpha> arguments. <xoffset> and <yoffset> specify a texel offset in the x and y direction respectively within the destination texture. + <x> and <y> specify specify a texel offset in the x and y direction + respectively within the source texture. + + <width> specifies the width of the texture subimage. + + <height> specifies the width of the texture subimage. + INVALID_OPERATION is generated if source internal_format and destination internal_format are not one of the valid formats described above. @@ -122,6 +139,11 @@ New Procedures and Functions INVALID_VALUE is generated if (<xoffset> + source_width) > dest_width, or (<yoffset> + source_height) > dest_height. +Dependencies on ARB_texture_rg + + If ARB_texture_rg is not supported: + * delete any reference to the R8 format. + Errors None. @@ -138,4 +160,6 @@ Revision History 8/1/2011 Documented the extension 7/4/2013 Add a new parameter dest_type to glCopyTextureCHROMIUM() - 16/7/2014 Add GL_TEXTURE_RECTANGLE_ARB as valid source_id target. + 16/7/2014 Add GL_TEXTURE_RECTANGLE_ARB as valid source_id target + 19/6/2015 Add arguments unpack_flip_y, unpack_premultiply_alpha, and + unpack_unmultiply_alpha to both commands. diff --git a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_flipy.txt b/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_flipy.txt deleted file mode 100644 index 7511fc432a3..00000000000 --- a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_flipy.txt +++ /dev/null @@ -1,118 +0,0 @@ -Name - - CHROMIUM_flipy - -Name Strings - - GL_CHROMIUM_flipy - -Version - - Last Modifed Date: April 9, 2012 - -Dependencies - - OpenGL ES 2.0 is required. - -Overview - - This extension adds the ability to vertically flip texture image data when - calling TexImage2D and TexSubImage2D. - -Issues - - -New Tokens - - Accepted by the <param> parameter of PixelStorei: - - UNPACK_FLIP_Y_CHROMIUM 0x9240 - -Additions to the OpenGL ES 2.0 Specification - - Modifications to Table 3.1 (PixelStore Parameters) - - Add the following entry: - - Parameter Name Type Initial Value Valid Range - ============== ==== ============= =========== - UNPACK_FLIP_Y_CHROMIUM boolean FALSE {TRUE, FALSE} - - Modifications to 3.6.2 Transfer of Pixel Rectangles, in the Unpacking - section: - - Change - "If p indicates the location in memory of the first element of the first - row, then the first element of the Nth row is indicated by - p + Nk (3.9)" - to - "If p indicates the location in memory of the first element of the first - row, then the first element of the Nth row is indicated by - p + Nk (3.9) - if UNPACK_FLIP_Y is FALSE. Otherwise, the first element of the Nth row - is indicated by - p - Nk (3.10) - - After the sentence - - "If the number of bits per element is not 1, 2, 4, or 8 times the number - of bits in a GL ubyte, then k = nl for all values of a." - - insert: - - "If UNPACK_FLIP_Y_CHROMIUM is FALSE then p is equal to pixels. Otherwise - p is pixels + (height - 1)k." - -Interactions with GL_EXT_unpack_subimage - - Do not add the sentence "If UNPACK_FLIP_Y_CHROMIUM is FALSE ..." described - in this extension. Instead do the following after applying - GL_EXT_unpack_subimage: - - Change - - "There is a mechanism for selecting a sub-rectangle of groups - from a larger containing rectangle. This mechanism relies on - three integer parameters: UNPACK_ROW_LENGTH, UNPACK_SKIP_ROWS, - and UNPACK_SKIP_PIXELS. Before obtaining the first group from - memory, the pointer supplied to TexImage2D is effectively - advanced by (UNPACK_SKIP_PIXELS)n + (UNPACK_SKIP_ROWS)k - elements. Then <width> groups are obtained from contiguous - elements in memory (without advancing the pointer), after - which the pointer is advanced by k elements. <height> sets of - <width> groups of values are obtained this way. See figure - 3.6." - - to - - "There is a mechanism for selecting a sub-rectangle of groups - from a larger containing rectangle. This mechanism relies on - three integer parameters: UNPACK_ROW_LENGTH, UNPACK_SKIP_ROWS, - and UNPACK_SKIP_PIXELS. IF UNPACK_FLIP_Y_CHROMIUM is FALSE then - p, the location of the first element of the first - group, is pixels + (UNPACK_SKIP_PIXELS)n + (UNPACK_SKIP_ROWS)k. - When UNPACK_FLIP_Y_CHROMIUM is TRUE then p is pixels + - (UNPACK_SKIP_PIXELS)n + (UNPACK_SKIP_ROWS + height - 1)k. After - p is determined <width> groups are obtained from contiguous - elements in memory (without advancing the pointer), after which - the pointer is advanced by +/-k elements depending on the value - of UNPACK_CHROMIUM_FLIP_Y. <height> sets of <width> groups of - values are obtained this way. See figure 3.6." - -New Procedures and Functions - - None. - -Errors - - None. - -New State - - None. - -Revision History - - 7/22/2011 Documented the extension - 4/09/2012 Added more documentation and described interactions with - GL_EXT_unpack_subimage diff --git a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_image.txt b/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_image.txt index e0ba0666b51..7118391a94d 100644 --- a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_image.txt +++ b/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_image.txt @@ -8,7 +8,7 @@ Name Strings Version - Last Modifed Date: Oct 7, 2014 + Last Modifed Date: May 13, 2015 Dependencies @@ -45,8 +45,10 @@ New Procedures and Functions INVALID_VALUE is generated if <width> or <height> is nonpositive. - INVALID_ENUM is generated if <internalformat> is not one of - R8, RGB, RGBA or BGRA_EXT. + INVALID_VALUE is generated if <internalformat> is not one of + R8, RGB, RGBA, BGRA_EXT, ATC_RGB_AMD, ATC_RGBA_INTERPOLATED_ALPHA_AMD, + COMPRESSED_RGB_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT5_EXT or + ETC1_RGB8_OES. void DestroyImageCHROMIUM(GLuint image_id) @@ -64,6 +66,23 @@ Dependencies on ARB_texture_rg If ARB_texture_rg is not supported: * delete any reference to the R8 format. +Dependencies on AMD_compressed_ATC_texture + + If AMD_compressed_ATC_texture is not supported: + * delete any reference to the ATC_RGB_AMD and + ATC_RGBA_INTERPOLATED_ALPHA_AMD formats. + +Dependencies on EXT_texture_compression_s3tc + + If EXT_texture_compression_s3tc is not supported: + * delete any reference to the COMPRESSED_RGB_S3TC_DXT1_EXT and + COMPRESSED_RGBA_S3TC_DXT5_EXT formats. + +Dependencies on OES_compressed_ETC1_RGB8_texture + + If OES_compressed_ETC1_RGB8_texture is not supported: + * delete any reference to the ETC1_RGB8_OES format. + Errors None. @@ -79,3 +98,4 @@ Revision History 10/7/2014 Remove map/unmap API. 4/6/2015 Add BGRA_EXT format. 2/7/2015 Add R8 format. + 5/13/2015 Add compressed formats. diff --git a/chromium/gpu/GLES2/gl2chromium_autogen.h b/chromium/gpu/GLES2/gl2chromium_autogen.h index 9dbe95de25c..05a7c50b93e 100644 --- a/chromium/gpu/GLES2/gl2chromium_autogen.h +++ b/chromium/gpu/GLES2/gl2chromium_autogen.h @@ -251,6 +251,7 @@ #define glEndTransformFeedback GLES2_GET_FUN(EndTransformFeedback) #define glGetQueryivEXT GLES2_GET_FUN(GetQueryivEXT) #define glGetQueryObjectuivEXT GLES2_GET_FUN(GetQueryObjectuivEXT) +#define glGetQueryObjectui64vEXT GLES2_GET_FUN(GetQueryObjectui64vEXT) #define glInsertEventMarkerEXT GLES2_GET_FUN(InsertEventMarkerEXT) #define glPushGroupMarkerEXT GLES2_GET_FUN(PushGroupMarkerEXT) #define glPopGroupMarkerEXT GLES2_GET_FUN(PopGroupMarkerEXT) @@ -291,6 +292,8 @@ #define glTexImageIOSurface2DCHROMIUM GLES2_GET_FUN(TexImageIOSurface2DCHROMIUM) #define glCopyTextureCHROMIUM GLES2_GET_FUN(CopyTextureCHROMIUM) #define glCopySubTextureCHROMIUM GLES2_GET_FUN(CopySubTextureCHROMIUM) +#define glCompressedCopyTextureCHROMIUM \ + GLES2_GET_FUN(CompressedCopyTextureCHROMIUM) #define glDrawArraysInstancedANGLE GLES2_GET_FUN(DrawArraysInstancedANGLE) #define glDrawElementsInstancedANGLE GLES2_GET_FUN(DrawElementsInstancedANGLE) #define glVertexAttribDivisorANGLE GLES2_GET_FUN(VertexAttribDivisorANGLE) @@ -328,8 +331,10 @@ #define glScheduleOverlayPlaneCHROMIUM \ GLES2_GET_FUN(ScheduleOverlayPlaneCHROMIUM) #define glSwapInterval GLES2_GET_FUN(SwapInterval) +#define glFlushDriverCachesCHROMIUM GLES2_GET_FUN(FlushDriverCachesCHROMIUM) #define glMatrixLoadfCHROMIUM GLES2_GET_FUN(MatrixLoadfCHROMIUM) #define glMatrixLoadIdentityCHROMIUM GLES2_GET_FUN(MatrixLoadIdentityCHROMIUM) +#define glGetGraphicsResetStatusKHR GLES2_GET_FUN(GetGraphicsResetStatusKHR) #define glBlendBarrierKHR GLES2_GET_FUN(BlendBarrierKHR) #endif // GPU_GLES2_GL2CHROMIUM_AUTOGEN_H_ diff --git a/chromium/gpu/GLES2/gl2extchromium.h b/chromium/gpu/GLES2/gl2extchromium.h index 415aa63bde0..038a303669a 100644 --- a/chromium/gpu/GLES2/gl2extchromium.h +++ b/chromium/gpu/GLES2/gl2extchromium.h @@ -390,39 +390,67 @@ typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERCHROMIUMPROC) (GLint srcX0, GLint #define GL_UNPACK_COLORSPACE_CONVERSION_CHROMIUM 0x9243 #endif -#ifndef GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM -#define GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM 0x9242 -#endif - -#ifndef GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM -#define GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM 0x9241 -#endif #ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glCopyTextureCHROMIUM(GLenum target, - GLenum source_id, - GLenum dest_id, - GLint internalformat, - GLenum dest_type); - -GL_APICALL void GL_APIENTRY glCopySubTextureCHROMIUM(GLenum target, - GLenum source_id, - GLenum dest_id, - GLint xoffset, - GLint yoffset); -#endif -typedef void(GL_APIENTRYP PFNGLCOPYTEXTURECHROMIUMPROC)(GLenum target, - GLenum source_id, - GLenum dest_id, - GLint internalformat, - GLenum dest_type); - -typedef void(GL_APIENTRYP PFNGLCOPYSUBTEXTURECHROMIUMPROC)(GLenum target, - GLenum source_id, - GLenum dest_id, - GLint xoffset, - GLint yoffset); +GL_APICALL void GL_APIENTRY glCopyTextureCHROMIUM( + GLenum target, + GLenum source_id, + GLenum dest_id, + GLint internalformat, + GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha); + +GL_APICALL void GL_APIENTRY glCopySubTextureCHROMIUM( + GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha); +#endif +typedef void(GL_APIENTRYP PFNGLCOPYTEXTURECHROMIUMPROC)( + GLenum target, + GLenum source_id, + GLenum dest_id, + GLint internalformat, + GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha); + +typedef void(GL_APIENTRYP PFNGLCOPYSUBTEXTURECHROMIUMPROC)( + GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha); #endif /* GL_CHROMIUM_copy_texture */ +/* GL_CHROMIUM_compressed_copy_texture */ +#ifndef GL_CHROMIUM_compressed_copy_texture +#define GL_CHROMIUM_compressed_copy_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glCompressedCopyTextureCHROMIUM( + GLenum target, GLenum source_id, GLenum dest_id); +#endif +typedef void(GL_APIENTRYP PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMPROC)( + GLenum target, GLenum source_id, GLenum dest_id); +#endif /* GL_CHROMIUM_compressed_copy_texture */ + /* GL_CHROMIUM_lose_context */ #ifndef GL_CHROMIUM_lose_context #define GL_CHROMIUM_lose_context 1 @@ -433,15 +461,6 @@ typedef void (GL_APIENTRYP PFNGLLOSECONTEXTCHROMIUMPROC) ( GLenum current, GLenum other); #endif /* GL_CHROMIUM_lose_context */ -/* GL_CHROMIUM_flipy */ -#ifndef GL_CHROMIUM_flipy -#define GL_CHROMIUM_flipy 1 - -#ifndef GL_UNPACK_FLIP_Y_CHROMIUM -#define GL_UNPACK_FLIP_Y_CHROMIUM 0x9240 -#endif -#endif /* GL_CHROMIUM_flipy */ - /* GL_ARB_texture_rectangle */ #ifndef GL_ARB_texture_rectangle #define GL_ARB_texture_rectangle 1 diff --git a/chromium/gpu/angle_deqp_tests_main.cc b/chromium/gpu/angle_deqp_tests_main.cc new file mode 100644 index 00000000000..9814d70e27c --- /dev/null +++ b/chromium/gpu/angle_deqp_tests_main.cc @@ -0,0 +1,30 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/at_exit.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/message_loop/message_loop.h" +#include "base/test/launcher/unit_test_launcher.h" +#include "base/test/test_suite.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +int RunHelper(base::TestSuite* test_suite) { + base::MessageLoop message_loop; + return test_suite->Run(); +} + +} // namespace + +int main(int argc, char** argv) { + base::CommandLine::Init(argc, argv); + base::TestSuite test_suite(argc, argv); + int rt = base::LaunchUnitTestsSerially( + argc, + argv, + base::Bind(&RunHelper, base::Unretained(&test_suite))); + return rt; +} diff --git a/chromium/gpu/angle_end2end_tests_main.cc b/chromium/gpu/angle_end2end_tests_main.cc index aed7f74b943..008868c2b6e 100644 --- a/chromium/gpu/angle_end2end_tests_main.cc +++ b/chromium/gpu/angle_end2end_tests_main.cc @@ -10,7 +10,7 @@ #include "base/test/test_suite.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/angle/src/tests/end2end_tests/ANGLETest.h" +#include "third_party/angle/src/tests/test_utils/ANGLETest.h" namespace { diff --git a/chromium/gpu/blink/webgraphicscontext3d_impl.cc b/chromium/gpu/blink/webgraphicscontext3d_impl.cc index 2a3e5c7defa..30fa260bb16 100644 --- a/chromium/gpu/blink/webgraphicscontext3d_impl.cc +++ b/chromium/gpu/blink/webgraphicscontext3d_impl.cc @@ -30,6 +30,7 @@ using blink::WGC3Dint; using blink::WGC3Dintptr; using blink::WGC3Dsizei; using blink::WGC3Dsizeiptr; +using blink::WGC3Dint64; using blink::WGC3Duint64; using blink::WGC3Duint; using blink::WebGLId; @@ -180,11 +181,18 @@ void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, \ gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); \ } +#define DELEGATE_TO_GL_12(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, \ + t9, t10, t11, t12) \ +void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, \ + t6 a6, t7 a7, t8 a8, t9 a9, t10 a10,\ + t11 a11, t12 a12) { \ + gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); \ +} + WebGraphicsContext3DImpl::WebGraphicsContext3DImpl() : initialized_(false), initialize_failed_(false), context_lost_callback_(0), - context_lost_reason_(GL_NO_ERROR), error_message_callback_(0), gl_(NULL), flush_id_(0) { @@ -454,6 +462,8 @@ DELEGATE_TO_GL_4(getFramebufferAttachmentParameteriv, DELEGATE_TO_GL_2(getIntegerv, GetIntegerv, WGC3Denum, WGC3Dint*) +DELEGATE_TO_GL_2(getInteger64v, GetInteger64v, WGC3Denum, WGC3Dint64*) + DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, WGC3Denum, WGC3Dint*) blink::WebString WebGraphicsContext3DImpl::getProgramInfoLog( @@ -816,21 +826,31 @@ DELEGATE_TO_GL_3(getQueryivEXT, GetQueryivEXT, WGC3Denum, WGC3Denum, WGC3Dint*) DELEGATE_TO_GL_3(getQueryObjectuivEXT, GetQueryObjectuivEXT, WebGLId, WGC3Denum, WGC3Duint*) -DELEGATE_TO_GL_5(copyTextureCHROMIUM, +DELEGATE_TO_GL_8(copyTextureCHROMIUM, CopyTextureCHROMIUM, WGC3Denum, WebGLId, WebGLId, WGC3Denum, - WGC3Denum); - -DELEGATE_TO_GL_5(copySubTextureCHROMIUM, - CopySubTextureCHROMIUM, WGC3Denum, - WebGLId, - WebGLId, - WGC3Dint, - WGC3Dint); + WGC3Dboolean, + WGC3Dboolean, + WGC3Dboolean); + +DELEGATE_TO_GL_12(copySubTextureCHROMIUM, + CopySubTextureCHROMIUM, + WGC3Denum, + WebGLId, + WebGLId, + WGC3Dint, + WGC3Dint, + WGC3Dint, + WGC3Dint, + WGC3Dsizei, + WGC3Dsizei, + WGC3Dboolean, + WGC3Dboolean, + WGC3Dboolean); DELEGATE_TO_GL_3(bindUniformLocationCHROMIUM, BindUniformLocationCHROMIUM, WebGLId, WGC3Dint, const WGC3Dchar*) @@ -1078,12 +1098,12 @@ DELEGATE_TO_GL_2R(getUniformBlockIndex, GetUniformBlockIndex, WGC3Duint, const WGC3Dchar *, WGC3Duint) DELEGATE_TO_GL_4(getUniformIndices, GetUniformIndices, WGC3Duint, WGC3Dsizei, const WGC3Dchar *const*, WGC3Duint *) -//DELEGATE_TO_GL_3(getUniformuiv, GetUniformuiv, WGC3Duint, WGC3Dint, -// WGC3Duint *) -//DELEGATE_TO_GL_3(getVertexAttribIiv, GetVertexAttribIiv, WGC3Duint, -// WGC3Denum, WGC3Dint *) -//DELEGATE_TO_GL_3(getVertexAttribIuiv, GetVertexAttribIuiv, WGC3Duint, -// WGC3Denum, WGC3Duint *) +DELEGATE_TO_GL_3(getUniformuiv, GetUniformuiv, WGC3Duint, WGC3Dint, + WGC3Duint *) +DELEGATE_TO_GL_3(getVertexAttribIiv, GetVertexAttribIiv, WGC3Duint, + WGC3Denum, WGC3Dint *) +DELEGATE_TO_GL_3(getVertexAttribIuiv, GetVertexAttribIuiv, WGC3Duint, + WGC3Denum, WGC3Duint *) DELEGATE_TO_GL_3(invalidateFramebuffer, InvalidateFramebuffer, WGC3Denum, WGC3Dsizei, const WGC3Denum *) DELEGATE_TO_GL_7(invalidateSubFramebuffer, InvalidateSubFramebuffer, WGC3Denum, @@ -1095,6 +1115,8 @@ WGC3Dboolean WebGraphicsContext3DImpl::isSync(WGC3Dsync sync) { } DELEGATE_TO_GL_1R(isTransformFeedback, IsTransformFeedback, WGC3Duint, WGC3Dboolean) +DELEGATE_TO_GL_4R(mapBufferRange, MapBufferRange, WGC3Denum, WGC3Dintptr, + WGC3Dsizeiptr, WGC3Dbitfield, void*); DELEGATE_TO_GL(pauseTransformFeedback, PauseTransformFeedback) //DELEGATE_TO_GL_3(programParameteri, ProgramParameteri, WGC3Duint, WGC3Denum, // WGC3Dint) @@ -1146,6 +1168,7 @@ DELEGATE_TO_GL_4(uniformMatrix4x2fv, UniformMatrix4x2fv, WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) DELEGATE_TO_GL_4(uniformMatrix4x3fv, UniformMatrix4x3fv, WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) +DELEGATE_TO_GL_1R(unmapBuffer, UnmapBuffer, WGC3Denum, WGC3Dboolean); DELEGATE_TO_GL_5(vertexAttribI4i, VertexAttribI4i, WGC3Duint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) DELEGATE_TO_GL_2(vertexAttribI4iv, VertexAttribI4iv, WGC3Duint, @@ -1167,6 +1190,14 @@ void WebGraphicsContext3DImpl::waitSync(WGC3Dsync sync, gl_->WaitSync(reinterpret_cast<GLsync>(sync), flags, timeout); } +bool WebGraphicsContext3DImpl::isContextLost() { + return getGraphicsResetStatusARB() != GL_NO_ERROR; +} + +blink::WGC3Denum WebGraphicsContext3DImpl::getGraphicsResetStatusARB() { + return gl_->GetGraphicsResetStatusKHR(); +} + GrGLInterface* WebGraphicsContext3DImpl::createGrGLInterface() { return skia_bindings::CreateCommandBufferSkiaGLBinding(); } @@ -1223,8 +1254,7 @@ void WebGraphicsContext3DImpl::ConvertAttributes( output_attribs->fail_if_major_perf_caveat = attributes.failIfMajorPerformanceCaveat; output_attribs->bind_generates_resource = false; - output_attribs->es3_context_required = - (attributes.webGL && attributes.webGLVersion == 2); + output_attribs->webgl_version = attributes.webGLVersion; } } // namespace gpu_blink diff --git a/chromium/gpu/blink/webgraphicscontext3d_impl.h b/chromium/gpu/blink/webgraphicscontext3d_impl.h index 00bca2ba0fa..f3d03d34a74 100644 --- a/chromium/gpu/blink/webgraphicscontext3d_impl.h +++ b/chromium/gpu/blink/webgraphicscontext3d_impl.h @@ -192,6 +192,8 @@ class GPU_BLINK_EXPORT WebGraphicsContext3DImpl virtual void getIntegerv(blink::WGC3Denum pname, blink::WGC3Dint* value); + virtual void getInteger64v(blink::WGC3Denum pname, blink::WGC3Dint64* value); + virtual void getProgramiv(blink::WebGLId program, blink::WGC3Denum pname, blink::WGC3Dint* value); @@ -516,17 +518,29 @@ class GPU_BLINK_EXPORT WebGraphicsContext3DImpl blink::WGC3Denum pname, blink::WGC3Duint* params); - void copyTextureCHROMIUM(blink::WGC3Denum target, - blink::WebGLId source_id, - blink::WebGLId dest_id, - blink::WGC3Denum internal_format, - blink::WGC3Denum dest_type) override; - - void copySubTextureCHROMIUM(blink::WGC3Denum target, - blink::WebGLId source_id, - blink::WebGLId dest_id, - blink::WGC3Dint xoffset, - blink::WGC3Dint yoffset) override; + void copyTextureCHROMIUM( + blink::WGC3Denum target, + blink::WebGLId source_id, + blink::WebGLId dest_id, + blink::WGC3Denum internal_format, + blink::WGC3Denum dest_type, + blink::WGC3Dboolean unpack_flip_y, + blink::WGC3Dboolean unpack_premultiply_alpha, + blink::WGC3Dboolean unpack_unmultiply_alpha) override; + + void copySubTextureCHROMIUM( + blink::WGC3Denum target, + blink::WebGLId source_id, + blink::WebGLId dest_id, + blink::WGC3Dint xoffset, + blink::WGC3Dint yoffset, + blink::WGC3Dint x, + blink::WGC3Dint y, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Dboolean unpack_flip_y, + blink::WGC3Dboolean unpack_premultiply_alpha, + blink::WGC3Dboolean unpack_unmultiply_alpha) override; virtual void bindUniformLocationCHROMIUM(blink::WebGLId program, blink::WGC3Dint location, @@ -768,15 +782,15 @@ class GPU_BLINK_EXPORT WebGraphicsContext3DImpl blink::WGC3Dsizei uniformCount, const blink::WGC3Dchar *const*uniformNames, blink::WGC3Duint *uniformIndices); - //virtual void getUniformuiv(blink::WGC3Duint program, - // blink::WGC3Dint location, - // blink::WGC3Duint *params); - //virtual void getVertexAttribIiv(blink::WGC3Duint index, - // blink::WGC3Denum pname, - // blink::WGC3Dint *params); - //virtual void getVertexAttribIuiv(blink::WGC3Duint index, - // blink::WGC3Denum pname, - // blink::WGC3Duint *params); + virtual void getUniformuiv(blink::WGC3Duint program, + blink::WGC3Dint location, + blink::WGC3Duint *params); + virtual void getVertexAttribIiv(blink::WGC3Duint index, + blink::WGC3Denum pname, + blink::WGC3Dint *params); + virtual void getVertexAttribIuiv(blink::WGC3Duint index, + blink::WGC3Denum pname, + blink::WGC3Duint *params); virtual void invalidateFramebuffer(blink::WGC3Denum target, blink::WGC3Dsizei numAttachments, const blink::WGC3Denum* attachments); @@ -790,6 +804,10 @@ class GPU_BLINK_EXPORT WebGraphicsContext3DImpl virtual blink::WGC3Dboolean isSampler(blink::WebGLId sampler); virtual blink::WGC3Dboolean isSync(blink::WGC3Dsync sync); virtual blink::WGC3Dboolean isTransformFeedback(blink::WGC3Duint id); + virtual void* mapBufferRange(blink::WGC3Denum target, + blink::WGC3Dintptr offset, + blink::WGC3Dsizeiptr length, + blink::WGC3Dbitfield access); virtual void pauseTransformFeedback(void); //virtual void programParameteri(blink::WGC3Duint program, // blink::WGC3Denum pname, @@ -892,6 +910,7 @@ class GPU_BLINK_EXPORT WebGraphicsContext3DImpl blink::WGC3Dsizei count, blink::WGC3Dboolean transpose, const blink::WGC3Dfloat* value); + virtual blink::WGC3Dboolean unmapBuffer(blink::WGC3Denum target); virtual void vertexAttribI4i(blink::WGC3Duint index, blink::WGC3Dint x, blink::WGC3Dint y, @@ -915,6 +934,9 @@ class GPU_BLINK_EXPORT WebGraphicsContext3DImpl blink::WGC3Dbitfield flags, blink::WGC3Duint64 timeout); + virtual bool isContextLost(); + virtual blink::WGC3Denum getGraphicsResetStatusARB(); + virtual GrGLInterface* createGrGLInterface(); ::gpu::gles2::GLES2Interface* GetGLInterface() { @@ -944,7 +966,6 @@ class GPU_BLINK_EXPORT WebGraphicsContext3DImpl bool initialize_failed_; WebGraphicsContext3D::WebGraphicsContextLostCallback* context_lost_callback_; - blink::WGC3Denum context_lost_reason_; WebGraphicsContext3D::WebGraphicsErrorMessageCallback* error_message_callback_; diff --git a/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc b/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc index cc7871cb1cd..4f83fa396b6 100644 --- a/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc +++ b/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc @@ -82,7 +82,6 @@ WebGraphicsContext3DInProcessCommandBufferImpl:: bool is_offscreen, gfx::AcceleratedWidget window) : share_resources_(attributes.shareResources), - webgl_context_(attributes.webGL), is_offscreen_(is_offscreen), window_(window), context_(context.Pass()) { @@ -140,9 +139,6 @@ bool WebGraphicsContext3DInProcessCommandBufferImpl::MaybeInitializeGL() { real_gl_ = context_->GetImplementation(); setGLInterface(real_gl_); - if (real_gl_ && webgl_context_) - real_gl_->EnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation"); - initialized_ = true; return true; } @@ -158,23 +154,12 @@ void WebGraphicsContext3DInProcessCommandBufferImpl::SetLock(base::Lock* lock) { context_->SetLock(lock); } -bool WebGraphicsContext3DInProcessCommandBufferImpl::isContextLost() { - return context_lost_reason_ != GL_NO_ERROR; -} - -WGC3Denum WebGraphicsContext3DInProcessCommandBufferImpl:: - getGraphicsResetStatusARB() { - return context_lost_reason_; -} - ::gpu::ContextSupport* WebGraphicsContext3DInProcessCommandBufferImpl::GetContextSupport() { return real_gl_; } void WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost() { - // TODO(kbr): improve the precision here. - context_lost_reason_ = GL_UNKNOWN_CONTEXT_RESET_ARB; if (context_lost_callback_) { context_lost_callback_->onContextLost(); } diff --git a/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h b/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h index 32bcbbf4fc9..d463582beaf 100644 --- a/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h +++ b/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h @@ -59,12 +59,6 @@ class GPU_BLINK_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl bool InitializeOnCurrentThread(); void SetLock(base::Lock* lock); - //---------------------------------------------------------------------- - // WebGraphicsContext3D methods - virtual bool isContextLost(); - - virtual blink::WGC3Denum getGraphicsResetStatusARB(); - ::gpu::ContextSupport* GetContextSupport(); ::gpu::gles2::GLES2Implementation* GetImplementation() { @@ -89,7 +83,6 @@ class GPU_BLINK_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl ::gpu::gles2::ContextCreationAttribHelper attribs_; bool share_resources_; - bool webgl_context_; bool is_offscreen_; // Only used when not offscreen. diff --git a/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py b/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py index 8ababfe5cb0..c3bf80e8a68 100755 --- a/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -761,9 +761,6 @@ _NAMED_TYPE_INFO = { 'GL_TEXTURE_BINDING_2D', 'GL_TEXTURE_BINDING_CUBE_MAP', 'GL_UNPACK_ALIGNMENT', - 'GL_UNPACK_FLIP_Y_CHROMIUM', - 'GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM', - 'GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM', 'GL_BIND_GENERATES_RESOURCE_CHROMIUM', # we can add this because we emulate it if the driver does not support it. 'GL_VERTEX_ARRAY_BINDING_OES', @@ -1412,9 +1409,6 @@ _NAMED_TYPE_INFO = { 'valid': [ 'GL_PACK_ALIGNMENT', 'GL_UNPACK_ALIGNMENT', - 'GL_UNPACK_FLIP_Y_CHROMIUM', - 'GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM', - 'GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM', ], 'valid_es3': [ 'GL_PACK_ROW_LENGTH', @@ -1695,6 +1689,7 @@ _NAMED_TYPE_INFO = { 'GL_RG16I', 'GL_RG32UI', 'GL_RG32I', + 'GL_RGB8', 'GL_SRGB8', 'GL_RGB8_SNORM', 'GL_R11F_G11F_B10F', @@ -1707,6 +1702,7 @@ _NAMED_TYPE_INFO = { 'GL_RGB16I', 'GL_RGB32UI', 'GL_RGB32I', + 'GL_RGBA8', 'GL_SRGB8_ALPHA8', 'GL_RGBA8_SNORM', 'GL_RGB10_A2', @@ -2074,7 +2070,7 @@ _FUNCTION_INFO = { 'gen_func': 'GenTextures', # TODO(gman): remove this once client side caching works. 'client_test': False, - 'trace_level': 1, + 'trace_level': 2, }, 'BindTransformFeedback': { 'type': 'Bind', @@ -2095,12 +2091,14 @@ _FUNCTION_INFO = { 'type': 'Manual', 'data_transfer_methods': ['shm'], 'client_test': False, + 'trace_level': 2, }, 'BufferSubData': { 'type': 'Data', 'client_test': False, 'decoder_func': 'DoBufferSubData', 'data_transfer_methods': ['shm'], + 'trace_level': 2, }, 'CheckFramebufferStatus': { 'type': 'Is', @@ -2112,27 +2110,31 @@ _FUNCTION_INFO = { 'Clear': { 'decoder_func': 'DoClear', 'defer_draws': True, - 'trace_level': 1, + 'trace_level': 2, }, 'ClearBufferiv': { 'type': 'PUT', 'use_count_func': True, 'count': 4, 'unsafe': True, + 'trace_level': 2, }, 'ClearBufferuiv': { 'type': 'PUT', 'count': 4, 'unsafe': True, + 'trace_level': 2, }, 'ClearBufferfv': { 'type': 'PUT', 'use_count_func': True, 'count': 4, 'unsafe': True, + 'trace_level': 2, }, 'ClearBufferfi': { 'unsafe': True, + 'trace_level': 2, }, 'ClearColor': { 'type': 'StateSet', @@ -2154,6 +2156,7 @@ _FUNCTION_INFO = { 'GLuint timeout_0, GLuint timeout_1, GLenum* result', 'unsafe': True, 'result': ['GLenum'], + 'trace_level': 2, }, 'ColorMask': { 'type': 'StateSet', @@ -2170,7 +2173,7 @@ _FUNCTION_INFO = { 'client_test': False, 'extension': "CHROMIUM_texture_mailbox", 'chromium': True, - 'trace_level': 1, + 'trace_level': 2, }, 'CopyBufferSubData': { 'unsafe': True, @@ -2184,6 +2187,7 @@ _FUNCTION_INFO = { 'client_test': False, 'extension': "CHROMIUM_texture_mailbox", 'chromium': True, + 'trace_level': 2, }, 'GenValuebuffersCHROMIUM': { 'type': 'GENn', @@ -2255,35 +2259,42 @@ _FUNCTION_INFO = { 'CompressedTexImage2D': { 'type': 'Manual', 'data_transfer_methods': ['bucket', 'shm'], + 'trace_level': 1, }, 'CompressedTexSubImage2D': { 'type': 'Data', 'data_transfer_methods': ['bucket', 'shm'], 'decoder_func': 'DoCompressedTexSubImage2D', + 'trace_level': 1, }, 'CopyTexImage2D': { 'decoder_func': 'DoCopyTexImage2D', 'unit_test': False, 'defer_reads': True, + 'trace_level': 1, }, 'CopyTexSubImage2D': { 'decoder_func': 'DoCopyTexSubImage2D', 'defer_reads': True, + 'trace_level': 1, }, 'CompressedTexImage3D': { 'type': 'Manual', 'data_transfer_methods': ['bucket', 'shm'], 'unsafe': True, + 'trace_level': 1, }, 'CompressedTexSubImage3D': { 'type': 'Data', 'data_transfer_methods': ['bucket', 'shm'], 'decoder_func': 'DoCompressedTexSubImage3D', 'unsafe': True, + 'trace_level': 1, }, 'CopyTexSubImage3D': { 'defer_reads': True, 'unsafe': True, + 'trace_level': 1, }, 'CreateImageCHROMIUM': { 'type': 'Manual', @@ -2294,15 +2305,17 @@ _FUNCTION_INFO = { 'client_test': False, 'gen_cmd': False, 'expectation': False, - 'extension': True, + 'extension': "CHROMIUM_image", 'chromium': True, + 'trace_level': 1, }, 'DestroyImageCHROMIUM': { 'type': 'Manual', 'client_test': False, 'gen_cmd': False, - 'extension': True, + 'extension': "CHROMIUM_image", 'chromium': True, + 'trace_level': 1, }, 'CreateGpuMemoryBufferImageCHROMIUM': { 'type': 'Manual', @@ -2312,8 +2325,9 @@ _FUNCTION_INFO = { 'client_test': False, 'gen_cmd': False, 'expectation': False, - 'extension': True, + 'extension': "CHROMIUM_image", 'chromium': True, + 'trace_level': 1, }, 'CreateProgram': { 'type': 'Create', @@ -2407,6 +2421,7 @@ _FUNCTION_INFO = { 'gl_test_func': 'glDeleteFramebuffersEXT', 'resource_type': 'Framebuffer', 'resource_types': 'Framebuffers', + 'trace_level': 2, }, 'DeleteProgram': { 'type': 'Delete' }, 'DeleteRenderbuffers': { @@ -2414,6 +2429,7 @@ _FUNCTION_INFO = { 'gl_test_func': 'glDeleteRenderbuffersEXT', 'resource_type': 'Renderbuffer', 'resource_types': 'Renderbuffers', + 'trace_level': 2, }, 'DeleteSamplers': { 'type': 'DELn', @@ -2491,20 +2507,24 @@ _FUNCTION_INFO = { 'type': 'Create', 'client_test': False, 'unsafe': True, + 'trace_level': 1, }, 'Finish': { 'impl_func': False, 'client_test': False, 'decoder_func': 'DoFinish', 'defer_reads': True, + 'trace_level': 1, }, 'Flush': { 'impl_func': False, 'decoder_func': 'DoFlush', + 'trace_level': 1, }, 'FramebufferRenderbuffer': { 'decoder_func': 'DoFramebufferRenderbuffer', 'gl_test_func': 'glFramebufferRenderbufferEXT', + 'trace_level': 1, }, 'FramebufferTexture2D': { 'decoder_func': 'DoFramebufferTexture2D', @@ -2522,10 +2542,12 @@ _FUNCTION_INFO = { 'FramebufferTextureLayer': { 'decoder_func': 'DoFramebufferTextureLayer', 'unsafe': True, + 'trace_level': 1, }, 'GenerateMipmap': { 'decoder_func': 'DoGenerateMipmap', 'gl_test_func': 'glGenerateMipmapEXT', + 'trace_level': 1, }, 'GenBuffers': { 'type': 'GENn', @@ -2673,6 +2695,12 @@ _FUNCTION_INFO = { 'gl_test_func': 'glGetFramebufferAttachmentParameterivEXT', 'result': ['SizedResult<GLint>'], }, + 'GetGraphicsResetStatusKHR': { + 'extension': True, + 'client_test': False, + 'gen_cmd': False, + 'trace_level': 1, + }, 'GetInteger64v': { 'type': 'GETn', 'result': ['SizedResult<GLint64>'], @@ -2699,8 +2727,12 @@ _FUNCTION_INFO = { 'unsafe': True }, 'GetInternalformativ': { - 'type': 'GETn', + 'type': 'Custom', + 'data_transfer_methods': ['shm'], 'result': ['SizedResult<GLint>'], + 'cmd_args': + 'GLenumRenderBufferTarget target, GLenumRenderBufferFormat format, ' + 'GLenumInternalFormatParameter pname, GLint* params', 'unsafe': True, }, 'GetMaxValueInBufferCHROMIUM': { @@ -3015,12 +3047,14 @@ _FUNCTION_INFO = { 'LinkProgram': { 'decoder_func': 'DoLinkProgram', 'impl_func': False, + 'trace_level': 1, }, 'MapBufferCHROMIUM': { 'gen_cmd': False, - 'extension': True, + 'extension': "CHROMIUM_pixel_transfer_buffer_object", 'chromium': True, 'client_test': False, + 'trace_level': 1, }, 'MapBufferSubDataCHROMIUM': { 'gen_cmd': False, @@ -3028,6 +3062,7 @@ _FUNCTION_INFO = { 'chromium': True, 'client_test': False, 'pepper_interface': 'ChromiumMapSub', + 'trace_level': 1, }, 'MapTexSubImage2DCHROMIUM': { 'gen_cmd': False, @@ -3035,6 +3070,7 @@ _FUNCTION_INFO = { 'chromium': True, 'client_test': False, 'pepper_interface': 'ChromiumMapSub', + 'trace_level': 1, }, 'MapBufferRange': { 'type': 'Custom', @@ -3045,6 +3081,7 @@ _FUNCTION_INFO = { 'uint32_t result_shm_id, uint32_t result_shm_offset', 'unsafe': True, 'result': ['uint32_t'], + 'trace_level': 1, }, 'PauseTransformFeedback': { 'unsafe': True, @@ -3084,6 +3121,7 @@ _FUNCTION_INFO = { 'decoder_func': 'DoRenderbufferStorage', 'gl_test_func': 'glRenderbufferStorageEXT', 'expectation': False, + 'trace_level': 1, }, 'RenderbufferStorageMultisampleCHROMIUM': { 'cmd_comment': @@ -3095,6 +3133,7 @@ _FUNCTION_INFO = { 'extension_flag': 'chromium_framebuffer_multisample', 'pepper_interface': 'FramebufferMultisample', 'pepper_name': 'RenderbufferStorageMultisampleEXT', + 'trace_level': 1, }, 'RenderbufferStorageMultisampleEXT': { 'cmd_comment': @@ -3104,9 +3143,11 @@ _FUNCTION_INFO = { 'expectation': False, 'unit_test': False, 'extension_flag': 'multisampled_render_to_texture', + 'trace_level': 1, }, 'ReadBuffer': { 'unsafe': True, + 'trace_level': 1, }, 'ReadPixels': { 'cmd_comment': @@ -3125,6 +3166,7 @@ _FUNCTION_INFO = { 'GLboolean async', 'result': ['uint32_t'], 'defer_reads': True, + 'trace_level': 1, }, 'ReleaseShaderCompiler': { 'decoder_func': 'DoReleaseShaderCompiler', @@ -3212,12 +3254,14 @@ _FUNCTION_INFO = { 'type': 'Manual', 'data_transfer_methods': ['shm'], 'client_test': False, + 'trace_level': 2, }, 'TexImage3D': { 'type': 'Manual', 'data_transfer_methods': ['shm'], 'client_test': False, 'unsafe': True, + 'trace_level': 2, }, 'TexParameterf': { 'decoder_func': 'DoTexParameterf', @@ -3249,11 +3293,13 @@ _FUNCTION_INFO = { }, 'TexStorage3D': { 'unsafe': True, + 'trace_level': 2, }, 'TexSubImage2D': { 'type': 'Manual', 'data_transfer_methods': ['shm'], 'client_test': False, + 'trace_level': 2, 'cmd_args': 'GLenumTextureTarget target, GLint level, ' 'GLint xoffset, GLint yoffset, ' 'GLsizei width, GLsizei height, ' @@ -3264,6 +3310,7 @@ _FUNCTION_INFO = { 'type': 'Manual', 'data_transfer_methods': ['shm'], 'client_test': False, + 'trace_level': 2, 'cmd_args': 'GLenumTextureTarget target, GLint level, ' 'GLint xoffset, GLint yoffset, GLint zoffset, ' 'GLsizei width, GLsizei height, GLsizei depth, ' @@ -3420,9 +3467,10 @@ _FUNCTION_INFO = { }, 'UnmapBufferCHROMIUM': { 'gen_cmd': False, - 'extension': True, + 'extension': "CHROMIUM_pixel_transfer_buffer_object", 'chromium': True, 'client_test': False, + 'trace_level': 1, }, 'UnmapBufferSubDataCHROMIUM': { 'gen_cmd': False, @@ -3430,10 +3478,12 @@ _FUNCTION_INFO = { 'chromium': True, 'client_test': False, 'pepper_interface': 'ChromiumMapSub', + 'trace_level': 1, }, 'UnmapBuffer': { 'type': 'Custom', 'unsafe': True, + 'trace_level': 1, }, 'UnmapTexSubImage2DCHROMIUM': { 'gen_cmd': False, @@ -3441,6 +3491,7 @@ _FUNCTION_INFO = { 'chromium': True, 'client_test': False, 'pepper_interface': 'ChromiumMapSub', + 'trace_level': 1, }, 'UseProgram': { 'type': 'Bind', @@ -3513,6 +3564,7 @@ _FUNCTION_INFO = { 'impl_func': False, 'client_test': False, 'unsafe': True, + 'trace_level': 1, }, 'Scissor': { 'type': 'StateSet', @@ -3527,6 +3579,7 @@ _FUNCTION_INFO = { 'unit_test': False, 'extension': True, 'chromium': True, + 'trace_level': 1, }, 'GetRequestableExtensionsCHROMIUM': { 'type': 'Custom', @@ -3555,22 +3608,32 @@ _FUNCTION_INFO = { 'gen_cmd': False, 'extension': True, 'chromium': True, + 'trace_level': 1, }, 'TexImageIOSurface2DCHROMIUM': { 'decoder_func': 'DoTexImageIOSurface2DCHROMIUM', 'unit_test': False, 'extension': True, 'chromium': True, + 'trace_level': 1, }, 'CopyTextureCHROMIUM': { 'decoder_func': 'DoCopyTextureCHROMIUM', 'unit_test': False, - 'extension': True, + 'extension': "CHROMIUM_copy_texture", 'chromium': True, + 'trace_level': 2, }, 'CopySubTextureCHROMIUM': { 'decoder_func': 'DoCopySubTextureCHROMIUM', 'unit_test': False, + 'extension': "CHROMIUM_copy_texture", + 'chromium': True, + 'trace_level': 2, + }, + 'CompressedCopyTextureCHROMIUM': { + 'decoder_func': 'DoCompressedCopyTextureCHROMIUM', + 'unit_test': False, 'extension': True, 'chromium': True, }, @@ -3578,6 +3641,7 @@ _FUNCTION_INFO = { 'unit_test': False, 'extension': True, 'decoder_func': 'DoTexStorage2DEXT', + 'trace_level': 2, }, 'DrawArraysInstancedANGLE': { 'type': 'Manual', @@ -3587,6 +3651,7 @@ _FUNCTION_INFO = { 'unit_test': False, 'pepper_interface': 'InstancedArrays', 'defer_draws': True, + 'trace_level': 2, }, 'DrawBuffersEXT': { 'type': 'PUTn', @@ -3598,6 +3663,7 @@ _FUNCTION_INFO = { # work without. 'extension': True, 'pepper_interface': 'DrawBuffers', + 'trace_level': 2, }, 'DrawElementsInstancedANGLE': { 'type': 'Manual', @@ -3608,6 +3674,7 @@ _FUNCTION_INFO = { 'client_test': False, 'pepper_interface': 'InstancedArrays', 'defer_draws': True, + 'trace_level': 2, }, 'VertexAttribDivisorANGLE': { 'type': 'Manual', @@ -3663,6 +3730,13 @@ _FUNCTION_INFO = { 'EndTransformFeedback': { 'unsafe': True, }, + 'FlushDriverCachesCHROMIUM': { + 'decoder_func': 'DoFlushDriverCachesCHROMIUM', + 'unit_test': False, + 'extension': True, + 'chromium': True, + 'trace_level': 1, + }, 'GetQueryivEXT': { 'gen_cmd': False, 'client_test': False, @@ -3677,6 +3751,12 @@ _FUNCTION_INFO = { 'pepper_interface': 'Query', 'extension': "occlusion_query_EXT", }, + 'GetQueryObjectui64vEXT': { + 'gen_cmd': False, + 'client_test': False, + 'gl_test_func': 'glGetQueryObjectui64v', + 'extension': "disjoint_timer_query_EXT", + }, 'BindUniformLocationCHROMIUM': { 'type': 'GLchar', 'extension': True, @@ -3743,13 +3823,13 @@ _FUNCTION_INFO = { 'BindTexImage2DCHROMIUM': { 'decoder_func': 'DoBindTexImage2DCHROMIUM', 'unit_test': False, - 'extension': True, + 'extension': "CHROMIUM_image", 'chromium': True, }, 'ReleaseTexImage2DCHROMIUM': { 'decoder_func': 'DoReleaseTexImage2DCHROMIUM', 'unit_test': False, - 'extension': True, + 'extension': "CHROMIUM_image", 'chromium': True, }, 'ShallowFinishCHROMIUM': { @@ -3803,6 +3883,7 @@ _FUNCTION_INFO = { 'void* sync_data', 'extension': True, 'chromium': True, + 'trace_level': 2, }, 'AsyncTexSubImage2DCHROMIUM': { 'type': 'Manual', @@ -3817,18 +3898,21 @@ _FUNCTION_INFO = { 'void* sync_data', 'extension': True, 'chromium': True, + 'trace_level': 2, }, 'WaitAsyncTexImage2DCHROMIUM': { 'type': 'Manual', 'client_test': False, 'extension': True, 'chromium': True, + 'trace_level': 1, }, 'WaitAllAsyncTexImage2DCHROMIUM': { 'type': 'Manual', 'client_test': False, 'extension': True, 'chromium': True, + 'trace_level': 1, }, 'DiscardFramebufferEXT': { 'type': 'PUTn', @@ -3837,18 +3921,21 @@ _FUNCTION_INFO = { 'unit_test': False, 'client_test': False, 'extension_flag': 'ext_discard_framebuffer', + 'trace_level': 2, }, 'LoseContextCHROMIUM': { 'decoder_func': 'DoLoseContextCHROMIUM', 'unit_test': False, 'extension': True, 'chromium': True, + 'trace_level': 1, }, 'InsertSyncPointCHROMIUM': { 'type': 'HandWritten', 'impl_func': False, 'extension': "CHROMIUM_sync_point", 'chromium': True, + 'trace_level': 1, }, 'WaitSyncPointCHROMIUM': { 'type': 'Custom', @@ -3862,6 +3949,7 @@ _FUNCTION_INFO = { 'impl_func': True, 'extension': True, 'chromium': True, + 'trace_level': 2, }, 'ScheduleOverlayPlaneCHROMIUM': { 'type': 'Custom', @@ -3898,17 +3986,14 @@ def Grouper(n, iterable, fillvalue=None): def SplitWords(input_string): - """Transforms a input_string into a list of lower-case components. - - Args: - input_string: the input string. + """Split by '_' if found, otherwise split at uppercase/numeric chars. - Returns: - a list of lower-case words. + Will split "some_TEXT" into ["some", "TEXT"], "CamelCase" into ["Camel", + "Case"], and "Vector3" into ["Vector", "3"]. """ if input_string.find('_') > -1: - # 'some_TEXT_' -> 'some text' - return input_string.replace('_', ' ').strip().lower().split() + # 'some_TEXT_' -> 'some TEXT' + return input_string.replace('_', ' ').strip().split() else: if re.search('[A-Z]', input_string) and re.search('[a-z]', input_string): # mixed case. @@ -3917,25 +4002,12 @@ def SplitWords(input_string): input_string = re.sub('([A-Z])', r' \1', input_string).strip() # 'Vector3' -> 'Vector 3' input_string = re.sub('([^0-9])([0-9])', r'\1 \2', input_string) - return input_string.lower().split() - - -def Lower(words): - """Makes a lower-case identifier from words. - - Args: - words: a list of lower-case words. - - Returns: - the lower-case identifier. - """ - return '_'.join(words) - + return input_string.split() def ToUnderscore(input_string): """converts CamelCase to camel_case.""" words = SplitWords(input_string) - return Lower(words) + return '_'.join([word.lower() for word in words]) def CachedStateName(item): if item.get('cached', False): @@ -4577,7 +4649,9 @@ TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) { func.MakeTypedOriginalArgString(""))) extensions = ["CHROMIUM_sync_point", "CHROMIUM_texture_mailbox", "CHROMIUM_sub_image", "CHROMIUM_miscellaneous", - "occlusion_query_EXT"] + "occlusion_query_EXT", "CHROMIUM_image", + "CHROMIUM_copy_texture", + "CHROMIUM_pixel_transfer_buffer_object"] if func.IsCoreGLFunction() or func.GetInfo("extension") in extensions: file.Write("MojoGLES2MakeCurrent(context_);"); func_return = "gl" + func.original_name + "(" + \ @@ -6329,11 +6403,9 @@ class GETnHandler(TypeHandler): } """ else: - code = """ GLenum error = glGetError(); + code = """ GLenum error = LOCAL_PEEK_GL_ERROR("%(func_name)s"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "%(func_name)s", ""); } return error::kNoError; } @@ -10416,7 +10488,10 @@ class MojoGLES2Impl : public gpu::gles2::GLES2Interface { #include "mojo/gpu/mojo_gles2_impl_autogen.h" #include "base/logging.h" +#include "third_party/mojo/src/mojo/public/c/gles2/chromium_copy_texture.h" +#include "third_party/mojo/src/mojo/public/c/gles2/chromium_image.h" #include "third_party/mojo/src/mojo/public/c/gles2/chromium_miscellaneous.h" +#include "third_party/mojo/src/mojo/public/c/gles2/chromium_pixel_transfer_buffer_object.h" #include "third_party/mojo/src/mojo/public/c/gles2/chromium_sub_image.h" #include "third_party/mojo/src/mojo/public/c/gles2/chromium_sync_point.h" #include "third_party/mojo/src/mojo/public/c/gles2/chromium_texture_mailbox.h" @@ -11020,6 +11095,15 @@ def main(argv): gen.WriteMojoGLCallVisitorForExtension( mojo_gles2_prefix + "_occlusion_query_ext_autogen.h", "occlusion_query_EXT") + gen.WriteMojoGLCallVisitorForExtension( + mojo_gles2_prefix + "_chromium_image_autogen.h", + "CHROMIUM_image") + gen.WriteMojoGLCallVisitorForExtension( + mojo_gles2_prefix + "_chromium_copy_texture_autogen.h", + "CHROMIUM_copy_texture") + gen.WriteMojoGLCallVisitorForExtension( + mojo_gles2_prefix + "_chromium_pixel_transfer_buffer_object_autogen.h", + "CHROMIUM_pixel_transfer_buffer_object") Format(gen.generated_cpp_filenames) diff --git a/chromium/gpu/command_buffer/client/buffer_tracker.cc b/chromium/gpu/command_buffer/client/buffer_tracker.cc index 5887e52a71c..63adba713bb 100644 --- a/chromium/gpu/command_buffer/client/buffer_tracker.cc +++ b/chromium/gpu/command_buffer/client/buffer_tracker.cc @@ -4,7 +4,7 @@ #include "gpu/command_buffer/client/buffer_tracker.h" -#include "gpu/command_buffer/client/cmd_buffer_helper.h" +#include <utility> #include "gpu/command_buffer/client/mapped_memory.h" namespace gpu { diff --git a/chromium/gpu/command_buffer/client/buffer_tracker.h b/chromium/gpu/command_buffer/client/buffer_tracker.h index 33bd94b0456..b092b8a6148 100644 --- a/chromium/gpu/command_buffer/client/buffer_tracker.h +++ b/chromium/gpu/command_buffer/client/buffer_tracker.h @@ -5,16 +5,14 @@ #ifndef GPU_COMMAND_BUFFER_CLIENT_BUFFER_TRACKER_H_ #define GPU_COMMAND_BUFFER_CLIENT_BUFFER_TRACKER_H_ -#include <GLES2/gl2.h> - -#include <queue> +#include "base/basictypes.h" #include "base/containers/hash_tables.h" +#include "base/macros.h" #include "gles2_impl_export.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" namespace gpu { -class CommandBufferHelper; class MappedMemoryManager; namespace gles2 { diff --git a/chromium/gpu/command_buffer/client/buffer_tracker_unittest.cc b/chromium/gpu/command_buffer/client/buffer_tracker_unittest.cc index a9283961340..e8d4d818308 100644 --- a/chromium/gpu/command_buffer/client/buffer_tracker_unittest.cc +++ b/chromium/gpu/command_buffer/client/buffer_tracker_unittest.cc @@ -6,6 +6,7 @@ #include "gpu/command_buffer/client/buffer_tracker.h" +#include <GLES2/gl2.h> #include <GLES2/gl2ext.h> #include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/client/client_test_helper.h" diff --git a/chromium/gpu/command_buffer/client/client_context_state.cc b/chromium/gpu/command_buffer/client/client_context_state.cc index 9f4fbad3c61..df81f30a264 100644 --- a/chromium/gpu/command_buffer/client/client_context_state.cc +++ b/chromium/gpu/command_buffer/client/client_context_state.cc @@ -4,8 +4,6 @@ #include "gpu/command_buffer/client/client_context_state.h" -#include "base/logging.h" - namespace gpu { namespace gles2 { @@ -22,5 +20,3 @@ ClientContextState::~ClientContextState() { } // namespace gles2 } // namespace gpu - - diff --git a/chromium/gpu/command_buffer/client/client_context_state.h b/chromium/gpu/command_buffer/client/client_context_state.h index a92c04a4385..45cd14b40a8 100644 --- a/chromium/gpu/command_buffer/client/client_context_state.h +++ b/chromium/gpu/command_buffer/client/client_context_state.h @@ -8,7 +8,6 @@ #define GPU_COMMAND_BUFFER_CLIENT_CLIENT_CONTEXT_STATE_H_ #include <GLES3/gl3.h> -#include <vector> #include "gles2_impl_export.h" namespace gpu { @@ -36,4 +35,3 @@ struct GLES2_IMPL_EXPORT ClientContextState { } // namespace gpu #endif // GPU_COMMAND_BUFFER_CLIENT_CLIENT_CONTEXT_STATE_H_ - diff --git a/chromium/gpu/command_buffer/client/client_test_helper.h b/chromium/gpu/command_buffer/client/client_test_helper.h index c155bf11717..07234c70ccb 100644 --- a/chromium/gpu/command_buffer/client/client_test_helper.h +++ b/chromium/gpu/command_buffer/client/client_test_helper.h @@ -23,7 +23,7 @@ class CommandBufferHelper; class MockCommandBufferBase : public CommandBufferServiceBase { public: static const int32 kTransferBufferBaseId = 0x123; - static const int32 kMaxTransferBuffers = 6; + static const int32 kMaxTransferBuffers = 32; MockCommandBufferBase(); ~MockCommandBufferBase() override; @@ -111,6 +111,7 @@ class MockClientGpuControl : public GpuControl { MOCK_METHOD1(SetSurfaceVisible, void(bool visible)); MOCK_METHOD1(CreateStreamTexture, uint32(uint32)); MOCK_METHOD1(SetLock, void(base::Lock*)); + MOCK_METHOD0(IsGpuChannelLost, bool()); private: DISALLOW_COPY_AND_ASSIGN(MockClientGpuControl); diff --git a/chromium/gpu/command_buffer/client/cmd_buffer_helper.cc b/chromium/gpu/command_buffer/client/cmd_buffer_helper.cc index 038ba41fda0..2b88cc1e7b1 100644 --- a/chromium/gpu/command_buffer/client/cmd_buffer_helper.cc +++ b/chromium/gpu/command_buffer/client/cmd_buffer_helper.cc @@ -6,9 +6,12 @@ #include "gpu/command_buffer/client/cmd_buffer_helper.h" +#include <algorithm> #include "base/logging.h" #include "base/time/time.h" +#include "gpu/command_buffer/common/buffer.h" #include "gpu/command_buffer/common/command_buffer.h" +#include "gpu/command_buffer/common/constants.h" #include "gpu/command_buffer/common/trace_event.h" namespace gpu { diff --git a/chromium/gpu/command_buffer/client/cmd_buffer_helper.h b/chromium/gpu/command_buffer/client/cmd_buffer_helper.h index 3f7fba78269..b5febb3eb8b 100644 --- a/chromium/gpu/command_buffer/client/cmd_buffer_helper.h +++ b/chromium/gpu/command_buffer/client/cmd_buffer_helper.h @@ -8,16 +8,21 @@ #define GPU_COMMAND_BUFFER_CLIENT_CMD_BUFFER_HELPER_H_ #include <string.h> -#include <time.h> +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" #include "base/time/time.h" +#include "build/build_config.h" #include "gpu/command_buffer/common/cmd_buffer_common.h" #include "gpu/command_buffer/common/command_buffer.h" -#include "gpu/command_buffer/common/constants.h" #include "gpu/gpu_export.h" namespace gpu { +class Buffer; + #if !defined(OS_ANDROID) #define CMD_HELPER_PERIODIC_FLUSH_CHECK const int kCommandsPerFlushCheck = 100; @@ -295,6 +300,7 @@ class GPU_EXPORT CommandBufferHelper { void ClearUsable() { usable_ = false; + context_lost_ = true; CalcImmediateEntries(0); } diff --git a/chromium/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/chromium/gpu/command_buffer/client/cmd_buffer_helper_test.cc index 6348abb3266..859c99553b9 100644 --- a/chromium/gpu/command_buffer/client/cmd_buffer_helper_test.cc +++ b/chromium/gpu/command_buffer/client/cmd_buffer_helper_test.cc @@ -89,7 +89,7 @@ class CommandBufferHelperTest : public testing::Test { { TransferBufferManager* manager = new TransferBufferManager(); - transfer_buffer_manager_.reset(manager); + transfer_buffer_manager_ = manager; EXPECT_TRUE(manager->Initialize()); } command_buffer_.reset( @@ -252,7 +252,7 @@ class CommandBufferHelperTest : public testing::Test { CommandBufferOffset get_helper_put() { return helper_->put_; } scoped_ptr<AsyncAPIMock> api_mock_; - scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; + scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; scoped_ptr<CommandBufferServiceLocked> command_buffer_; scoped_ptr<GpuScheduler> gpu_scheduler_; scoped_ptr<CommandBufferHelper> helper_; diff --git a/chromium/gpu/command_buffer/client/context_support.h b/chromium/gpu/command_buffer/client/context_support.h index 6c5b23f0d1e..4a6f5868d5c 100644 --- a/chromium/gpu/command_buffer/client/context_support.h +++ b/chromium/gpu/command_buffer/client/context_support.h @@ -25,6 +25,12 @@ class ContextSupport { // Clients aren't expected to draw to an invisible surface. virtual void SetSurfaceVisible(bool visible) = 0; + // Indicates whether the context should aggressively free allocated resources. + // If set to true, the context will purge all temporary resources when + // flushed. + virtual void SetAggressivelyFreeResources( + bool aggressively_free_resources) = 0; + virtual void Swap() = 0; virtual void PartialSwapBuffers(const gfx::Rect& sub_buffer) = 0; diff --git a/chromium/gpu/command_buffer/client/fenced_allocator_test.cc b/chromium/gpu/command_buffer/client/fenced_allocator_test.cc index 6b9f00f41a3..0b40a42d949 100644 --- a/chromium/gpu/command_buffer/client/fenced_allocator_test.cc +++ b/chromium/gpu/command_buffer/client/fenced_allocator_test.cc @@ -45,7 +45,7 @@ class BaseFencedAllocatorTest : public testing::Test { { TransferBufferManager* manager = new TransferBufferManager(); - transfer_buffer_manager_.reset(manager); + transfer_buffer_manager_ = manager; EXPECT_TRUE(manager->Initialize()); } command_buffer_.reset( @@ -70,7 +70,7 @@ class BaseFencedAllocatorTest : public testing::Test { } scoped_ptr<AsyncAPIMock> api_mock_; - scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; + scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; scoped_ptr<CommandBufferService> command_buffer_; scoped_ptr<GpuScheduler> gpu_scheduler_; scoped_ptr<CommandBufferHelper> helper_; diff --git a/chromium/gpu/command_buffer/client/gl_in_process_context.cc b/chromium/gpu/command_buffer/client/gl_in_process_context.cc index 5d8049bceee..3b32c4815ec 100644 --- a/chromium/gpu/command_buffer/client/gl_in_process_context.cc +++ b/chromium/gpu/command_buffer/client/gl_in_process_context.cc @@ -22,6 +22,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" +#include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/command_buffer/client/transfer_buffer.h" #include "gpu/command_buffer/common/command_buffer.h" diff --git a/chromium/gpu/command_buffer/client/gles2_c_lib.cc b/chromium/gpu/command_buffer/client/gles2_c_lib.cc index fbe7b55eab1..2d07755ddde 100644 --- a/chromium/gpu/command_buffer/client/gles2_c_lib.cc +++ b/chromium/gpu/command_buffer/client/gles2_c_lib.cc @@ -4,15 +4,15 @@ // These functions emulate GLES2 over command buffers for C. -#include <assert.h> -#include <stdlib.h> #include "gpu/command_buffer/client/gles2_lib.h" #ifndef GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES #endif + #include <GLES2/gl2ext.h> #include <GLES2/gl2extchromium.h> +#include <stddef.h> extern "C" { // Include the auto-generated part of this file. We split this because it means @@ -20,5 +20,3 @@ extern "C" { // instead of having to edit some template or the code generator. #include "gpu/command_buffer/client/gles2_c_lib_autogen.h" } // extern "C" - - diff --git a/chromium/gpu/command_buffer/client/gles2_c_lib_autogen.h b/chromium/gpu/command_buffer/client/gles2_c_lib_autogen.h index 58881b7d77a..8e59df28865 100644 --- a/chromium/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -1070,6 +1070,9 @@ void GLES2GetQueryivEXT(GLenum target, GLenum pname, GLint* params) { void GLES2GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* params) { gles2::GetGLContext()->GetQueryObjectuivEXT(id, pname, params); } +void GLES2GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64* params) { + gles2::GetGLContext()->GetQueryObjectui64vEXT(id, pname, params); +} void GLES2InsertEventMarkerEXT(GLsizei length, const GLchar* marker) { gles2::GetGLContext()->InsertEventMarkerEXT(length, marker); } @@ -1223,17 +1226,35 @@ void GLES2CopyTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id, GLint internalformat, - GLenum dest_type) { - gles2::GetGLContext()->CopyTextureCHROMIUM(target, source_id, dest_id, - internalformat, dest_type); + GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) { + gles2::GetGLContext()->CopyTextureCHROMIUM( + target, source_id, dest_id, internalformat, dest_type, unpack_flip_y, + unpack_premultiply_alpha, unpack_unmultiply_alpha); } void GLES2CopySubTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id, GLint xoffset, - GLint yoffset) { - gles2::GetGLContext()->CopySubTextureCHROMIUM(target, source_id, dest_id, - xoffset, yoffset); + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) { + gles2::GetGLContext()->CopySubTextureCHROMIUM( + target, source_id, dest_id, xoffset, yoffset, x, y, width, height, + unpack_flip_y, unpack_premultiply_alpha, unpack_unmultiply_alpha); +} +void GLES2CompressedCopyTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id) { + gles2::GetGLContext()->CompressedCopyTextureCHROMIUM(target, source_id, + dest_id); } void GLES2DrawArraysInstancedANGLE(GLenum mode, GLint first, @@ -1383,12 +1404,18 @@ void GLES2ScheduleOverlayPlaneCHROMIUM(GLint plane_z_order, void GLES2SwapInterval(GLint interval) { gles2::GetGLContext()->SwapInterval(interval); } +void GLES2FlushDriverCachesCHROMIUM() { + gles2::GetGLContext()->FlushDriverCachesCHROMIUM(); +} void GLES2MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) { gles2::GetGLContext()->MatrixLoadfCHROMIUM(matrixMode, m); } void GLES2MatrixLoadIdentityCHROMIUM(GLenum matrixMode) { gles2::GetGLContext()->MatrixLoadIdentityCHROMIUM(matrixMode); } +GLenum GLES2GetGraphicsResetStatusKHR() { + return gles2::GetGLContext()->GetGraphicsResetStatusKHR(); +} void GLES2BlendBarrierKHR() { gles2::GetGLContext()->BlendBarrierKHR(); } @@ -2337,6 +2364,10 @@ extern const NameToFunc g_gles2_function_table[] = { reinterpret_cast<GLES2FunctionPointer>(glGetQueryObjectuivEXT), }, { + "glGetQueryObjectui64vEXT", + reinterpret_cast<GLES2FunctionPointer>(glGetQueryObjectui64vEXT), + }, + { "glInsertEventMarkerEXT", reinterpret_cast<GLES2FunctionPointer>(glInsertEventMarkerEXT), }, @@ -2480,6 +2511,10 @@ extern const NameToFunc g_gles2_function_table[] = { reinterpret_cast<GLES2FunctionPointer>(glCopySubTextureCHROMIUM), }, { + "glCompressedCopyTextureCHROMIUM", + reinterpret_cast<GLES2FunctionPointer>(glCompressedCopyTextureCHROMIUM), + }, + { "glDrawArraysInstancedANGLE", reinterpret_cast<GLES2FunctionPointer>(glDrawArraysInstancedANGLE), }, @@ -2608,6 +2643,10 @@ extern const NameToFunc g_gles2_function_table[] = { reinterpret_cast<GLES2FunctionPointer>(glSwapInterval), }, { + "glFlushDriverCachesCHROMIUM", + reinterpret_cast<GLES2FunctionPointer>(glFlushDriverCachesCHROMIUM), + }, + { "glMatrixLoadfCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(glMatrixLoadfCHROMIUM), }, @@ -2616,6 +2655,10 @@ extern const NameToFunc g_gles2_function_table[] = { reinterpret_cast<GLES2FunctionPointer>(glMatrixLoadIdentityCHROMIUM), }, { + "glGetGraphicsResetStatusKHR", + reinterpret_cast<GLES2FunctionPointer>(glGetGraphicsResetStatusKHR), + }, + { "glBlendBarrierKHR", reinterpret_cast<GLES2FunctionPointer>(glBlendBarrierKHR), }, diff --git a/chromium/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/chromium/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 838cec68f3b..27b98d3d561 100644 --- a/chromium/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -943,13 +943,12 @@ void GetIntegerv(GLenum pname, void GetInternalformativ(GLenum target, GLenum format, GLenum pname, - GLsizei bufSize, uint32_t params_shm_id, uint32_t params_shm_offset) { gles2::cmds::GetInternalformativ* c = GetCmdSpace<gles2::cmds::GetInternalformativ>(); if (c) { - c->Init(target, format, pname, bufSize, params_shm_id, params_shm_offset); + c->Init(target, format, pname, params_shm_id, params_shm_offset); } } @@ -2465,11 +2464,15 @@ void CopyTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id, GLint internalformat, - GLenum dest_type) { + GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) { gles2::cmds::CopyTextureCHROMIUM* c = GetCmdSpace<gles2::cmds::CopyTextureCHROMIUM>(); if (c) { - c->Init(target, source_id, dest_id, internalformat, dest_type); + c->Init(target, source_id, dest_id, internalformat, dest_type, + unpack_flip_y, unpack_premultiply_alpha, unpack_unmultiply_alpha); } } @@ -2477,11 +2480,29 @@ void CopySubTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id, GLint xoffset, - GLint yoffset) { + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) { gles2::cmds::CopySubTextureCHROMIUM* c = GetCmdSpace<gles2::cmds::CopySubTextureCHROMIUM>(); if (c) { - c->Init(target, source_id, dest_id, xoffset, yoffset); + c->Init(target, source_id, dest_id, xoffset, yoffset, x, y, width, height, + unpack_flip_y, unpack_premultiply_alpha, unpack_unmultiply_alpha); + } +} + +void CompressedCopyTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id) { + gles2::cmds::CompressedCopyTextureCHROMIUM* c = + GetCmdSpace<gles2::cmds::CompressedCopyTextureCHROMIUM>(); + if (c) { + c->Init(target, source_id, dest_id); } } @@ -2793,6 +2814,14 @@ void SwapInterval(GLint interval) { } } +void FlushDriverCachesCHROMIUM() { + gles2::cmds::FlushDriverCachesCHROMIUM* c = + GetCmdSpace<gles2::cmds::FlushDriverCachesCHROMIUM>(); + if (c) { + c->Init(); + } +} + void MatrixLoadfCHROMIUMImmediate(GLenum matrixMode, const GLfloat* m) { const uint32_t size = gles2::cmds::MatrixLoadfCHROMIUMImmediate::ComputeSize(); diff --git a/chromium/gpu/command_buffer/client/gles2_implementation.cc b/chromium/gpu/command_buffer/client/gles2_implementation.cc index 34fbd502067..ae721bde5b8 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation.cc +++ b/chromium/gpu/command_buffer/client/gles2_implementation.cc @@ -6,26 +6,25 @@ #include "gpu/command_buffer/client/gles2_implementation.h" +#include <GLES2/gl2.h> #include <GLES2/gl2ext.h> #include <GLES2/gl2extchromium.h> #include <GLES3/gl3.h> #include <algorithm> -#include <limits> #include <map> -#include <queue> #include <set> #include <sstream> #include <string> -#include "base/bind.h" #include "base/compiler_specific.h" -#include "base/numerics/safe_math.h" #include "gpu/command_buffer/client/buffer_tracker.h" +#include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/gpu_control.h" #include "gpu/command_buffer/client/program_info_manager.h" #include "gpu/command_buffer/client/query_tracker.h" #include "gpu/command_buffer/client/transfer_buffer.h" #include "gpu/command_buffer/client/vertex_array_object_manager.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/common/id_allocator.h" #include "gpu/command_buffer/common/trace_event.h" #if defined(GPU_CLIENT_DEBUG) @@ -78,7 +77,6 @@ GLES2Implementation::GLES2Implementation( chromium_framebuffer_multisample_(kUnknownExtensionStatus), pack_alignment_(4), unpack_alignment_(4), - unpack_flip_y_(false), unpack_row_length_(0), unpack_image_height_(0), unpack_skip_rows_(0), @@ -91,7 +89,13 @@ GLES2Implementation::GLES2Implementation( bound_renderbuffer_(0), bound_valuebuffer_(0), current_program_(0), - bound_array_buffer_id_(0), + bound_array_buffer_(0), + bound_copy_read_buffer_(0), + bound_copy_write_buffer_(0), + bound_pixel_pack_buffer_(0), + bound_pixel_unpack_buffer_(0), + bound_transform_feedback_buffer_(0), + bound_uniform_buffer_(0), bound_pixel_pack_transfer_buffer_id_(0), bound_pixel_unpack_transfer_buffer_id_(0), async_upload_token_(0), @@ -107,6 +111,7 @@ GLES2Implementation::GLES2Implementation( current_trace_stack_(0), gpu_control_(gpu_control), capabilities_(gpu_control->GetCapabilities()), + aggressively_free_resources_(false), weak_ptr_factory_(this) { DCHECK(helper); DCHECK(transfer_buffer); @@ -311,11 +316,26 @@ void GLES2Implementation::SignalQuery(uint32 query, void GLES2Implementation::SetSurfaceVisible(bool visible) { TRACE_EVENT1( "gpu", "GLES2Implementation::SetSurfaceVisible", "visible", visible); - // TODO(piman): This probably should be ShallowFlushCHROMIUM(). - Flush(); + ShallowFlushCHROMIUM(); gpu_control_->SetSurfaceVisible(visible); - if (!visible) - FreeEverything(); +} + +void GLES2Implementation::SetAggressivelyFreeResources( + bool aggressively_free_resources) { + TRACE_EVENT1("gpu", "GLES2Implementation::SetAggressivelyFreeResources", + "aggressively_free_resources", aggressively_free_resources); + aggressively_free_resources_ = aggressively_free_resources; + + if (aggressively_free_resources_ && helper_->HaveRingBuffer()) { + // Ensure that we clean up as much cache memory as possible and fully flush. + FlushDriverCachesCHROMIUM(); + + // Flush will delete transfer buffer resources if + // |aggressively_free_resources_| is true. + Flush(); + } else { + ShallowFlushCHROMIUM(); + } } void GLES2Implementation::WaitForCmd() { @@ -621,7 +641,7 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { *params = active_texture_unit_ + GL_TEXTURE0; return true; case GL_ARRAY_BUFFER_BINDING: - *params = bound_array_buffer_id_; + *params = bound_array_buffer_; return true; case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = @@ -693,6 +713,13 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { return true; } break; + // TODO(dyen): Also support GL_GPU_DISJOINT_EXT. + case GL_TIMESTAMP_EXT: + // We convert all GPU timestamps to CPU time. + *params = base::saturated_cast<GLint>( + (base::TraceTicks::Now() - base::TraceTicks()).InMicroseconds() + * base::Time::kNanosecondsPerMicrosecond); + return true; // Non-cached parameters. case GL_ALIASED_LINE_WIDTH_RANGE: @@ -773,6 +800,12 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { // ES3 parameters. switch (pname) { + case GL_COPY_READ_BUFFER_BINDING: + *params = bound_copy_read_buffer_; + return true; + case GL_COPY_WRITE_BUFFER_BINDING: + *params = bound_copy_write_buffer_; + return true; case GL_MAJOR_VERSION: *params = capabilities_.major_version; return true; @@ -786,19 +819,21 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { *params = capabilities_.max_color_attachments; return true; case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: - *params = capabilities_.max_combined_fragment_uniform_components; + *params = static_cast<GLint>( + capabilities_.max_combined_fragment_uniform_components); return true; case GL_MAX_COMBINED_UNIFORM_BLOCKS: *params = capabilities_.max_combined_uniform_blocks; return true; case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: - *params = capabilities_.max_combined_vertex_uniform_components; + *params = static_cast<GLint>( + capabilities_.max_combined_vertex_uniform_components); return true; case GL_MAX_DRAW_BUFFERS: *params = capabilities_.max_draw_buffers; return true; case GL_MAX_ELEMENT_INDEX: - *params = capabilities_.max_element_index; + *params = static_cast<GLint>(capabilities_.max_element_index); return true; case GL_MAX_ELEMENTS_INDICES: *params = capabilities_.max_elements_indices; @@ -822,7 +857,10 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { *params = capabilities_.max_samples; return true; case GL_MAX_SERVER_WAIT_TIMEOUT: - *params = capabilities_.max_server_wait_timeout; + *params = static_cast<GLint>(capabilities_.max_server_wait_timeout); + return true; + case GL_MAX_TEXTURE_LOD_BIAS: + *params = static_cast<GLint>(capabilities_.max_texture_lod_bias); return true; case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: *params = capabilities_.max_transform_feedback_interleaved_components; @@ -834,7 +872,7 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { *params = capabilities_.max_transform_feedback_separate_components; return true; case GL_MAX_UNIFORM_BLOCK_SIZE: - *params = capabilities_.max_uniform_block_size; + *params = static_cast<GLint>(capabilities_.max_uniform_block_size); return true; case GL_MAX_UNIFORM_BUFFER_BINDINGS: *params = capabilities_.max_uniform_buffer_bindings; @@ -863,13 +901,23 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { case GL_NUM_PROGRAM_BINARY_FORMATS: *params = capabilities_.num_program_binary_formats; return true; + case GL_PIXEL_PACK_BUFFER_BINDING: + *params = bound_pixel_pack_buffer_; + return true; + case GL_PIXEL_UNPACK_BUFFER_BINDING: + *params = bound_pixel_unpack_buffer_; + return true; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + *params = bound_transform_feedback_buffer_; + return true; + case GL_UNIFORM_BUFFER_BINDING: + *params = bound_uniform_buffer_; + return true; case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: *params = capabilities_.uniform_buffer_offset_alignment; return true; // Non-cached ES3 parameters. - case GL_COPY_READ_BUFFER_BINDING: - case GL_COPY_WRITE_BUFFER_BINDING: case GL_DRAW_BUFFER0: case GL_DRAW_BUFFER1: case GL_DRAW_BUFFER2: @@ -888,12 +936,9 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { case GL_DRAW_BUFFER15: case GL_DRAW_FRAMEBUFFER_BINDING: case GL_FRAGMENT_SHADER_DERIVATIVE_HINT: - case GL_MAX_TEXTURE_LOD_BIAS: case GL_PACK_ROW_LENGTH: case GL_PACK_SKIP_PIXELS: case GL_PACK_SKIP_ROWS: - case GL_PIXEL_PACK_BUFFER_BINDING: - case GL_PIXEL_UNPACK_BUFFER_BINDING: case GL_PRIMITIVE_RESTART_FIXED_INDEX: case GL_PROGRAM_BINARY_FORMATS: case GL_RASTERIZER_DISCARD: @@ -904,11 +949,9 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { case GL_TEXTURE_BINDING_3D: case GL_TRANSFORM_FEEDBACK_BINDING: case GL_TRANSFORM_FEEDBACK_ACTIVE: - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: case GL_TRANSFORM_FEEDBACK_PAUSED: case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: case GL_TRANSFORM_FEEDBACK_BUFFER_START: - case GL_UNIFORM_BUFFER_BINDING: case GL_UNIFORM_BUFFER_SIZE: case GL_UNIFORM_BUFFER_START: case GL_UNPACK_IMAGE_HEIGHT: @@ -935,6 +978,13 @@ bool GLES2Implementation::GetBooleanvHelper(GLenum pname, GLboolean* params) { bool GLES2Implementation::GetFloatvHelper(GLenum pname, GLfloat* params) { // TODO(gman): Make this handle pnames that return more than 1 value. + switch (pname) { + case GL_MAX_TEXTURE_LOD_BIAS: + *params = capabilities_.max_texture_lod_bias; + return true; + default: + break; + } GLint value; if (!GetHelper(pname, &value)) { return false; @@ -944,12 +994,35 @@ bool GLES2Implementation::GetFloatvHelper(GLenum pname, GLfloat* params) { } bool GLES2Implementation::GetInteger64vHelper(GLenum pname, GLint64* params) { - // TODO(zmo): we limit values to 32-bit, which is OK for now. + switch (pname) { + case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: + *params = capabilities_.max_combined_fragment_uniform_components; + return true; + case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: + *params = capabilities_.max_combined_vertex_uniform_components; + return true; + case GL_MAX_ELEMENT_INDEX: + *params = capabilities_.max_element_index; + return true; + case GL_MAX_SERVER_WAIT_TIMEOUT: + *params = capabilities_.max_server_wait_timeout; + return true; + case GL_MAX_UNIFORM_BLOCK_SIZE: + *params = capabilities_.max_uniform_block_size; + return true; + case GL_TIMESTAMP_EXT: + // We convert all GPU timestamps to CPU time. + *params = (base::TraceTicks::Now() - base::TraceTicks()).InMicroseconds() + * base::Time::kNanosecondsPerMicrosecond; + return true; + default: + break; + } GLint value; if (!GetHelper(pname, &value)) { return false; } - *params = value; + *params = static_cast<GLint64>(value); return true; } @@ -1003,6 +1076,62 @@ bool GLES2Implementation::GetSyncivHelper( return true; } +bool GLES2Implementation::GetQueryObjectValueHelper( + const char* function_name, GLuint id, GLenum pname, GLuint64* params) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryObjectValueHelper(" + << id << ", " + << GLES2Util::GetStringQueryObjectParameter(pname) << ", " + << static_cast<const void*>(params) << ")"); + + QueryTracker::Query* query = query_tracker_->GetQuery(id); + if (!query) { + SetGLError(GL_INVALID_OPERATION, + function_name, "unknown query id"); + return false; + } + + if (query->Active()) { + SetGLError( + GL_INVALID_OPERATION, + function_name, + "query active. Did you to call glEndQueryEXT?"); + return false; + } + + if (query->NeverUsed()) { + SetGLError( + GL_INVALID_OPERATION, + function_name, "Never used. Did you call glBeginQueryEXT?"); + return false; + } + + bool valid_value = false; + switch (pname) { + case GL_QUERY_RESULT_EXT: + if (!query->CheckResultsAvailable(helper_)) { + helper_->WaitForToken(query->token()); + if (!query->CheckResultsAvailable(helper_)) { + FinishHelper(); + CHECK(query->CheckResultsAvailable(helper_)); + } + } + *params = query->GetResult(); + valid_value = true; + break; + case GL_QUERY_RESULT_AVAILABLE_EXT: + *params = query->CheckResultsAvailable(helper_); + valid_value = true; + break; + default: + SetGLErrorInvalidEnum(function_name, pname, "pname"); + break; + } + GPU_CLIENT_LOG(" " << *params); + CheckGLError(); + return valid_value; +} + GLuint GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper( GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) { typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result; @@ -1045,7 +1174,7 @@ void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore) { void GLES2Implementation::RestoreArrayBuffer(bool restore) { if (restore) { // Restore the user's current binding. - helper_->BindBuffer(GL_ARRAY_BUFFER, bound_array_buffer_id_); + helper_->BindBuffer(GL_ARRAY_BUFFER, bound_array_buffer_); } } @@ -1106,18 +1235,22 @@ void GLES2Implementation::Flush() { GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()"); // Insert the cmd to call glFlush helper_->Flush(); - // Flush our command buffer - // (tell the service to execute up to the flush cmd.) - helper_->CommandBufferHelper::Flush(); + FlushHelper(); } void GLES2Implementation::ShallowFlushCHROMIUM() { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()"); + FlushHelper(); +} + +void GLES2Implementation::FlushHelper() { // Flush our command buffer // (tell the service to execute up to the flush cmd.) helper_->CommandBufferHelper::Flush(); - // TODO(piman): Add the FreeEverything() logic here. + + if (aggressively_free_resources_) + FreeEverything(); } void GLES2Implementation::OrderingBarrierCHROMIUM() { @@ -1138,6 +1271,9 @@ void GLES2Implementation::ShallowFinishCHROMIUM() { // Flush our command buffer (tell the service to execute up to the flush cmd // and don't return until it completes). helper_->CommandBufferHelper::Finish(); + + if (aggressively_free_resources_) + FreeEverything(); } void GLES2Implementation::FinishHelper() { @@ -1149,6 +1285,9 @@ void GLES2Implementation::FinishHelper() { // (tell the service to execute up to the Finish cmd and wait for it to // execute.) helper_->CommandBufferHelper::Finish(); + + if (aggressively_free_resources_) + FreeEverything(); } void GLES2Implementation::SwapBuffers() { @@ -1534,9 +1673,6 @@ void GLES2Implementation::PixelStorei(GLenum pname, GLint param) { case GL_UNPACK_SKIP_IMAGES: unpack_skip_images_ = param; return; - case GL_UNPACK_FLIP_Y_CHROMIUM: - unpack_flip_y_ = (param != 0); - break; case GL_PACK_REVERSE_ROW_ORDER_ANGLE: pack_reverse_row_order_ = IsAnglePackReverseRowOrderAvailable() ? (param != 0) : false; @@ -1558,7 +1694,7 @@ void GLES2Implementation::VertexAttribIPointer( << stride << ", " << ptr << ")"); // Record the info on the client side. - if (!vertex_array_object_manager_->SetAttribPointer(bound_array_buffer_id_, + if (!vertex_array_object_manager_->SetAttribPointer(bound_array_buffer_, index, size, type, @@ -1570,7 +1706,7 @@ void GLES2Implementation::VertexAttribIPointer( "client side arrays are not allowed in vertex array objects."); return; } - if (!support_client_side_arrays_ || bound_array_buffer_id_ != 0) { + if (!support_client_side_arrays_ || bound_array_buffer_ != 0) { // Only report NON client side buffers to the service. if (!ValidateOffset("glVertexAttribIPointer", reinterpret_cast<GLintptr>(ptr))) { @@ -1593,7 +1729,7 @@ void GLES2Implementation::VertexAttribPointer( << stride << ", " << ptr << ")"); // Record the info on the client side. - if (!vertex_array_object_manager_->SetAttribPointer(bound_array_buffer_id_, + if (!vertex_array_object_manager_->SetAttribPointer(bound_array_buffer_, index, size, type, @@ -1605,7 +1741,7 @@ void GLES2Implementation::VertexAttribPointer( "client side arrays are not allowed in vertex array objects."); return; } - if (!support_client_side_arrays_ || bound_array_buffer_id_ != 0) { + if (!support_client_side_arrays_ || bound_array_buffer_ != 0) { // Only report NON client side buffers to the service. if (!ValidateOffset("glVertexAttribPointer", reinterpret_cast<GLintptr>(ptr))) { @@ -2032,23 +2168,15 @@ void CopyRectToBuffer( uint32 height, uint32 unpadded_row_size, uint32 pixels_padded_row_size, - bool flip_y, void* buffer, uint32 buffer_padded_row_size) { const int8* source = static_cast<const int8*>(pixels); int8* dest = static_cast<int8*>(buffer); - if (flip_y || pixels_padded_row_size != buffer_padded_row_size) { - if (flip_y) { - dest += buffer_padded_row_size * (height - 1); - } + if (pixels_padded_row_size != buffer_padded_row_size) { // the last row is copied unpadded at the end for (; height > 1; --height) { memcpy(dest, source, buffer_padded_row_size); - if (flip_y) { - dest -= buffer_padded_row_size; - } else { - dest += buffer_padded_row_size; - } + dest += buffer_padded_row_size; source += pixels_padded_row_size; } memcpy(dest, source, unpadded_row_size); @@ -2140,18 +2268,36 @@ void GLES2Implementation::TexImage2D( } // Check if we can send it all at once. - ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); - if (!buffer.valid()) { - return; + int32_t shm_id = 0; + uint32_t shm_offset = 0; + void* buffer_pointer = nullptr; + + ScopedTransferBufferPtr transfer_alloc(size, helper_, transfer_buffer_); + ScopedMappedMemoryPtr mapped_alloc(0, helper_, mapped_memory_.get()); + + if (transfer_alloc.valid() && transfer_alloc.size() >= size) { + shm_id = transfer_alloc.shm_id(); + shm_offset = transfer_alloc.offset(); + buffer_pointer = transfer_alloc.address(); + } else { + mapped_alloc.Reset(size); + if (mapped_alloc.valid()) { + transfer_alloc.Discard(); + + mapped_alloc.SetFlushAfterRelease(true); + shm_id = mapped_alloc.shm_id(); + shm_offset = mapped_alloc.offset(); + buffer_pointer = mapped_alloc.address(); + } } - if (buffer.size() >= size) { + if (buffer_pointer) { CopyRectToBuffer( - pixels, height, unpadded_row_size, src_padded_row_size, unpack_flip_y_, - buffer.address(), padded_row_size); + pixels, height, unpadded_row_size, src_padded_row_size, + buffer_pointer, padded_row_size); helper_->TexImage2D( target, level, internalformat, width, height, format, type, - buffer.shm_id(), buffer.offset()); + shm_id, shm_offset); CheckGLError(); return; } @@ -2162,7 +2308,7 @@ void GLES2Implementation::TexImage2D( 0, 0); TexSubImage2DImpl( target, level, 0, 0, width, height, format, type, unpadded_row_size, - pixels, src_padded_row_size, GL_TRUE, &buffer, padded_row_size); + pixels, src_padded_row_size, GL_TRUE, &transfer_alloc, padded_row_size); CheckGLError(); } @@ -2248,20 +2394,36 @@ void GLES2Implementation::TexImage3D( } // Check if we can send it all at once. - ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); - if (!buffer.valid()) { - return; + int32_t shm_id = 0; + uint32_t shm_offset = 0; + void* buffer_pointer = nullptr; + + ScopedTransferBufferPtr transfer_alloc(size, helper_, transfer_buffer_); + ScopedMappedMemoryPtr mapped_alloc(0, helper_, mapped_memory_.get()); + + if (transfer_alloc.valid() && transfer_alloc.size() >= size) { + shm_id = transfer_alloc.shm_id(); + shm_offset = transfer_alloc.offset(); + buffer_pointer = transfer_alloc.address(); + } else { + mapped_alloc.Reset(size); + if (mapped_alloc.valid()) { + transfer_alloc.Discard(); + + mapped_alloc.SetFlushAfterRelease(true); + shm_id = mapped_alloc.shm_id(); + shm_offset = mapped_alloc.offset(); + buffer_pointer = mapped_alloc.address(); + } } - if (buffer.size() >= size) { - void* buffer_pointer = buffer.address(); + if (buffer_pointer) { for (GLsizei z = 0; z < depth; ++z) { // Only the last row of the last image is unpadded. uint32 src_unpadded_row_size = (z == depth - 1) ? unpadded_row_size : src_padded_row_size; - // TODO(zmo): Ignore flip_y flag for now. CopyRectToBuffer( - pixels, height, src_unpadded_row_size, src_padded_row_size, false, + pixels, height, src_unpadded_row_size, src_padded_row_size, buffer_pointer, padded_row_size); pixels = reinterpret_cast<const int8*>(pixels) + src_padded_row_size * src_height; @@ -2270,7 +2432,7 @@ void GLES2Implementation::TexImage3D( } helper_->TexImage3D( target, level, internalformat, width, height, depth, format, type, - buffer.shm_id(), buffer.offset()); + shm_id, shm_offset); CheckGLError(); return; } @@ -2281,7 +2443,7 @@ void GLES2Implementation::TexImage3D( 0, 0); TexSubImage3DImpl( target, level, 0, 0, 0, width, height, depth, format, type, - unpadded_row_size, pixels, src_padded_row_size, GL_TRUE, &buffer, + unpadded_row_size, pixels, src_padded_row_size, GL_TRUE, &transfer_alloc, padded_row_size); CheckGLError(); } @@ -2471,7 +2633,6 @@ void GLES2Implementation::TexSubImage2DImpl( DCHECK_GT(width, 0); const int8* source = reinterpret_cast<const int8*>(pixels); - GLint original_yoffset = yoffset; // Transfer by rows. while (height) { unsigned int desired_size = @@ -2488,10 +2649,9 @@ void GLES2Implementation::TexSubImage2DImpl( num_rows = std::min(num_rows, height); CopyRectToBuffer( source, num_rows, unpadded_row_size, pixels_padded_row_size, - unpack_flip_y_, buffer->address(), buffer_padded_row_size); - GLint y = unpack_flip_y_ ? original_yoffset + height - num_rows : yoffset; + buffer->address(), buffer_padded_row_size); helper_->TexSubImage2D( - target, level, xoffset, y, width, num_rows, format, type, + target, level, xoffset, yoffset, width, num_rows, format, type, buffer->shm_id(), buffer->offset(), internal); buffer->Release(); yoffset += num_rows; @@ -2555,7 +2715,6 @@ void GLES2Implementation::TexSubImage3DImpl( my_depth = 1; } - // TODO(zmo): Ignore flip_y flag for now. if (num_images > 0) { int8* buffer_pointer = reinterpret_cast<int8*>(buffer->address()); uint32 src_height = @@ -2570,7 +2729,7 @@ void GLES2Implementation::TexSubImage3DImpl( my_unpadded_row_size = pixels_padded_row_size; CopyRectToBuffer( source + ii * image_size_src, my_height, my_unpadded_row_size, - pixels_padded_row_size, false, buffer_pointer + ii * image_size_dst, + pixels_padded_row_size, buffer_pointer + ii * image_size_dst, buffer_padded_row_size); } } else { @@ -2581,7 +2740,7 @@ void GLES2Implementation::TexSubImage3DImpl( my_unpadded_row_size = pixels_padded_row_size; CopyRectToBuffer( source, my_height, my_unpadded_row_size, pixels_padded_row_size, - false, buffer->address(), buffer_padded_row_size); + buffer->address(), buffer_padded_row_size); } helper_->TexSubImage3D( target, level, xoffset, yoffset + row_index, zoffset + depth_index, @@ -3020,7 +3179,6 @@ const GLubyte* GLES2Implementation::GetStringHelper(GLenum name) { switch (name) { case GL_EXTENSIONS: str += std::string(str.empty() ? "" : " ") + - "GL_CHROMIUM_flipy " "GL_EXT_unpack_subimage " "GL_CHROMIUM_map_sub"; if (capabilities_.image) @@ -3405,20 +3563,56 @@ void GLES2Implementation::BindBufferHelper( bool changed = false; switch (target) { case GL_ARRAY_BUFFER: - if (bound_array_buffer_id_ != buffer_id) { - bound_array_buffer_id_ = buffer_id; + if (bound_array_buffer_ != buffer_id) { + bound_array_buffer_ = buffer_id; + changed = true; + } + break; + case GL_COPY_READ_BUFFER: + if (bound_copy_read_buffer_ != buffer_id) { + bound_copy_read_buffer_ = buffer_id; + changed = true; + } + break; + case GL_COPY_WRITE_BUFFER: + if (bound_copy_write_buffer_ != buffer_id) { + bound_copy_write_buffer_ = buffer_id; changed = true; } break; case GL_ELEMENT_ARRAY_BUFFER: changed = vertex_array_object_manager_->BindElementArray(buffer_id); break; + case GL_PIXEL_PACK_BUFFER: + if (bound_pixel_pack_buffer_ != buffer_id) { + bound_pixel_pack_buffer_ = buffer_id; + changed = true; + } + break; case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: bound_pixel_pack_transfer_buffer_id_ = buffer_id; break; + case GL_PIXEL_UNPACK_BUFFER: + if (bound_pixel_unpack_buffer_ != buffer_id) { + bound_pixel_unpack_buffer_ = buffer_id; + changed = true; + } + break; case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM: bound_pixel_unpack_transfer_buffer_id_ = buffer_id; break; + case GL_TRANSFORM_FEEDBACK_BUFFER: + if (bound_transform_feedback_buffer_ != buffer_id) { + bound_transform_feedback_buffer_ = buffer_id; + changed = true; + } + break; + case GL_UNIFORM_BUFFER: + if (bound_uniform_buffer_ != buffer_id) { + bound_uniform_buffer_ = buffer_id; + changed = true; + } + break; default: changed = true; break; @@ -3669,8 +3863,26 @@ void GLES2Implementation::DeleteBuffersHelper( return; } for (GLsizei ii = 0; ii < n; ++ii) { - if (buffers[ii] == bound_array_buffer_id_) { - bound_array_buffer_id_ = 0; + if (buffers[ii] == bound_array_buffer_) { + bound_array_buffer_ = 0; + } + if (buffers[ii] == bound_copy_read_buffer_) { + bound_copy_read_buffer_ = 0; + } + if (buffers[ii] == bound_copy_write_buffer_) { + bound_copy_write_buffer_ = 0; + } + if (buffers[ii] == bound_pixel_pack_buffer_) { + bound_pixel_pack_buffer_ = 0; + } + if (buffers[ii] == bound_pixel_unpack_buffer_) { + bound_pixel_unpack_buffer_ = 0; + } + if (buffers[ii] == bound_transform_feedback_buffer_) { + bound_transform_feedback_buffer_ = 0; + } + if (buffers[ii] == bound_uniform_buffer_) { + bound_uniform_buffer_ = 0; } vertex_array_object_manager_->UnbindBuffer(buffers[ii]); @@ -4002,6 +4214,21 @@ void GLES2Implementation::GetVertexAttribIuiv( CheckGLError(); } +GLenum GLES2Implementation::GetGraphicsResetStatusKHR() { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetGraphicsResetStatusKHR()"); + // If we can't make command buffers then the context is lost. + if (gpu_control_->IsGpuChannelLost()) + return GL_UNKNOWN_CONTEXT_RESET_KHR; + // Otherwise, check the command buffer if it is lost. + if (helper_->IsContextLost()) { + // TODO(danakj): We could GetLastState() off the CommandBuffer and return + // the actual reason here if we cared to. + return GL_UNKNOWN_CONTEXT_RESET_KHR; + } + return GL_NO_ERROR; +} + void GLES2Implementation::Swap() { SwapBuffers(); } @@ -4631,9 +4858,48 @@ void GLES2Implementation::BeginQueryEXT(GLenum target, GLuint id) { << GLES2Util::GetStringQueryTarget(target) << ", " << id << ")"); + // Check capabilities + switch (target) { + case GL_COMMANDS_ISSUED_CHROMIUM: + case GL_LATENCY_QUERY_CHROMIUM: + case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM: + case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM: + case GL_GET_ERROR_QUERY_CHROMIUM: + break; + case GL_COMMANDS_COMPLETED_CHROMIUM: + if (!capabilities_.sync_query) { + SetGLError( + GL_INVALID_OPERATION, "glBeginQueryEXT", + "not enabled for commands completed queries"); + return; + } + break; + case GL_ANY_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + if (!capabilities_.occlusion_query_boolean) { + SetGLError( + GL_INVALID_OPERATION, "glBeginQueryEXT", + "not enabled for occlusion queries"); + return; + } + break; + // TODO(dyen): Also support GL_TIMESTAMP. + case GL_TIME_ELAPSED_EXT: + if (!capabilities_.timer_queries) { + SetGLError( + GL_INVALID_OPERATION, "glBeginQueryEXT", + "not enabled for timing queries"); + return; + } + break; + default: + SetGLError( + GL_INVALID_OPERATION, "glBeginQueryEXT", "unknown query target"); + return; + } + // if any outstanding queries INV_OP - QueryMap::iterator it = current_queries_.find(target); - if (it != current_queries_.end()) { + if (query_tracker_->GetCurrentQuery(target)) { SetGLError( GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress"); return; @@ -4651,26 +4917,8 @@ void GLES2Implementation::BeginQueryEXT(GLenum target, GLuint id) { return; } - // if id does not have an object - QueryTracker::Query* query = query_tracker_->GetQuery(id); - if (!query) { - query = query_tracker_->CreateQuery(id, target); - if (!query) { - SetGLError(GL_OUT_OF_MEMORY, - "glBeginQueryEXT", - "transfer buffer allocation failed"); - return; - } - } else if (query->target() != target) { - SetGLError( - GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match"); - return; - } - - current_queries_[target] = query; - - query->Begin(this); - CheckGLError(); + if (query_tracker_->BeginQuery(id, target, this)) + CheckGLError(); } void GLES2Implementation::EndQueryEXT(GLenum target) { @@ -4682,16 +4930,8 @@ void GLES2Implementation::EndQueryEXT(GLenum target) { return; } - QueryMap::iterator it = current_queries_.find(target); - if (it == current_queries_.end()) { - SetGLError(GL_INVALID_OPERATION, "glEndQueryEXT", "no active query"); - return; - } - - QueryTracker::Query* query = it->second; - query->End(this); - current_queries_.erase(it); - CheckGLError(); + if (query_tracker_->EndQuery(target, this)) + CheckGLError(); } void GLES2Implementation::GetQueryivEXT( @@ -4701,70 +4941,32 @@ void GLES2Implementation::GetQueryivEXT( << GLES2Util::GetStringQueryTarget(target) << ", " << GLES2Util::GetStringQueryParameter(pname) << ", " << static_cast<const void*>(params) << ")"); - - if (pname != GL_CURRENT_QUERY_EXT) { + if (pname == GL_QUERY_COUNTER_BITS_EXT) { + // We convert all queries to CPU time so we support 64 bits. + *params = 64; + return; + } else if (pname != GL_CURRENT_QUERY_EXT) { SetGLErrorInvalidEnum("glGetQueryivEXT", pname, "pname"); return; } - QueryMap::iterator it = current_queries_.find(target); - if (it != current_queries_.end()) { - QueryTracker::Query* query = it->second; - *params = query->id(); - } else { - *params = 0; - } + QueryTracker::Query* query = query_tracker_->GetCurrentQuery(target); + *params = query ? query->id() : 0; GPU_CLIENT_LOG(" " << *params); CheckGLError(); } void GLES2Implementation::GetQueryObjectuivEXT( GLuint id, GLenum pname, GLuint* params) { - GPU_CLIENT_SINGLE_THREAD_CHECK(); - GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT(" << id << ", " - << GLES2Util::GetStringQueryObjectParameter(pname) << ", " - << static_cast<const void*>(params) << ")"); - - QueryTracker::Query* query = query_tracker_->GetQuery(id); - if (!query) { - SetGLError(GL_INVALID_OPERATION, "glQueryObjectuivEXT", "unknown query id"); - return; - } - - QueryMap::iterator it = current_queries_.find(query->target()); - if (it != current_queries_.end()) { - SetGLError( - GL_INVALID_OPERATION, - "glQueryObjectuivEXT", "query active. Did you to call glEndQueryEXT?"); - return; - } - - if (query->NeverUsed()) { - SetGLError( - GL_INVALID_OPERATION, - "glQueryObjectuivEXT", "Never used. Did you call glBeginQueryEXT?"); - return; - } + GLuint64 result = 0; + if (GetQueryObjectValueHelper("glQueryObjectuivEXT", id, pname, &result)) + *params = base::saturated_cast<GLuint>(result); +} - switch (pname) { - case GL_QUERY_RESULT_EXT: - if (!query->CheckResultsAvailable(helper_)) { - helper_->WaitForToken(query->token()); - if (!query->CheckResultsAvailable(helper_)) { - FinishHelper(); - CHECK(query->CheckResultsAvailable(helper_)); - } - } - *params = query->GetResult(); - break; - case GL_QUERY_RESULT_AVAILABLE_EXT: - *params = query->CheckResultsAvailable(helper_); - break; - default: - SetGLErrorInvalidEnum("glQueryObjectuivEXT", pname, "pname"); - break; - } - GPU_CLIENT_LOG(" " << *params); - CheckGLError(); +void GLES2Implementation::GetQueryObjectui64vEXT( + GLuint id, GLenum pname, GLuint64* params) { + GLuint64 result = 0; + if (GetQueryObjectValueHelper("glQueryObjectui64vEXT", id, pname, &result)) + *params = result; } void GLES2Implementation::DrawArraysInstancedANGLE( @@ -5109,7 +5311,7 @@ void GLES2Implementation::FreeAllAsyncUploadBuffers() { // Synchronously free rest of the unmanaged async upload buffers. if (!detached_async_upload_memory_.empty()) { - WaitAllAsyncTexImage2DCHROMIUM(); + WaitAllAsyncTexImage2DCHROMIUMHelper(); WaitForCmd(); PollAsyncUploads(); } @@ -5239,11 +5441,15 @@ void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target) { CheckGLError(); } +void GLES2Implementation::WaitAllAsyncTexImage2DCHROMIUMHelper() { + helper_->WaitAllAsyncTexImage2DCHROMIUM(); +} + void GLES2Implementation::WaitAllAsyncTexImage2DCHROMIUM() { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAllAsyncTexImage2DCHROMIUM()"); - helper_->WaitAllAsyncTexImage2DCHROMIUM(); + WaitAllAsyncTexImage2DCHROMIUMHelper(); CheckGLError(); } @@ -5272,8 +5478,18 @@ void GLES2Implementation::RetireSyncPointCHROMIUM(GLuint sync_point) { namespace { -bool ValidImageFormat(GLenum internalformat) { +bool ValidImageFormat(GLenum internalformat, + const Capabilities& capabilities) { switch (internalformat) { + case GL_ATC_RGB_AMD: + case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: + return capabilities.texture_format_atc; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + return capabilities.texture_format_dxt1; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return capabilities.texture_format_dxt5; + case GL_ETC1_RGB8_OES: + return capabilities.texture_format_etc1; case GL_R8: case GL_RGB: case GL_RGBA: @@ -5310,7 +5526,7 @@ GLuint GLES2Implementation::CreateImageCHROMIUMHelper(ClientBuffer buffer, return 0; } - if (!ValidImageFormat(internalformat)) { + if (!ValidImageFormat(internalformat, capabilities_)) { SetGLError(GL_INVALID_VALUE, "glCreateImageCHROMIUM", "invalid format"); return 0; } @@ -5372,7 +5588,7 @@ GLuint GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUMHelper( return 0; } - if (!ValidImageFormat(internalformat)) { + if (!ValidImageFormat(internalformat, capabilities_)) { SetGLError(GL_INVALID_VALUE, "glCreateGpuMemoryBufferImageCHROMIUM", "invalid format"); @@ -5574,6 +5790,51 @@ void GLES2Implementation::WaitSync( CheckGLError(); } +void GLES2Implementation::GetInternalformativ( + GLenum target, GLenum format, GLenum pname, + GLsizei buf_size, GLint* params) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint, params); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetInternalformativ(" + << GLES2Util::GetStringRenderBufferTarget(target) << ", " + << GLES2Util::GetStringRenderBufferFormat(format) << ", " + << GLES2Util::GetStringInternalFormatParameter(pname) + << ", " << buf_size << ", " + << static_cast<const void*>(params) << ")"); + if (buf_size < 0) { + SetGLError(GL_INVALID_VALUE, "glGetInternalformativ", "bufSize < 0"); + return; + } + TRACE_EVENT0("gpu", "GLES2Implementation::GetInternalformativ"); + if (GetInternalformativHelper(target, format, pname, buf_size, params)) { + return; + } + typedef cmds::GetInternalformativ::Result Result; + Result* result = GetResultAs<Result*>(); + if (!result) { + return; + } + result->SetNumResults(0); + helper_->GetInternalformativ(target, format, pname, + GetResultShmId(), GetResultShmOffset()); + WaitForCmd(); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + if (buf_size > 0 && params) { + GLint* data = result->GetData(); + if (buf_size >= result->GetNumResults()) { + buf_size = result->GetNumResults(); + } + for (GLsizei ii = 0; ii < buf_size; ++ii) { + params[ii] = data[ii]; + } + } + 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/chromium/gpu/command_buffer/client/gles2_implementation.h b/chromium/gpu/command_buffer/client/gles2_implementation.h index 9c1a2fa9c95..5c5e93f9920 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation.h +++ b/chromium/gpu/command_buffer/client/gles2_implementation.h @@ -5,8 +5,6 @@ #ifndef GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_H_ #define GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_H_ -#include <GLES2/gl2.h> - #include <list> #include <map> #include <queue> @@ -15,24 +13,22 @@ #include <utility> #include <vector> +#include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "gpu/command_buffer/client/buffer_tracker.h" #include "gpu/command_buffer/client/client_context_state.h" #include "gpu/command_buffer/client/context_support.h" -#include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/gles2_impl_export.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/mapped_memory.h" -#include "gpu/command_buffer/client/query_tracker.h" #include "gpu/command_buffer/client/ref_counted.h" -#include "gpu/command_buffer/client/ring_buffer.h" #include "gpu/command_buffer/client/share_group.h" #include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/common/debug_marker_manager.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" -#include "gpu/command_buffer/common/id_allocator.h" #if !defined(NDEBUG) && !defined(__native_client__) && !defined(GLES2_CONFORMANCE_TESTS) // NOLINT #if defined(GLES2_INLINE_OPTIMIZATION) @@ -99,18 +95,18 @@ GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION_ASSERT(!ptr || \ (ptr[0] == static_cast<type>(0) || ptr[0] == static_cast<type>(-1))); -struct GLUniformDefinitionCHROMIUM; - namespace gpu { class GpuControl; +class IdAllocator; class ScopedTransferBufferPtr; class TransferBufferInterface; namespace gles2 { -class ImageFactory; +class GLES2CmdHelper; class VertexArrayObjectManager; +class QueryTracker; class GLES2ImplementationErrorMessageCallback { public: @@ -245,6 +241,8 @@ class GLES2_IMPL_EXPORT GLES2Implementation bool GetSyncivHelper( GLsync sync, GLenum pname, GLsizei bufsize, GLsizei* length, GLint* values); + bool GetQueryObjectValueHelper( + const char* function_name, GLuint id, GLenum pname, GLuint64* params); void FreeUnusedSharedMemory(); void FreeEverything(); @@ -254,6 +252,7 @@ class GLES2_IMPL_EXPORT GLES2Implementation const base::Closure& callback) override; void SignalQuery(uint32 query, const base::Closure& callback) override; void SetSurfaceVisible(bool visible) override; + void SetAggressivelyFreeResources(bool aggressively_free_resources) override; void SetErrorMessageCallback( GLES2ImplementationErrorMessageCallback* callback) { @@ -279,6 +278,7 @@ class GLES2_IMPL_EXPORT GLES2Implementation private: friend class GLES2ImplementationTest; friend class VertexArrayObjectManager; + friend class QueryTracker; // Used to track whether an extension is available enum ExtensionStatus { @@ -543,6 +543,8 @@ class GLES2_IMPL_EXPORT GLES2Implementation GLuint GetMaxValueInBufferCHROMIUMHelper( GLuint buffer_id, GLsizei count, GLenum type, GLuint offset); + void WaitAllAsyncTexImage2DCHROMIUMHelper(); + void RestoreElementAndArrayBuffers(bool restore); void RestoreArrayBuffer(bool restrore); @@ -599,6 +601,7 @@ class GLES2_IMPL_EXPORT GLES2Implementation IdAllocator* GetIdAllocator(int id_namespace) const; void FinishHelper(); + void FlushHelper(); void RunIfContextNotLost(const base::Closure& callback); @@ -694,9 +697,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation // unpack alignment as last set by glPixelStorei GLint unpack_alignment_; - // unpack yflip as last set by glPixelstorei - bool unpack_flip_y_; - // unpack row length as last set by glPixelStorei GLint unpack_row_length_; @@ -728,8 +728,13 @@ class GLES2_IMPL_EXPORT GLES2Implementation // The program in use by glUseProgram GLuint current_program_; - // The currently bound array buffer. - GLuint bound_array_buffer_id_; + GLuint bound_array_buffer_; + GLuint bound_copy_read_buffer_; + GLuint bound_copy_write_buffer_; + GLuint bound_pixel_pack_buffer_; + GLuint bound_pixel_unpack_buffer_; + GLuint bound_transform_feedback_buffer_; + GLuint bound_uniform_buffer_; // The currently bound pixel transfer buffers. GLuint bound_pixel_pack_transfer_buffer_id_; @@ -793,8 +798,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation ShareGroupContextData share_group_context_data_; scoped_ptr<QueryTracker> query_tracker_; - typedef std::map<GLuint, QueryTracker::Query*> QueryMap; - QueryMap current_queries_; scoped_ptr<IdAllocator> query_id_allocator_; scoped_ptr<BufferTracker> buffer_tracker_; @@ -807,6 +810,10 @@ class GLES2_IMPL_EXPORT GLES2Implementation Capabilities capabilities_; + // Flag to indicate whether the implementation can retain resources, or + // whether it should aggressively free them. + bool aggressively_free_resources_; + base::WeakPtrFactory<GLES2Implementation> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(GLES2Implementation); diff --git a/chromium/gpu/command_buffer/client/gles2_implementation_autogen.h b/chromium/gpu/command_buffer/client/gles2_implementation_autogen.h index af6ce6f80b0..7e49ceb990f 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -803,6 +803,8 @@ void GetQueryivEXT(GLenum target, GLenum pname, GLint* params) override; void GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* params) override; +void GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64* params) override; + void InsertEventMarkerEXT(GLsizei length, const GLchar* marker) override; void PushGroupMarkerEXT(GLsizei length, const GLchar* marker) override; @@ -918,13 +920,27 @@ void CopyTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id, GLint internalformat, - GLenum dest_type) override; + GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) override; void CopySubTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id, GLint xoffset, - GLint yoffset) override; + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) override; + +void CompressedCopyTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id) override; void DrawArraysInstancedANGLE(GLenum mode, GLint first, @@ -1033,10 +1049,14 @@ void ScheduleOverlayPlaneCHROMIUM(GLint plane_z_order, void SwapInterval(GLint interval) override; +void FlushDriverCachesCHROMIUM() override; + void MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) override; void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) override; +GLenum GetGraphicsResetStatusKHR() override; + void BlendBarrierKHR() override; #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_ diff --git a/chromium/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/chromium/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 55cafb99d78..6f776ffbc4d 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_implementation_impl_autogen.h @@ -1103,44 +1103,6 @@ void GLES2Implementation::GetIntegerv(GLenum pname, GLint* params) { }); CheckGLError(); } -void GLES2Implementation::GetInternalformativ(GLenum target, - GLenum format, - GLenum pname, - GLsizei bufSize, - GLint* params) { - GPU_CLIENT_SINGLE_THREAD_CHECK(); - GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint, params); - GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetInternalformativ(" - << GLES2Util::GetStringRenderBufferTarget(target) << ", " - << GLES2Util::GetStringRenderBufferFormat(format) << ", " - << GLES2Util::GetStringInternalFormatParameter(pname) - << ", " << bufSize << ", " - << static_cast<const void*>(params) << ")"); - if (bufSize < 0) { - SetGLError(GL_INVALID_VALUE, "glGetInternalformativ", "bufSize < 0"); - return; - } - TRACE_EVENT0("gpu", "GLES2Implementation::GetInternalformativ"); - if (GetInternalformativHelper(target, format, pname, bufSize, params)) { - return; - } - typedef cmds::GetInternalformativ::Result Result; - Result* result = GetResultAs<Result*>(); - if (!result) { - return; - } - result->SetNumResults(0); - helper_->GetInternalformativ(target, format, pname, bufSize, GetResultShmId(), - GetResultShmOffset()); - WaitForCmd(); - result->CopyResult(params); - GPU_CLIENT_LOG_CODE_BLOCK({ - for (int32_t i = 0; i < result->GetNumResults(); ++i) { - GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); - } - }); - CheckGLError(); -} void GLES2Implementation::GetProgramiv(GLuint program, GLenum pname, GLint* params) { @@ -2980,7 +2942,8 @@ void GLES2Implementation::TexStorage2DEXT(GLenum target, GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG( "[" << GetLogPrefix() << "] glTexStorage2DEXT(" - << GLES2Util::GetStringTextureTarget(target) << ", " << levels << ", " + << GLES2Util::GetStringTextureBindTarget(target) << ", " << levels + << ", " << GLES2Util::GetStringTextureInternalFormatStorage(internalFormat) << ", " << width << ", " << height << ")"); if (levels < 0) { @@ -3186,35 +3149,77 @@ void GLES2Implementation::TexImageIOSurface2DCHROMIUM(GLenum target, CheckGLError(); } -void GLES2Implementation::CopyTextureCHROMIUM(GLenum target, - GLenum source_id, - GLenum dest_id, - GLint internalformat, - GLenum dest_type) { +void GLES2Implementation::CopyTextureCHROMIUM( + GLenum target, + GLenum source_id, + GLenum dest_id, + GLint internalformat, + GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) { GPU_CLIENT_SINGLE_THREAD_CHECK(); - GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCopyTextureCHROMIUM(" - << GLES2Util::GetStringEnum(target) << ", " - << GLES2Util::GetStringEnum(source_id) << ", " - << GLES2Util::GetStringEnum(dest_id) << ", " - << internalformat << ", " - << GLES2Util::GetStringPixelType(dest_type) << ")"); - helper_->CopyTextureCHROMIUM(target, source_id, dest_id, internalformat, - dest_type); + GPU_CLIENT_LOG( + "[" << GetLogPrefix() << "] glCopyTextureCHROMIUM(" + << GLES2Util::GetStringEnum(target) << ", " + << GLES2Util::GetStringEnum(source_id) << ", " + << GLES2Util::GetStringEnum(dest_id) << ", " << internalformat << ", " + << GLES2Util::GetStringPixelType(dest_type) << ", " + << GLES2Util::GetStringBool(unpack_flip_y) << ", " + << GLES2Util::GetStringBool(unpack_premultiply_alpha) << ", " + << GLES2Util::GetStringBool(unpack_unmultiply_alpha) << ")"); + helper_->CopyTextureCHROMIUM( + target, source_id, dest_id, internalformat, dest_type, unpack_flip_y, + unpack_premultiply_alpha, unpack_unmultiply_alpha); CheckGLError(); } -void GLES2Implementation::CopySubTextureCHROMIUM(GLenum target, - GLenum source_id, - GLenum dest_id, - GLint xoffset, - GLint yoffset) { +void GLES2Implementation::CopySubTextureCHROMIUM( + GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) { GPU_CLIENT_SINGLE_THREAD_CHECK(); - GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCopySubTextureCHROMIUM(" + GPU_CLIENT_LOG( + "[" << GetLogPrefix() << "] glCopySubTextureCHROMIUM(" + << GLES2Util::GetStringEnum(target) << ", " + << GLES2Util::GetStringEnum(source_id) << ", " + << GLES2Util::GetStringEnum(dest_id) << ", " << xoffset << ", " + << yoffset << ", " << x << ", " << y << ", " << width << ", " + << height << ", " << GLES2Util::GetStringBool(unpack_flip_y) << ", " + << GLES2Util::GetStringBool(unpack_premultiply_alpha) << ", " + << GLES2Util::GetStringBool(unpack_unmultiply_alpha) << ")"); + if (width < 0) { + SetGLError(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM", "width < 0"); + return; + } + if (height < 0) { + SetGLError(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM", "height < 0"); + return; + } + helper_->CopySubTextureCHROMIUM( + target, source_id, dest_id, xoffset, yoffset, x, y, width, height, + unpack_flip_y, unpack_premultiply_alpha, unpack_unmultiply_alpha); + CheckGLError(); +} + +void GLES2Implementation::CompressedCopyTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedCopyTextureCHROMIUM(" << GLES2Util::GetStringEnum(target) << ", " << GLES2Util::GetStringEnum(source_id) << ", " - << GLES2Util::GetStringEnum(dest_id) << ", " << xoffset - << ", " << yoffset << ")"); - helper_->CopySubTextureCHROMIUM(target, source_id, dest_id, xoffset, yoffset); + << GLES2Util::GetStringEnum(dest_id) << ")"); + helper_->CompressedCopyTextureCHROMIUM(target, source_id, dest_id); CheckGLError(); } @@ -3436,6 +3441,14 @@ void GLES2Implementation::ScheduleOverlayPlaneCHROMIUM( CheckGLError(); } +void GLES2Implementation::FlushDriverCachesCHROMIUM() { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlushDriverCachesCHROMIUM(" + << ")"); + helper_->FlushDriverCachesCHROMIUM(); + CheckGLError(); +} + void GLES2Implementation::MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) { GPU_CLIENT_SINGLE_THREAD_CHECK(); diff --git a/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc b/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc index 0b02f94897a..c354fd9343c 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -6,14 +6,16 @@ #include "gpu/command_buffer/client/gles2_implementation.h" -#include <limits> - +#include <GLES2/gl2.h> #include <GLES2/gl2ext.h> #include <GLES2/gl2extchromium.h> #include <GLES3/gl3.h> #include "base/compiler_specific.h" #include "gpu/command_buffer/client/client_test_helper.h" +#include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/program_info_manager.h" +#include "gpu/command_buffer/client/query_tracker.h" +#include "gpu/command_buffer/client/ring_buffer.h" #include "gpu/command_buffer/client/transfer_buffer.h" #include "gpu/command_buffer/common/command_buffer.h" #include "testing/gtest/include/gtest/gtest.h" @@ -133,6 +135,7 @@ class MockTransferBuffer : public TransferBufferInterface { void* AllocUpTo(unsigned int size, unsigned int* size_allocated) override; void* Alloc(unsigned int size) override; RingBuffer::Offset GetOffset(void* pointer) const override; + void DiscardBlock(void* p) override; void FreePendingToken(void* p, unsigned int /* token */) override; size_t MaxTransferBufferSize() { @@ -296,6 +299,11 @@ RingBuffer::Offset MockTransferBuffer::GetOffset(void* pointer) const { return static_cast<uint8*>(pointer) - actual_buffer(); } +void MockTransferBuffer::DiscardBlock(void* p) { + EXPECT_EQ(last_alloc_, p); + last_alloc_ = NULL; +} + void MockTransferBuffer::FreePendingToken(void* p, unsigned int /* token */) { EXPECT_EQ(last_alloc_, p); last_alloc_ = NULL; @@ -402,7 +410,9 @@ class GLES2ImplementationTest : public testing::Test { bool bind_generates_resource_client, bool bind_generates_resource_service, bool lose_context_when_out_of_memory, - bool transfer_buffer_initialize_fail) { + bool transfer_buffer_initialize_fail, + bool sync_query, + bool occlusion_query_boolean) { command_buffer_.reset(new StrictMock<MockClientCommandBuffer>()); if (!command_buffer_->Initialize()) return false; @@ -445,6 +455,8 @@ class GLES2ImplementationTest : public testing::Test { capabilities.max_uniform_buffer_bindings = kMaxUniformBufferBindings; capabilities.bind_generates_resource_chromium = bind_generates_resource_service ? 1 : 0; + capabilities.sync_query = sync_query; + capabilities.occlusion_query_boolean = occlusion_query_boolean; EXPECT_CALL(*gpu_control_, GetCapabilities()) .WillOnce(testing::Return(capabilities)); @@ -535,12 +547,16 @@ class GLES2ImplementationTest : public testing::Test { : bind_generates_resource_client(true), bind_generates_resource_service(true), lose_context_when_out_of_memory(false), - transfer_buffer_initialize_fail(false) {} + transfer_buffer_initialize_fail(false), + sync_query(true), + occlusion_query_boolean(true) {} bool bind_generates_resource_client; bool bind_generates_resource_service; bool lose_context_when_out_of_memory; bool transfer_buffer_initialize_fail; + bool sync_query; + bool occlusion_query_boolean; }; bool Initialize(const ContextInitOptions& init_options) { @@ -553,7 +569,9 @@ class GLES2ImplementationTest : public testing::Test { init_options.bind_generates_resource_client, init_options.bind_generates_resource_service, init_options.lose_context_when_out_of_memory, - init_options.transfer_buffer_initialize_fail)) + init_options.transfer_buffer_initialize_fail, + init_options.sync_query, + init_options.occlusion_query_boolean)) success = false; } @@ -585,6 +603,10 @@ class GLES2ImplementationTest : public testing::Test { return transfer_buffer_->MaxTransferBufferSize(); } + void SetMappedMemoryLimit(size_t limit) { + gl_->mapped_memory_->set_max_allocated_bytes(limit); + } + ExpectedMemoryInfo GetExpectedMemory(size_t size) { return transfer_buffer_->GetExpectedMemory(size); } @@ -593,6 +615,18 @@ class GLES2ImplementationTest : public testing::Test { return transfer_buffer_->GetExpectedResultMemory(size); } + ExpectedMemoryInfo GetExpectedMappedMemory(size_t size) { + ExpectedMemoryInfo mem; + + // Temporarily allocate memory and expect that memory block to be reused. + mem.ptr = static_cast<uint8*>(gl_->mapped_memory_->Alloc(size, + &mem.id, + &mem.offset)); + gl_->mapped_memory_->Free(mem.ptr); + + return mem; + } + // Sets the ProgramInfoManager. The manager will be owned // by the ShareGroup. void SetProgramInfoManager(ProgramInfoManager* manager) { @@ -2211,7 +2245,7 @@ TEST_F(GLES2ImplementationTest, GetIntegerCacheWrite) { static bool CheckRect( int width, int height, GLenum format, GLenum type, int alignment, - bool flip_y, const uint8* r1, const uint8* r2) { + const uint8* r1, const uint8* r2) { uint32 size = 0; uint32 unpadded_row_size = 0; uint32 padded_row_size = 0; @@ -2221,10 +2255,7 @@ static bool CheckRect( return false; } - int r2_stride = flip_y ? - -static_cast<int>(padded_row_size) : - static_cast<int>(padded_row_size); - r2 = flip_y ? (r2 + (height - 1) * padded_row_size) : r2; + int r2_stride = static_cast<int>(padded_row_size); for (int y = 0; y < height; ++y) { if (memcmp(r1, r2, unpadded_row_size) != 0) { @@ -2236,13 +2267,11 @@ static bool CheckRect( return true; } -ACTION_P8(CheckRectAction, width, height, format, type, alignment, flip_y, - r1, r2) { +ACTION_P7(CheckRectAction, width, height, format, type, alignment, r1, r2) { EXPECT_TRUE(CheckRect( - width, height, format, type, alignment, flip_y, r1, r2)); + width, height, format, type, alignment, r1, r2)); } -// Test TexImage2D with and without flip_y TEST_F(GLES2ImplementationTest, TexImage2D) { struct Cmds { cmds::TexImage2D tex_image_2d; @@ -2279,30 +2308,61 @@ TEST_F(GLES2ImplementationTest, TexImage2D) { pixels); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); EXPECT_TRUE(CheckRect( - kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, false, + kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, pixels, mem1.ptr)); +} - ClearCommands(); - gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); +TEST_F(GLES2ImplementationTest, TexImage2DViaMappedMem) { + struct Cmds { + cmds::TexImage2D tex_image_2d; + cmd::SetToken set_token; + }; + const GLenum kTarget = GL_TEXTURE_2D; + const GLint kLevel = 0; + const GLenum kFormat = GL_RGB; + const GLsizei kWidth = 3; + const GLint kBorder = 0; + const GLenum kType = GL_UNSIGNED_BYTE; + const GLint kPixelStoreUnpackAlignment = 4; - ExpectedMemoryInfo mem2 = GetExpectedMemory(sizeof(pixels)); - Cmds2 expected2; - expected2.tex_image_2d.Init( + uint32 size = 0; + uint32 unpadded_row_size = 0; + uint32 padded_row_size = 0; + ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, 2, 1, kFormat, kType, kPixelStoreUnpackAlignment, + &size, &unpadded_row_size, &padded_row_size)); + const GLsizei kMaxHeight = (MaxTransferBufferSize() / padded_row_size) * 2; + const GLsizei kHeight = kMaxHeight * 2; + ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, 1, kFormat, kType, kPixelStoreUnpackAlignment, + &size, &unpadded_row_size, &padded_row_size)); + + scoped_ptr<uint8[]> pixels(new uint8[size]); + for (uint32 ii = 0; ii < size; ++ii) { + pixels[ii] = static_cast<uint8>(ii); + } + + ExpectedMemoryInfo mem1 = GetExpectedMappedMemory(size); + + Cmds expected; + expected.tex_image_2d.Init( kTarget, kLevel, kFormat, kWidth, kHeight, kFormat, kType, - mem2.id, mem2.offset); - expected2.set_token.Init(GetNextToken()); - const void* commands2 = GetPut(); + mem1.id, mem1.offset); + expected.set_token.Init(GetNextToken()); gl_->TexImage2D( kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, - pixels); - EXPECT_EQ(0, memcmp(&expected2, commands2, sizeof(expected2))); + pixels.get()); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); EXPECT_TRUE(CheckRect( - kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, true, - pixels, mem2.ptr)); + kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, + pixels.get(), mem1.ptr)); } // Test TexImage2D with 2 writes -TEST_F(GLES2ImplementationTest, TexImage2D2Writes) { +TEST_F(GLES2ImplementationTest, TexImage2DViaTexSubImage2D) { + // Set limit to 1 to effectively disable mapped memory. + SetMappedMemoryLimit(1); + struct Cmds { cmds::TexImage2D tex_image_2d; cmds::TexSubImage2D tex_sub_image_2d1; @@ -2367,111 +2427,8 @@ TEST_F(GLES2ImplementationTest, TexImage2D2Writes) { pixels.get()); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); EXPECT_TRUE(CheckRect( - kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, false, + kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, pixels.get() + kHeight / 2 * padded_row_size, mem2.ptr)); - - ClearCommands(); - gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); - const void* commands2 = GetPut(); - ExpectedMemoryInfo mem3 = GetExpectedMemory(half_size); - ExpectedMemoryInfo mem4 = GetExpectedMemory(half_size); - expected.tex_image_2d.Init( - kTarget, kLevel, kFormat, kWidth, kHeight, kFormat, kType, - 0, 0); - expected.tex_sub_image_2d1.Init( - kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, - mem3.id, mem3.offset, true); - expected.set_token1.Init(GetNextToken()); - expected.tex_sub_image_2d2.Init( - kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType, - mem4.id, mem4.offset, true); - expected.set_token2.Init(GetNextToken()); - - // TODO(gman): Make it possible to run this test - // EXPECT_CALL(*command_buffer(), OnFlush()) - // .WillOnce(CheckRectAction( - // kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, - // true, pixels.get(), - // GetExpectedTransferAddressFromOffsetAs<uint8>(offset3, half_size))) - // .RetiresOnSaturation(); - - gl_->TexImage2D( - kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, - pixels.get()); - EXPECT_EQ(0, memcmp(&expected, commands2, sizeof(expected))); - EXPECT_TRUE(CheckRect( - kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, true, - pixels.get() + kHeight / 2 * padded_row_size, mem4.ptr)); -} - -// Test TexSubImage2D with GL_PACK_FLIP_Y set and partial multirow transfers -TEST_F(GLES2ImplementationTest, TexSubImage2DFlipY) { - const GLsizei kTextureWidth = MaxTransferBufferSize() / 4; - const GLsizei kTextureHeight = 7; - const GLsizei kSubImageWidth = MaxTransferBufferSize() / 8; - const GLsizei kSubImageHeight = 4; - const GLint kSubImageXOffset = 1; - const GLint kSubImageYOffset = 2; - const GLenum kFormat = GL_RGBA; - const GLenum kType = GL_UNSIGNED_BYTE; - const GLenum kTarget = GL_TEXTURE_2D; - const GLint kLevel = 0; - const GLint kBorder = 0; - const GLint kPixelStoreUnpackAlignment = 4; - - struct Cmds { - cmds::PixelStorei pixel_store_i1; - cmds::TexImage2D tex_image_2d; - cmds::PixelStorei pixel_store_i2; - cmds::TexSubImage2D tex_sub_image_2d1; - cmd::SetToken set_token1; - cmds::TexSubImage2D tex_sub_image_2d2; - cmd::SetToken set_token2; - }; - - uint32 sub_2_high_size = 0; - ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( - kSubImageWidth, 2, 1, kFormat, kType, kPixelStoreUnpackAlignment, - &sub_2_high_size, NULL, NULL)); - - ExpectedMemoryInfo mem1 = GetExpectedMemory(sub_2_high_size); - ExpectedMemoryInfo mem2 = GetExpectedMemory(sub_2_high_size); - - Cmds expected; - expected.pixel_store_i1.Init(GL_UNPACK_ALIGNMENT, kPixelStoreUnpackAlignment); - expected.tex_image_2d.Init( - kTarget, kLevel, kFormat, kTextureWidth, kTextureHeight, kFormat, - kType, 0, 0); - expected.pixel_store_i2.Init(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); - expected.tex_sub_image_2d1.Init(kTarget, kLevel, kSubImageXOffset, - kSubImageYOffset + 2, kSubImageWidth, 2, kFormat, kType, - mem1.id, mem1.offset, false); - expected.set_token1.Init(GetNextToken()); - expected.tex_sub_image_2d2.Init(kTarget, kLevel, kSubImageXOffset, - kSubImageYOffset, kSubImageWidth , 2, kFormat, kType, - mem2.id, mem2.offset, false); - expected.set_token2.Init(GetNextToken()); - - gl_->PixelStorei(GL_UNPACK_ALIGNMENT, kPixelStoreUnpackAlignment); - gl_->TexImage2D( - kTarget, kLevel, kFormat, kTextureWidth, kTextureHeight, kBorder, kFormat, - kType, NULL); - gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); - scoped_ptr<uint32[]> pixels(new uint32[kSubImageWidth * kSubImageHeight]); - for (int y = 0; y < kSubImageHeight; ++y) { - for (int x = 0; x < kSubImageWidth; ++x) { - pixels.get()[kSubImageWidth * y + x] = x | (y << 16); - } - } - gl_->TexSubImage2D( - GL_TEXTURE_2D, 0, kSubImageXOffset, kSubImageYOffset, kSubImageWidth, - kSubImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); - - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); - EXPECT_TRUE(CheckRect( - kSubImageWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, true, - reinterpret_cast<uint8*>(pixels.get() + 2 * kSubImageWidth), - mem2.ptr)); } TEST_F(GLES2ImplementationTest, SubImageUnpack) { @@ -2500,13 +2457,11 @@ TEST_F(GLES2ImplementationTest, SubImageUnpack) { struct { cmds::PixelStorei pixel_store_i; - cmds::PixelStorei pixel_store_i2; cmds::TexImage2D tex_image_2d; } texImageExpected; struct { cmds::PixelStorei pixel_store_i; - cmds::PixelStorei pixel_store_i2; cmds::TexImage2D tex_image_2d; cmds::TexSubImage2D tex_sub_image_2d; } texSubImageExpected; @@ -2521,74 +2476,66 @@ TEST_F(GLES2ImplementationTest, SubImageUnpack) { } for (int sub = 0; sub < 2; ++sub) { - for (int flip_y = 0; flip_y < 2; ++flip_y) { - for (size_t a = 0; a < arraysize(unpack_alignments); ++a) { - GLint alignment = unpack_alignments[a]; - uint32 size; - uint32 unpadded_row_size; - uint32 padded_row_size; - ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( - kSrcSubImageWidth, kSrcSubImageHeight, 1, kFormat, kType, alignment, - &size, &unpadded_row_size, &padded_row_size)); - ASSERT_TRUE(size <= MaxTransferBufferSize()); - ExpectedMemoryInfo mem = GetExpectedMemory(size); - - const void* commands = GetPut(); - gl_->PixelStorei(GL_UNPACK_ALIGNMENT, alignment); - gl_->PixelStorei(GL_UNPACK_ROW_LENGTH_EXT, kSrcWidth); - gl_->PixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, kSrcSubImageX0); - gl_->PixelStorei(GL_UNPACK_SKIP_ROWS_EXT, kSrcSubImageY0); - gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y); - if (sub) { - gl_->TexImage2D( - GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, kBorder, - kFormat, kType, NULL); - gl_->TexSubImage2D( - GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset, - kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, - src_pixels.get()); - texSubImageExpected.pixel_store_i.Init( - GL_UNPACK_ALIGNMENT, alignment); - texSubImageExpected.pixel_store_i2.Init( - GL_UNPACK_FLIP_Y_CHROMIUM, flip_y); - texSubImageExpected.tex_image_2d.Init( - GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, - kFormat, kType, 0, 0); - texSubImageExpected.tex_sub_image_2d.Init( - GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset, - kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, mem.id, - mem.offset, GL_FALSE); - EXPECT_EQ(0, memcmp( - &texSubImageExpected, commands, sizeof(texSubImageExpected))); - } else { - gl_->TexImage2D( - GL_TEXTURE_2D, kLevel, kFormat, - kSrcSubImageWidth, kSrcSubImageHeight, kBorder, kFormat, kType, - src_pixels.get()); - texImageExpected.pixel_store_i.Init(GL_UNPACK_ALIGNMENT, alignment); - texImageExpected.pixel_store_i2.Init( - GL_UNPACK_FLIP_Y_CHROMIUM, flip_y); - texImageExpected.tex_image_2d.Init( - GL_TEXTURE_2D, kLevel, kFormat, kSrcSubImageWidth, - kSrcSubImageHeight, kFormat, kType, mem.id, mem.offset); - EXPECT_EQ(0, memcmp( - &texImageExpected, commands, sizeof(texImageExpected))); - } - uint32 src_padded_row_size; - ASSERT_TRUE(GLES2Util::ComputeImagePaddedRowSize( - kSrcWidth, kFormat, kType, alignment, &src_padded_row_size)); - uint32 bytes_per_group = GLES2Util::ComputeImageGroupSize( - kFormat, kType); - for (int y = 0; y < kSrcSubImageHeight; ++y) { - GLint src_sub_y = flip_y ? kSrcSubImageHeight - y - 1 : y; - const uint8* src_row = src_pixels.get() + - (kSrcSubImageY0 + src_sub_y) * src_padded_row_size + - bytes_per_group * kSrcSubImageX0; - const uint8* dst_row = mem.ptr + y * padded_row_size; - EXPECT_EQ(0, memcmp(src_row, dst_row, unpadded_row_size)); - } - ClearCommands(); + for (size_t a = 0; a < arraysize(unpack_alignments); ++a) { + GLint alignment = unpack_alignments[a]; + uint32 size; + uint32 unpadded_row_size; + uint32 padded_row_size; + ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( + kSrcSubImageWidth, kSrcSubImageHeight, 1, kFormat, kType, alignment, + &size, &unpadded_row_size, &padded_row_size)); + ASSERT_TRUE(size <= MaxTransferBufferSize()); + ExpectedMemoryInfo mem = GetExpectedMemory(size); + + const void* commands = GetPut(); + gl_->PixelStorei(GL_UNPACK_ALIGNMENT, alignment); + gl_->PixelStorei(GL_UNPACK_ROW_LENGTH_EXT, kSrcWidth); + gl_->PixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, kSrcSubImageX0); + gl_->PixelStorei(GL_UNPACK_SKIP_ROWS_EXT, kSrcSubImageY0); + if (sub) { + gl_->TexImage2D( + GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, kBorder, + kFormat, kType, NULL); + gl_->TexSubImage2D( + GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset, + kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, + src_pixels.get()); + texSubImageExpected.pixel_store_i.Init( + GL_UNPACK_ALIGNMENT, alignment); + texSubImageExpected.tex_image_2d.Init( + GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, + kFormat, kType, 0, 0); + texSubImageExpected.tex_sub_image_2d.Init( + GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset, + kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, mem.id, + mem.offset, GL_FALSE); + EXPECT_EQ(0, memcmp( + &texSubImageExpected, commands, sizeof(texSubImageExpected))); + } else { + gl_->TexImage2D( + GL_TEXTURE_2D, kLevel, kFormat, + kSrcSubImageWidth, kSrcSubImageHeight, kBorder, kFormat, kType, + src_pixels.get()); + texImageExpected.pixel_store_i.Init(GL_UNPACK_ALIGNMENT, alignment); + texImageExpected.tex_image_2d.Init( + GL_TEXTURE_2D, kLevel, kFormat, kSrcSubImageWidth, + kSrcSubImageHeight, kFormat, kType, mem.id, mem.offset); + EXPECT_EQ(0, memcmp( + &texImageExpected, commands, sizeof(texImageExpected))); + } + uint32 src_padded_row_size; + ASSERT_TRUE(GLES2Util::ComputeImagePaddedRowSize( + kSrcWidth, kFormat, kType, alignment, &src_padded_row_size)); + uint32 bytes_per_group = GLES2Util::ComputeImageGroupSize( + kFormat, kType); + for (int y = 0; y < kSrcSubImageHeight; ++y) { + const uint8* src_row = src_pixels.get() + + (kSrcSubImageY0 + y) * src_padded_row_size + + bytes_per_group * kSrcSubImageX0; + const uint8* dst_row = mem.ptr + y * padded_row_size; + EXPECT_EQ(0, memcmp(src_row, dst_row, unpadded_row_size)); } + ClearCommands(); } } } @@ -2629,7 +2576,7 @@ TEST_F(GLES2ImplementationTest, TextureInvalidArguments) { pixels); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); EXPECT_TRUE(CheckRect( - kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, false, + kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, pixels, mem1.ptr)); ClearCommands(); @@ -2723,10 +2670,61 @@ TEST_F(GLES2ImplementationTest, TexImage3DSingleCommand) { EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); EXPECT_TRUE(CheckRect( kWidth, kHeight * kDepth, kFormat, kType, kPixelStoreUnpackAlignment, - false, reinterpret_cast<uint8*>(pixels.get()), mem.ptr)); + reinterpret_cast<uint8*>(pixels.get()), mem.ptr)); +} + +TEST_F(GLES2ImplementationTest, TexImage3DViaMappedMem) { + struct Cmds { + cmds::TexImage3D tex_image_3d; + }; + const GLenum kTarget = GL_TEXTURE_3D; + const GLint kLevel = 0; + const GLint kBorder = 0; + const GLenum kFormat = GL_RGB; + const GLenum kType = GL_UNSIGNED_BYTE; + const GLint kPixelStoreUnpackAlignment = 4; + const GLsizei kWidth = 3; + const GLsizei kDepth = 2; + + uint32 size = 0; + uint32 unpadded_row_size = 0; + uint32 padded_row_size = 0; + ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, 2, kDepth, kFormat, kType, kPixelStoreUnpackAlignment, + &size, &unpadded_row_size, &padded_row_size)); + // Makes sure we can just send over the data in one command. + const GLsizei kMaxHeight = MaxTransferBufferSize() / padded_row_size / kDepth; + const GLsizei kHeight = kMaxHeight * 2; + ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, kDepth, kFormat, kType, kPixelStoreUnpackAlignment, + &size, NULL, NULL)); + + scoped_ptr<uint8[]> pixels(new uint8[size]); + for (uint32 ii = 0; ii < size; ++ii) { + pixels[ii] = static_cast<uint8>(ii); + } + + ExpectedMemoryInfo mem = GetExpectedMappedMemory(size); + + Cmds expected; + expected.tex_image_3d.Init( + kTarget, kLevel, kFormat, kWidth, kHeight, kDepth, + kFormat, kType, mem.id, mem.offset); + + gl_->TexImage3D( + kTarget, kLevel, kFormat, kWidth, kHeight, kDepth, kBorder, + kFormat, kType, pixels.get()); + + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_TRUE(CheckRect( + kWidth, kHeight * kDepth, kFormat, kType, kPixelStoreUnpackAlignment, + reinterpret_cast<uint8*>(pixels.get()), mem.ptr)); } TEST_F(GLES2ImplementationTest, TexImage3DViaTexSubImage3D) { + // Set limit to 1 to effectively disable mapped memory. + SetMappedMemoryLimit(1); + struct Cmds { cmds::TexImage3D tex_image_3d; cmds::TexSubImage3D tex_sub_image_3d1; @@ -2854,7 +2852,7 @@ TEST_F(GLES2ImplementationTest, TexSubImage3D4Writes) { EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); uint32 offset_to_last = first_size + second_size + third_size; EXPECT_TRUE(CheckRect( - kWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, false, + kWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, reinterpret_cast<uint8*>(pixels.get()) + offset_to_last, mem2_2.ptr)); } @@ -2913,11 +2911,9 @@ TEST_F(GLES2ImplementationStrictSharedTest, TEST_F(GLES2ImplementationTest, GetString) { const uint32 kBucketId = GLES2Implementation::kResultBucketId; const Str7 kString = {"foobar"}; - // GL_CHROMIUM_map_sub GL_CHROMIUM_flipy are hard coded into - // GLES2Implementation. + // GL_CHROMIUM_map_sub is hard coded into GLES2Implementation. const char* expected_str = "foobar " - "GL_CHROMIUM_flipy " "GL_EXT_unpack_subimage " "GL_CHROMIUM_map_sub"; const char kBad = 0x12; @@ -3195,6 +3191,53 @@ TEST_F(GLES2ImplementationTest, BeginEndQueryEXT) { ClearCommands(); gl_->GetQueryObjectuivEXT(id1, GL_QUERY_RESULT_AVAILABLE_EXT, &available); EXPECT_EQ(0u, available); + + // Test GetQueryObjectui64vEXT fails if unused id + GLuint64 available2 = 0xBDu; + ClearCommands(); + gl_->GetQueryObjectui64vEXT(id2, GL_QUERY_RESULT_AVAILABLE_EXT, &available2); + EXPECT_TRUE(NoCommandsWritten()); + EXPECT_EQ(0xBDu, available2); + EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); + + // Test GetQueryObjectui64vEXT fails if bad id + ClearCommands(); + gl_->GetQueryObjectui64vEXT(4567, GL_QUERY_RESULT_AVAILABLE_EXT, &available2); + EXPECT_TRUE(NoCommandsWritten()); + EXPECT_EQ(0xBDu, available2); + EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); + + // Test GetQueryObjectui64vEXT CheckResultsAvailable + ClearCommands(); + gl_->GetQueryObjectui64vEXT(id1, GL_QUERY_RESULT_AVAILABLE_EXT, &available2); + EXPECT_EQ(0u, available2); +} + +TEST_F(GLES2ImplementationManualInitTest, BadQueryTargets) { + ContextInitOptions init_options; + init_options.sync_query = false; + init_options.occlusion_query_boolean = false; + ASSERT_TRUE(Initialize(init_options)); + + GLuint id = 0; + gl_->GenQueriesEXT(1, &id); + ClearCommands(); + + gl_->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, id); + EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); + EXPECT_EQ(nullptr, GetQuery(id)); + + gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED, id); + EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); + EXPECT_EQ(nullptr, GetQuery(id)); + + gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, id); + EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); + EXPECT_EQ(nullptr, GetQuery(id)); + + gl_->BeginQueryEXT(0x123, id); + EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); + EXPECT_EQ(nullptr, GetQuery(id)); } TEST_F(GLES2ImplementationTest, ErrorQuery) { @@ -3744,6 +3787,27 @@ TEST_F(GLES2ImplementationTest, DeleteBuffersUnmapsDataStore) { EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); } +TEST_F(GLES2ImplementationTest, GetInternalformativ) { + const GLint kNumSampleCounts = 8; + struct Cmds { + cmds::GetInternalformativ cmd; + }; + typedef cmds::GetInternalformativ::Result::Type ResultType; + ResultType result = 0; + Cmds expected; + ExpectedMemoryInfo result1 = + GetExpectedResultMemory(sizeof(uint32_t) + sizeof(ResultType)); + expected.cmd.Init(123, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, + result1.id, result1.offset); + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result1.ptr, + SizedResultHelper<ResultType>(kNumSampleCounts))) + .RetiresOnSaturation(); + gl_->GetInternalformativ(123, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &result); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_EQ(static_cast<ResultType>(kNumSampleCounts), result); +} + TEST_F(GLES2ImplementationManualInitTest, LoseContextOnOOM) { ContextInitOptions init_options; init_options.lose_context_when_out_of_memory = true; diff --git a/chromium/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/chromium/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index ae9b5e15aa9..cf9a177118a 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h @@ -909,25 +909,7 @@ TEST_F(GLES2ImplementationTest, GetIntegerv) { EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); EXPECT_EQ(static_cast<ResultType>(1), result); } - -TEST_F(GLES2ImplementationTest, GetInternalformativ) { - struct Cmds { - cmds::GetInternalformativ cmd; - }; - typedef cmds::GetInternalformativ::Result::Type ResultType; - ResultType result = 0; - Cmds expected; - ExpectedMemoryInfo result1 = - GetExpectedResultMemory(sizeof(uint32_t) + sizeof(ResultType)); - expected.cmd.Init(123, GL_RGBA4, GL_NUM_SAMPLE_COUNTS, 4, result1.id, - result1.offset); - EXPECT_CALL(*command_buffer(), OnFlush()) - .WillOnce(SetMemory(result1.ptr, SizedResultHelper<ResultType>(1))) - .RetiresOnSaturation(); - gl_->GetInternalformativ(123, GL_RGBA4, GL_NUM_SAMPLE_COUNTS, 4, &result); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); - EXPECT_EQ(static_cast<ResultType>(1), result); -} +// TODO(zmo): Implement unit test for GetInternalformativ TEST_F(GLES2ImplementationTest, GetProgramiv) { struct Cmds { @@ -2863,9 +2845,10 @@ TEST_F(GLES2ImplementationTest, CopyTextureCHROMIUM) { cmds::CopyTextureCHROMIUM cmd; }; Cmds expected; - expected.cmd.Init(1, 2, 3, GL_ALPHA, GL_UNSIGNED_BYTE); + expected.cmd.Init(1, 2, 3, GL_ALPHA, GL_UNSIGNED_BYTE, true, true, true); - gl_->CopyTextureCHROMIUM(1, 2, 3, GL_ALPHA, GL_UNSIGNED_BYTE); + gl_->CopyTextureCHROMIUM(1, 2, 3, GL_ALPHA, GL_UNSIGNED_BYTE, true, true, + true); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } @@ -2874,9 +2857,20 @@ TEST_F(GLES2ImplementationTest, CopySubTextureCHROMIUM) { cmds::CopySubTextureCHROMIUM cmd; }; Cmds expected; - expected.cmd.Init(1, 2, 3, 4, 5); + expected.cmd.Init(1, 2, 3, 4, 5, 6, 7, 8, 9, true, true, true); - gl_->CopySubTextureCHROMIUM(1, 2, 3, 4, 5); + gl_->CopySubTextureCHROMIUM(1, 2, 3, 4, 5, 6, 7, 8, 9, true, true, true); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, CompressedCopyTextureCHROMIUM) { + struct Cmds { + cmds::CompressedCopyTextureCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(1, 2, 3); + + gl_->CompressedCopyTextureCHROMIUM(1, 2, 3); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } @@ -3099,6 +3093,17 @@ TEST_F(GLES2ImplementationTest, DiscardBackbufferCHROMIUM) { EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, FlushDriverCachesCHROMIUM) { + struct Cmds { + cmds::FlushDriverCachesCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(); + + gl_->FlushDriverCachesCHROMIUM(); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, MatrixLoadfCHROMIUM) { GLfloat data[16] = {0}; struct Cmds { diff --git a/chromium/gpu/command_buffer/client/gles2_interface_autogen.h b/chromium/gpu/command_buffer/client/gles2_interface_autogen.h index a8bde2922cd..c3e197f9f2e 100644 --- a/chromium/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_interface_autogen.h @@ -597,6 +597,9 @@ virtual void EndQueryEXT(GLenum target) = 0; virtual void EndTransformFeedback() = 0; virtual void GetQueryivEXT(GLenum target, GLenum pname, GLint* params) = 0; virtual void GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* params) = 0; +virtual void GetQueryObjectui64vEXT(GLuint id, + GLenum pname, + GLuint64* params) = 0; virtual void InsertEventMarkerEXT(GLsizei length, const GLchar* marker) = 0; virtual void PushGroupMarkerEXT(GLsizei length, const GLchar* marker) = 0; virtual void PopGroupMarkerEXT() = 0; @@ -681,12 +684,25 @@ virtual void CopyTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id, GLint internalformat, - GLenum dest_type) = 0; + GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) = 0; virtual void CopySubTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id, GLint xoffset, - GLint yoffset) = 0; + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) = 0; +virtual void CompressedCopyTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id) = 0; virtual void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, @@ -763,7 +779,9 @@ virtual void ScheduleOverlayPlaneCHROMIUM(GLint plane_z_order, GLfloat uv_width, GLfloat uv_height) = 0; virtual void SwapInterval(GLint interval) = 0; +virtual void FlushDriverCachesCHROMIUM() = 0; virtual void MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) = 0; virtual void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) = 0; +virtual GLenum GetGraphicsResetStatusKHR() = 0; virtual void BlendBarrierKHR() = 0; #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_AUTOGEN_H_ diff --git a/chromium/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/chromium/gpu/command_buffer/client/gles2_interface_stub_autogen.h index fd5151b8d21..be5cbb8fbeb 100644 --- a/chromium/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_interface_stub_autogen.h @@ -580,6 +580,7 @@ void EndQueryEXT(GLenum target) override; void EndTransformFeedback() override; void GetQueryivEXT(GLenum target, GLenum pname, GLint* params) override; void GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* params) override; +void GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64* params) override; void InsertEventMarkerEXT(GLsizei length, const GLchar* marker) override; void PushGroupMarkerEXT(GLsizei length, const GLchar* marker) override; void PopGroupMarkerEXT() override; @@ -662,12 +663,25 @@ void CopyTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id, GLint internalformat, - GLenum dest_type) override; + GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) override; void CopySubTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id, GLint xoffset, - GLint yoffset) override; + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) override; +void CompressedCopyTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id) override; void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, @@ -743,7 +757,9 @@ void ScheduleOverlayPlaneCHROMIUM(GLint plane_z_order, GLfloat uv_width, GLfloat uv_height) override; void SwapInterval(GLint interval) override; +void FlushDriverCachesCHROMIUM() override; void MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) override; void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) override; +GLenum GetGraphicsResetStatusKHR() override; void BlendBarrierKHR() override; #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_AUTOGEN_H_ diff --git a/chromium/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/chromium/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index 464f1ed8f32..f06af17d214 100644 --- a/chromium/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h @@ -994,6 +994,10 @@ void GLES2InterfaceStub::GetQueryObjectuivEXT(GLuint /* id */, GLenum /* pname */, GLuint* /* params */) { } +void GLES2InterfaceStub::GetQueryObjectui64vEXT(GLuint /* id */, + GLenum /* pname */, + GLuint64* /* params */) { +} void GLES2InterfaceStub::InsertEventMarkerEXT(GLsizei /* length */, const GLchar* /* marker */) { } @@ -1127,17 +1131,33 @@ void GLES2InterfaceStub::TexImageIOSurface2DCHROMIUM(GLenum /* target */, GLuint /* ioSurfaceId */, GLuint /* plane */) { } -void GLES2InterfaceStub::CopyTextureCHROMIUM(GLenum /* target */, - GLenum /* source_id */, - GLenum /* dest_id */, - GLint /* internalformat */, - GLenum /* dest_type */) { +void GLES2InterfaceStub::CopyTextureCHROMIUM( + GLenum /* target */, + GLenum /* source_id */, + GLenum /* dest_id */, + GLint /* internalformat */, + GLenum /* dest_type */, + GLboolean /* unpack_flip_y */, + GLboolean /* unpack_premultiply_alpha */, + GLboolean /* unpack_unmultiply_alpha */) { +} +void GLES2InterfaceStub::CopySubTextureCHROMIUM( + GLenum /* target */, + GLenum /* source_id */, + GLenum /* dest_id */, + GLint /* xoffset */, + GLint /* yoffset */, + GLint /* x */, + GLint /* y */, + GLsizei /* width */, + GLsizei /* height */, + GLboolean /* unpack_flip_y */, + GLboolean /* unpack_premultiply_alpha */, + GLboolean /* unpack_unmultiply_alpha */) { } -void GLES2InterfaceStub::CopySubTextureCHROMIUM(GLenum /* target */, - GLenum /* source_id */, - GLenum /* dest_id */, - GLint /* xoffset */, - GLint /* yoffset */) { +void GLES2InterfaceStub::CompressedCopyTextureCHROMIUM(GLenum /* target */, + GLenum /* source_id */, + GLenum /* dest_id */) { } void GLES2InterfaceStub::DrawArraysInstancedANGLE(GLenum /* mode */, GLint /* first */, @@ -1265,11 +1285,16 @@ void GLES2InterfaceStub::ScheduleOverlayPlaneCHROMIUM( } void GLES2InterfaceStub::SwapInterval(GLint /* interval */) { } +void GLES2InterfaceStub::FlushDriverCachesCHROMIUM() { +} void GLES2InterfaceStub::MatrixLoadfCHROMIUM(GLenum /* matrixMode */, const GLfloat* /* m */) { } void GLES2InterfaceStub::MatrixLoadIdentityCHROMIUM(GLenum /* matrixMode */) { } +GLenum GLES2InterfaceStub::GetGraphicsResetStatusKHR() { + return 0; +} void GLES2InterfaceStub::BlendBarrierKHR() { } #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_IMPL_AUTOGEN_H_ diff --git a/chromium/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/chromium/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index 8ad90c561ca..c9fa2ec767a 100644 --- a/chromium/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_trace_implementation_autogen.h @@ -580,6 +580,7 @@ void EndQueryEXT(GLenum target) override; void EndTransformFeedback() override; void GetQueryivEXT(GLenum target, GLenum pname, GLint* params) override; void GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* params) override; +void GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64* params) override; void InsertEventMarkerEXT(GLsizei length, const GLchar* marker) override; void PushGroupMarkerEXT(GLsizei length, const GLchar* marker) override; void PopGroupMarkerEXT() override; @@ -662,12 +663,25 @@ void CopyTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id, GLint internalformat, - GLenum dest_type) override; + GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) override; void CopySubTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id, GLint xoffset, - GLint yoffset) override; + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) override; +void CompressedCopyTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id) override; void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, @@ -743,7 +757,9 @@ void ScheduleOverlayPlaneCHROMIUM(GLint plane_z_order, GLfloat uv_width, GLfloat uv_height) override; void SwapInterval(GLint interval) override; +void FlushDriverCachesCHROMIUM() override; void MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) override; void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) override; +GLenum GetGraphicsResetStatusKHR() override; void BlendBarrierKHR() override; #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_TRACE_IMPLEMENTATION_AUTOGEN_H_ diff --git a/chromium/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/chromium/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index 5d4641fb5f3..893cc910fb9 100644 --- a/chromium/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h @@ -1681,6 +1681,13 @@ void GLES2TraceImplementation::GetQueryObjectuivEXT(GLuint id, gl_->GetQueryObjectuivEXT(id, pname, params); } +void GLES2TraceImplementation::GetQueryObjectui64vEXT(GLuint id, + GLenum pname, + GLuint64* params) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetQueryObjectui64vEXT"); + gl_->GetQueryObjectui64vEXT(id, pname, params); +} + void GLES2TraceImplementation::InsertEventMarkerEXT(GLsizei length, const GLchar* marker) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::InsertEventMarkerEXT"); @@ -1911,23 +1918,46 @@ void GLES2TraceImplementation::TexImageIOSurface2DCHROMIUM(GLenum target, gl_->TexImageIOSurface2DCHROMIUM(target, width, height, ioSurfaceId, plane); } -void GLES2TraceImplementation::CopyTextureCHROMIUM(GLenum target, - GLenum source_id, - GLenum dest_id, - GLint internalformat, - GLenum dest_type) { +void GLES2TraceImplementation::CopyTextureCHROMIUM( + GLenum target, + GLenum source_id, + GLenum dest_id, + GLint internalformat, + GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::CopyTextureCHROMIUM"); gl_->CopyTextureCHROMIUM(target, source_id, dest_id, internalformat, - dest_type); + dest_type, unpack_flip_y, unpack_premultiply_alpha, + unpack_unmultiply_alpha); } -void GLES2TraceImplementation::CopySubTextureCHROMIUM(GLenum target, - GLenum source_id, - GLenum dest_id, - GLint xoffset, - GLint yoffset) { +void GLES2TraceImplementation::CopySubTextureCHROMIUM( + GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::CopySubTextureCHROMIUM"); - gl_->CopySubTextureCHROMIUM(target, source_id, dest_id, xoffset, yoffset); + gl_->CopySubTextureCHROMIUM( + target, source_id, dest_id, xoffset, yoffset, x, y, width, height, + unpack_flip_y, unpack_premultiply_alpha, unpack_unmultiply_alpha); +} + +void GLES2TraceImplementation::CompressedCopyTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", + "GLES2Trace::CompressedCopyTextureCHROMIUM"); + gl_->CompressedCopyTextureCHROMIUM(target, source_id, dest_id); } void GLES2TraceImplementation::DrawArraysInstancedANGLE(GLenum mode, @@ -2164,6 +2194,11 @@ void GLES2TraceImplementation::SwapInterval(GLint interval) { gl_->SwapInterval(interval); } +void GLES2TraceImplementation::FlushDriverCachesCHROMIUM() { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::FlushDriverCachesCHROMIUM"); + gl_->FlushDriverCachesCHROMIUM(); +} + void GLES2TraceImplementation::MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::MatrixLoadfCHROMIUM"); @@ -2176,6 +2211,11 @@ void GLES2TraceImplementation::MatrixLoadIdentityCHROMIUM(GLenum matrixMode) { gl_->MatrixLoadIdentityCHROMIUM(matrixMode); } +GLenum GLES2TraceImplementation::GetGraphicsResetStatusKHR() { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetGraphicsResetStatusKHR"); + return gl_->GetGraphicsResetStatusKHR(); +} + void GLES2TraceImplementation::BlendBarrierKHR() { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::BlendBarrierKHR"); gl_->BlendBarrierKHR(); diff --git a/chromium/gpu/command_buffer/client/gpu_control.h b/chromium/gpu/command_buffer/client/gpu_control.h index 2b303b3b4d5..75bd082a34d 100644 --- a/chromium/gpu/command_buffer/client/gpu_control.h +++ b/chromium/gpu/command_buffer/client/gpu_control.h @@ -85,6 +85,10 @@ class GPU_EXPORT GpuControl { // may not be supported with all implementations. virtual void SetLock(base::Lock*) = 0; + // Returns true if the channel to the Gpu is lost. When true, all contexts + // should be considered as lost. + virtual bool IsGpuChannelLost() = 0; + private: DISALLOW_COPY_AND_ASSIGN(GpuControl); }; diff --git a/chromium/gpu/command_buffer/client/mapped_memory.cc b/chromium/gpu/command_buffer/client/mapped_memory.cc index 6d57af4ed57..7c5864a4710 100644 --- a/chromium/gpu/command_buffer/client/mapped_memory.cc +++ b/chromium/gpu/command_buffer/client/mapped_memory.cc @@ -30,7 +30,8 @@ MappedMemoryManager::MappedMemoryManager(CommandBufferHelper* helper, helper_(helper), poll_callback_(poll_callback), allocated_memory_(0), - max_free_bytes_(unused_memory_reclaim_limit) { + max_free_bytes_(unused_memory_reclaim_limit), + max_allocated_bytes_(kNoLimit) { } MappedMemoryManager::~MappedMemoryManager() { @@ -81,6 +82,11 @@ void* MappedMemoryManager::Alloc( } } + if (max_allocated_bytes_ != kNoLimit && + (allocated_memory_ + size) > max_allocated_bytes_) { + return nullptr; + } + // Make a new chunk to satisfy the request. CommandBuffer* cmd_buf = helper_->command_buffer(); unsigned int chunk_size = @@ -140,4 +146,26 @@ void MappedMemoryManager::FreeUnused() { } } +void ScopedMappedMemoryPtr::Release() { + if (buffer_) { + mapped_memory_manager_->FreePendingToken(buffer_, helper_->InsertToken()); + buffer_ = nullptr; + size_ = 0; + shm_id_ = 0; + shm_offset_ = 0; + + if (flush_after_release_) + helper_->CommandBufferHelper::Flush(); + } +} + +void ScopedMappedMemoryPtr::Reset(uint32_t new_size) { + Release(); + + if (new_size) { + buffer_ = mapped_memory_manager_->Alloc(new_size, &shm_id_, &shm_offset_); + size_ = buffer_ ? new_size : 0; + } +} + } // namespace gpu diff --git a/chromium/gpu/command_buffer/client/mapped_memory.h b/chromium/gpu/command_buffer/client/mapped_memory.h index 10ac639929f..55d94e56068 100644 --- a/chromium/gpu/command_buffer/client/mapped_memory.h +++ b/chromium/gpu/command_buffer/client/mapped_memory.h @@ -139,6 +139,14 @@ class GPU_EXPORT MappedMemoryManager { chunk_size_multiple_ = multiple; } + size_t max_allocated_bytes() const { + return max_allocated_bytes_; + } + + void set_max_allocated_bytes(size_t max_allocated_bytes) { + max_allocated_bytes_ = max_allocated_bytes; + } + // Allocates a block of memory // Parameters: // size: size of memory to allocate. @@ -195,10 +203,71 @@ class GPU_EXPORT MappedMemoryManager { MemoryChunkVector chunks_; size_t allocated_memory_; size_t max_free_bytes_; + size_t max_allocated_bytes_; DISALLOW_COPY_AND_ASSIGN(MappedMemoryManager); }; +// A class that will manage the lifetime of a mapped memory allocation +class GPU_EXPORT ScopedMappedMemoryPtr { + public: + ScopedMappedMemoryPtr( + uint32_t size, + CommandBufferHelper* helper, + MappedMemoryManager* mapped_memory_manager) + : buffer_(NULL), + size_(0), + shm_id_(0), + shm_offset_(0), + flush_after_release_(false), + helper_(helper), + mapped_memory_manager_(mapped_memory_manager) { + Reset(size); + } + + ~ScopedMappedMemoryPtr() { + Release(); + } + + bool valid() const { + return buffer_ != NULL; + } + + void SetFlushAfterRelease(bool flush_after_release) { + flush_after_release_ = flush_after_release; + } + + uint32_t size() const { + return size_; + } + + int32_t shm_id() const { + return shm_id_; + } + + uint32_t offset() const { + return shm_offset_; + } + + void* address() const { + return buffer_; + } + + void Release(); + + void Reset(uint32_t new_size); + + private: + void* buffer_; + uint32_t size_; + int32_t shm_id_; + uint32_t shm_offset_; + bool flush_after_release_; + CommandBufferHelper* helper_; + MappedMemoryManager* mapped_memory_manager_; + DISALLOW_COPY_AND_ASSIGN(ScopedMappedMemoryPtr); +}; + } // namespace gpu #endif // GPU_COMMAND_BUFFER_CLIENT_MAPPED_MEMORY_H_ diff --git a/chromium/gpu/command_buffer/client/mapped_memory_unittest.cc b/chromium/gpu/command_buffer/client/mapped_memory_unittest.cc index 6430b667d3f..981bbbad712 100644 --- a/chromium/gpu/command_buffer/client/mapped_memory_unittest.cc +++ b/chromium/gpu/command_buffer/client/mapped_memory_unittest.cc @@ -42,7 +42,7 @@ class MappedMemoryTestBase : public testing::Test { { TransferBufferManager* manager = new TransferBufferManager(); - transfer_buffer_manager_.reset(manager); + transfer_buffer_manager_ = manager; EXPECT_TRUE(manager->Initialize()); } @@ -68,7 +68,7 @@ class MappedMemoryTestBase : public testing::Test { } scoped_ptr<AsyncAPIMock> api_mock_; - scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; + scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; scoped_ptr<CommandBufferService> command_buffer_; scoped_ptr<GpuScheduler> gpu_scheduler_; scoped_ptr<CommandBufferHelper> helper_; @@ -394,6 +394,54 @@ TEST_F(MappedMemoryManagerTest, MemoryLimitWithReuse) { manager_->Free(mem3); } +TEST_F(MappedMemoryManagerTest, MaxAllocationTest) { + const unsigned int kSize = 1024; + // Reset the manager with a memory limit. + manager_.reset(new MappedMemoryManager( + helper_.get(), base::Bind(&EmptyPoll), kSize)); + + const size_t kLimit = 512; + manager_->set_chunk_size_multiple(kLimit); + + // Allocate twice the limit worth of memory (currently unbounded). + int32 id1 = -1; + unsigned int offset1 = 0xFFFFFFFFU; + void* mem1 = manager_->Alloc(kLimit, &id1, &offset1); + ASSERT_TRUE(mem1); + EXPECT_NE(-1, id1); + EXPECT_EQ(0u, offset1); + + int32 id2 = -1; + unsigned int offset2 = 0xFFFFFFFFU; + void* mem2 = manager_->Alloc(kLimit, &id2, &offset2); + ASSERT_TRUE(mem2); + EXPECT_NE(-1, id2); + EXPECT_EQ(0u, offset2); + + manager_->set_max_allocated_bytes(kLimit); + + // A new allocation should now fail. + int32 id3 = -1; + unsigned int offset3 = 0xFFFFFFFFU; + void* mem3 = manager_->Alloc(kLimit, &id3, &offset3); + ASSERT_FALSE(mem3); + EXPECT_EQ(-1, id3); + EXPECT_EQ(0xFFFFFFFFU, offset3); + + manager_->Free(mem2); + + // New allocation is over the limit but should reuse allocated space + int32 id4 = -1; + unsigned int offset4 = 0xFFFFFFFFU; + void* mem4 = manager_->Alloc(kLimit, &id4, &offset4); + ASSERT_TRUE(mem4); + EXPECT_EQ(id2, id4); + EXPECT_EQ(offset2, offset4); + + manager_->Free(mem1); + manager_->Free(mem4); +} + namespace { void Poll(MappedMemoryManagerTest *test, std::list<void*>* list) { std::list<void*>::iterator it = list->begin(); diff --git a/chromium/gpu/command_buffer/client/query_tracker.cc b/chromium/gpu/command_buffer/client/query_tracker.cc index e215c16061b..37a147878a7 100644 --- a/chromium/gpu/command_buffer/client/query_tracker.cc +++ b/chromium/gpu/command_buffer/client/query_tracker.cc @@ -8,6 +8,8 @@ #include <GLES2/gl2ext.h> #include <GLES2/gl2extchromium.h> +#include <limits.h> + #include "base/atomicops.h" #include "base/numerics/safe_conversions.h" #include "gpu/command_buffer/client/gles2_cmd_helper.h" @@ -18,6 +20,16 @@ namespace gpu { namespace gles2 { +QuerySyncManager::Bucket::Bucket(QuerySync* sync_mem, + int32 shm_id, + unsigned int shm_offset) + : syncs(sync_mem), + shm_id(shm_id), + base_shm_offset(shm_offset) { +} + +QuerySyncManager::Bucket::~Bucket() = default; + QuerySyncManager::QuerySyncManager(MappedMemoryManager* manager) : mapped_memory_(manager) { DCHECK(manager); @@ -33,7 +45,16 @@ QuerySyncManager::~QuerySyncManager() { bool QuerySyncManager::Alloc(QuerySyncManager::QueryInfo* info) { DCHECK(info); - if (free_queries_.empty()) { + Bucket* bucket = nullptr; + for (Bucket* bucket_candidate : buckets_) { + // In C++11 STL this could be replaced with + // if (!bucket_candidate->in_use_queries.all()) { ... } + if (bucket_candidate->in_use_queries.count() != kSyncsPerBucket) { + bucket = bucket_candidate; + break; + } + } + if (!bucket) { int32 shm_id; unsigned int shm_offset; void* mem = mapped_memory_->Alloc( @@ -42,40 +63,39 @@ bool QuerySyncManager::Alloc(QuerySyncManager::QueryInfo* info) { return false; } QuerySync* syncs = static_cast<QuerySync*>(mem); - Bucket* bucket = new Bucket(syncs); + bucket = new Bucket(syncs, shm_id, shm_offset); buckets_.push_back(bucket); - for (size_t ii = 0; ii < kSyncsPerBucket; ++ii) { - free_queries_.push_back(QueryInfo(bucket, shm_id, shm_offset, syncs)); - ++syncs; - shm_offset += sizeof(*syncs); + } + + unsigned short index_in_bucket = 0; + for (size_t i = 0; i < kSyncsPerBucket; i++) { + if (!bucket->in_use_queries[i]) { + index_in_bucket = i; + break; } } - *info = free_queries_.front(); - ++(info->bucket->used_query_count); + + uint32 shm_offset = + bucket->base_shm_offset + index_in_bucket * sizeof(QuerySync); + QuerySync* sync = bucket->syncs + index_in_bucket; + *info = QueryInfo(bucket, bucket->shm_id, shm_offset, sync); info->sync->Reset(); - free_queries_.pop_front(); + bucket->in_use_queries[index_in_bucket] = true; return true; } void QuerySyncManager::Free(const QuerySyncManager::QueryInfo& info) { - DCHECK_GT(info.bucket->used_query_count, 0u); - --(info.bucket->used_query_count); - free_queries_.push_back(info); + DCHECK_NE(info.bucket->in_use_queries.count(), 0u); + unsigned short index_in_bucket = info.sync - info.bucket->syncs; + DCHECK(info.bucket->in_use_queries[index_in_bucket]); + info.bucket->in_use_queries[index_in_bucket] = false; } void QuerySyncManager::Shrink() { - std::deque<QueryInfo> new_queue; - while (!free_queries_.empty()) { - if (free_queries_.front().bucket->used_query_count) - new_queue.push_back(free_queries_.front()); - free_queries_.pop_front(); - } - free_queries_.swap(new_queue); - std::deque<Bucket*> new_buckets; while (!buckets_.empty()) { Bucket* bucket = buckets_.front(); - if (bucket->used_query_count) { + if (bucket->in_use_queries.any()) { new_buckets.push_back(bucket); } else { mapped_memory_->Free(bucket->syncs); @@ -154,18 +174,17 @@ bool QueryTracker::Query::CheckResultsAvailable( helper->IsContextLost()) { switch (target()) { case GL_COMMANDS_ISSUED_CHROMIUM: - result_ = base::saturated_cast<uint32>(info_.sync->result); + result_ = info_.sync->result; break; case GL_LATENCY_QUERY_CHROMIUM: // Disabled DCHECK because of http://crbug.com/419236. //DCHECK(info_.sync->result >= client_begin_time_us_); - result_ = base::saturated_cast<uint32>( - info_.sync->result - client_begin_time_us_); + result_ = info_.sync->result - client_begin_time_us_; break; case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM: case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM: default: - result_ = static_cast<uint32>(info_.sync->result); + result_ = info_.sync->result; break; } state_ = kComplete; @@ -181,7 +200,7 @@ bool QueryTracker::Query::CheckResultsAvailable( return state_ == kComplete; } -uint32 QueryTracker::Query::GetResult() const { +uint64 QueryTracker::Query::GetResult() const { DCHECK(state_ == kComplete || state_ == kUninitialized); return result_; } @@ -206,25 +225,37 @@ QueryTracker::Query* QueryTracker::CreateQuery(GLuint id, GLenum target) { FreeCompletedQueries(); QuerySyncManager::QueryInfo info; if (!query_sync_manager_.Alloc(&info)) { - return NULL; + return nullptr; } Query* query = new Query(id, target, info); - std::pair<QueryMap::iterator, bool> result = + std::pair<QueryIdMap::iterator, bool> result = queries_.insert(std::make_pair(id, query)); DCHECK(result.second); return query; } -QueryTracker::Query* QueryTracker::GetQuery( - GLuint client_id) { - QueryMap::iterator it = queries_.find(client_id); - return it != queries_.end() ? it->second : NULL; +QueryTracker::Query* QueryTracker::GetQuery(GLuint client_id) { + QueryIdMap::iterator it = queries_.find(client_id); + return it != queries_.end() ? it->second : nullptr; +} + +QueryTracker::Query* QueryTracker::GetCurrentQuery(GLenum target) { + QueryTargetMap::iterator it = current_queries_.find(target); + return it != current_queries_.end() ? it->second : nullptr; } void QueryTracker::RemoveQuery(GLuint client_id) { - QueryMap::iterator it = queries_.find(client_id); + QueryIdMap::iterator it = queries_.find(client_id); if (it != queries_.end()) { Query* query = it->second; + + // Erase from current targets map if it is the current target. + const GLenum target = query->target(); + QueryTargetMap::iterator target_it = current_queries_.find(target); + if (target_it != current_queries_.end() && target_it->second == query) { + current_queries_.erase(target_it); + } + // When you delete a query you can't mark its memory as unused until it's // completed. // Note: If you don't do this you won't mess up the service but you will @@ -257,5 +288,41 @@ void QueryTracker::FreeCompletedQueries() { } } +bool QueryTracker::BeginQuery(GLuint id, GLenum target, + GLES2Implementation* gl) { + QueryTracker::Query* query = GetQuery(id); + if (!query) { + query = CreateQuery(id, target); + if (!query) { + gl->SetGLError(GL_OUT_OF_MEMORY, + "glBeginQueryEXT", + "transfer buffer allocation failed"); + return false; + } + } else if (query->target() != target) { + gl->SetGLError(GL_INVALID_OPERATION, + "glBeginQueryEXT", + "target does not match"); + return false; + } + + current_queries_[query->target()] = query; + query->Begin(gl); + return true; +} + +bool QueryTracker::EndQuery(GLenum target, GLES2Implementation* gl) { + QueryTargetMap::iterator target_it = current_queries_.find(target); + if (target_it == current_queries_.end()) { + gl->SetGLError(GL_INVALID_OPERATION, + "glEndQueryEXT", "no active query"); + return false; + } + + target_it->second->End(gl); + current_queries_.erase(target_it); + return true; +} + } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/client/query_tracker.h b/chromium/gpu/command_buffer/client/query_tracker.h index d7e65cadb7d..abd2f5d331e 100644 --- a/chromium/gpu/command_buffer/client/query_tracker.h +++ b/chromium/gpu/command_buffer/client/query_tracker.h @@ -7,6 +7,7 @@ #include <GLES2/gl2.h> +#include <bitset> #include <deque> #include <list> @@ -27,15 +28,15 @@ class GLES2Implementation; // Manages buckets of QuerySync instances in mapped memory. class GLES2_IMPL_EXPORT QuerySyncManager { public: - static const size_t kSyncsPerBucket = 1024; + static const size_t kSyncsPerBucket = 256; struct Bucket { - explicit Bucket(QuerySync* sync_mem) - : syncs(sync_mem), - used_query_count(0) { - } + Bucket(QuerySync* sync_mem, int32 shm_id, uint32 shm_offset); + ~Bucket(); QuerySync* syncs; - unsigned used_query_count; + int32 shm_id; + uint32 base_shm_offset; + std::bitset<kSyncsPerBucket> in_use_queries; }; struct QueryInfo { QueryInfo(Bucket* bucket, int32 id, uint32 offset, QuerySync* sync_mem) @@ -68,7 +69,6 @@ class GLES2_IMPL_EXPORT QuerySyncManager { private: MappedMemoryManager* mapped_memory_; std::deque<Bucket*> buckets_; - std::deque<QueryInfo> free_queries_; DISALLOW_COPY_AND_ASSIGN(QuerySyncManager); }; @@ -91,7 +91,7 @@ class GLES2_IMPL_EXPORT QueryTracker { return target_; } - GLenum id() const { + GLuint id() const { return id_; } @@ -125,21 +125,25 @@ class GLES2_IMPL_EXPORT QueryTracker { return state_ == kUninitialized; } + bool Active() const { + return state_ == kActive; + } + bool Pending() const { return state_ == kPending; } bool CheckResultsAvailable(CommandBufferHelper* helper); - uint32 GetResult() const; - - void Begin(GLES2Implementation* gl); - void End(GLES2Implementation* gl); + uint64 GetResult() const; private: friend class QueryTracker; friend class QueryTrackerTest; + void Begin(GLES2Implementation* gl); + void End(GLES2Implementation* gl); + GLuint id_; GLenum target_; QuerySyncManager::QueryInfo info_; @@ -148,7 +152,7 @@ class GLES2_IMPL_EXPORT QueryTracker { int32 token_; uint32 flush_count_; uint64 client_begin_time_us_; // Only used for latency query target. - uint32 result_; + uint64 result_; }; QueryTracker(MappedMemoryManager* manager); @@ -156,15 +160,21 @@ class GLES2_IMPL_EXPORT QueryTracker { Query* CreateQuery(GLuint id, GLenum target); Query* GetQuery(GLuint id); + Query* GetCurrentQuery(GLenum target); void RemoveQuery(GLuint id); void Shrink(); void FreeCompletedQueries(); + bool BeginQuery(GLuint id, GLenum target, GLES2Implementation* gl); + bool EndQuery(GLenum target, GLES2Implementation* gl); + private: - typedef base::hash_map<GLuint, Query*> QueryMap; + typedef base::hash_map<GLuint, Query*> QueryIdMap; + typedef base::hash_map<GLenum, Query*> QueryTargetMap; typedef std::list<Query*> QueryList; - QueryMap queries_; + QueryIdMap queries_; + QueryTargetMap current_queries_; QueryList removed_queries_; QuerySyncManager query_sync_manager_; diff --git a/chromium/gpu/command_buffer/client/query_tracker_unittest.cc b/chromium/gpu/command_buffer/client/query_tracker_unittest.cc index f6f48ecef2a..51c86994d60 100644 --- a/chromium/gpu/command_buffer/client/query_tracker_unittest.cc +++ b/chromium/gpu/command_buffer/client/query_tracker_unittest.cc @@ -7,6 +7,9 @@ #include "gpu/command_buffer/client/query_tracker.h" #include <GLES2/gl2ext.h> + +#include <vector> + #include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/client/client_test_helper.h" #include "gpu/command_buffer/client/gles2_cmd_helper.h" @@ -107,6 +110,10 @@ class QueryTrackerTest : public testing::Test { return query->info_.bucket; } + uint32 GetBucketUsedCount(QuerySyncManager::Bucket* bucket) { + return bucket->in_use_queries.count(); + } + uint32 GetFlushGeneration() { return helper_->flush_generation(); } scoped_ptr<CommandBuffer> command_buffer_; @@ -209,7 +216,7 @@ TEST_F(QueryTrackerTest, Remove) { ASSERT_TRUE(query != NULL); QuerySyncManager::Bucket* bucket = GetBucket(query); - EXPECT_EQ(1u, bucket->used_query_count); + EXPECT_EQ(1u, GetBucketUsedCount(bucket)); query->MarkAsActive(); query->MarkAsPending(kToken); @@ -219,7 +226,7 @@ TEST_F(QueryTrackerTest, Remove) { EXPECT_TRUE(query_tracker_->GetQuery(kId1) == NULL); // Check that memory was not freed. - EXPECT_EQ(1u, bucket->used_query_count); + EXPECT_EQ(1u, GetBucketUsedCount(bucket)); // Simulate GPU process marking it as available. QuerySync* sync = GetSync(query); @@ -228,9 +235,61 @@ TEST_F(QueryTrackerTest, Remove) { // Check FreeCompletedQueries. query_tracker_->FreeCompletedQueries(); - EXPECT_EQ(0u, bucket->used_query_count); + EXPECT_EQ(0u, GetBucketUsedCount(bucket)); } +TEST_F(QueryTrackerTest, ManyQueries) { + const GLuint kId1 = 123; + const int32 kToken = 46; + const uint32 kResult = 456; + + const size_t kTestSize = 4000; + static_assert(kTestSize > QuerySyncManager::kSyncsPerBucket, + "We want to use more than one bucket"); + // Create lots of queries. + std::vector<QueryTracker::Query*> queries; + for (size_t i = 0; i < kTestSize; i++) { + QueryTracker::Query* query = + query_tracker_->CreateQuery(kId1 + i, GL_ANY_SAMPLES_PASSED_EXT); + ASSERT_TRUE(query != NULL); + queries.push_back(query); + QuerySyncManager::Bucket* bucket = GetBucket(query); + EXPECT_LE(1u, GetBucketUsedCount(bucket)); + } + + QuerySyncManager::Bucket* query_0_bucket = GetBucket(queries[0]); + uint32 expected_use_count = QuerySyncManager::kSyncsPerBucket; + EXPECT_EQ(expected_use_count, GetBucketUsedCount(query_0_bucket)); + + while (!queries.empty()) { + QueryTracker::Query* query = queries.back(); + queries.pop_back(); + GLuint query_id = kId1 + queries.size(); + EXPECT_EQ(query_id, query->id()); + query->MarkAsActive(); + query->MarkAsPending(kToken); + + QuerySyncManager::Bucket* bucket = GetBucket(query); + uint32 use_count_before_remove = GetBucketUsedCount(bucket); + query_tracker_->FreeCompletedQueries(); + EXPECT_EQ(use_count_before_remove, GetBucketUsedCount(bucket)); + query_tracker_->RemoveQuery(query_id); + // Check we get nothing for a non-existent query. + EXPECT_TRUE(query_tracker_->GetQuery(query_id) == NULL); + + // Check that memory was not freed since it was not completed. + EXPECT_EQ(use_count_before_remove, GetBucketUsedCount(bucket)); + + // Simulate GPU process marking it as available. + QuerySync* sync = GetSync(query); + sync->process_count = query->submit_count(); + sync->result = kResult; + + // Check FreeCompletedQueries. + query_tracker_->FreeCompletedQueries(); + EXPECT_EQ(use_count_before_remove - 1, GetBucketUsedCount(bucket)); + } +} } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/client/ring_buffer.cc b/chromium/gpu/command_buffer/client/ring_buffer.cc index 813bb348863..c66fc06c147 100644 --- a/chromium/gpu/command_buffer/client/ring_buffer.cc +++ b/chromium/gpu/command_buffer/client/ring_buffer.cc @@ -103,6 +103,45 @@ void RingBuffer::FreePendingToken(void* pointer, NOTREACHED() << "attempt to free non-existant block"; } +void RingBuffer::DiscardBlock(void* pointer) { + Offset offset = GetOffset(pointer); + offset -= base_offset_; + DCHECK(!blocks_.empty()) << "no allocations to discard"; + for (Container::reverse_iterator it = blocks_.rbegin(); + it != blocks_.rend(); + ++it) { + Block& block = *it; + if (block.offset == offset) { + DCHECK(block.state != PADDING) + << "block that corresponds to offset already discarded"; + block.state = PADDING; + + // Remove block if it were in the back along with any extra padding. + while (!blocks_.empty() && blocks_.back().state == PADDING) { + free_offset_= blocks_.back().offset; + blocks_.pop_back(); + } + + // Remove blocks if it were in the front along with extra padding. + while (!blocks_.empty() && blocks_.front().state == PADDING) { + blocks_.pop_front(); + if (blocks_.empty()) + break; + + in_use_offset_ = blocks_.front().offset; + } + + // In the special case when there are no blocks, we should be reset it. + if (blocks_.empty()) { + in_use_offset_ = 0; + free_offset_ = 0; + } + return; + } + } + NOTREACHED() << "attempt to discard non-existant block"; +} + unsigned int RingBuffer::GetLargestFreeSizeNoWaiting() { unsigned int last_token_read = helper_->last_token_read(); while (!blocks_.empty()) { diff --git a/chromium/gpu/command_buffer/client/ring_buffer.h b/chromium/gpu/command_buffer/client/ring_buffer.h index dfe16f7326e..00de8a59bad 100644 --- a/chromium/gpu/command_buffer/client/ring_buffer.h +++ b/chromium/gpu/command_buffer/client/ring_buffer.h @@ -54,6 +54,12 @@ class GPU_EXPORT RingBuffer { // token: the token value to wait for before re-using the memory. void FreePendingToken(void* pointer, unsigned int token); + // Discards a block within the ring buffer. + // + // Parameters: + // pointer: the pointer to the memory block to free. + void DiscardBlock(void* pointer); + // Gets the size of the largest free block that is available without waiting. unsigned int GetLargestFreeSizeNoWaiting(); diff --git a/chromium/gpu/command_buffer/client/ring_buffer_test.cc b/chromium/gpu/command_buffer/client/ring_buffer_test.cc index ac5634aa236..dad9cbc3686 100644 --- a/chromium/gpu/command_buffer/client/ring_buffer_test.cc +++ b/chromium/gpu/command_buffer/client/ring_buffer_test.cc @@ -67,7 +67,7 @@ class BaseRingBufferTest : public testing::Test { { TransferBufferManager* manager = new TransferBufferManager(); - transfer_buffer_manager_.reset(manager); + transfer_buffer_manager_ = manager; EXPECT_TRUE(manager->Initialize()); } command_buffer_.reset( @@ -92,7 +92,7 @@ class BaseRingBufferTest : public testing::Test { } scoped_ptr<AsyncAPIMock> api_mock_; - scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; + scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; scoped_ptr<CommandBufferService> command_buffer_; scoped_ptr<GpuScheduler> gpu_scheduler_; scoped_ptr<CommandBufferHelper> helper_; @@ -204,4 +204,229 @@ TEST_F(RingBufferTest, TestFreeBug) { allocator_->FreePendingToken(pointer, helper_.get()->InsertToken()); } +// Test that discarding a single allocation clears the block. +TEST_F(RingBufferTest, DiscardTest) { + const unsigned int kAlloc1 = 3*kAlignment; + void* ptr = allocator_->Alloc(kAlloc1); + EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->DiscardBlock(ptr); + EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSizeNoWaiting()); +} + +// Test that discarding front of the buffer effectively frees the block. +TEST_F(RingBufferTest, DiscardFrontTest) { + const unsigned int kAlloc1 = 3*kAlignment; + const unsigned int kAlloc2 = 2*kAlignment; + const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2; + void* ptr1 = allocator_->Alloc(kAlloc1); + EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken()); + + void* ptr2 = allocator_->Alloc(kAlloc2); + EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1, + static_cast<uint8_t*>(ptr2)); + EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2, + allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken()); + + void* ptr3 = allocator_->Alloc(kAlloc3); + EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2, + static_cast<uint8_t*>(ptr3)); + EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting()); + + // Discard first block should free it up upon GetLargestFreeSizeNoWaiting(). + allocator_->DiscardBlock(ptr1); + EXPECT_EQ(kAlloc1, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr3, helper_.get()->InsertToken()); +} + +// Test that discarding middle of the buffer merely marks it as padding. +TEST_F(RingBufferTest, DiscardMiddleTest) { + const unsigned int kAlloc1 = 3*kAlignment; + const unsigned int kAlloc2 = 2*kAlignment; + const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2; + void* ptr1 = allocator_->Alloc(kAlloc1); + EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken()); + + void* ptr2 = allocator_->Alloc(kAlloc2); + EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1, + static_cast<uint8_t*>(ptr2)); + EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2, + allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken()); + + void* ptr3 = allocator_->Alloc(kAlloc3); + EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2, + static_cast<uint8_t*>(ptr3)); + EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting()); + + // Discard middle block should just set it as padding. + allocator_->DiscardBlock(ptr2); + EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr3, helper_.get()->InsertToken()); +} + +// Test that discarding end of the buffer frees it for no waiting. +TEST_F(RingBufferTest, DiscardEndTest) { + const unsigned int kAlloc1 = 3*kAlignment; + const unsigned int kAlloc2 = 2*kAlignment; + const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2; + void* ptr1 = allocator_->Alloc(kAlloc1); + EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken()); + + void* ptr2 = allocator_->Alloc(kAlloc2); + EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1, + static_cast<uint8_t*>(ptr2)); + EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2, + allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken()); + + void* ptr3 = allocator_->Alloc(kAlloc3); + EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2, + static_cast<uint8_t*>(ptr3)); + EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting()); + + // Discard end block should discard it. + allocator_->DiscardBlock(ptr3); + EXPECT_EQ(kAlloc3, allocator_->GetLargestFreeSizeNoWaiting()); +} + +// Test discard end of the buffer that has looped around. +TEST_F(RingBufferTest, DiscardLoopedEndTest) { + const unsigned int kAlloc1 = 3*kAlignment; + const unsigned int kAlloc2 = 2*kAlignment; + const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2; + void* ptr1 = allocator_->Alloc(kAlloc1); + EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken()); + + void* ptr2 = allocator_->Alloc(kAlloc2); + EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1, + static_cast<uint8_t*>(ptr2)); + EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2, + allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken()); + + void* ptr3 = allocator_->Alloc(kAlloc3); + EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2, + static_cast<uint8_t*>(ptr3)); + EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr3, helper_.get()->InsertToken()); + + // This allocation should be at the beginning again, we need to utilize + // DiscardBlock here to discard the first item so that we can allocate + // at the beginning without the FreeOldestBlock() getting called and freeing + // the whole ring buffer. + allocator_->DiscardBlock(ptr1); + void* ptr4 = allocator_->Alloc(kAlloc1); + EXPECT_EQ(ptr1, ptr4); + EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting()); + + // Discard end block should work properly still. + allocator_->DiscardBlock(ptr4); + EXPECT_EQ(kAlloc1, allocator_->GetLargestFreeSizeNoWaiting()); +} + +// Test discard end of the buffer that has looped around with padding. +TEST_F(RingBufferTest, DiscardEndWithPaddingTest) { + const unsigned int kAlloc1 = 3*kAlignment; + const unsigned int kAlloc2 = 2*kAlignment; + const unsigned int kPadding = kAlignment; + const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2 - kPadding; + void* ptr1 = allocator_->Alloc(kAlloc1); + EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken()); + + void* ptr2 = allocator_->Alloc(kAlloc2); + EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1, + static_cast<uint8_t*>(ptr2)); + EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2, + allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken()); + + void* ptr3 = allocator_->Alloc(kAlloc3); + EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2, + static_cast<uint8_t*>(ptr3)); + EXPECT_EQ(kPadding, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr3, helper_.get()->InsertToken()); + + // Cause it to loop around with padding at the end of ptr3. + allocator_->DiscardBlock(ptr1); + void* ptr4 = allocator_->Alloc(kAlloc1); + EXPECT_EQ(ptr1, ptr4); + EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting()); + + // Discard end block should also discard the padding. + allocator_->DiscardBlock(ptr4); + EXPECT_EQ(kAlloc1, allocator_->GetLargestFreeSizeNoWaiting()); + + // We can test that there is padding by attempting to allocate the padding. + void* padding = allocator_->Alloc(kPadding); + EXPECT_EQ(kAlloc1, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(padding, helper_.get()->InsertToken()); +} + +// Test that discard will effectively remove all padding at the end. +TEST_F(RingBufferTest, DiscardAllPaddingFromEndTest) { + const unsigned int kAlloc1 = 3*kAlignment; + const unsigned int kAlloc2 = 2*kAlignment; + const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2; + void* ptr1 = allocator_->Alloc(kAlloc1); + EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken()); + + void* ptr2 = allocator_->Alloc(kAlloc2); + EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1, + static_cast<uint8_t*>(ptr2)); + EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2, + allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken()); + + void* ptr3 = allocator_->Alloc(kAlloc3); + EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2, + static_cast<uint8_t*>(ptr3)); + EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting()); + + // Discarding the middle allocation should turn it into padding. + allocator_->DiscardBlock(ptr2); + EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting()); + + // Discarding the last allocation should discard the middle padding as well. + allocator_->DiscardBlock(ptr3); + EXPECT_EQ(kAlloc2 + kAlloc3, allocator_->GetLargestFreeSizeNoWaiting()); +} + +// Test that discard will effectively remove all padding from the beginning. +TEST_F(RingBufferTest, DiscardAllPaddingFromBeginningTest) { + const unsigned int kAlloc1 = 3*kAlignment; + const unsigned int kAlloc2 = 2*kAlignment; + const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2; + void* ptr1 = allocator_->Alloc(kAlloc1); + EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken()); + + void* ptr2 = allocator_->Alloc(kAlloc2); + EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1, + static_cast<uint8_t*>(ptr2)); + EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2, + allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken()); + + void* ptr3 = allocator_->Alloc(kAlloc3); + EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2, + static_cast<uint8_t*>(ptr3)); + EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting()); + allocator_->FreePendingToken(ptr3, helper_.get()->InsertToken()); + + // Discarding the middle allocation should turn it into padding. + allocator_->DiscardBlock(ptr2); + EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting()); + + // Discarding the first allocation should discard the middle padding as well. + allocator_->DiscardBlock(ptr1); + EXPECT_EQ(kAlloc1 + kAlloc2, allocator_->GetLargestFreeSizeNoWaiting()); +} + } // namespace gpu diff --git a/chromium/gpu/command_buffer/client/share_group.cc b/chromium/gpu/command_buffer/client/share_group.cc index f5c9bf1144c..32e853b7f2f 100644 --- a/chromium/gpu/command_buffer/client/share_group.cc +++ b/chromium/gpu/command_buffer/client/share_group.cc @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <stack> -#include <vector> - #include "gpu/command_buffer/client/share_group.h" +#include <stack> +#include <vector> +#include "base/basictypes.h" #include "base/logging.h" #include "base/synchronization/lock.h" +#include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/command_buffer/client/program_info_manager.h" #include "gpu/command_buffer/common/id_allocator.h" diff --git a/chromium/gpu/command_buffer/client/transfer_buffer.cc b/chromium/gpu/command_buffer/client/transfer_buffer.cc index cb02f15144e..3ff257da5ad 100644 --- a/chromium/gpu/command_buffer/client/transfer_buffer.cc +++ b/chromium/gpu/command_buffer/client/transfer_buffer.cc @@ -73,6 +73,10 @@ RingBuffer::Offset TransferBuffer::GetOffset(void* pointer) const { return ring_buffer_->GetOffset(pointer); } +void TransferBuffer::DiscardBlock(void* p) { + ring_buffer_->DiscardBlock(p); +} + void TransferBuffer::FreePendingToken(void* p, unsigned int token) { ring_buffer_->FreePendingToken(p, token); if (bytes_since_last_flush_ >= size_to_flush_ && size_to_flush_ > 0) { @@ -188,6 +192,14 @@ void ScopedTransferBufferPtr::Release() { } } +void ScopedTransferBufferPtr::Discard() { + if (buffer_) { + transfer_buffer_->DiscardBlock(buffer_); + buffer_ = NULL; + size_ = 0; + } +} + void ScopedTransferBufferPtr::Reset(unsigned int new_size) { Release(); // NOTE: we allocate buffers of size 0 so that HaveBuffer will be true, so diff --git a/chromium/gpu/command_buffer/client/transfer_buffer.h b/chromium/gpu/command_buffer/client/transfer_buffer.h index 39e62a6c67d..e1f8e91ba43 100644 --- a/chromium/gpu/command_buffer/client/transfer_buffer.h +++ b/chromium/gpu/command_buffer/client/transfer_buffer.h @@ -47,6 +47,8 @@ class GPU_EXPORT TransferBufferInterface { virtual RingBuffer::Offset GetOffset(void* pointer) const = 0; + virtual void DiscardBlock(void* p) = 0; + virtual void FreePendingToken(void* p, unsigned int token) = 0; }; @@ -71,6 +73,7 @@ class GPU_EXPORT TransferBuffer : public TransferBufferInterface { void* AllocUpTo(unsigned int size, unsigned int* size_allocated) override; void* Alloc(unsigned int size) override; RingBuffer::Offset GetOffset(void* pointer) const override; + void DiscardBlock(void* p) override; void FreePendingToken(void* p, unsigned int token) override; // These are for testing. @@ -163,6 +166,8 @@ class GPU_EXPORT ScopedTransferBufferPtr { void Release(); + void Discard(); + void Reset(unsigned int new_size); private: diff --git a/chromium/gpu/command_buffer/cmd_buffer_functions.txt b/chromium/gpu/command_buffer/cmd_buffer_functions.txt index a7ec6cebbf1..8b3176a9f4f 100644 --- a/chromium/gpu/command_buffer/cmd_buffer_functions.txt +++ b/chromium/gpu/command_buffer/cmd_buffer_functions.txt @@ -228,7 +228,7 @@ GL_APICALL void GL_APIENTRY glBlitFramebufferCHROMIUM (GLint srcX0, GLin GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleCHROMIUM (GLenumRenderBufferTarget target, GLsizei samples, GLenumRenderBufferFormat internalformat, GLsizei width, GLsizei height); GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenumRenderBufferTarget target, GLsizei samples, GLenumRenderBufferFormat internalformat, GLsizei width, GLsizei height); GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenumFrameBufferTarget target, GLenumAttachment attachment, GLenumTextureTarget textarget, GLidTexture texture, GLintZeroOnly level, GLsizei samples); -GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenumTextureTarget target, GLsizei levels, GLenumTextureInternalFormatStorage internalFormat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenumTextureBindTarget target, GLsizei levels, GLenumTextureInternalFormatStorage internalFormat, GLsizei width, GLsizei height); GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizeiNotNegative n, GLuint* queries); GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizeiNotNegative n, const GLuint* queries); GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLidQuery id); @@ -238,6 +238,7 @@ GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenumQueryTarget target); GL_APICALL void GL_APIENTRY glEndTransformFeedback (void); GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenumQueryTarget target, GLenumQueryParameter pname, GLint* params); GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLidQuery id, GLenumQueryObjectParameter pname, GLuint* params); +GL_APICALL void GL_APIENTRY glGetQueryObjectui64vEXT (GLidQuery id, GLenumQueryObjectParameter pname, GLuint64* params); GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar* marker); GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar* marker); GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void); @@ -274,8 +275,9 @@ GL_APICALL GLuint GL_APIENTRY glCreateGpuMemoryBufferImageCHROMIUM (GLsize GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLidShader shader, GLsizeiNotNegative bufsize, GLsizeiOptional* length, char* source); GL_APICALL void GL_APIENTRY glPostSubBufferCHROMIUM (GLint x, GLint y, GLint width, GLint height); GL_APICALL void GL_APIENTRY glTexImageIOSurface2DCHROMIUM (GLenumTextureBindTarget target, GLsizei width, GLsizei height, GLuint ioSurfaceId, GLuint plane); -GL_APICALL void GL_APIENTRY glCopyTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id, GLintTextureInternalFormat internalformat, GLenumPixelType dest_type); -GL_APICALL void GL_APIENTRY glCopySubTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id, GLint xoffset, GLint yoffset); +GL_APICALL void GL_APIENTRY glCopyTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id, GLintTextureInternalFormat internalformat, GLenumPixelType dest_type, GLboolean unpack_flip_y, GLboolean unpack_premultiply_alpha, GLboolean unpack_unmultiply_alpha); +GL_APICALL void GL_APIENTRY glCopySubTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, GLboolean unpack_flip_y, GLboolean unpack_premultiply_alpha, GLboolean unpack_unmultiply_alpha); +GL_APICALL void GL_APIENTRY glCompressedCopyTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id); GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenumDrawMode mode, GLint first, GLsizei count, GLsizei primcount); GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenumDrawMode mode, GLsizei count, GLenumIndexType type, const void* indices, GLsizei primcount); GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor); @@ -308,10 +310,14 @@ GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei count, const GLenu GL_APICALL void GL_APIENTRY glDiscardBackbufferCHROMIUM (void); GL_APICALL void GL_APIENTRY glScheduleOverlayPlaneCHROMIUM (GLint plane_z_order, GLenum plane_transform, GLuint overlay_texture_id, GLint bounds_x, GLint bounds_y, GLint bounds_width, GLint bounds_height, GLfloat uv_x, GLfloat uv_y, GLfloat uv_width, GLfloat uv_height); GL_APICALL void GL_APIENTRY glSwapInterval (GLint interval); +GL_APICALL void GL_APIENTRY glFlushDriverCachesCHROMIUM (void); // Extension CHROMIUM_path_rendering. GL_APICALL void GL_APIENTRY glMatrixLoadfCHROMIUM (GLenumMatrixMode matrixMode, const GLfloat* m); GL_APICALL void GL_APIENTRY glMatrixLoadIdentityCHROMIUM (GLenumMatrixMode matrixMode); +// Extension KHR_robustness +GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void); + // Extension KHR_blend_equation_advanced GL_APICALL void GL_APIENTRY glBlendBarrierKHR (void); diff --git a/chromium/gpu/command_buffer/common/capabilities.cc b/chromium/gpu/command_buffer/common/capabilities.cc index 8dd208beca4..baec1541118 100644 --- a/chromium/gpu/command_buffer/common/capabilities.cc +++ b/chromium/gpu/command_buffer/common/capabilities.cc @@ -29,6 +29,7 @@ Capabilities::Capabilities() max_combined_fragment_uniform_components(0), max_combined_uniform_blocks(0), max_combined_vertex_uniform_components(0), + max_copy_texture_chromium_size(0), max_draw_buffers(0), max_element_index(0), max_elements_indices(0), @@ -39,6 +40,7 @@ Capabilities::Capabilities() max_program_texel_offset(0), max_samples(0), max_server_wait_timeout(0), + max_texture_lod_bias(0.f), max_transform_feedback_interleaved_components(0), max_transform_feedback_separate_attribs(0), max_transform_feedback_separate_components(0), @@ -71,6 +73,8 @@ Capabilities::Capabilities() blend_equation_advanced(false), blend_equation_advanced_coherent(false), texture_rg(false), + render_buffer_format_bgra8888(false), + occlusion_query_boolean(false), major_version(2), minor_version(0) { } diff --git a/chromium/gpu/command_buffer/common/capabilities.h b/chromium/gpu/command_buffer/common/capabilities.h index 569d573ed62..19f1d26fa05 100644 --- a/chromium/gpu/command_buffer/common/capabilities.h +++ b/chromium/gpu/command_buffer/common/capabilities.h @@ -5,6 +5,8 @@ #ifndef GPU_COMMAND_BUFFER_COMMON_CAPABILITIES_H_ #define GPU_COMMAND_BUFFER_COMMON_CAPABILITIES_H_ +#include <stdint.h> + #include "gpu/gpu_export.h" // From gl2.h. We want to avoid including gl headers because client-side and @@ -82,11 +84,12 @@ struct GPU_EXPORT Capabilities { int max_3d_texture_size; int max_array_texture_layers; int max_color_attachments; - int max_combined_fragment_uniform_components; + int64_t max_combined_fragment_uniform_components; int max_combined_uniform_blocks; - int max_combined_vertex_uniform_components; + int64_t max_combined_vertex_uniform_components; + int max_copy_texture_chromium_size; int max_draw_buffers; - int max_element_index; + int64_t max_element_index; int max_elements_indices; int max_elements_vertices; int max_fragment_input_components; @@ -94,11 +97,12 @@ struct GPU_EXPORT Capabilities { int max_fragment_uniform_components; int max_program_texel_offset; int max_samples; - int max_server_wait_timeout; + int64_t max_server_wait_timeout; + float max_texture_lod_bias; int max_transform_feedback_interleaved_components; int max_transform_feedback_separate_attribs; int max_transform_feedback_separate_components; - int max_uniform_block_size; + int64_t max_uniform_block_size; int max_uniform_buffer_bindings; int max_varying_components; int max_vertex_output_components; @@ -128,6 +132,9 @@ struct GPU_EXPORT Capabilities { bool blend_equation_advanced; bool blend_equation_advanced_coherent; bool texture_rg; + bool render_buffer_format_bgra8888; + bool occlusion_query_boolean; + bool timer_queries; int major_version; int minor_version; diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/chromium/gpu/command_buffer/common/gles2_cmd_format_autogen.h index c25d9d25c72..ae5d0e29891 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -376,7 +376,7 @@ struct BindTexture { typedef BindTexture ValueType; static const CommandId kCmdId = kBindTexture; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -654,7 +654,7 @@ struct BufferData { typedef BufferData ValueType; static const CommandId kCmdId = kBufferData; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -712,7 +712,7 @@ struct BufferSubData { typedef BufferSubData ValueType; static const CommandId kCmdId = kBufferSubData; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -821,7 +821,7 @@ struct Clear { typedef Clear ValueType; static const CommandId kCmdId = kClear; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -852,7 +852,7 @@ struct ClearBufferfi { typedef ClearBufferfi ValueType; static const CommandId kCmdId = kClearBufferfi; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -904,7 +904,7 @@ struct ClearBufferfvImmediate { typedef ClearBufferfvImmediate ValueType; static const CommandId kCmdId = kClearBufferfvImmediate; static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeDataSize() { return static_cast<uint32_t>(sizeof(GLfloat) * 4); @@ -960,7 +960,7 @@ struct ClearBufferivImmediate { typedef ClearBufferivImmediate ValueType; static const CommandId kCmdId = kClearBufferivImmediate; static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeDataSize() { return static_cast<uint32_t>(sizeof(GLint) * 4); @@ -1016,7 +1016,7 @@ struct ClearBufferuivImmediate { typedef ClearBufferuivImmediate ValueType; static const CommandId kCmdId = kClearBufferuivImmediate; static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeDataSize() { return static_cast<uint32_t>(sizeof(GLuint) * 4); @@ -1174,7 +1174,7 @@ struct ClientWaitSync { typedef ClientWaitSync ValueType; static const CommandId kCmdId = kClientWaitSync; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); typedef GLenum Result; @@ -1324,7 +1324,7 @@ struct CompressedTexImage2DBucket { typedef CompressedTexImage2DBucket ValueType; static const CommandId kCmdId = kCompressedTexImage2DBucket; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -1391,7 +1391,7 @@ struct CompressedTexImage2D { typedef CompressedTexImage2D ValueType; static const CommandId kCmdId = kCompressedTexImage2D; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -1470,7 +1470,7 @@ struct CompressedTexSubImage2DBucket { typedef CompressedTexSubImage2DBucket ValueType; static const CommandId kCmdId = kCompressedTexSubImage2DBucket; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -1547,7 +1547,7 @@ struct CompressedTexSubImage2D { typedef CompressedTexSubImage2D ValueType; static const CommandId kCmdId = kCompressedTexSubImage2D; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -1637,7 +1637,7 @@ struct CompressedTexImage3DBucket { typedef CompressedTexImage3DBucket ValueType; static const CommandId kCmdId = kCompressedTexImage3DBucket; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -1710,7 +1710,7 @@ struct CompressedTexImage3D { typedef CompressedTexImage3D ValueType; static const CommandId kCmdId = kCompressedTexImage3D; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -1795,7 +1795,7 @@ struct CompressedTexSubImage3DBucket { typedef CompressedTexSubImage3DBucket ValueType; static const CommandId kCmdId = kCompressedTexSubImage3DBucket; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -1885,7 +1885,7 @@ struct CompressedTexSubImage3D { typedef CompressedTexSubImage3D ValueType; static const CommandId kCmdId = kCompressedTexSubImage3D; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -2046,7 +2046,7 @@ struct CopyTexImage2D { typedef CopyTexImage2D ValueType; static const CommandId kCmdId = kCopyTexImage2D; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -2118,7 +2118,7 @@ struct CopyTexSubImage2D { typedef CopyTexSubImage2D ValueType; static const CommandId kCmdId = kCopyTexSubImage2D; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -2195,7 +2195,7 @@ struct CopyTexSubImage3D { typedef CopyTexSubImage3D ValueType; static const CommandId kCmdId = kCopyTexSubImage3D; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -2420,7 +2420,7 @@ struct DeleteFramebuffersImmediate { typedef DeleteFramebuffersImmediate ValueType; static const CommandId kCmdId = kDeleteFramebuffersImmediate; static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeDataSize(GLsizei n) { return static_cast<uint32_t>(sizeof(GLuint) * n); // NOLINT @@ -2494,7 +2494,7 @@ struct DeleteRenderbuffersImmediate { typedef DeleteRenderbuffersImmediate ValueType; static const CommandId kCmdId = kDeleteRenderbuffersImmediate; static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeDataSize(GLsizei n) { return static_cast<uint32_t>(sizeof(GLuint) * n); // NOLINT @@ -3078,7 +3078,7 @@ struct FenceSync { typedef FenceSync ValueType; static const CommandId kCmdId = kFenceSync; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -3112,7 +3112,7 @@ struct Finish { typedef Finish ValueType; static const CommandId kCmdId = kFinish; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -3138,7 +3138,7 @@ struct Flush { typedef Flush ValueType; static const CommandId kCmdId = kFlush; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -3164,7 +3164,7 @@ struct FramebufferRenderbuffer { typedef FramebufferRenderbuffer ValueType; static const CommandId kCmdId = kFramebufferRenderbuffer; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -3272,7 +3272,7 @@ struct FramebufferTextureLayer { typedef FramebufferTextureLayer ValueType; static const CommandId kCmdId = kFramebufferTextureLayer; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -3405,7 +3405,7 @@ struct GenerateMipmap { typedef GenerateMipmap ValueType; static const CommandId kCmdId = kGenerateMipmap; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -4624,14 +4624,12 @@ struct GetInternalformativ { void Init(GLenum _target, GLenum _format, GLenum _pname, - GLsizei _bufSize, uint32_t _params_shm_id, uint32_t _params_shm_offset) { SetHeader(); target = _target; format = _format; pname = _pname; - bufSize = _bufSize; params_shm_id = _params_shm_id; params_shm_offset = _params_shm_offset; } @@ -4640,11 +4638,10 @@ struct GetInternalformativ { GLenum _target, GLenum _format, GLenum _pname, - GLsizei _bufSize, uint32_t _params_shm_id, uint32_t _params_shm_offset) { - static_cast<ValueType*>(cmd)->Init(_target, _format, _pname, _bufSize, - _params_shm_id, _params_shm_offset); + static_cast<ValueType*>(cmd) + ->Init(_target, _format, _pname, _params_shm_id, _params_shm_offset); return NextCmdAddress<ValueType>(cmd); } @@ -4652,13 +4649,12 @@ struct GetInternalformativ { uint32_t target; uint32_t format; uint32_t pname; - int32_t bufSize; uint32_t params_shm_id; uint32_t params_shm_offset; }; -static_assert(sizeof(GetInternalformativ) == 28, - "size of GetInternalformativ should be 28"); +static_assert(sizeof(GetInternalformativ) == 24, + "size of GetInternalformativ should be 24"); static_assert(offsetof(GetInternalformativ, header) == 0, "offset of GetInternalformativ header should be 0"); static_assert(offsetof(GetInternalformativ, target) == 4, @@ -4667,12 +4663,10 @@ static_assert(offsetof(GetInternalformativ, format) == 8, "offset of GetInternalformativ format should be 8"); static_assert(offsetof(GetInternalformativ, pname) == 12, "offset of GetInternalformativ pname should be 12"); -static_assert(offsetof(GetInternalformativ, bufSize) == 16, - "offset of GetInternalformativ bufSize should be 16"); -static_assert(offsetof(GetInternalformativ, params_shm_id) == 20, - "offset of GetInternalformativ params_shm_id should be 20"); -static_assert(offsetof(GetInternalformativ, params_shm_offset) == 24, - "offset of GetInternalformativ params_shm_offset should be 24"); +static_assert(offsetof(GetInternalformativ, params_shm_id) == 16, + "offset of GetInternalformativ params_shm_id should be 16"); +static_assert(offsetof(GetInternalformativ, params_shm_offset) == 20, + "offset of GetInternalformativ params_shm_offset should be 20"); struct GetProgramiv { typedef GetProgramiv ValueType; @@ -6689,7 +6683,7 @@ struct LinkProgram { typedef LinkProgram ValueType; static const CommandId kCmdId = kLinkProgram; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -6821,7 +6815,7 @@ struct ReadBuffer { typedef ReadBuffer ValueType; static const CommandId kCmdId = kReadBuffer; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -6856,7 +6850,7 @@ struct ReadPixels { typedef ReadPixels ValueType; static const CommandId kCmdId = kReadPixels; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); typedef uint32_t Result; @@ -6980,7 +6974,7 @@ struct RenderbufferStorage { typedef RenderbufferStorage ValueType; static const CommandId kCmdId = kRenderbufferStorage; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -7658,7 +7652,7 @@ struct TexImage2D { typedef TexImage2D ValueType; static const CommandId kCmdId = kTexImage2D; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -7742,7 +7736,7 @@ struct TexImage3D { typedef TexImage3D ValueType; static const CommandId kCmdId = kTexImage3D; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -8000,7 +7994,7 @@ struct TexStorage3D { typedef TexStorage3D ValueType; static const CommandId kCmdId = kTexStorage3D; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -8064,7 +8058,7 @@ struct TexSubImage2D { typedef TexSubImage2D ValueType; static const CommandId kCmdId = kTexSubImage2D; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -8160,7 +8154,7 @@ struct TexSubImage3D { typedef TexSubImage3D ValueType; static const CommandId kCmdId = kTexSubImage3D; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -10586,7 +10580,7 @@ struct WaitSync { typedef WaitSync ValueType; static const CommandId kCmdId = kWaitSync; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -10727,7 +10721,7 @@ struct RenderbufferStorageMultisampleCHROMIUM { typedef RenderbufferStorageMultisampleCHROMIUM ValueType; static const CommandId kCmdId = kRenderbufferStorageMultisampleCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -10794,7 +10788,7 @@ struct RenderbufferStorageMultisampleEXT { typedef RenderbufferStorageMultisampleEXT ValueType; static const CommandId kCmdId = kRenderbufferStorageMultisampleEXT; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -10922,7 +10916,7 @@ struct TexStorage2DEXT { typedef TexStorage2DEXT ValueType; static const CommandId kCmdId = kTexStorage2DEXT; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -11617,7 +11611,7 @@ struct MapBufferRange { typedef MapBufferRange ValueType; static const CommandId kCmdId = kMapBufferRange; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); typedef uint32_t Result; @@ -11697,7 +11691,7 @@ struct UnmapBuffer { typedef UnmapBuffer ValueType; static const CommandId kCmdId = kUnmapBuffer; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -11729,7 +11723,7 @@ struct ResizeCHROMIUM { typedef ResizeCHROMIUM ValueType; static const CommandId kCmdId = kResizeCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -12091,7 +12085,7 @@ struct TexImageIOSurface2DCHROMIUM { typedef TexImageIOSurface2DCHROMIUM ValueType; static const CommandId kCmdId = kTexImageIOSurface2DCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -12150,7 +12144,7 @@ struct CopyTextureCHROMIUM { typedef CopyTextureCHROMIUM ValueType; static const CommandId kCmdId = kCopyTextureCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -12162,13 +12156,19 @@ struct CopyTextureCHROMIUM { GLenum _source_id, GLenum _dest_id, GLint _internalformat, - GLenum _dest_type) { + GLenum _dest_type, + GLboolean _unpack_flip_y, + GLboolean _unpack_premultiply_alpha, + GLboolean _unpack_unmultiply_alpha) { SetHeader(); target = _target; source_id = _source_id; dest_id = _dest_id; internalformat = _internalformat; dest_type = _dest_type; + unpack_flip_y = _unpack_flip_y; + unpack_premultiply_alpha = _unpack_premultiply_alpha; + unpack_unmultiply_alpha = _unpack_unmultiply_alpha; } void* Set(void* cmd, @@ -12176,9 +12176,13 @@ struct CopyTextureCHROMIUM { GLenum _source_id, GLenum _dest_id, GLint _internalformat, - GLenum _dest_type) { - static_cast<ValueType*>(cmd) - ->Init(_target, _source_id, _dest_id, _internalformat, _dest_type); + GLenum _dest_type, + GLboolean _unpack_flip_y, + GLboolean _unpack_premultiply_alpha, + GLboolean _unpack_unmultiply_alpha) { + static_cast<ValueType*>(cmd)->Init( + _target, _source_id, _dest_id, _internalformat, _dest_type, + _unpack_flip_y, _unpack_premultiply_alpha, _unpack_unmultiply_alpha); return NextCmdAddress<ValueType>(cmd); } @@ -12188,10 +12192,13 @@ struct CopyTextureCHROMIUM { uint32_t dest_id; int32_t internalformat; uint32_t dest_type; + uint32_t unpack_flip_y; + uint32_t unpack_premultiply_alpha; + uint32_t unpack_unmultiply_alpha; }; -static_assert(sizeof(CopyTextureCHROMIUM) == 24, - "size of CopyTextureCHROMIUM should be 24"); +static_assert(sizeof(CopyTextureCHROMIUM) == 36, + "size of CopyTextureCHROMIUM should be 36"); static_assert(offsetof(CopyTextureCHROMIUM, header) == 0, "offset of CopyTextureCHROMIUM header should be 0"); static_assert(offsetof(CopyTextureCHROMIUM, target) == 4, @@ -12204,12 +12211,20 @@ static_assert(offsetof(CopyTextureCHROMIUM, internalformat) == 16, "offset of CopyTextureCHROMIUM internalformat should be 16"); static_assert(offsetof(CopyTextureCHROMIUM, dest_type) == 20, "offset of CopyTextureCHROMIUM dest_type should be 20"); +static_assert(offsetof(CopyTextureCHROMIUM, unpack_flip_y) == 24, + "offset of CopyTextureCHROMIUM unpack_flip_y should be 24"); +static_assert( + offsetof(CopyTextureCHROMIUM, unpack_premultiply_alpha) == 28, + "offset of CopyTextureCHROMIUM unpack_premultiply_alpha should be 28"); +static_assert( + offsetof(CopyTextureCHROMIUM, unpack_unmultiply_alpha) == 32, + "offset of CopyTextureCHROMIUM unpack_unmultiply_alpha should be 32"); struct CopySubTextureCHROMIUM { typedef CopySubTextureCHROMIUM ValueType; static const CommandId kCmdId = kCopySubTextureCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -12221,13 +12236,27 @@ struct CopySubTextureCHROMIUM { GLenum _source_id, GLenum _dest_id, GLint _xoffset, - GLint _yoffset) { + GLint _yoffset, + GLint _x, + GLint _y, + GLsizei _width, + GLsizei _height, + GLboolean _unpack_flip_y, + GLboolean _unpack_premultiply_alpha, + GLboolean _unpack_unmultiply_alpha) { SetHeader(); target = _target; source_id = _source_id; dest_id = _dest_id; xoffset = _xoffset; yoffset = _yoffset; + x = _x; + y = _y; + width = _width; + height = _height; + unpack_flip_y = _unpack_flip_y; + unpack_premultiply_alpha = _unpack_premultiply_alpha; + unpack_unmultiply_alpha = _unpack_unmultiply_alpha; } void* Set(void* cmd, @@ -12235,9 +12264,18 @@ struct CopySubTextureCHROMIUM { GLenum _source_id, GLenum _dest_id, GLint _xoffset, - GLint _yoffset) { + GLint _yoffset, + GLint _x, + GLint _y, + GLsizei _width, + GLsizei _height, + GLboolean _unpack_flip_y, + GLboolean _unpack_premultiply_alpha, + GLboolean _unpack_unmultiply_alpha) { static_cast<ValueType*>(cmd) - ->Init(_target, _source_id, _dest_id, _xoffset, _yoffset); + ->Init(_target, _source_id, _dest_id, _xoffset, _yoffset, _x, _y, + _width, _height, _unpack_flip_y, _unpack_premultiply_alpha, + _unpack_unmultiply_alpha); return NextCmdAddress<ValueType>(cmd); } @@ -12247,10 +12285,17 @@ struct CopySubTextureCHROMIUM { uint32_t dest_id; int32_t xoffset; int32_t yoffset; + int32_t x; + int32_t y; + int32_t width; + int32_t height; + uint32_t unpack_flip_y; + uint32_t unpack_premultiply_alpha; + uint32_t unpack_unmultiply_alpha; }; -static_assert(sizeof(CopySubTextureCHROMIUM) == 24, - "size of CopySubTextureCHROMIUM should be 24"); +static_assert(sizeof(CopySubTextureCHROMIUM) == 52, + "size of CopySubTextureCHROMIUM should be 52"); static_assert(offsetof(CopySubTextureCHROMIUM, header) == 0, "offset of CopySubTextureCHROMIUM header should be 0"); static_assert(offsetof(CopySubTextureCHROMIUM, target) == 4, @@ -12263,12 +12308,69 @@ static_assert(offsetof(CopySubTextureCHROMIUM, xoffset) == 16, "offset of CopySubTextureCHROMIUM xoffset should be 16"); static_assert(offsetof(CopySubTextureCHROMIUM, yoffset) == 20, "offset of CopySubTextureCHROMIUM yoffset should be 20"); +static_assert(offsetof(CopySubTextureCHROMIUM, x) == 24, + "offset of CopySubTextureCHROMIUM x should be 24"); +static_assert(offsetof(CopySubTextureCHROMIUM, y) == 28, + "offset of CopySubTextureCHROMIUM y should be 28"); +static_assert(offsetof(CopySubTextureCHROMIUM, width) == 32, + "offset of CopySubTextureCHROMIUM width should be 32"); +static_assert(offsetof(CopySubTextureCHROMIUM, height) == 36, + "offset of CopySubTextureCHROMIUM height should be 36"); +static_assert(offsetof(CopySubTextureCHROMIUM, unpack_flip_y) == 40, + "offset of CopySubTextureCHROMIUM unpack_flip_y should be 40"); +static_assert( + offsetof(CopySubTextureCHROMIUM, unpack_premultiply_alpha) == 44, + "offset of CopySubTextureCHROMIUM unpack_premultiply_alpha should be 44"); +static_assert( + offsetof(CopySubTextureCHROMIUM, unpack_unmultiply_alpha) == 48, + "offset of CopySubTextureCHROMIUM unpack_unmultiply_alpha should be 48"); + +struct CompressedCopyTextureCHROMIUM { + typedef CompressedCopyTextureCHROMIUM ValueType; + static const CommandId kCmdId = kCompressedCopyTextureCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLenum _target, GLenum _source_id, GLenum _dest_id) { + SetHeader(); + target = _target; + source_id = _source_id; + dest_id = _dest_id; + } + + void* Set(void* cmd, GLenum _target, GLenum _source_id, GLenum _dest_id) { + static_cast<ValueType*>(cmd)->Init(_target, _source_id, _dest_id); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t target; + uint32_t source_id; + uint32_t dest_id; +}; + +static_assert(sizeof(CompressedCopyTextureCHROMIUM) == 16, + "size of CompressedCopyTextureCHROMIUM should be 16"); +static_assert(offsetof(CompressedCopyTextureCHROMIUM, header) == 0, + "offset of CompressedCopyTextureCHROMIUM header should be 0"); +static_assert(offsetof(CompressedCopyTextureCHROMIUM, target) == 4, + "offset of CompressedCopyTextureCHROMIUM target should be 4"); +static_assert(offsetof(CompressedCopyTextureCHROMIUM, source_id) == 8, + "offset of CompressedCopyTextureCHROMIUM source_id should be 8"); +static_assert(offsetof(CompressedCopyTextureCHROMIUM, dest_id) == 12, + "offset of CompressedCopyTextureCHROMIUM dest_id should be 12"); struct DrawArraysInstancedANGLE { typedef DrawArraysInstancedANGLE ValueType; static const CommandId kCmdId = kDrawArraysInstancedANGLE; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -12317,7 +12419,7 @@ struct DrawElementsInstancedANGLE { typedef DrawElementsInstancedANGLE ValueType; static const CommandId kCmdId = kDrawElementsInstancedANGLE; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -12501,7 +12603,7 @@ struct ConsumeTextureCHROMIUMImmediate { typedef ConsumeTextureCHROMIUMImmediate ValueType; static const CommandId kCmdId = kConsumeTextureCHROMIUMImmediate; static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeDataSize() { return static_cast<uint32_t>(sizeof(GLbyte) * 64); @@ -13007,7 +13109,7 @@ struct AsyncTexSubImage2DCHROMIUM { typedef AsyncTexSubImage2DCHROMIUM ValueType; static const CommandId kCmdId = kAsyncTexSubImage2DCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -13120,7 +13222,7 @@ struct AsyncTexImage2DCHROMIUM { typedef AsyncTexImage2DCHROMIUM ValueType; static const CommandId kCmdId = kAsyncTexImage2DCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -13228,7 +13330,7 @@ struct WaitAsyncTexImage2DCHROMIUM { typedef WaitAsyncTexImage2DCHROMIUM ValueType; static const CommandId kCmdId = kWaitAsyncTexImage2DCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -13261,7 +13363,7 @@ struct WaitAllAsyncTexImage2DCHROMIUM { typedef WaitAllAsyncTexImage2DCHROMIUM ValueType; static const CommandId kCmdId = kWaitAllAsyncTexImage2DCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -13288,7 +13390,7 @@ struct DiscardFramebufferEXTImmediate { typedef DiscardFramebufferEXTImmediate ValueType; static const CommandId kCmdId = kDiscardFramebufferEXTImmediate; static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeDataSize(GLsizei count) { return static_cast<uint32_t>(sizeof(GLenum) * 1 * count); // NOLINT @@ -13337,7 +13439,7 @@ struct LoseContextCHROMIUM { typedef LoseContextCHROMIUM ValueType; static const CommandId kCmdId = kLoseContextCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -13407,7 +13509,7 @@ struct DrawBuffersEXTImmediate { typedef DrawBuffersEXTImmediate ValueType; static const CommandId kCmdId = kDrawBuffersEXTImmediate; static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeDataSize(GLsizei count) { return static_cast<uint32_t>(sizeof(GLenum) * 1 * count); // NOLINT @@ -13449,7 +13551,7 @@ struct DiscardBackbufferCHROMIUM { typedef DiscardBackbufferCHROMIUM ValueType; static const CommandId kCmdId = kDiscardBackbufferCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); static uint32_t ComputeSize() { return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT @@ -13606,6 +13708,33 @@ static_assert(offsetof(SwapInterval, header) == 0, static_assert(offsetof(SwapInterval, interval) == 4, "offset of SwapInterval interval should be 4"); +struct FlushDriverCachesCHROMIUM { + typedef FlushDriverCachesCHROMIUM ValueType; + static const CommandId kCmdId = kFlushDriverCachesCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init() { SetHeader(); } + + void* Set(void* cmd) { + static_cast<ValueType*>(cmd)->Init(); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; +}; + +static_assert(sizeof(FlushDriverCachesCHROMIUM) == 4, + "size of FlushDriverCachesCHROMIUM should be 4"); +static_assert(offsetof(FlushDriverCachesCHROMIUM, header) == 0, + "offset of FlushDriverCachesCHROMIUM header should be 0"); + struct MatrixLoadfCHROMIUMImmediate { typedef MatrixLoadfCHROMIUMImmediate ValueType; static const CommandId kCmdId = kMatrixLoadfCHROMIUMImmediate; diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/chromium/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index ad56c24d423..bc74f593935 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -1441,17 +1441,16 @@ TEST_F(GLES2FormatTest, GetInternalformativ) { cmds::GetInternalformativ& cmd = *GetBufferAs<cmds::GetInternalformativ>(); void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<GLenum>(12), - static_cast<GLenum>(13), static_cast<GLsizei>(14), - static_cast<uint32_t>(15), static_cast<uint32_t>(16)); + static_cast<GLenum>(13), static_cast<uint32_t>(14), + static_cast<uint32_t>(15)); EXPECT_EQ(static_cast<uint32_t>(cmds::GetInternalformativ::kCmdId), cmd.header.command); EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); EXPECT_EQ(static_cast<GLenum>(11), cmd.target); EXPECT_EQ(static_cast<GLenum>(12), cmd.format); EXPECT_EQ(static_cast<GLenum>(13), cmd.pname); - EXPECT_EQ(static_cast<GLsizei>(14), cmd.bufSize); - EXPECT_EQ(static_cast<uint32_t>(15), cmd.params_shm_id); - EXPECT_EQ(static_cast<uint32_t>(16), cmd.params_shm_offset); + EXPECT_EQ(static_cast<uint32_t>(14), cmd.params_shm_id); + EXPECT_EQ(static_cast<uint32_t>(15), cmd.params_shm_offset); CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } @@ -4130,9 +4129,11 @@ TEST_F(GLES2FormatTest, TexImageIOSurface2DCHROMIUM) { TEST_F(GLES2FormatTest, CopyTextureCHROMIUM) { cmds::CopyTextureCHROMIUM& cmd = *GetBufferAs<cmds::CopyTextureCHROMIUM>(); - void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11), - static_cast<GLenum>(12), static_cast<GLenum>(13), - static_cast<GLint>(14), static_cast<GLenum>(15)); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<GLenum>(12), + static_cast<GLenum>(13), static_cast<GLint>(14), + static_cast<GLenum>(15), static_cast<GLboolean>(16), + static_cast<GLboolean>(17), static_cast<GLboolean>(18)); EXPECT_EQ(static_cast<uint32_t>(cmds::CopyTextureCHROMIUM::kCmdId), cmd.header.command); EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); @@ -4141,15 +4142,21 @@ TEST_F(GLES2FormatTest, CopyTextureCHROMIUM) { EXPECT_EQ(static_cast<GLenum>(13), cmd.dest_id); EXPECT_EQ(static_cast<GLint>(14), cmd.internalformat); EXPECT_EQ(static_cast<GLenum>(15), cmd.dest_type); + EXPECT_EQ(static_cast<GLboolean>(16), cmd.unpack_flip_y); + EXPECT_EQ(static_cast<GLboolean>(17), cmd.unpack_premultiply_alpha); + EXPECT_EQ(static_cast<GLboolean>(18), cmd.unpack_unmultiply_alpha); CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } TEST_F(GLES2FormatTest, CopySubTextureCHROMIUM) { cmds::CopySubTextureCHROMIUM& cmd = *GetBufferAs<cmds::CopySubTextureCHROMIUM>(); - void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11), - static_cast<GLenum>(12), static_cast<GLenum>(13), - static_cast<GLint>(14), static_cast<GLint>(15)); + void* next_cmd = cmd.Set( + &cmd, static_cast<GLenum>(11), static_cast<GLenum>(12), + static_cast<GLenum>(13), static_cast<GLint>(14), static_cast<GLint>(15), + static_cast<GLint>(16), static_cast<GLint>(17), static_cast<GLsizei>(18), + static_cast<GLsizei>(19), static_cast<GLboolean>(20), + static_cast<GLboolean>(21), static_cast<GLboolean>(22)); EXPECT_EQ(static_cast<uint32_t>(cmds::CopySubTextureCHROMIUM::kCmdId), cmd.header.command); EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); @@ -4158,6 +4165,27 @@ TEST_F(GLES2FormatTest, CopySubTextureCHROMIUM) { EXPECT_EQ(static_cast<GLenum>(13), cmd.dest_id); EXPECT_EQ(static_cast<GLint>(14), cmd.xoffset); EXPECT_EQ(static_cast<GLint>(15), cmd.yoffset); + EXPECT_EQ(static_cast<GLint>(16), cmd.x); + EXPECT_EQ(static_cast<GLint>(17), cmd.y); + EXPECT_EQ(static_cast<GLsizei>(18), cmd.width); + EXPECT_EQ(static_cast<GLsizei>(19), cmd.height); + EXPECT_EQ(static_cast<GLboolean>(20), cmd.unpack_flip_y); + EXPECT_EQ(static_cast<GLboolean>(21), cmd.unpack_premultiply_alpha); + EXPECT_EQ(static_cast<GLboolean>(22), cmd.unpack_unmultiply_alpha); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, CompressedCopyTextureCHROMIUM) { + cmds::CompressedCopyTextureCHROMIUM& cmd = + *GetBufferAs<cmds::CompressedCopyTextureCHROMIUM>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11), + static_cast<GLenum>(12), static_cast<GLenum>(13)); + EXPECT_EQ(static_cast<uint32_t>(cmds::CompressedCopyTextureCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + EXPECT_EQ(static_cast<GLenum>(12), cmd.source_id); + EXPECT_EQ(static_cast<GLenum>(13), cmd.dest_id); CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } @@ -4815,6 +4843,16 @@ TEST_F(GLES2FormatTest, SwapInterval) { CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, FlushDriverCachesCHROMIUM) { + cmds::FlushDriverCachesCHROMIUM& cmd = + *GetBufferAs<cmds::FlushDriverCachesCHROMIUM>(); + void* next_cmd = cmd.Set(&cmd); + EXPECT_EQ(static_cast<uint32_t>(cmds::FlushDriverCachesCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, MatrixLoadfCHROMIUMImmediate) { const int kSomeBaseValueToTestWith = 51; static GLfloat data[] = { diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/chromium/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index ba8f073ca42..35c09fa4f36 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -267,41 +267,43 @@ OP(TexImageIOSurface2DCHROMIUM) /* 508 */ \ OP(CopyTextureCHROMIUM) /* 509 */ \ OP(CopySubTextureCHROMIUM) /* 510 */ \ - OP(DrawArraysInstancedANGLE) /* 511 */ \ - OP(DrawElementsInstancedANGLE) /* 512 */ \ - OP(VertexAttribDivisorANGLE) /* 513 */ \ - OP(GenMailboxCHROMIUM) /* 514 */ \ - OP(ProduceTextureCHROMIUMImmediate) /* 515 */ \ - OP(ProduceTextureDirectCHROMIUMImmediate) /* 516 */ \ - OP(ConsumeTextureCHROMIUMImmediate) /* 517 */ \ - OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 518 */ \ - OP(BindUniformLocationCHROMIUMBucket) /* 519 */ \ - OP(GenValuebuffersCHROMIUMImmediate) /* 520 */ \ - OP(DeleteValuebuffersCHROMIUMImmediate) /* 521 */ \ - OP(IsValuebufferCHROMIUM) /* 522 */ \ - OP(BindValuebufferCHROMIUM) /* 523 */ \ - OP(SubscribeValueCHROMIUM) /* 524 */ \ - OP(PopulateSubscribedValuesCHROMIUM) /* 525 */ \ - OP(UniformValuebufferCHROMIUM) /* 526 */ \ - OP(BindTexImage2DCHROMIUM) /* 527 */ \ - OP(ReleaseTexImage2DCHROMIUM) /* 528 */ \ - OP(TraceBeginCHROMIUM) /* 529 */ \ - OP(TraceEndCHROMIUM) /* 530 */ \ - OP(AsyncTexSubImage2DCHROMIUM) /* 531 */ \ - OP(AsyncTexImage2DCHROMIUM) /* 532 */ \ - OP(WaitAsyncTexImage2DCHROMIUM) /* 533 */ \ - OP(WaitAllAsyncTexImage2DCHROMIUM) /* 534 */ \ - OP(DiscardFramebufferEXTImmediate) /* 535 */ \ - OP(LoseContextCHROMIUM) /* 536 */ \ - OP(InsertSyncPointCHROMIUM) /* 537 */ \ - OP(WaitSyncPointCHROMIUM) /* 538 */ \ - OP(DrawBuffersEXTImmediate) /* 539 */ \ - OP(DiscardBackbufferCHROMIUM) /* 540 */ \ - OP(ScheduleOverlayPlaneCHROMIUM) /* 541 */ \ - OP(SwapInterval) /* 542 */ \ - OP(MatrixLoadfCHROMIUMImmediate) /* 543 */ \ - OP(MatrixLoadIdentityCHROMIUM) /* 544 */ \ - OP(BlendBarrierKHR) /* 545 */ + OP(CompressedCopyTextureCHROMIUM) /* 511 */ \ + OP(DrawArraysInstancedANGLE) /* 512 */ \ + OP(DrawElementsInstancedANGLE) /* 513 */ \ + OP(VertexAttribDivisorANGLE) /* 514 */ \ + OP(GenMailboxCHROMIUM) /* 515 */ \ + OP(ProduceTextureCHROMIUMImmediate) /* 516 */ \ + OP(ProduceTextureDirectCHROMIUMImmediate) /* 517 */ \ + OP(ConsumeTextureCHROMIUMImmediate) /* 518 */ \ + OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 519 */ \ + OP(BindUniformLocationCHROMIUMBucket) /* 520 */ \ + OP(GenValuebuffersCHROMIUMImmediate) /* 521 */ \ + OP(DeleteValuebuffersCHROMIUMImmediate) /* 522 */ \ + OP(IsValuebufferCHROMIUM) /* 523 */ \ + OP(BindValuebufferCHROMIUM) /* 524 */ \ + OP(SubscribeValueCHROMIUM) /* 525 */ \ + OP(PopulateSubscribedValuesCHROMIUM) /* 526 */ \ + OP(UniformValuebufferCHROMIUM) /* 527 */ \ + OP(BindTexImage2DCHROMIUM) /* 528 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 529 */ \ + OP(TraceBeginCHROMIUM) /* 530 */ \ + OP(TraceEndCHROMIUM) /* 531 */ \ + OP(AsyncTexSubImage2DCHROMIUM) /* 532 */ \ + OP(AsyncTexImage2DCHROMIUM) /* 533 */ \ + OP(WaitAsyncTexImage2DCHROMIUM) /* 534 */ \ + OP(WaitAllAsyncTexImage2DCHROMIUM) /* 535 */ \ + OP(DiscardFramebufferEXTImmediate) /* 536 */ \ + OP(LoseContextCHROMIUM) /* 537 */ \ + OP(InsertSyncPointCHROMIUM) /* 538 */ \ + OP(WaitSyncPointCHROMIUM) /* 539 */ \ + OP(DrawBuffersEXTImmediate) /* 540 */ \ + OP(DiscardBackbufferCHROMIUM) /* 541 */ \ + OP(ScheduleOverlayPlaneCHROMIUM) /* 542 */ \ + OP(SwapInterval) /* 543 */ \ + OP(FlushDriverCachesCHROMIUM) /* 544 */ \ + OP(MatrixLoadfCHROMIUMImmediate) /* 545 */ \ + OP(MatrixLoadIdentityCHROMIUM) /* 546 */ \ + OP(BlendBarrierKHR) /* 547 */ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this. diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_utils.cc b/chromium/gpu/command_buffer/common/gles2_cmd_utils.cc index d58156f37e6..7a33ab1e48f 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_utils.cc +++ b/chromium/gpu/command_buffer/common/gles2_cmd_utils.cc @@ -207,6 +207,21 @@ int GLES2Util::GLGetNumValuesReturned(int id) const { return 1; case GL_VIEWPORT: return 4; + + // ES3 + case GL_COPY_READ_BUFFER_BINDING: + return 1; + case GL_COPY_WRITE_BUFFER_BINDING: + return 1; + case GL_PIXEL_PACK_BUFFER_BINDING: + return 1; + case GL_PIXEL_UNPACK_BUFFER_BINDING: + return 1; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + return 1; + case GL_UNIFORM_BUFFER_BINDING: + return 1; + // -- glGetBooleanv, glGetFloatv, glGetIntergerv with // GL_CHROMIUM_framebuffer_multisample case GL_MAX_SAMPLES_EXT: @@ -258,7 +273,6 @@ int GLES2Util::GLGetNumValuesReturned(int id) const { case GL_ACTIVE_UNIFORM_MAX_LENGTH: return 1; - // -- glGetRenderbufferAttachmentParameteriv case GL_RENDERBUFFER_WIDTH: return 1; @@ -1068,7 +1082,7 @@ const int32 kBufferDestroyed = 0x3095; // EGL_BUFFER_DESTROYED const int32 kBindGeneratesResource = 0x10000; const int32 kFailIfMajorPerfCaveat = 0x10001; const int32 kLoseContextWhenOutOfMemory = 0x10002; -const int32 kES3ContextRequired = 0x10003; +const int32 kWebGLVersion = 0x10003; } // namespace @@ -1085,7 +1099,8 @@ ContextCreationAttribHelper::ContextCreationAttribHelper() bind_generates_resource(true), fail_if_major_perf_caveat(false), lose_context_when_out_of_memory(false), - es3_context_required(false) {} + webgl_version(0) { +} void ContextCreationAttribHelper::Serialize(std::vector<int32>* attribs) const { if (alpha_size != -1) { @@ -1128,8 +1143,8 @@ void ContextCreationAttribHelper::Serialize(std::vector<int32>* attribs) const { attribs->push_back(fail_if_major_perf_caveat ? 1 : 0); attribs->push_back(kLoseContextWhenOutOfMemory); attribs->push_back(lose_context_when_out_of_memory ? 1 : 0); - attribs->push_back(kES3ContextRequired); - attribs->push_back(es3_context_required ? 1 : 0); + attribs->push_back(kWebGLVersion); + attribs->push_back(webgl_version); attribs->push_back(kNone); } @@ -1184,8 +1199,8 @@ bool ContextCreationAttribHelper::Parse(const std::vector<int32>& attribs) { case kLoseContextWhenOutOfMemory: lose_context_when_out_of_memory = value != 0; break; - case kES3ContextRequired: - es3_context_required = value != 0; + case kWebGLVersion: + webgl_version = value; break; case kNone: // Terminate list, even if more attributes. diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_utils.h b/chromium/gpu/command_buffer/common/gles2_cmd_utils.h index aac9d6036ed..12b155145f6 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_utils.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_utils.h @@ -216,7 +216,8 @@ struct GLES2_UTILS_EXPORT ContextCreationAttribHelper { bool bind_generates_resource; bool fail_if_major_perf_caveat; bool lose_context_when_out_of_memory; - bool es3_context_required; + // 0 if not a WebGL context. + unsigned webgl_version; }; } // namespace gles2 diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/chromium/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index 7cba5373ee6..3dd31caeb66 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -529,10 +529,6 @@ static const GLES2Util::EnumToString enum_to_string_table[] = { "GL_UNIFORM_BLOCK_DATA_SIZE", }, { - 0x9242, - "GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM", - }, - { 0x821D, "GL_NUM_EXTENSIONS", }, @@ -2197,10 +2193,6 @@ static const GLES2Util::EnumToString enum_to_string_table[] = { "GL_RG8UI", }, { - 0x9240, - "GL_UNPACK_FLIP_Y_CHROMIUM", - }, - { 0x8DF6, "GL_UNSIGNED_INT_10_10_10_2_OES", }, @@ -3465,10 +3457,6 @@ static const GLES2Util::EnumToString enum_to_string_table[] = { "GL_FLOAT_MAT2x3_NV", }, { - 0x9241, - "GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM", - }, - { 0x00010000, "GL_STENCIL_BUFFER_BIT0_QCOM", }, @@ -4774,11 +4762,6 @@ std::string GLES2Util::GetStringGLState(uint32_t value) { {GL_TEXTURE_BINDING_2D, "GL_TEXTURE_BINDING_2D"}, {GL_TEXTURE_BINDING_CUBE_MAP, "GL_TEXTURE_BINDING_CUBE_MAP"}, {GL_UNPACK_ALIGNMENT, "GL_UNPACK_ALIGNMENT"}, - {GL_UNPACK_FLIP_Y_CHROMIUM, "GL_UNPACK_FLIP_Y_CHROMIUM"}, - {GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, - "GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM"}, - {GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, - "GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM"}, {GL_BIND_GENERATES_RESOURCE_CHROMIUM, "GL_BIND_GENERATES_RESOURCE_CHROMIUM"}, {GL_VERTEX_ARRAY_BINDING_OES, "GL_VERTEX_ARRAY_BINDING_OES"}, @@ -5055,11 +5038,6 @@ std::string GLES2Util::GetStringPixelStore(uint32_t value) { static const EnumToString string_table[] = { {GL_PACK_ALIGNMENT, "GL_PACK_ALIGNMENT"}, {GL_UNPACK_ALIGNMENT, "GL_UNPACK_ALIGNMENT"}, - {GL_UNPACK_FLIP_Y_CHROMIUM, "GL_UNPACK_FLIP_Y_CHROMIUM"}, - {GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, - "GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM"}, - {GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, - "GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM"}, {GL_PACK_ROW_LENGTH, "GL_PACK_ROW_LENGTH"}, {GL_PACK_SKIP_PIXELS, "GL_PACK_SKIP_PIXELS"}, {GL_PACK_SKIP_ROWS, "GL_PACK_SKIP_ROWS"}, @@ -5546,6 +5524,7 @@ std::string GLES2Util::GetStringTextureInternalFormatStorage(uint32_t value) { {GL_RG16I, "GL_RG16I"}, {GL_RG32UI, "GL_RG32UI"}, {GL_RG32I, "GL_RG32I"}, + {GL_RGB8, "GL_RGB8"}, {GL_SRGB8, "GL_SRGB8"}, {GL_RGB8_SNORM, "GL_RGB8_SNORM"}, {GL_R11F_G11F_B10F, "GL_R11F_G11F_B10F"}, @@ -5558,6 +5537,7 @@ std::string GLES2Util::GetStringTextureInternalFormatStorage(uint32_t value) { {GL_RGB16I, "GL_RGB16I"}, {GL_RGB32UI, "GL_RGB32UI"}, {GL_RGB32I, "GL_RGB32I"}, + {GL_RGBA8, "GL_RGBA8"}, {GL_SRGB8_ALPHA8, "GL_SRGB8_ALPHA8"}, {GL_RGBA8_SNORM, "GL_RGBA8_SNORM"}, {GL_RGB10_A2, "GL_RGB10_A2"}, diff --git a/chromium/gpu/command_buffer/common/mailbox.h b/chromium/gpu/command_buffer/common/mailbox.h index a45c91f279b..67b023e9936 100644 --- a/chromium/gpu/command_buffer/common/mailbox.h +++ b/chromium/gpu/command_buffer/common/mailbox.h @@ -18,6 +18,8 @@ namespace gpu { struct GPU_EXPORT Mailbox { + using Name = int8_t[GL_MAILBOX_SIZE_CHROMIUM]; + Mailbox(); bool IsZero() const; void SetZero(); @@ -31,7 +33,8 @@ struct GPU_EXPORT Mailbox { // check, only to catch bugs where clients forgot to call Mailbox::Generate. bool Verify() const; - int8_t name[GL_MAILBOX_SIZE_CHROMIUM]; + Name name; + bool operator<(const Mailbox& other) const { return memcmp(this, &other, sizeof other) < 0; } diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc index 971dc0d79da..6e1c3e7c61e 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc @@ -90,10 +90,11 @@ void PerformNotifyCompletion( class TransferThread : public base::Thread { public: TransferThread() : base::Thread(kAsyncTransferThreadName) { - Start(); -#if defined(OS_ANDROID) || defined(OS_LINUX) - SetPriority(base::ThreadPriority::BACKGROUND); + base::Thread::Options options; +#if defined(OS_ANDROID) + options.priority = base::ThreadPriority::BACKGROUND; #endif + StartWithOptions(options); } ~TransferThread() override { Stop(); } @@ -467,16 +468,8 @@ bool AsyncPixelTransferDelegateEGL::TransferIsInProgress() { void AsyncPixelTransferDelegateEGL::WaitForTransferCompletion() { if (state_->TransferIsInProgress()) { -#if defined(OS_ANDROID) || defined(OS_LINUX) - g_transfer_thread.Pointer()->SetPriority(base::ThreadPriority::DISPLAY); -#endif - state_->WaitForTransferCompletion(); DCHECK(!state_->TransferIsInProgress()); - -#if defined(OS_ANDROID) || defined(OS_LINUX) - g_transfer_thread.Pointer()->SetPriority(base::ThreadPriority::BACKGROUND); -#endif } } diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc index 3c65f7210b0..86eb71803cf 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc @@ -47,10 +47,11 @@ class TransferThread : public base::Thread { TransferThread() : base::Thread(kAsyncTransferThreadName), initialized_(false) { - Start(); + base::Thread::Options options; #if defined(OS_ANDROID) || defined(OS_LINUX) - SetPriority(base::ThreadPriority::BACKGROUND); + options.priority = base::ThreadPriority::BACKGROUND; #endif + StartWithOptions(options); } ~TransferThread() override { diff --git a/chromium/gpu/command_buffer/service/buffer_manager.cc b/chromium/gpu/command_buffer/service/buffer_manager.cc index c2a0ba5c297..6b12f83d712 100644 --- a/chromium/gpu/command_buffer/service/buffer_manager.cc +++ b/chromium/gpu/command_buffer/service/buffer_manager.cc @@ -102,7 +102,7 @@ Buffer::Buffer(BufferManager* manager, GLuint service_id) shadowed_(false), is_client_side_array_(false), service_id_(service_id), - target_(0), + initial_target_(0), usage_(GL_STATIC_DRAW) { manager_->StartTracking(this); } @@ -271,14 +271,15 @@ bool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() { .use_non_zero_size_for_client_side_stream_buffers; } -void BufferManager::SetInfo( - Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data) { +void BufferManager::SetInfo(Buffer* buffer, GLenum target, GLsizeiptr size, + GLenum usage, const GLvoid* data) { DCHECK(buffer); memory_tracker_->TrackMemFree(buffer->size()); const bool is_client_side_array = IsUsageClientSideArray(usage); const bool support_fixed_attribs = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; - const bool shadow = buffer->target() == GL_ELEMENT_ARRAY_BUFFER || + // TODO(zmo): Don't shadow buffer data on ES3. crbug.com/491002. + const bool shadow = target == GL_ELEMENT_ARRAY_BUFFER || allow_buffers_on_multiple_targets_ || (allow_fixed_attribs_ && !support_fixed_attribs) || is_client_side_array; @@ -288,7 +289,7 @@ void BufferManager::SetInfo( void BufferManager::ValidateAndDoBufferData( ContextState* context_state, GLenum target, GLsizeiptr size, - const GLvoid * data, GLenum usage) { + const GLvoid* data, GLenum usage) { ErrorState* error_state = context_state->GetErrorState(); if (!feature_info_->validators()->buffer_target.IsValid(target)) { ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( @@ -319,13 +320,14 @@ void BufferManager::ValidateAndDoBufferData( return; } - DoBufferData(error_state, buffer, size, usage, data); + DoBufferData(error_state, buffer, target, size, usage, data); } void BufferManager::DoBufferData( ErrorState* error_state, Buffer* buffer, + GLenum target, GLsizeiptr size, GLenum usage, const GLvoid* data) { @@ -340,15 +342,15 @@ void BufferManager::DoBufferData( ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData"); if (IsUsageClientSideArray(usage)) { GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0; - glBufferData(buffer->target(), empty_size, NULL, usage); + glBufferData(target, empty_size, NULL, usage); } else { - glBufferData(buffer->target(), size, data, usage); + glBufferData(target, size, data, usage); } GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData"); if (error == GL_NO_ERROR) { - SetInfo(buffer, size, usage, data); + SetInfo(buffer, target, size, usage, data); } else { - SetInfo(buffer, 0, usage, NULL); + SetInfo(buffer, target, 0, usage, NULL); } } @@ -363,12 +365,13 @@ void BufferManager::ValidateAndDoBufferSubData( return; } - DoBufferSubData(error_state, buffer, offset, size, data); + DoBufferSubData(error_state, buffer, target, offset, size, data); } void BufferManager::DoBufferSubData( ErrorState* error_state, Buffer* buffer, + GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) { @@ -379,7 +382,7 @@ void BufferManager::DoBufferSubData( } if (!buffer->IsClientSideArray()) { - glBufferSubData(buffer->target(), offset, size, data); + glBufferSubData(target, offset, size, data); } } @@ -405,14 +408,46 @@ void BufferManager::ValidateAndDoGetBufferParameteriv( } bool BufferManager::SetTarget(Buffer* buffer, GLenum target) { - // Check that we are not trying to bind it to a different target. - if (buffer->target() != 0 && buffer->target() != target && - !allow_buffers_on_multiple_targets_) { - return false; - } - if (buffer->target() == 0) { - buffer->set_target(target); + if (!allow_buffers_on_multiple_targets_) { + // After being bound to ELEMENT_ARRAY_BUFFER target, a buffer cannot be + // bound to any other targets except for COPY_READ/WRITE_BUFFER target; + // After being bound to non ELEMENT_ARRAY_BUFFER target, a buffer cannot + // be bound to ELEMENT_ARRAY_BUFFER target. + + // Note that we don't force the WebGL 2 rule that a buffer bound to + // TRANSFORM_FEEDBACK_BUFFER target should not be bound to any other + // targets, because that is not a security threat, so we only enforce it + // in the WebGL2RenderingContextBase. + switch (buffer->initial_target()) { + case GL_ELEMENT_ARRAY_BUFFER: + switch (target) { + case GL_ARRAY_BUFFER: + case GL_PIXEL_PACK_BUFFER: + case GL_PIXEL_UNPACK_BUFFER: + case GL_TRANSFORM_FEEDBACK_BUFFER: + case GL_UNIFORM_BUFFER: + return false; + default: + break; + } + break; + case GL_ARRAY_BUFFER: + case GL_COPY_READ_BUFFER: + case GL_COPY_WRITE_BUFFER: + case GL_PIXEL_PACK_BUFFER: + case GL_PIXEL_UNPACK_BUFFER: + case GL_TRANSFORM_FEEDBACK_BUFFER: + case GL_UNIFORM_BUFFER: + if (target == GL_ELEMENT_ARRAY_BUFFER) { + return false; + } + break; + default: + break; + } } + if (buffer->initial_target() == 0) + buffer->set_initial_target(target); return true; } @@ -426,13 +461,17 @@ Buffer* BufferManager::GetBufferInfoForTarget( case GL_ELEMENT_ARRAY_BUFFER: return state->vertex_attrib_manager->element_array_buffer(); case GL_COPY_READ_BUFFER: + return state->bound_copy_read_buffer.get(); case GL_COPY_WRITE_BUFFER: + return state->bound_copy_write_buffer.get(); case GL_PIXEL_PACK_BUFFER: + return state->bound_pixel_pack_buffer.get(); case GL_PIXEL_UNPACK_BUFFER: + return state->bound_pixel_unpack_buffer.get(); case GL_TRANSFORM_FEEDBACK_BUFFER: + return state->bound_transform_feedback_buffer.get(); case GL_UNIFORM_BUFFER: - NOTIMPLEMENTED(); - return nullptr; + return state->bound_uniform_buffer.get(); default: NOTREACHED(); return nullptr; diff --git a/chromium/gpu/command_buffer/service/buffer_manager.h b/chromium/gpu/command_buffer/service/buffer_manager.h index 29bfaf4d431..9f69cf060b0 100644 --- a/chromium/gpu/command_buffer/service/buffer_manager.h +++ b/chromium/gpu/command_buffer/service/buffer_manager.h @@ -47,10 +47,6 @@ class GPU_EXPORT Buffer : public base::RefCounted<Buffer> { return service_id_; } - GLenum target() const { - return target_; - } - GLsizeiptr size() const { return size_; } @@ -74,7 +70,7 @@ class GPU_EXPORT Buffer : public base::RefCounted<Buffer> { } bool IsValid() const { - return target() && !IsDeleted(); + return initial_target() && !IsDeleted(); } bool IsClientSideArray() const { @@ -129,9 +125,13 @@ class GPU_EXPORT Buffer : public base::RefCounted<Buffer> { ~Buffer(); - void set_target(GLenum target) { - DCHECK_EQ(target_, 0u); // you can only set this once. - target_ = target; + GLenum initial_target() const { + return initial_target_; + } + + void set_initial_target(GLenum target) { + DCHECK_EQ(0u, initial_target_); + initial_target_ = target; } bool shadowed() const { @@ -182,10 +182,9 @@ class GPU_EXPORT Buffer : public base::RefCounted<Buffer> { // Service side buffer id. GLuint service_id_; - // The type of buffer. 0 = unset, GL_BUFFER_ARRAY = vertex data, - // GL_ELEMENT_BUFFER_ARRAY = index data. - // Once set a buffer can not be used for something else. - GLenum target_; + // The first target of buffer. 0 = unset. + // It is set the first time bindBuffer() is called and cannot be changed. + GLenum initial_target_; // Usage of buffer. GLenum usage_; @@ -277,6 +276,7 @@ class GPU_EXPORT BufferManager { void DoBufferSubData( ErrorState* error_state, Buffer* buffer, + GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); @@ -286,14 +286,15 @@ class GPU_EXPORT BufferManager { void DoBufferData( ErrorState* error_state, Buffer* buffer, + GLenum target, GLsizeiptr size, GLenum usage, const GLvoid* data); // Sets the size, usage and initial data of a buffer. // If data is NULL buffer will be initialized to 0 if shadowed. - void SetInfo( - Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data); + void SetInfo(Buffer* buffer, GLenum target, GLsizeiptr size, GLenum usage, + const GLvoid* data); scoped_ptr<MemoryTypeTracker> memory_tracker_; scoped_refptr<FeatureInfo> feature_info_; diff --git a/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc index bef00896e69..c537c2f6cc4 100644 --- a/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc @@ -40,20 +40,20 @@ class BufferManagerTestBase : public GpuServiceTest { GpuServiceTest::TearDown(); } - GLenum GetTarget(const Buffer* buffer) const { - return buffer->target(); + GLenum GetInitialTarget(const Buffer* buffer) const { + return buffer->initial_target(); } void DoBufferData( - Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data, - GLenum error) { + Buffer* buffer, GLenum target, GLsizeiptr size, GLenum usage, + const GLvoid* data, GLenum error) { TestHelper::DoBufferData( gl_.get(), error_state_.get(), manager_.get(), - buffer, size, usage, data, error); + buffer, target, size, usage, data, error); } bool DoBufferSubData( - Buffer* buffer, GLintptr offset, GLsizeiptr size, + Buffer* buffer, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) { bool success = true; if (!buffer->CheckRange(offset, size)) { @@ -62,13 +62,12 @@ class BufferManagerTestBase : public GpuServiceTest { .RetiresOnSaturation(); success = false; } else if (!buffer->IsClientSideArray()) { - EXPECT_CALL(*gl_, BufferSubData( - buffer->target(), offset, size, _)) + EXPECT_CALL(*gl_, BufferSubData(target, offset, size, _)) .Times(1) .RetiresOnSaturation(); } manager_->DoBufferSubData( - error_state_.get(), buffer, offset, size, data); + error_state_.get(), buffer, target, offset, size, data); return success; } @@ -109,6 +108,7 @@ class BufferManagerClientSideArraysTest : public BufferManagerTestBase { .Times(1).RetiresOnSaturation() TEST_F(BufferManagerTest, Basic) { + const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; const GLuint kClientBuffer1Id = 1; const GLuint kServiceBuffer1Id = 11; const GLsizeiptr kBuffer1Size = 123; @@ -118,7 +118,7 @@ TEST_F(BufferManagerTest, Basic) { // Check buffer got created. Buffer* buffer1 = manager_->GetBuffer(kClientBuffer1Id); ASSERT_TRUE(buffer1 != NULL); - EXPECT_EQ(0u, GetTarget(buffer1)); + EXPECT_EQ(0u, GetInitialTarget(buffer1)); EXPECT_EQ(0, buffer1->size()); EXPECT_EQ(static_cast<GLenum>(GL_STATIC_DRAW), buffer1->usage()); EXPECT_FALSE(buffer1->IsDeleted()); @@ -127,10 +127,11 @@ TEST_F(BufferManagerTest, Basic) { GLuint client_id = 0; EXPECT_TRUE(manager_->GetClientId(buffer1->service_id(), &client_id)); EXPECT_EQ(kClientBuffer1Id, client_id); - manager_->SetTarget(buffer1, GL_ELEMENT_ARRAY_BUFFER); - EXPECT_EQ(static_cast<GLenum>(GL_ELEMENT_ARRAY_BUFFER), GetTarget(buffer1)); + manager_->SetTarget(buffer1, kTarget); + EXPECT_EQ(kTarget, GetInitialTarget(buffer1)); // Check we and set its size. - DoBufferData(buffer1, kBuffer1Size, GL_DYNAMIC_DRAW, NULL, GL_NO_ERROR); + DoBufferData( + buffer1, kTarget, kBuffer1Size, GL_DYNAMIC_DRAW, NULL, GL_NO_ERROR); EXPECT_EQ(kBuffer1Size, buffer1->size()); EXPECT_EQ(static_cast<GLenum>(GL_DYNAMIC_DRAW), buffer1->usage()); // Check we get nothing for a non-existent buffer. @@ -147,6 +148,7 @@ TEST_F(BufferManagerTest, Basic) { } TEST_F(BufferManagerMemoryTrackerTest, Basic) { + const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; const GLuint kClientBuffer1Id = 1; const GLuint kServiceBuffer1Id = 11; const GLsizeiptr kBuffer1Size1 = 123; @@ -157,13 +159,15 @@ TEST_F(BufferManagerMemoryTrackerTest, Basic) { // Check buffer got created. Buffer* buffer1 = manager_->GetBuffer(kClientBuffer1Id); ASSERT_TRUE(buffer1 != NULL); - manager_->SetTarget(buffer1, GL_ELEMENT_ARRAY_BUFFER); + manager_->SetTarget(buffer1, kTarget); // Check we and set its size. EXPECT_MEMORY_ALLOCATION_CHANGE(0, kBuffer1Size1, MemoryTracker::kManaged); - DoBufferData(buffer1, kBuffer1Size1, GL_DYNAMIC_DRAW, NULL, GL_NO_ERROR); + DoBufferData( + buffer1, kTarget, kBuffer1Size1, GL_DYNAMIC_DRAW, NULL, GL_NO_ERROR); EXPECT_MEMORY_ALLOCATION_CHANGE(kBuffer1Size1, 0, MemoryTracker::kManaged); EXPECT_MEMORY_ALLOCATION_CHANGE(0, kBuffer1Size2, MemoryTracker::kManaged); - DoBufferData(buffer1, kBuffer1Size2, GL_DYNAMIC_DRAW, NULL, GL_NO_ERROR); + DoBufferData( + buffer1, kTarget, kBuffer1Size2, GL_DYNAMIC_DRAW, NULL, GL_NO_ERROR); // On delete it will get freed. EXPECT_MEMORY_ALLOCATION_CHANGE(kBuffer1Size2, 0, MemoryTracker::kManaged); } @@ -186,36 +190,39 @@ TEST_F(BufferManagerTest, Destroy) { } TEST_F(BufferManagerTest, DoBufferSubData) { + const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; const GLuint kClientBufferId = 1; const GLuint kServiceBufferId = 11; const uint8 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; manager_->CreateBuffer(kClientBufferId, kServiceBufferId); Buffer* buffer = manager_->GetBuffer(kClientBufferId); ASSERT_TRUE(buffer != NULL); - manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER); - DoBufferData(buffer, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR); - EXPECT_TRUE(DoBufferSubData(buffer, 0, sizeof(data), data)); - EXPECT_TRUE(DoBufferSubData(buffer, sizeof(data), 0, data)); - EXPECT_FALSE(DoBufferSubData(buffer, sizeof(data), 1, data)); - EXPECT_FALSE(DoBufferSubData(buffer, 0, sizeof(data) + 1, data)); - EXPECT_FALSE(DoBufferSubData(buffer, -1, sizeof(data), data)); - EXPECT_FALSE(DoBufferSubData(buffer, 0, -1, data)); - DoBufferData(buffer, 1, GL_STATIC_DRAW, NULL, GL_NO_ERROR); + manager_->SetTarget(buffer, kTarget); + DoBufferData( + buffer, kTarget, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR); + EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 0, sizeof(data), data)); + EXPECT_TRUE(DoBufferSubData(buffer, kTarget, sizeof(data), 0, data)); + EXPECT_FALSE(DoBufferSubData(buffer, kTarget, sizeof(data), 1, data)); + EXPECT_FALSE(DoBufferSubData(buffer, kTarget, 0, sizeof(data) + 1, data)); + EXPECT_FALSE(DoBufferSubData(buffer, kTarget, -1, sizeof(data), data)); + EXPECT_FALSE(DoBufferSubData(buffer, kTarget, 0, -1, data)); + DoBufferData(buffer, kTarget, 1, GL_STATIC_DRAW, NULL, GL_NO_ERROR); const int size = 0x20000; scoped_ptr<uint8[]> temp(new uint8[size]); - EXPECT_FALSE(DoBufferSubData(buffer, 0 - size, size, temp.get())); - EXPECT_FALSE(DoBufferSubData(buffer, 1, size / 2, temp.get())); + EXPECT_FALSE(DoBufferSubData(buffer, kTarget, 0 - size, size, temp.get())); + EXPECT_FALSE(DoBufferSubData(buffer, kTarget, 1, size / 2, temp.get())); } TEST_F(BufferManagerTest, GetRange) { + const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; const GLuint kClientBufferId = 1; const GLuint kServiceBufferId = 11; const GLsizeiptr kDataSize = 10; manager_->CreateBuffer(kClientBufferId, kServiceBufferId); Buffer* buffer = manager_->GetBuffer(kClientBufferId); ASSERT_TRUE(buffer != NULL); - manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER); - DoBufferData(buffer, kDataSize, GL_STATIC_DRAW, NULL, GL_NO_ERROR); + manager_->SetTarget(buffer, kTarget); + DoBufferData(buffer, kTarget, kDataSize, GL_STATIC_DRAW, NULL, GL_NO_ERROR); const char* buf = static_cast<const char*>(buffer->GetRange(0, kDataSize)); ASSERT_TRUE(buf != NULL); @@ -227,12 +234,13 @@ TEST_F(BufferManagerTest, GetRange) { EXPECT_TRUE(buffer->GetRange(-1, kDataSize) == NULL); EXPECT_TRUE(buffer->GetRange(-0, -1) == NULL); const int size = 0x20000; - DoBufferData(buffer, size / 2, GL_STATIC_DRAW, NULL, GL_NO_ERROR); + DoBufferData(buffer, kTarget, size / 2, GL_STATIC_DRAW, NULL, GL_NO_ERROR); EXPECT_TRUE(buffer->GetRange(0 - size, size) == NULL); EXPECT_TRUE(buffer->GetRange(1, size / 2) == NULL); } TEST_F(BufferManagerTest, GetMaxValueForRangeUint8) { + const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; const GLuint kClientBufferId = 1; const GLuint kServiceBufferId = 11; const uint8 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; @@ -240,9 +248,10 @@ TEST_F(BufferManagerTest, GetMaxValueForRangeUint8) { manager_->CreateBuffer(kClientBufferId, kServiceBufferId); Buffer* buffer = manager_->GetBuffer(kClientBufferId); ASSERT_TRUE(buffer != NULL); - manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER); - DoBufferData(buffer, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR); - EXPECT_TRUE(DoBufferSubData(buffer, 0, sizeof(data), data)); + manager_->SetTarget(buffer, kTarget); + DoBufferData( + buffer, kTarget, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR); + EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 0, sizeof(data), data)); GLuint max_value; // Check entire range succeeds. EXPECT_TRUE(buffer->GetMaxValueForRange( @@ -253,7 +262,7 @@ TEST_F(BufferManagerTest, GetMaxValueForRangeUint8) { 4, 3, GL_UNSIGNED_BYTE, &max_value)); EXPECT_EQ(6u, max_value); // Check changing sub range succeeds. - EXPECT_TRUE(DoBufferSubData(buffer, 4, sizeof(new_data), new_data)); + EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 4, sizeof(new_data), new_data)); EXPECT_TRUE(buffer->GetMaxValueForRange( 4, 3, GL_UNSIGNED_BYTE, &max_value)); EXPECT_EQ(120u, max_value); @@ -269,6 +278,7 @@ TEST_F(BufferManagerTest, GetMaxValueForRangeUint8) { } TEST_F(BufferManagerTest, GetMaxValueForRangeUint16) { + const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; const GLuint kClientBufferId = 1; const GLuint kServiceBufferId = 11; const uint16 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; @@ -276,9 +286,10 @@ TEST_F(BufferManagerTest, GetMaxValueForRangeUint16) { manager_->CreateBuffer(kClientBufferId, kServiceBufferId); Buffer* buffer = manager_->GetBuffer(kClientBufferId); ASSERT_TRUE(buffer != NULL); - manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER); - DoBufferData(buffer, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR); - EXPECT_TRUE(DoBufferSubData(buffer, 0, sizeof(data), data)); + manager_->SetTarget(buffer, kTarget); + DoBufferData( + buffer, kTarget, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR); + EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 0, sizeof(data), data)); GLuint max_value; // Check entire range succeeds. EXPECT_TRUE(buffer->GetMaxValueForRange( @@ -292,7 +303,7 @@ TEST_F(BufferManagerTest, GetMaxValueForRangeUint16) { 8, 3, GL_UNSIGNED_SHORT, &max_value)); EXPECT_EQ(6u, max_value); // Check changing sub range succeeds. - EXPECT_TRUE(DoBufferSubData(buffer, 8, sizeof(new_data), new_data)); + EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 8, sizeof(new_data), new_data)); EXPECT_TRUE(buffer->GetMaxValueForRange( 8, 3, GL_UNSIGNED_SHORT, &max_value)); EXPECT_EQ(120u, max_value); @@ -308,6 +319,7 @@ TEST_F(BufferManagerTest, GetMaxValueForRangeUint16) { } TEST_F(BufferManagerTest, GetMaxValueForRangeUint32) { + const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; const GLuint kClientBufferId = 1; const GLuint kServiceBufferId = 11; const uint32 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; @@ -315,9 +327,10 @@ TEST_F(BufferManagerTest, GetMaxValueForRangeUint32) { manager_->CreateBuffer(kClientBufferId, kServiceBufferId); Buffer* buffer = manager_->GetBuffer(kClientBufferId); ASSERT_TRUE(buffer != NULL); - manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER); - DoBufferData(buffer, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR); - EXPECT_TRUE(DoBufferSubData(buffer, 0, sizeof(data), data)); + manager_->SetTarget(buffer, kTarget); + DoBufferData( + buffer, kTarget, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR); + EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 0, sizeof(data), data)); GLuint max_value; // Check entire range succeeds. EXPECT_TRUE( @@ -334,7 +347,7 @@ TEST_F(BufferManagerTest, GetMaxValueForRangeUint32) { EXPECT_TRUE(buffer->GetMaxValueForRange(16, 3, GL_UNSIGNED_INT, &max_value)); EXPECT_EQ(6u, max_value); // Check changing sub range succeeds. - EXPECT_TRUE(DoBufferSubData(buffer, 16, sizeof(new_data), new_data)); + EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 16, sizeof(new_data), new_data)); EXPECT_TRUE(buffer->GetMaxValueForRange(16, 3, GL_UNSIGNED_INT, &max_value)); EXPECT_EQ(120u, max_value); max_value = 0; @@ -348,17 +361,19 @@ TEST_F(BufferManagerTest, GetMaxValueForRangeUint32) { } TEST_F(BufferManagerTest, UseDeletedBuffer) { + const GLenum kTarget = GL_ARRAY_BUFFER; const GLuint kClientBufferId = 1; const GLuint kServiceBufferId = 11; const GLsizeiptr kDataSize = 10; manager_->CreateBuffer(kClientBufferId, kServiceBufferId); scoped_refptr<Buffer> buffer = manager_->GetBuffer(kClientBufferId); ASSERT_TRUE(buffer.get() != NULL); - manager_->SetTarget(buffer.get(), GL_ARRAY_BUFFER); + manager_->SetTarget(buffer.get(), kTarget); // Remove buffer manager_->RemoveBuffer(kClientBufferId); // Use it after removing - DoBufferData(buffer.get(), kDataSize, GL_STATIC_DRAW, NULL, GL_NO_ERROR); + DoBufferData( + buffer.get(), kTarget, kDataSize, GL_STATIC_DRAW, NULL, GL_NO_ERROR); // Check that it gets deleted when the last reference is released. EXPECT_CALL(*gl_, DeleteBuffersARB(1, ::testing::Pointee(kServiceBufferId))) .Times(1) @@ -368,21 +383,25 @@ TEST_F(BufferManagerTest, UseDeletedBuffer) { // Test buffers get shadowed when they are supposed to be. TEST_F(BufferManagerClientSideArraysTest, StreamBuffersAreShadowed) { + const GLenum kTarget = GL_ARRAY_BUFFER; const GLuint kClientBufferId = 1; const GLuint kServiceBufferId = 11; static const uint32 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; manager_->CreateBuffer(kClientBufferId, kServiceBufferId); Buffer* buffer = manager_->GetBuffer(kClientBufferId); ASSERT_TRUE(buffer != NULL); - manager_->SetTarget(buffer, GL_ARRAY_BUFFER); - DoBufferData(buffer, sizeof(data), GL_STREAM_DRAW, data, GL_NO_ERROR); + manager_->SetTarget(buffer, kTarget); + DoBufferData( + buffer, kTarget, sizeof(data), GL_STREAM_DRAW, data, GL_NO_ERROR); EXPECT_TRUE(buffer->IsClientSideArray()); EXPECT_EQ(0, memcmp(data, buffer->GetRange(0, sizeof(data)), sizeof(data))); - DoBufferData(buffer, sizeof(data), GL_DYNAMIC_DRAW, data, GL_NO_ERROR); + DoBufferData( + buffer, kTarget, sizeof(data), GL_DYNAMIC_DRAW, data, GL_NO_ERROR); EXPECT_FALSE(buffer->IsClientSideArray()); } TEST_F(BufferManagerTest, MaxValueCacheClearedCorrectly) { + const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; const GLuint kClientBufferId = 1; const GLuint kServiceBufferId = 11; const uint32 data1[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; @@ -391,30 +410,107 @@ TEST_F(BufferManagerTest, MaxValueCacheClearedCorrectly) { manager_->CreateBuffer(kClientBufferId, kServiceBufferId); Buffer* buffer = manager_->GetBuffer(kClientBufferId); ASSERT_TRUE(buffer != NULL); - manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER); + manager_->SetTarget(buffer, kTarget); GLuint max_value; // Load the buffer with some initial data, and then get the maximum value for // a range, which has the side effect of caching it. - DoBufferData(buffer, sizeof(data1), GL_STATIC_DRAW, data1, GL_NO_ERROR); + DoBufferData( + buffer, kTarget, sizeof(data1), GL_STATIC_DRAW, data1, GL_NO_ERROR); EXPECT_TRUE( buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, &max_value)); EXPECT_EQ(10u, max_value); // Check that any cached values are invalidated if the buffer is reloaded // with the same amount of data (but different content) ASSERT_EQ(sizeof(data2), sizeof(data1)); - DoBufferData(buffer, sizeof(data2), GL_STATIC_DRAW, data2, GL_NO_ERROR); + DoBufferData( + buffer, kTarget, sizeof(data2), GL_STATIC_DRAW, data2, GL_NO_ERROR); EXPECT_TRUE( buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, &max_value)); EXPECT_EQ(20u, max_value); // Check that any cached values are invalidated if the buffer is reloaded // with entirely different content. ASSERT_NE(sizeof(data3), sizeof(data1)); - DoBufferData(buffer, sizeof(data3), GL_STATIC_DRAW, data3, GL_NO_ERROR); + DoBufferData( + buffer, kTarget, sizeof(data3), GL_STATIC_DRAW, data3, GL_NO_ERROR); EXPECT_TRUE( buffer->GetMaxValueForRange(0, 3, GL_UNSIGNED_INT, &max_value)); EXPECT_EQ(30u, max_value); } +TEST_F(BufferManagerTest, BindBufferConflicts) { + manager_->set_allow_buffers_on_multiple_targets(false); + GLuint client_id = 1; + GLuint service_id = 101; + + { + // Once a buffer is bound to ELEMENT_ARRAY_BUFFER, it can't be bound to + // any other targets except for GL_COPY_READ/WRITE_BUFFER. + manager_->CreateBuffer(client_id, service_id); + Buffer* buffer = manager_->GetBuffer(client_id); + ASSERT_TRUE(buffer != NULL); + EXPECT_TRUE(manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER)); + EXPECT_TRUE(manager_->SetTarget(buffer, GL_COPY_READ_BUFFER)); + EXPECT_TRUE(manager_->SetTarget(buffer, GL_COPY_WRITE_BUFFER)); + EXPECT_FALSE(manager_->SetTarget(buffer, GL_ARRAY_BUFFER)); + EXPECT_FALSE(manager_->SetTarget(buffer, GL_PIXEL_PACK_BUFFER)); + EXPECT_FALSE(manager_->SetTarget(buffer, GL_PIXEL_UNPACK_BUFFER)); + EXPECT_FALSE(manager_->SetTarget(buffer, GL_TRANSFORM_FEEDBACK_BUFFER)); + EXPECT_FALSE(manager_->SetTarget(buffer, GL_UNIFORM_BUFFER)); + } + + { + // Except for ELEMENT_ARRAY_BUFFER, a buffer can switch to any targets. + const GLenum kTargets[] = { + GL_ARRAY_BUFFER, + GL_COPY_READ_BUFFER, + GL_COPY_WRITE_BUFFER, + GL_PIXEL_PACK_BUFFER, + GL_PIXEL_UNPACK_BUFFER, + GL_TRANSFORM_FEEDBACK_BUFFER, + GL_UNIFORM_BUFFER + }; + for (size_t ii = 0; ii < arraysize(kTargets); ++ii) { + client_id++; + service_id++; + manager_->CreateBuffer(client_id, service_id); + Buffer* buffer = manager_->GetBuffer(client_id); + ASSERT_TRUE(buffer != NULL); + + EXPECT_TRUE(manager_->SetTarget(buffer, kTargets[ii])); + for (size_t jj = 0; jj < arraysize(kTargets); ++jj) { + EXPECT_TRUE(manager_->SetTarget(buffer, kTargets[jj])); + } + EXPECT_EQ(kTargets[ii], GetInitialTarget(buffer)); + } + } + + { + // Once a buffer is bound to non ELEMENT_ARRAY_BUFFER target, it can't be + // bound to ELEMENT_ARRAY_BUFFER target. + const GLenum kTargets[] = { + GL_ARRAY_BUFFER, + GL_COPY_READ_BUFFER, + GL_COPY_WRITE_BUFFER, + GL_PIXEL_PACK_BUFFER, + GL_PIXEL_UNPACK_BUFFER, + GL_TRANSFORM_FEEDBACK_BUFFER, + GL_UNIFORM_BUFFER + }; + for (size_t ii = 0; ii < arraysize(kTargets); ++ii) { + client_id++; + service_id++; + manager_->CreateBuffer(client_id, service_id); + Buffer* buffer = manager_->GetBuffer(client_id); + ASSERT_TRUE(buffer != NULL); + + EXPECT_TRUE(manager_->SetTarget(buffer, kTargets[ii])); + for (size_t jj = 0; jj < arraysize(kTargets); ++jj) { + EXPECT_TRUE(manager_->SetTarget(buffer, kTargets[jj])); + } + } + } +} + } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/command_buffer_service.h b/chromium/gpu/command_buffer/service/command_buffer_service.h index 28a5f6f7a9b..809891b6747 100644 --- a/chromium/gpu/command_buffer/service/command_buffer_service.h +++ b/chromium/gpu/command_buffer/service/command_buffer_service.h @@ -102,7 +102,7 @@ class GPU_EXPORT CommandBufferService : public CommandBufferServiceBase { base::Closure put_offset_change_callback_; GetBufferChangedCallback get_buffer_change_callback_; base::Closure parse_error_callback_; - TransferBufferManagerInterface* transfer_buffer_manager_; + scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; int32 token_; uint32 generation_; error::Error error_; diff --git a/chromium/gpu/command_buffer/service/command_buffer_service_unittest.cc b/chromium/gpu/command_buffer/service/command_buffer_service_unittest.cc index 8a7d43ca986..7b112c59596 100644 --- a/chromium/gpu/command_buffer/service/command_buffer_service_unittest.cc +++ b/chromium/gpu/command_buffer/service/command_buffer_service_unittest.cc @@ -25,7 +25,7 @@ class CommandBufferServiceTest : public testing::Test { void SetUp() override { { TransferBufferManager* manager = new TransferBufferManager(); - transfer_buffer_manager_.reset(manager); + transfer_buffer_manager_ = manager; EXPECT_TRUE(manager->Initialize()); } command_buffer_.reset( @@ -57,7 +57,7 @@ class CommandBufferServiceTest : public testing::Test { return true; } - scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; + scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; scoped_ptr<CommandBufferService> command_buffer_; }; diff --git a/chromium/gpu/command_buffer/service/context_group.cc b/chromium/gpu/command_buffer/service/context_group.cc index 98ebbdbd033..c975347ea68 100644 --- a/chromium/gpu/command_buffer/service/context_group.cc +++ b/chromium/gpu/command_buffer/service/context_group.cc @@ -35,7 +35,8 @@ ContextGroup::ContextGroup( const scoped_refptr<SubscriptionRefSet>& subscription_ref_set, const scoped_refptr<ValueStateMap>& pending_valuebuffer_state, bool bind_generates_resource) - : mailbox_manager_(mailbox_manager), + : context_type_(CONTEXT_TYPE_UNDEFINED), + mailbox_manager_(mailbox_manager), memory_tracker_(memory_tracker), shader_translator_cache_(shader_translator_cache), subscription_ref_set_(subscription_ref_set), @@ -65,7 +66,7 @@ ContextGroup::ContextGroup( if (!feature_info.get()) feature_info_ = new FeatureInfo; TransferBufferManager* manager = new TransferBufferManager(); - transfer_buffer_manager_.reset(manager); + transfer_buffer_manager_ = manager; manager->Initialize(); } } @@ -76,9 +77,38 @@ static void GetIntegerv(GLenum pname, uint32* var) { *var = value; } +// static +ContextGroup::ContextType ContextGroup::GetContextType( + unsigned webgl_version) { + switch (webgl_version) { + case 0: + return CONTEXT_TYPE_OTHER; + case 1: + return CONTEXT_TYPE_WEBGL1; + case 2: + return CONTEXT_TYPE_WEBGL2; + default: + return CONTEXT_TYPE_UNDEFINED; + } +} + bool ContextGroup::Initialize( GLES2Decoder* decoder, + ContextGroup::ContextType context_type, const DisallowedFeatures& disallowed_features) { + if (context_type == CONTEXT_TYPE_UNDEFINED) { + LOG(ERROR) << "ContextGroup::Initialize failed because of unknown " + << "context type."; + return false; + } + if (context_type_ == CONTEXT_TYPE_UNDEFINED) { + context_type_ = context_type; + } else if (context_type_ != context_type) { + LOG(ERROR) << "ContextGroup::Initialize failed because the type of " + << "the context does not fit with the group."; + return false; + } + // If we've already initialized the group just add the context. if (HaveContexts()) { decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder)); diff --git a/chromium/gpu/command_buffer/service/context_group.h b/chromium/gpu/command_buffer/service/context_group.h index f2e832f0fd5..466f918a19c 100644 --- a/chromium/gpu/command_buffer/service/context_group.h +++ b/chromium/gpu/command_buffer/service/context_group.h @@ -44,6 +44,15 @@ struct DisallowedFeatures; // resources. class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { public: + enum ContextType { + CONTEXT_TYPE_WEBGL1, + CONTEXT_TYPE_WEBGL2, + CONTEXT_TYPE_OTHER, + CONTEXT_TYPE_UNDEFINED + }; + + static ContextType GetContextType(unsigned webgl_version); + ContextGroup( const scoped_refptr<MailboxManager>& mailbox_manager, const scoped_refptr<MemoryTracker>& memory_tracker, @@ -57,6 +66,7 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { // call to destroy if it succeeds. bool Initialize( GLES2Decoder* decoder, + ContextType context_type, const DisallowedFeatures& disallowed_features); // Destroys all the resources when called for the last context in the group. @@ -202,6 +212,12 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { bool GetTransformFeedbackServiceId( GLuint client_id, GLuint* service_id) const { + if (client_id == 0) { + // Default one. + if (service_id) + *service_id = 0; + return true; + } base::hash_map<GLuint, GLuint>::const_iterator iter = transformfeedbacks_id_map_.find(client_id); if (iter == transformfeedbacks_id_map_.end()) @@ -243,10 +259,12 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { bool QueryGLFeatureU(GLenum pname, GLint min_required, uint32* v); bool HaveContexts(); + ContextType context_type_; + scoped_refptr<MailboxManager> mailbox_manager_; scoped_refptr<MemoryTracker> memory_tracker_; scoped_refptr<ShaderTranslatorCache> shader_translator_cache_; - scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; + scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; scoped_refptr<SubscriptionRefSet> subscription_ref_set_; scoped_refptr<ValueStateMap> pending_valuebuffer_state_; diff --git a/chromium/gpu/command_buffer/service/context_group_unittest.cc b/chromium/gpu/command_buffer/service/context_group_unittest.cc index afd343d169d..7c6d5c1c8bd 100644 --- a/chromium/gpu/command_buffer/service/context_group_unittest.cc +++ b/chromium/gpu/command_buffer/service/context_group_unittest.cc @@ -68,7 +68,8 @@ TEST_F(ContextGroupTest, Basic) { TEST_F(ContextGroupTest, InitializeNoExtensions) { TestHelper::SetupContextGroupInitExpectations( gl_.get(), DisallowedFeatures(), "", "", kBindGeneratesResource); - group_->Initialize(decoder_.get(), DisallowedFeatures()); + group_->Initialize( + decoder_.get(), ContextGroup::CONTEXT_TYPE_OTHER, DisallowedFeatures()); EXPECT_EQ(static_cast<uint32>(TestHelper::kNumVertexAttribs), group_->max_vertex_attribs()); EXPECT_EQ(static_cast<uint32>(TestHelper::kNumTextureUnits), @@ -103,8 +104,19 @@ TEST_F(ContextGroupTest, MultipleContexts) { scoped_ptr<MockGLES2Decoder> decoder2_(new MockGLES2Decoder()); TestHelper::SetupContextGroupInitExpectations( gl_.get(), DisallowedFeatures(), "", "", kBindGeneratesResource); - group_->Initialize(decoder_.get(), DisallowedFeatures()); - group_->Initialize(decoder2_.get(), DisallowedFeatures()); + EXPECT_TRUE(group_->Initialize( + decoder_.get(), ContextGroup::CONTEXT_TYPE_OTHER, DisallowedFeatures())); + EXPECT_FALSE(group_->Initialize( + decoder2_.get(), ContextGroup::CONTEXT_TYPE_WEBGL1, + DisallowedFeatures())); + EXPECT_FALSE(group_->Initialize( + decoder2_.get(), ContextGroup::CONTEXT_TYPE_WEBGL2, + DisallowedFeatures())); + EXPECT_FALSE(group_->Initialize( + decoder2_.get(), ContextGroup::CONTEXT_TYPE_UNDEFINED, + DisallowedFeatures())); + EXPECT_TRUE(group_->Initialize( + decoder2_.get(), ContextGroup::CONTEXT_TYPE_OTHER, DisallowedFeatures())); EXPECT_TRUE(group_->buffer_manager() != NULL); EXPECT_TRUE(group_->framebuffer_manager() != NULL); diff --git a/chromium/gpu/command_buffer/service/context_state.cc b/chromium/gpu/command_buffer/service/context_state.cc index 13c56b420f9..38b70a1f2f5 100644 --- a/chromium/gpu/command_buffer/service/context_state.cc +++ b/chromium/gpu/command_buffer/service/context_state.cc @@ -72,6 +72,12 @@ bool TargetIsSupported(const FeatureInfo* feature_info, GLuint target) { } } +GLuint GetBufferId(const Buffer* buffer) { + if (buffer) + return buffer->service_id(); + return 0; +} + } // anonymous namespace. TextureUnit::TextureUnit() @@ -253,11 +259,22 @@ void ContextState::RestoreBufferBindings() const { if (vertex_attrib_manager.get()) { Buffer* element_array_buffer = vertex_attrib_manager->element_array_buffer(); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, - element_array_buffer ? element_array_buffer->service_id() : 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, GetBufferId(element_array_buffer)); + } + glBindBuffer(GL_ARRAY_BUFFER, GetBufferId(bound_array_buffer.get())); + if (feature_info_->IsES3Enabled()) { + glBindBuffer(GL_COPY_READ_BUFFER, + GetBufferId(bound_copy_read_buffer.get())); + glBindBuffer(GL_COPY_WRITE_BUFFER, + GetBufferId(bound_copy_write_buffer.get())); + glBindBuffer(GL_PIXEL_PACK_BUFFER, + GetBufferId(bound_pixel_pack_buffer.get())); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, + GetBufferId(bound_pixel_unpack_buffer.get())); + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, + GetBufferId(bound_transform_feedback_buffer.get())); + glBindBuffer(GL_UNIFORM_BUFFER, GetBufferId(bound_uniform_buffer.get())); } - glBindBuffer(GL_ARRAY_BUFFER, - bound_array_buffer.get() ? bound_array_buffer->service_id() : 0); } void ContextState::RestoreRenderbufferBindings() { @@ -424,6 +441,64 @@ void ContextState::EnableDisable(GLenum pname, bool enable) const { } } +void ContextState::SetBoundBuffer(GLenum target, Buffer* buffer) { + switch (target) { + case GL_ARRAY_BUFFER: + bound_array_buffer = buffer; + break; + case GL_ELEMENT_ARRAY_BUFFER: + vertex_attrib_manager->SetElementArrayBuffer(buffer); + break; + case GL_COPY_READ_BUFFER: + bound_copy_read_buffer = buffer; + break; + case GL_COPY_WRITE_BUFFER: + bound_copy_write_buffer = buffer; + break; + case GL_PIXEL_PACK_BUFFER: + bound_pixel_pack_buffer = buffer; + break; + case GL_PIXEL_UNPACK_BUFFER: + bound_pixel_unpack_buffer = buffer; + break; + case GL_TRANSFORM_FEEDBACK_BUFFER: + bound_transform_feedback_buffer = buffer; + break; + case GL_UNIFORM_BUFFER: + bound_uniform_buffer = buffer; + break; + default: + NOTREACHED(); + break; + } +} + +void ContextState::RemoveBoundBuffer(Buffer* buffer) { + DCHECK(buffer); + vertex_attrib_manager->Unbind(buffer); + if (bound_array_buffer.get() == buffer) { + bound_array_buffer = nullptr; + } + if (bound_copy_read_buffer.get() == buffer) { + bound_copy_read_buffer = nullptr; + } + if (bound_copy_write_buffer.get() == buffer) { + bound_copy_write_buffer = nullptr; + } + if (bound_pixel_pack_buffer.get() == buffer) { + bound_pixel_pack_buffer = nullptr; + } + if (bound_pixel_unpack_buffer.get() == buffer) { + bound_pixel_unpack_buffer = nullptr; + } + if (bound_transform_feedback_buffer.get() == buffer) { + bound_transform_feedback_buffer = nullptr; + } + if (bound_uniform_buffer.get() == buffer) { + bound_uniform_buffer = nullptr; + } +} + // 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/chromium/gpu/command_buffer/service/context_state.h b/chromium/gpu/command_buffer/service/context_state.h index 166a906f221..88c9423d012 100644 --- a/chromium/gpu/command_buffer/service/context_state.h +++ b/chromium/gpu/command_buffer/service/context_state.h @@ -231,6 +231,9 @@ struct GPU_EXPORT ContextState { ErrorState* GetErrorState(); + void SetBoundBuffer(GLenum target, Buffer* buffer); + void RemoveBoundBuffer(Buffer* buffer); + #include "gpu/command_buffer/service/context_state_autogen.h" EnableFlags enable_flags; @@ -244,6 +247,13 @@ struct GPU_EXPORT ContextState { // glVertexAttribPointer. scoped_refptr<Buffer> bound_array_buffer; + scoped_refptr<Buffer> bound_copy_read_buffer; + scoped_refptr<Buffer> bound_copy_write_buffer; + scoped_refptr<Buffer> bound_pixel_pack_buffer; + scoped_refptr<Buffer> bound_pixel_unpack_buffer; + scoped_refptr<Buffer> bound_transform_feedback_buffer; + scoped_refptr<Buffer> bound_uniform_buffer; + // Which textures are bound to texture units through glActiveTexture. std::vector<TextureUnit> texture_units; diff --git a/chromium/gpu/command_buffer/service/error_state.cc b/chromium/gpu/command_buffer/service/error_state.cc index ca4af85036b..6667e1d4454 100644 --- a/chromium/gpu/command_buffer/service/error_state.cc +++ b/chromium/gpu/command_buffer/service/error_state.cc @@ -6,6 +6,7 @@ #include <string> +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/logger.h" @@ -170,7 +171,7 @@ void ErrorStateImpl::SetGLErrorInvalidParami( filename, line, error, function_name, (std::string("trying to set ") + GLES2Util::GetStringEnum(pname) + " to " + - base::StringPrintf("%d", param)).c_str()); + base::IntToString(param)).c_str()); } } diff --git a/chromium/gpu/command_buffer/service/feature_info.cc b/chromium/gpu/command_buffer/service/feature_info.cc index c5479d0d8ec..0ce99809114 100644 --- a/chromium/gpu/command_buffer/service/feature_info.cc +++ b/chromium/gpu/command_buffer/service/feature_info.cc @@ -56,8 +56,8 @@ class StringSet { } void Init(const std::string& str) { - std::vector<std::string> tokens; - Tokenize(str, " ", &tokens); + std::vector<std::string> tokens = base::SplitString( + str, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); string_set_.insert(tokens.begin(), tokens.end()); } @@ -114,6 +114,9 @@ void StringToWorkarounds( workarounds->max_varying_vectors = 16; if (workarounds->max_vertex_uniform_vectors_256) workarounds->max_vertex_uniform_vectors = 256; + + if (workarounds->max_copy_texture_chromium_size_262144) + workarounds->max_copy_texture_chromium_size = 262144; } } // anonymous namespace. @@ -164,7 +167,8 @@ FeatureInfo::FeatureFlags::FeatureFlags() blend_equation_advanced_coherent(false), ext_texture_rg(false), enable_subscribe_uniform(false), - emulate_primitive_restart_fixed_index(false) { + emulate_primitive_restart_fixed_index(false), + ext_render_buffer_format_bgra8888(false) { } FeatureInfo::Workarounds::Workarounds() : @@ -175,7 +179,8 @@ FeatureInfo::Workarounds::Workarounds() : max_cube_map_texture_size(0), max_fragment_uniform_vectors(0), max_varying_vectors(0), - max_vertex_uniform_vectors(0) { + max_vertex_uniform_vectors(0), + max_copy_texture_chromium_size(0) { } FeatureInfo::FeatureInfo() { @@ -201,42 +206,10 @@ void FeatureInfo::InitializeBasicState(const base::CommandLine& command_line) { feature_flags_.enable_subscribe_uniform = command_line.HasSwitch(switches::kEnableSubscribeUniformExtension); - unsafe_es3_apis_enabled_ = + enable_unsafe_es3_apis_switch_ = command_line.HasSwitch(switches::kEnableUnsafeES3APIs); - static const GLenum kAlphaTypes[] = { - GL_UNSIGNED_BYTE, - }; - static const GLenum kRGBTypes[] = { - GL_UNSIGNED_BYTE, - GL_UNSIGNED_SHORT_5_6_5, - }; - static const GLenum kRGBATypes[] = { - GL_UNSIGNED_BYTE, - GL_UNSIGNED_SHORT_4_4_4_4, - GL_UNSIGNED_SHORT_5_5_5_1, - }; - static const GLenum kLuminanceTypes[] = { - GL_UNSIGNED_BYTE, - }; - static const GLenum kLuminanceAlphaTypes[] = { - GL_UNSIGNED_BYTE, - }; - static const FormatInfo kFormatTypes[] = { - { GL_ALPHA, kAlphaTypes, arraysize(kAlphaTypes), }, - { GL_RGB, kRGBTypes, arraysize(kRGBTypes), }, - { GL_RGBA, kRGBATypes, arraysize(kRGBATypes), }, - { GL_LUMINANCE, kLuminanceTypes, arraysize(kLuminanceTypes), }, - { GL_LUMINANCE_ALPHA, kLuminanceAlphaTypes, - arraysize(kLuminanceAlphaTypes), } , - }; - for (size_t ii = 0; ii < arraysize(kFormatTypes); ++ii) { - const FormatInfo& info = kFormatTypes[ii]; - ValueValidator<GLenum>& validator = texture_format_validators_[info.format]; - for (size_t jj = 0; jj < info.count; ++jj) { - validator.AddValue(info.types[jj]); - } - } + unsafe_es3_apis_enabled_ = false; } bool FeatureInfo::Initialize() { @@ -446,8 +419,6 @@ void FeatureInfo::InitializeFeatures() { if (enable_depth_texture) { AddExtensionString("GL_CHROMIUM_depth_texture"); AddExtensionString("GL_GOOGLE_depth_texture"); - texture_format_validators_[GL_DEPTH_COMPONENT].AddValue(GL_UNSIGNED_SHORT); - texture_format_validators_[GL_DEPTH_COMPONENT].AddValue(GL_UNSIGNED_INT); validators_.texture_internal_format.AddValue(GL_DEPTH_COMPONENT); validators_.texture_format.AddValue(GL_DEPTH_COMPONENT); validators_.pixel_type.AddValue(GL_UNSIGNED_SHORT); @@ -461,8 +432,6 @@ void FeatureInfo::InitializeFeatures() { AddExtensionString("GL_OES_packed_depth_stencil"); feature_flags_.packed_depth24_stencil8 = true; if (enable_depth_texture) { - texture_format_validators_[GL_DEPTH_STENCIL] - .AddValue(GL_UNSIGNED_INT_24_8); validators_.texture_internal_format.AddValue(GL_DEPTH_STENCIL); validators_.texture_format.AddValue(GL_DEPTH_STENCIL); validators_.pixel_type.AddValue(GL_UNSIGNED_INT_24_8); @@ -502,8 +471,6 @@ void FeatureInfo::InitializeFeatures() { extensions.Contains("GL_OES_rgb8_rgba8")) && extensions.Contains("GL_EXT_sRGB")) || gfx::HasDesktopGLFeatures()) { AddExtensionString("GL_EXT_sRGB"); - texture_format_validators_[GL_SRGB_EXT].AddValue(GL_UNSIGNED_BYTE); - texture_format_validators_[GL_SRGB_ALPHA_EXT].AddValue(GL_UNSIGNED_BYTE); validators_.texture_internal_format.AddValue(GL_SRGB_EXT); validators_.texture_internal_format.AddValue(GL_SRGB_ALPHA_EXT); validators_.texture_format.AddValue(GL_SRGB_EXT); @@ -540,7 +507,6 @@ void FeatureInfo::InitializeFeatures() { if (enable_texture_format_bgra8888) { feature_flags_.ext_texture_format_bgra8888 = true; AddExtensionString("GL_EXT_texture_format_BGRA8888"); - texture_format_validators_[GL_BGRA_EXT].AddValue(GL_UNSIGNED_BYTE); validators_.texture_internal_format.AddValue(GL_BGRA_EXT); validators_.texture_format.AddValue(GL_BGRA_EXT); } @@ -551,6 +517,7 @@ void FeatureInfo::InitializeFeatures() { } if (enable_render_buffer_bgra) { + feature_flags_.ext_render_buffer_format_bgra8888 = true; AddExtensionString("GL_CHROMIUM_renderbuffer_format_BGRA8888"); validators_.render_buffer_format.AddValue(GL_BGRA8_EXT); } @@ -562,10 +529,11 @@ void FeatureInfo::InitializeFeatures() { } // Check if we should allow GL_OES_texture_npot - if (gl_version_info_->is_es3 || - gl_version_info_->is_desktop_core_profile || - extensions.Contains("GL_ARB_texture_non_power_of_two") || - extensions.Contains("GL_OES_texture_npot")) { + if (!disallowed_features_.npot_support && + (gl_version_info_->is_es3 || + gl_version_info_->is_desktop_core_profile || + extensions.Contains("GL_ARB_texture_non_power_of_two") || + extensions.Contains("GL_OES_texture_npot"))) { AddExtensionString("GL_OES_texture_npot"); feature_flags_.npot_ok = true; } @@ -615,11 +583,6 @@ void FeatureInfo::InitializeFeatures() { } if (enable_texture_float) { - texture_format_validators_[GL_ALPHA].AddValue(GL_FLOAT); - texture_format_validators_[GL_RGB].AddValue(GL_FLOAT); - texture_format_validators_[GL_RGBA].AddValue(GL_FLOAT); - texture_format_validators_[GL_LUMINANCE].AddValue(GL_FLOAT); - texture_format_validators_[GL_LUMINANCE_ALPHA].AddValue(GL_FLOAT); validators_.pixel_type.AddValue(GL_FLOAT); validators_.read_pixel_type.AddValue(GL_FLOAT); AddExtensionString("GL_OES_texture_float"); @@ -629,11 +592,6 @@ void FeatureInfo::InitializeFeatures() { } if (enable_texture_half_float) { - texture_format_validators_[GL_ALPHA].AddValue(GL_HALF_FLOAT_OES); - texture_format_validators_[GL_RGB].AddValue(GL_HALF_FLOAT_OES); - texture_format_validators_[GL_RGBA].AddValue(GL_HALF_FLOAT_OES); - texture_format_validators_[GL_LUMINANCE].AddValue(GL_HALF_FLOAT_OES); - texture_format_validators_[GL_LUMINANCE_ALPHA].AddValue(GL_HALF_FLOAT_OES); validators_.pixel_type.AddValue(GL_HALF_FLOAT_OES); validators_.read_pixel_type.AddValue(GL_HALF_FLOAT_OES); AddExtensionString("GL_OES_texture_half_float"); @@ -745,10 +703,9 @@ void FeatureInfo::InitializeFeatures() { validators_.render_buffer_format.AddValue(GL_DEPTH_COMPONENT24); } - if (!workarounds_.disable_oes_standard_derivatives && - (gl_version_info_->is_es3 || - extensions.Contains("GL_OES_standard_derivatives") || - gfx::HasDesktopGLFeatures())) { + if (gl_version_info_->is_es3 || + extensions.Contains("GL_OES_standard_derivatives") || + gfx::HasDesktopGLFeatures()) { AddExtensionString("GL_OES_standard_derivatives"); feature_flags_.oes_standard_derivatives = true; validators_.hint_target.AddValue(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES); @@ -882,10 +839,9 @@ void FeatureInfo::InitializeFeatures() { bool have_arb_occlusion_query = extensions.Contains("GL_ARB_occlusion_query"); - if (!workarounds_.disable_ext_occlusion_query && - (have_ext_occlusion_query_boolean || - have_arb_occlusion_query2 || - have_arb_occlusion_query)) { + if (have_ext_occlusion_query_boolean || + have_arb_occlusion_query2 || + have_arb_occlusion_query) { AddExtensionString("GL_EXT_occlusion_query_boolean"); feature_flags_.occlusion_query_boolean = true; feature_flags_.use_arb_occlusion_query2_for_occlusion_query_boolean = @@ -969,16 +925,6 @@ void FeatureInfo::InitializeFeatures() { feature_flags_.ext_shader_texture_lod = true; } -#if !defined(OS_MACOSX) - if (workarounds_.disable_egl_khr_fence_sync) { - gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync = false; - } - if (workarounds_.disable_egl_khr_wait_sync) { - gfx::g_driver_egl.ext.b_EGL_KHR_wait_sync = false; - } -#endif - if (workarounds_.disable_arb_sync) - gfx::g_driver_gl.ext.b_GL_ARB_sync = false; bool ui_gl_fence_works = gfx::GLFence::IsSupported(); UMA_HISTOGRAM_BOOLEAN("GPU.FenceSupport", ui_gl_fence_works); @@ -1085,18 +1031,6 @@ void FeatureInfo::InitializeFeatures() { validators_.read_pixel_format.AddValue(GL_RG_EXT); validators_.render_buffer_format.AddValue(GL_R8_EXT); validators_.render_buffer_format.AddValue(GL_RG8_EXT); - - texture_format_validators_[GL_RED_EXT].AddValue(GL_UNSIGNED_BYTE); - texture_format_validators_[GL_RG_EXT].AddValue(GL_UNSIGNED_BYTE); - - if (enable_texture_float) { - texture_format_validators_[GL_RED_EXT].AddValue(GL_FLOAT); - texture_format_validators_[GL_RG_EXT].AddValue(GL_FLOAT); - } - if (enable_texture_half_float) { - texture_format_validators_[GL_RED_EXT].AddValue(GL_HALF_FLOAT_OES); - texture_format_validators_[GL_RG_EXT].AddValue(GL_HALF_FLOAT_OES); - } } UMA_HISTOGRAM_BOOLEAN("GPU.TextureRG", feature_flags_.ext_texture_rg); @@ -1119,7 +1053,7 @@ void FeatureInfo::InitializeFeatures() { } bool FeatureInfo::IsES3Capable() const { - if (!unsafe_es3_apis_enabled_) + if (!enable_unsafe_es3_apis_switch_) return false; if (gl_version_info_) return gl_version_info_->IsES3Capable(); @@ -1183,6 +1117,8 @@ void FeatureInfo::EnableES3Validators() { kDrawBuffers + max_draw_buffers, kTotalDrawBufferEnums - max_draw_buffers); } + + unsafe_es3_apis_enabled_ = true; } void FeatureInfo::AddExtensionString(const char* s) { diff --git a/chromium/gpu/command_buffer/service/feature_info.h b/chromium/gpu/command_buffer/service/feature_info.h index c3ed1502d02..1ebff2a02a1 100644 --- a/chromium/gpu/command_buffer/service/feature_info.h +++ b/chromium/gpu/command_buffer/service/feature_info.h @@ -79,6 +79,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool ext_texture_rg; bool enable_subscribe_uniform; bool emulate_primitive_restart_fixed_index; + bool ext_render_buffer_format_bgra8888; }; struct Workarounds { @@ -94,6 +95,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { GLint max_fragment_uniform_vectors; GLint max_varying_vectors; GLint max_vertex_uniform_vectors; + GLint max_copy_texture_chromium_size; }; // Constructor with workarounds taken from the current process's CommandLine @@ -110,10 +112,6 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { return &validators_; } - const ValueValidator<GLenum>& GetTextureFormatValidator(GLenum format) { - return texture_format_validators_[format]; - } - const std::string& extensions() const { return extensions_; } @@ -134,13 +132,14 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool IsES3Capable() const; void EnableES3Validators(); + bool IsES3Enabled() const { + return unsafe_es3_apis_enabled_; + } + private: friend class base::RefCounted<FeatureInfo>; friend class BufferManagerClientSideArraysTest; - typedef base::hash_map<GLenum, ValueValidator<GLenum> > ValidatorMap; - ValidatorMap texture_format_validators_; - ~FeatureInfo(); void AddExtensionString(const char* s); @@ -161,6 +160,8 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { Workarounds workarounds_; // Whether the command line switch kEnableUnsafeES3APIs is passed in. + bool enable_unsafe_es3_apis_switch_; + bool unsafe_es3_apis_enabled_; scoped_ptr<gfx::GLVersionInfo> gl_version_info_; diff --git a/chromium/gpu/command_buffer/service/feature_info_unittest.cc b/chromium/gpu/command_buffer/service/feature_info_unittest.cc index 0136f41fe14..fdff1754715 100644 --- a/chromium/gpu/command_buffer/service/feature_info_unittest.cc +++ b/chromium/gpu/command_buffer/service/feature_info_unittest.cc @@ -167,97 +167,6 @@ TEST_P(FeatureInfoTest, Basic) { EXPECT_EQ(0, info_->workarounds().max_texture_size); EXPECT_EQ(0, info_->workarounds().max_cube_map_texture_size); EXPECT_FALSE(info_->workarounds().gl_clear_broken); - - // Test good types. - { - static const GLenum kAlphaTypes[] = { - GL_UNSIGNED_BYTE, - }; - static const GLenum kRGBTypes[] = { - GL_UNSIGNED_BYTE, - GL_UNSIGNED_SHORT_5_6_5, - }; - static const GLenum kRGBATypes[] = { - GL_UNSIGNED_BYTE, - GL_UNSIGNED_SHORT_4_4_4_4, - GL_UNSIGNED_SHORT_5_5_5_1, - }; - static const GLenum kLuminanceTypes[] = { - GL_UNSIGNED_BYTE, - }; - static const GLenum kLuminanceAlphaTypes[] = { - GL_UNSIGNED_BYTE, - }; - static const FormatInfo kFormatTypes[] = { - { GL_ALPHA, kAlphaTypes, arraysize(kAlphaTypes), }, - { GL_RGB, kRGBTypes, arraysize(kRGBTypes), }, - { GL_RGBA, kRGBATypes, arraysize(kRGBATypes), }, - { GL_LUMINANCE, kLuminanceTypes, arraysize(kLuminanceTypes), }, - { GL_LUMINANCE_ALPHA, kLuminanceAlphaTypes, - arraysize(kLuminanceAlphaTypes), } , - }; - for (size_t ii = 0; ii < arraysize(kFormatTypes); ++ii) { - const FormatInfo& info = kFormatTypes[ii]; - const ValueValidator<GLenum>& validator = - info_->GetTextureFormatValidator(info.format); - for (size_t jj = 0; jj < info.count; ++jj) { - EXPECT_TRUE(validator.IsValid(info.types[jj])); - } - } - } - - // Test some bad types - { - static const GLenum kAlphaTypes[] = { - GL_UNSIGNED_SHORT_5_5_5_1, - GL_FLOAT, - }; - static const GLenum kRGBTypes[] = { - GL_UNSIGNED_SHORT_4_4_4_4, - GL_FLOAT, - }; - static const GLenum kRGBATypes[] = { - GL_UNSIGNED_SHORT_5_6_5, - GL_FLOAT, - }; - static const GLenum kLuminanceTypes[] = { - GL_UNSIGNED_SHORT_4_4_4_4, - GL_FLOAT, - }; - static const GLenum kLuminanceAlphaTypes[] = { - GL_UNSIGNED_SHORT_5_5_5_1, - GL_FLOAT, - }; - static const GLenum kBGRATypes[] = { - GL_UNSIGNED_BYTE, - GL_UNSIGNED_SHORT_5_6_5, - GL_FLOAT, - }; - static const GLenum kDepthTypes[] = { - GL_UNSIGNED_BYTE, - GL_UNSIGNED_SHORT, - GL_UNSIGNED_INT, - GL_FLOAT, - }; - static const FormatInfo kFormatTypes[] = { - { GL_ALPHA, kAlphaTypes, arraysize(kAlphaTypes), }, - { GL_RGB, kRGBTypes, arraysize(kRGBTypes), }, - { GL_RGBA, kRGBATypes, arraysize(kRGBATypes), }, - { GL_LUMINANCE, kLuminanceTypes, arraysize(kLuminanceTypes), }, - { GL_LUMINANCE_ALPHA, kLuminanceAlphaTypes, - arraysize(kLuminanceAlphaTypes), } , - { GL_BGRA_EXT, kBGRATypes, arraysize(kBGRATypes), }, - { GL_DEPTH_COMPONENT, kDepthTypes, arraysize(kDepthTypes), }, - }; - for (size_t ii = 0; ii < arraysize(kFormatTypes); ++ii) { - const FormatInfo& info = kFormatTypes[ii]; - const ValueValidator<GLenum>& validator = - info_->GetTextureFormatValidator(info.format); - for (size_t jj = 0; jj < info.count; ++jj) { - EXPECT_FALSE(validator.IsValid(info.types[jj])); - } - } - } } TEST_P(FeatureInfoTest, InitializeNoExtensions) { @@ -358,10 +267,6 @@ TEST_P(FeatureInfoTest, InitializeNoExtensions) { EXPECT_FALSE(info_->validators()->equation.IsValid(GL_MIN_EXT)); EXPECT_FALSE(info_->validators()->equation.IsValid(GL_MAX_EXT)); EXPECT_FALSE(info_->feature_flags().chromium_sync_query); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_SRGB_EXT).IsValid( - GL_UNSIGNED_BYTE)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_SRGB_ALPHA_EXT).IsValid( - GL_UNSIGNED_BYTE)); EXPECT_FALSE(info_->validators()->texture_format.IsValid( GL_SRGB_EXT)); EXPECT_FALSE(info_->validators()->texture_format.IsValid( @@ -433,10 +338,9 @@ TEST_P(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GLES2) { GL_BGRA_EXT)); EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( GL_BGRA_EXT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_BGRA_EXT).IsValid( - GL_UNSIGNED_BYTE)); EXPECT_FALSE(info_->validators()->render_buffer_format.IsValid( GL_BGRA8_EXT)); + EXPECT_FALSE(info_->feature_flags().ext_render_buffer_format_bgra8888); } TEST_P(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GL) { @@ -447,14 +351,13 @@ TEST_P(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GL) { HasSubstr("GL_EXT_read_format_bgra")); EXPECT_THAT(info_->extensions(), HasSubstr("GL_CHROMIUM_renderbuffer_format_BGRA8888")); + EXPECT_TRUE(info_->feature_flags().ext_render_buffer_format_bgra8888); EXPECT_TRUE(info_->validators()->texture_format.IsValid( GL_BGRA_EXT)); EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( GL_BGRA_EXT)); EXPECT_TRUE(info_->validators()->read_pixel_format.IsValid( GL_BGRA_EXT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_BGRA_EXT).IsValid( - GL_UNSIGNED_BYTE)); EXPECT_TRUE(info_->validators()->render_buffer_format.IsValid( GL_BGRA8_EXT)); } @@ -467,10 +370,9 @@ TEST_P(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888Apple) { GL_BGRA_EXT)); EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( GL_BGRA_EXT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_BGRA_EXT).IsValid( - GL_UNSIGNED_BYTE)); EXPECT_FALSE(info_->validators()->render_buffer_format.IsValid( GL_BGRA8_EXT)); + EXPECT_FALSE(info_->feature_flags().ext_render_buffer_format_bgra8888); } TEST_P(FeatureInfoTest, InitializeEXT_read_format_bgra) { @@ -485,16 +387,13 @@ TEST_P(FeatureInfoTest, InitializeEXT_read_format_bgra) { GL_BGRA_EXT)); EXPECT_FALSE(info_->validators()->render_buffer_format.IsValid( GL_BGRA8_EXT)); + EXPECT_FALSE(info_->feature_flags().ext_render_buffer_format_bgra8888); } TEST_P(FeatureInfoTest, InitializeEXT_sRGB) { SetupInitExpectations("GL_EXT_sRGB GL_OES_rgb8_rgba8"); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_sRGB")); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_SRGB_EXT).IsValid( - GL_UNSIGNED_BYTE)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_SRGB_ALPHA_EXT).IsValid( - GL_UNSIGNED_BYTE)); EXPECT_TRUE(info_->validators()->texture_format.IsValid( GL_SRGB_EXT)); EXPECT_TRUE(info_->validators()->texture_format.IsValid( @@ -697,6 +596,7 @@ TEST_P(FeatureInfoTest, InitializeWithANGLE_BGRA8) { EXPECT_TRUE(info_->gl_version_info().is_angle); EXPECT_THAT(info_->extensions(), HasSubstr("GL_CHROMIUM_renderbuffer_format_BGRA8888")); + EXPECT_TRUE(info_->feature_flags().ext_render_buffer_format_bgra8888); EXPECT_TRUE(info_->validators()->render_buffer_format.IsValid(GL_BGRA8_EXT)); } @@ -704,6 +604,7 @@ TEST_P(FeatureInfoTest, InitializeWithANGLE_BGRA8) { TEST_P(FeatureInfoTest, InitializeGLES2_no_CHROMIUM_renderbuffer_format_BGRA8888) { SetupInitExpectationsWithGLVersion("", "", "OpenGL ES 2.0"); + EXPECT_FALSE(info_->feature_flags().ext_render_buffer_format_bgra8888); EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_CHROMIUM_renderbuffer_format_BGRA8888"))); } @@ -729,25 +630,11 @@ TEST_P(FeatureInfoTest, Initialize_texture_floatGLES3) { Not(HasSubstr("GL_OES_texture_float_linear"))); EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_OES_texture_half_float_linear"))); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGB).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( - GL_FLOAT)); } TEST_P(FeatureInfoTest, Initialize_sRGBGLES3) { SetupInitExpectationsWithGLVersion("", "", "OpenGL ES 3.0"); EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_EXT_sRGB"))); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_SRGB_EXT).IsValid( - GL_UNSIGNED_BYTE)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_SRGB_ALPHA_EXT).IsValid( - GL_UNSIGNED_BYTE)); EXPECT_FALSE(info_->validators()->texture_format.IsValid( GL_SRGB_EXT)); EXPECT_FALSE(info_->validators()->texture_format.IsValid( @@ -774,26 +661,6 @@ TEST_P(FeatureInfoTest, InitializeOES_texture_floatGLES2) { Not(HasSubstr("GL_OES_texture_half_float_linear"))); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_FLOAT)); EXPECT_FALSE(info_->validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( - GL_FLOAT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGB).IsValid( - GL_FLOAT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( - GL_FLOAT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( - GL_FLOAT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGB).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( - GL_HALF_FLOAT_OES)); } TEST_P(FeatureInfoTest, InitializeOES_texture_float_linearGLES2) { @@ -807,26 +674,6 @@ TEST_P(FeatureInfoTest, InitializeOES_texture_float_linearGLES2) { Not(HasSubstr("GL_OES_texture_half_float_linear"))); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_FLOAT)); EXPECT_FALSE(info_->validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( - GL_FLOAT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGB).IsValid( - GL_FLOAT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( - GL_FLOAT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( - GL_FLOAT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGB).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( - GL_HALF_FLOAT_OES)); } TEST_P(FeatureInfoTest, InitializeOES_texture_half_floatGLES2) { @@ -841,26 +688,6 @@ TEST_P(FeatureInfoTest, InitializeOES_texture_half_floatGLES2) { Not(HasSubstr("GL_OES_texture_half_float_linear"))); EXPECT_FALSE(info_->validators()->pixel_type.IsValid(GL_FLOAT)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGB).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( - GL_FLOAT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGB).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( - GL_HALF_FLOAT_OES)); } TEST_P(FeatureInfoTest, InitializeOES_texture_half_float_linearGLES2) { @@ -876,26 +703,6 @@ TEST_P(FeatureInfoTest, InitializeOES_texture_half_float_linearGLES2) { HasSubstr("GL_OES_texture_half_float_linear")); EXPECT_FALSE(info_->validators()->pixel_type.IsValid(GL_FLOAT)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGB).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( - GL_FLOAT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( - GL_FLOAT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGB).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( - GL_HALF_FLOAT_OES)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( - GL_HALF_FLOAT_OES)); } TEST_P(FeatureInfoTest, InitializeEXT_framebuffer_multisample) { @@ -1007,12 +814,6 @@ TEST_P(FeatureInfoTest, InitializeEXT_ARB_depth_texture) { EXPECT_FALSE(info_->validators()->texture_format.IsValid(GL_DEPTH_STENCIL)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( - GL_UNSIGNED_SHORT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( - GL_UNSIGNED_INT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_DEPTH_STENCIL).IsValid( - GL_UNSIGNED_INT_24_8)); } TEST_P(FeatureInfoTest, InitializeOES_ARB_depth_texture) { @@ -1027,12 +828,6 @@ TEST_P(FeatureInfoTest, InitializeOES_ARB_depth_texture) { EXPECT_FALSE(info_->validators()->texture_format.IsValid(GL_DEPTH_STENCIL)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( - GL_UNSIGNED_SHORT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( - GL_UNSIGNED_INT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_DEPTH_STENCIL).IsValid( - GL_UNSIGNED_INT_24_8)); } TEST_P(FeatureInfoTest, InitializeANGLE_depth_texture) { @@ -1056,12 +851,6 @@ TEST_P(FeatureInfoTest, InitializeANGLE_depth_texture) { GL_DEPTH_COMPONENT32_OES)); EXPECT_FALSE(info_->validators()->texture_internal_format_storage.IsValid( GL_DEPTH24_STENCIL8_OES)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( - GL_UNSIGNED_SHORT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( - GL_UNSIGNED_INT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_DEPTH_STENCIL).IsValid( - GL_UNSIGNED_INT_24_8)); } TEST_P(FeatureInfoTest, InitializeEXT_packed_depth_stencil) { @@ -1103,12 +892,6 @@ TEST_P(FeatureInfoTest, GL_DEPTH_STENCIL)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid( GL_UNSIGNED_INT_24_8)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( - GL_UNSIGNED_SHORT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( - GL_UNSIGNED_INT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_STENCIL).IsValid( - GL_UNSIGNED_INT_24_8)); } TEST_P(FeatureInfoTest, InitializeOES_depth24) { @@ -1323,12 +1106,6 @@ TEST_P(FeatureInfoTest, InitializeWithES3) { EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_INT_24_8)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT) - .IsValid(GL_UNSIGNED_SHORT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT) - .IsValid(GL_UNSIGNED_INT)); - EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_STENCIL) - .IsValid(GL_UNSIGNED_INT_24_8)); EXPECT_TRUE(info_->feature_flags().packed_depth24_stencil8); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_depth24")); EXPECT_TRUE( @@ -1402,16 +1179,6 @@ TEST_P(FeatureInfoTest, InitializeWithPreferredEXTDrawBuffers) { EXPECT_TRUE(info_->feature_flags().ext_draw_buffers); } -TEST_P(FeatureInfoTest, ARBSyncDisabled) { - base::CommandLine command_line(0, NULL); - command_line.AppendSwitchASCII( - switches::kGpuDriverBugWorkarounds, - base::IntToString(gpu::DISABLE_ARB_SYNC)); - SetupInitExpectationsWithCommandLine("GL_ARB_sync", command_line); - EXPECT_FALSE(info_->feature_flags().chromium_sync_query); - EXPECT_FALSE(gfx::GLFence::IsSupported()); -} - TEST_P(FeatureInfoTest, BlendEquationAdvancedDisabled) { base::CommandLine command_line(0, NULL); command_line.AppendSwitchASCII( @@ -1501,20 +1268,6 @@ TEST_P(FeatureInfoTest, InitializeEXT_texture_rgWithFloat) { EXPECT_TRUE(info_->validators()->read_pixel_format.IsValid(GL_RG_EXT)); EXPECT_TRUE(info_->validators()->render_buffer_format.IsValid(GL_R8_EXT)); EXPECT_TRUE(info_->validators()->render_buffer_format.IsValid(GL_RG8_EXT)); - - EXPECT_TRUE( - info_->GetTextureFormatValidator(GL_RED_EXT).IsValid(GL_HALF_FLOAT_OES)); - EXPECT_TRUE( - info_->GetTextureFormatValidator(GL_RG_EXT).IsValid(GL_HALF_FLOAT_OES)); - EXPECT_TRUE( - info_->GetTextureFormatValidator(GL_RED_EXT).IsValid(GL_UNSIGNED_BYTE)); - EXPECT_TRUE( - info_->GetTextureFormatValidator(GL_RG_EXT).IsValid(GL_UNSIGNED_BYTE)); - - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RED_EXT).IsValid(GL_BYTE)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RG_EXT).IsValid(GL_BYTE)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RED_EXT).IsValid(GL_SHORT)); - EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RG_EXT).IsValid(GL_SHORT)); } TEST_P(FeatureInfoTest, InitializeARB_texture_rgNoFloat) { @@ -1529,15 +1282,6 @@ TEST_P(FeatureInfoTest, InitializeARB_texture_rgNoFloat) { EXPECT_TRUE(info_->validators()->read_pixel_format.IsValid(GL_RG_EXT)); EXPECT_TRUE(info_->validators()->render_buffer_format.IsValid(GL_R8_EXT)); EXPECT_TRUE(info_->validators()->render_buffer_format.IsValid(GL_RG8_EXT)); - - EXPECT_FALSE( - info_->GetTextureFormatValidator(GL_RED_EXT).IsValid(GL_HALF_FLOAT_OES)); - EXPECT_FALSE( - info_->GetTextureFormatValidator(GL_RG_EXT).IsValid(GL_HALF_FLOAT_OES)); - EXPECT_TRUE( - info_->GetTextureFormatValidator(GL_RED_EXT).IsValid(GL_UNSIGNED_BYTE)); - EXPECT_TRUE( - info_->GetTextureFormatValidator(GL_RG_EXT).IsValid(GL_UNSIGNED_BYTE)); } } // namespace gles2 diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc index e1af82d1059..5f42390f62d 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc @@ -446,46 +446,22 @@ TEST_F(FramebufferInfoTest, AttachTexture) { // Try format that doesn't work with COLOR_ATTACHMENT0 texture_manager_->SetTarget(texture1.get(), GL_TEXTURE_2D); - texture_manager_->SetLevelInfo(texture1.get(), - GL_TEXTURE_2D, - kLevel1, - kBadFormat1, - kWidth1, - kHeight1, - kDepth, - kBorder, - kBadFormat1, - kType, - true); + texture_manager_->SetLevelInfo( + texture1.get(), GL_TEXTURE_2D, kLevel1, kBadFormat1, kWidth1, kHeight1, + kDepth, kBorder, kBadFormat1, kType, gfx::Rect(kWidth1, kHeight1)); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT), framebuffer_->IsPossiblyComplete()); // Try a good format. - texture_manager_->SetLevelInfo(texture1.get(), - GL_TEXTURE_2D, - kLevel1, - kFormat1, - kWidth1, - kHeight1, - kDepth, - kBorder, - kFormat1, - kType, - false); + texture_manager_->SetLevelInfo(texture1.get(), GL_TEXTURE_2D, kLevel1, + kFormat1, kWidth1, kHeight1, kDepth, kBorder, + kFormat1, kType, gfx::Rect()); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), framebuffer_->IsPossiblyComplete()); EXPECT_FALSE(framebuffer_->IsCleared()); - texture_manager_->SetLevelInfo(texture1.get(), - GL_TEXTURE_2D, - kLevel1, - kFormat1, - kWidth1, - kHeight1, - kDepth, - kBorder, - kFormat1, - kType, - true); + texture_manager_->SetLevelInfo(texture1.get(), GL_TEXTURE_2D, kLevel1, + kFormat1, kWidth1, kHeight1, kDepth, kBorder, + kFormat1, kType, gfx::Rect(kWidth1, kHeight1)); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), framebuffer_->IsPossiblyComplete()); EXPECT_TRUE(framebuffer_->IsCleared()); @@ -507,17 +483,9 @@ TEST_F(FramebufferInfoTest, AttachTexture) { texture_manager_->GetTexture(kTextureClient2Id)); ASSERT_TRUE(texture2.get() != NULL); texture_manager_->SetTarget(texture2.get(), GL_TEXTURE_2D); - texture_manager_->SetLevelInfo(texture2.get(), - GL_TEXTURE_2D, - kLevel2, - kFormat2, - kWidth2, - kHeight2, - kDepth, - kBorder, - kFormat2, - kType, - true); + texture_manager_->SetLevelInfo(texture2.get(), GL_TEXTURE_2D, kLevel2, + kFormat2, kWidth2, kHeight2, kDepth, kBorder, + kFormat2, kType, gfx::Rect(kWidth2, kHeight2)); framebuffer_->AttachTexture( GL_COLOR_ATTACHMENT0, texture2.get(), kTarget2, kLevel2, kSamples2); @@ -536,17 +504,9 @@ TEST_F(FramebufferInfoTest, AttachTexture) { EXPECT_TRUE(attachment->cleared()); // Check changing attachment - texture_manager_->SetLevelInfo(texture2.get(), - GL_TEXTURE_2D, - kLevel3, - kFormat3, - kWidth3, - kHeight3, - kDepth, - kBorder, - kFormat3, - kType, - false); + texture_manager_->SetLevelInfo(texture2.get(), GL_TEXTURE_2D, kLevel3, + kFormat3, kWidth3, kHeight3, kDepth, kBorder, + kFormat3, kType, gfx::Rect()); attachment = framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0); ASSERT_TRUE(attachment != NULL); EXPECT_EQ(kWidth3, attachment->width()); @@ -561,17 +521,9 @@ TEST_F(FramebufferInfoTest, AttachTexture) { EXPECT_FALSE(framebuffer_->IsCleared()); // Set to size 0 - texture_manager_->SetLevelInfo(texture2.get(), - GL_TEXTURE_2D, - kLevel3, - kFormat3, - 0, - 0, - kDepth, - kBorder, - kFormat3, - kType, - false); + texture_manager_->SetLevelInfo(texture2.get(), GL_TEXTURE_2D, kLevel3, + kFormat3, 0, 0, kDepth, kBorder, kFormat3, + kType, gfx::Rect()); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT), framebuffer_->IsPossiblyComplete()); @@ -627,9 +579,9 @@ TEST_F(FramebufferInfoTest, DrawBuffers) { scoped_refptr<TextureRef> texture1( texture_manager_->GetTexture(kTextureClientId[1])); texture_manager_->SetTarget(texture1.get(), GL_TEXTURE_2D); - texture_manager_->SetLevelInfo( - texture1.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, - 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false); + texture_manager_->SetLevelInfo(texture1.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, + 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect()); const Framebuffer::Attachment* attachment1 = framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT1); @@ -719,17 +671,9 @@ TEST_F(FramebufferInfoFloatTest, AttachFloatTexture) { EXPECT_EQ(static_cast<GLenum>(0), framebuffer_->GetColorAttachmentFormat()); texture_manager_->SetTarget(texture.get(), GL_TEXTURE_2D); - texture_manager_->SetLevelInfo(texture.get(), - GL_TEXTURE_2D, - kLevel, - kInternalFormat, - kWidth, - kHeight, - kDepth, - kBorder, - kFormat, - kType, - false); + texture_manager_->SetLevelInfo(texture.get(), GL_TEXTURE_2D, kLevel, + kInternalFormat, kWidth, kHeight, kDepth, + kBorder, kFormat, kType, gfx::Rect()); // Texture with a sized float internalformat is allowed as an attachment // since float color attachment extension is present. EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), diff --git a/chromium/gpu/command_buffer/service/gl_surface_mock.h b/chromium/gpu/command_buffer/service/gl_surface_mock.h index 0652be64de3..1d756d4d359 100644 --- a/chromium/gpu/command_buffer/service/gl_surface_mock.h +++ b/chromium/gpu/command_buffer/service/gl_surface_mock.h @@ -5,8 +5,9 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GL_SURFACE_MOCK_H_ #define GPU_COMMAND_BUFFER_SERVICE_GL_SURFACE_MOCK_H_ -#include "ui/gl/gl_surface.h" #include "testing/gmock/include/gmock/gmock.h" +#include "ui/gfx/swap_result.h" +#include "ui/gl/gl_surface.h" namespace gpu { @@ -18,8 +19,9 @@ class GLSurfaceMock : public gfx::GLSurface { MOCK_METHOD0(Destroy, void()); MOCK_METHOD1(Resize, bool(const gfx::Size& size)); MOCK_METHOD0(IsOffscreen, bool()); - MOCK_METHOD0(SwapBuffers, bool()); - MOCK_METHOD4(PostSubBuffer, bool(int x, int y, int width, int height)); + MOCK_METHOD0(SwapBuffers, gfx::SwapResult()); + MOCK_METHOD4(PostSubBuffer, + gfx::SwapResult(int x, int y, int width, int height)); MOCK_METHOD0(SupportsPostSubBuffer, bool()); MOCK_METHOD0(GetSize, gfx::Size()); MOCK_METHOD0(GetHandle, void*()); diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc b/chromium/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc index 4a9aaa7824f..e8057912bbb 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "ui/gfx/geometry/size.h" namespace { diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc b/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc index d41ee9db3a3..846ac0d6a12 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc @@ -59,23 +59,23 @@ enum FragmentShaderId { const char* vertex_shader_source[NUM_VERTEX_SHADERS] = { // VERTEX_SHADER_COPY_TEXTURE SHADER( - uniform mat4 u_matrix; + uniform vec2 u_vertex_translate; uniform vec2 u_half_size; attribute vec4 a_position; varying TexCoordPrecision vec2 v_uv; void main(void) { - gl_Position = u_matrix * a_position; + gl_Position = a_position + vec4(u_vertex_translate, 0.0, 0.0); v_uv = a_position.xy * vec2(u_half_size.s, u_half_size.t) + vec2(u_half_size.s, u_half_size.t); }), // VERTEX_SHADER_COPY_TEXTURE_FLIP_Y SHADER( - uniform mat4 u_matrix; + uniform vec2 u_vertex_translate; uniform vec2 u_half_size; attribute vec4 a_position; varying TexCoordPrecision vec2 v_uv; void main(void) { - gl_Position = u_matrix * a_position; + gl_Position = a_position + vec4(u_vertex_translate, 0.0, 0.0); v_uv = a_position.xy * vec2(u_half_size.s, -u_half_size.t) + vec2(u_half_size.s, u_half_size.t); }), @@ -85,24 +85,30 @@ const char* fragment_shader_source[NUM_FRAGMENT_SHADERS] = { // FRAGMENT_SHADER_COPY_TEXTURE_* FRAGMENT_SHADERS( uniform SamplerType u_sampler; + uniform mat4 u_tex_coord_transform; varying TexCoordPrecision vec2 v_uv; void main(void) { - gl_FragColor = TextureLookup(u_sampler, v_uv.st); + TexCoordPrecision vec4 uv = u_tex_coord_transform * vec4(v_uv, 0, 1); + gl_FragColor = TextureLookup(u_sampler, uv.st); }), // FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_* FRAGMENT_SHADERS( uniform SamplerType u_sampler; + uniform mat4 u_tex_coord_transform; varying TexCoordPrecision vec2 v_uv; void main(void) { - gl_FragColor = TextureLookup(u_sampler, v_uv.st); + TexCoordPrecision vec4 uv = u_tex_coord_transform * vec4(v_uv, 0, 1); + gl_FragColor = TextureLookup(u_sampler, uv.st); gl_FragColor.rgb *= gl_FragColor.a; }), // FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_* FRAGMENT_SHADERS( uniform SamplerType u_sampler; + uniform mat4 u_tex_coord_transform; varying TexCoordPrecision vec2 v_uv; void main(void) { - gl_FragColor = TextureLookup(u_sampler, v_uv.st); + TexCoordPrecision vec4 uv = u_tex_coord_transform * vec4(v_uv, 0, 1); + gl_FragColor = TextureLookup(u_sampler, uv.st); if (gl_FragColor.a > 0.0) gl_FragColor.rgb /= gl_FragColor.a; }), @@ -250,6 +256,8 @@ void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder, GLuint dest_id, GLint xoffset, GLint yoffset, + GLint source_x, + GLint source_y, GLsizei source_width, GLsizei source_height, GLuint framebuffer) { @@ -262,7 +270,7 @@ void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glCopyTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, xoffset, yoffset, - 0 /* x */, 0 /* y */, source_width, source_height); + source_x, source_y, source_width, source_height); } decoder->RestoreTextureState(source_id); @@ -272,17 +280,6 @@ void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder, decoder->RestoreFramebufferBindings(); } -// Copy from SkMatrix44::preTranslate -void PreTranslate(GLfloat* matrix, GLfloat dx, GLfloat dy, GLfloat dz) { - if (!dx && !dy && !dz) - return; - - for (int i = 0; i < 4; ++i) { - matrix[(3 * 4) + i] = matrix[(0 * 4) + i] * dx + matrix[(1 * 4) + i] * dy + - matrix[(2 * 4) + i] * dz + matrix[(3 * 4) + i]; - } -} - } // namespace namespace gpu { @@ -398,6 +395,10 @@ void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( GLenum dest_internal_format, GLint xoffset, GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, GLsizei dest_width, GLsizei dest_height, GLsizei source_width, @@ -419,15 +420,14 @@ void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change && source_format_contain_superset_of_dest_format) { DoCopyTexSubImage2D(decoder, source_target, source_id, dest_id, xoffset, - yoffset, source_width, source_height, framebuffer_); + yoffset, x, y, width, height, framebuffer_); return; } - // Use kIdentityMatrix if no transform passed in. - DoCopySubTextureWithTransform( - decoder, source_target, source_id, dest_id, xoffset, yoffset, dest_width, - dest_height, source_width, source_height, flip_y, premultiply_alpha, - unpremultiply_alpha, kIdentityMatrix); + DoCopyTextureInternal(decoder, source_target, source_id, dest_id, xoffset, + yoffset, x, y, width, height, dest_width, dest_height, + source_width, source_height, flip_y, premultiply_alpha, + unpremultiply_alpha, kIdentityMatrix); } void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( @@ -443,33 +443,12 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( const GLfloat transform_matrix[16]) { GLsizei dest_width = width; GLsizei dest_height = height; - DoCopyTextureInternal(decoder, source_target, source_id, dest_id, 0, 0, - dest_width, dest_height, width, height, flip_y, - premultiply_alpha, unpremultiply_alpha, + DoCopyTextureInternal(decoder, source_target, source_id, dest_id, 0, 0, 0, 0, + width, height, dest_width, dest_height, width, height, + flip_y, premultiply_alpha, unpremultiply_alpha, transform_matrix); } -void CopyTextureCHROMIUMResourceManager::DoCopySubTextureWithTransform( - const gles2::GLES2Decoder* decoder, - GLenum source_target, - GLuint source_id, - GLuint dest_id, - GLint xoffset, - GLint yoffset, - GLsizei dest_width, - GLsizei dest_height, - GLsizei source_width, - GLsizei source_height, - bool flip_y, - bool premultiply_alpha, - bool unpremultiply_alpha, - const GLfloat transform_matrix[16]) { - DoCopyTextureInternal(decoder, source_target, source_id, dest_id, xoffset, - yoffset, dest_width, dest_height, source_width, - source_height, flip_y, premultiply_alpha, - unpremultiply_alpha, transform_matrix); -} - void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( const gles2::GLES2Decoder* decoder, GLenum source_target, @@ -477,6 +456,10 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( GLuint dest_id, GLint xoffset, GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, GLsizei dest_width, GLsizei dest_height, GLsizei source_width, @@ -527,25 +510,31 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( if (!linked) DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; #endif - info->matrix_handle = glGetUniformLocation(info->program, "u_matrix"); + info->vertex_translate_handle = glGetUniformLocation(info->program, + "u_vertex_translate"); + info->tex_coord_transform_handle = + glGetUniformLocation(info->program, "u_tex_coord_transform"); info->half_size_handle = glGetUniformLocation(info->program, "u_half_size"); info->sampler_handle = glGetUniformLocation(info->program, "u_sampler"); } glUseProgram(info->program); - if (!xoffset && !yoffset) { - glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, transform_matrix); + glUniformMatrix4fv(info->tex_coord_transform_handle, 1, GL_FALSE, + transform_matrix); + + GLint x_translate = xoffset - x; + GLint y_translate = yoffset - y; + if (!x_translate && !y_translate) { + glUniform2f(info->vertex_translate_handle, 0.0f, 0.0f); } else { // transform offsets from ([0, dest_width], [0, dest_height]) coord. // to ([-1, 1], [-1, 1]) coord. - GLfloat xoffset_on_vertex = ((2.f * xoffset) / dest_width); - GLfloat yoffset_on_vertex = ((2.f * yoffset) / dest_height); - - // Pass view_matrix * offset_matrix to the program. - GLfloat view_transform[16]; - memcpy(view_transform, transform_matrix, 16 * sizeof(GLfloat)); - PreTranslate(view_transform, xoffset_on_vertex, yoffset_on_vertex, 0); - glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, view_transform); + GLfloat x_translate_on_vertex = ((2.f * x_translate) / dest_width); + GLfloat y_translate_on_vertex = ((2.f * y_translate) / dest_height); + + // Pass translation to the shader program. + glUniform2f(info->vertex_translate_handle, x_translate_on_vertex, + y_translate_on_vertex); } if (source_target == GL_TEXTURE_RECTANGLE_ARB) glUniform2f(info->half_size_handle, source_width / 2.0f, @@ -580,13 +569,18 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( glTexParameteri(source_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); glDisable(GL_STENCIL_TEST); glDisable(GL_CULL_FACE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_FALSE); glDisable(GL_BLEND); + bool need_scissor = + xoffset || yoffset || width != dest_width || height != dest_height; + if (need_scissor) { + glEnable(GL_SCISSOR_TEST); + glScissor(xoffset, yoffset, width, height); + } glViewport(0, 0, dest_width, dest_height); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h b/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h index 5c62141149d..f0438b4d2ca 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h @@ -50,6 +50,10 @@ class GPU_EXPORT CopyTextureCHROMIUMResourceManager { GLenum dest_internal_format, GLint xoffset, GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, GLsizei dest_width, GLsizei dest_height, GLsizei source_width, @@ -58,8 +62,10 @@ class GPU_EXPORT CopyTextureCHROMIUMResourceManager { bool premultiply_alpha, bool unpremultiply_alpha); - // This will apply a transform on the source texture before copying to - // destination texture. + // This will apply a transform on the texture coordinates before sampling + // the source texture and copying to the destination texture. The transform + // matrix should be given in column-major form, so it can be passed + // directly to GL. void DoCopyTextureWithTransform(const gles2::GLES2Decoder* decoder, GLenum source_target, GLuint source_id, @@ -71,21 +77,6 @@ class GPU_EXPORT CopyTextureCHROMIUMResourceManager { bool unpremultiply_alpha, const GLfloat transform_matrix[16]); - void DoCopySubTextureWithTransform(const gles2::GLES2Decoder* decoder, - GLenum source_target, - GLuint source_id, - GLuint dest_id, - GLint xoffset, - GLint yoffset, - GLsizei dest_width, - GLsizei dest_height, - GLsizei source_width, - GLsizei source_height, - bool flip_y, - bool premultiply_alpha, - bool unpremultiply_alpha, - const GLfloat transform_matrix[16]); - // The attributes used during invocation of the extension. static const GLuint kVertexPositionAttrib = 0; @@ -93,12 +84,14 @@ class GPU_EXPORT CopyTextureCHROMIUMResourceManager { struct ProgramInfo { ProgramInfo() : program(0u), - matrix_handle(0u), + vertex_translate_handle(0u), + tex_coord_transform_handle(0u), half_size_handle(0u), sampler_handle(0u) {} GLuint program; - GLuint matrix_handle; + GLuint vertex_translate_handle; + GLuint tex_coord_transform_handle; GLuint half_size_handle; GLuint sampler_handle; }; @@ -109,6 +102,10 @@ class GPU_EXPORT CopyTextureCHROMIUMResourceManager { GLuint dest_id, GLint xoffset, GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, GLsizei dest_width, GLsizei dest_height, GLsizei source_width, diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc index 89a65acee04..2c3bc1291f3 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -11,18 +11,16 @@ #include <list> #include <map> #include <queue> -#include <stack> -#include <string> -#include <vector> -#include "base/at_exit.h" -#include "base/bind.h" +#include "base/callback.h" #include "base/callback_helpers.h" #include "base/command_line.h" +#include "base/logging.h" +#include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" +#include "base/metrics/histogram_macros.h" #include "base/numerics/safe_math.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_synthetic_delay.h" #include "build/build_config.h" @@ -30,12 +28,10 @@ #include "gpu/command_buffer/common/debug_marker_manager.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" -#include "gpu/command_buffer/common/id_allocator.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h" #include "gpu/command_buffer/service/async_pixel_transfer_manager.h" #include "gpu/command_buffer/service/buffer_manager.h" -#include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/context_state.h" #include "gpu/command_buffer/service/error_state.h" @@ -49,6 +45,7 @@ #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/gpu_tracer.h" #include "gpu/command_buffer/service/image_manager.h" +#include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/program_manager.h" @@ -56,16 +53,22 @@ #include "gpu/command_buffer/service/renderbuffer_manager.h" #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/shader_translator.h" -#include "gpu/command_buffer/service/shader_translator_cache.h" #include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/valuebuffer_manager.h" #include "gpu/command_buffer/service/vertex_array_manager.h" #include "gpu/command_buffer/service/vertex_attrib_manager.h" #include "third_party/smhasher/src/City.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/overlay_transform.h" +#include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_context.h" #include "ui/gl/gl_fence.h" #include "ui/gl/gl_image.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_surface.h" +#include "ui/gl/gpu_timing.h" #if defined(OS_MACOSX) #include <IOSurface/IOSurfaceAPI.h> @@ -73,10 +76,6 @@ #include <OpenGL/CGLIOSurface.h> #endif -#if defined(OS_WIN) -#include "base/win/win_util.h" -#endif - namespace gpu { namespace gles2 { @@ -92,13 +91,13 @@ const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; -static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin, +bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin, GLint rangeMax, GLint precision) { return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16); } -static void GetShaderPrecisionFormatImpl(GLenum shader_type, +void GetShaderPrecisionFormatImpl(GLenum shader_type, GLenum precision_type, GLint* range, GLint* precision) { switch (precision_type) { @@ -154,7 +153,7 @@ static void GetShaderPrecisionFormatImpl(GLenum shader_type, } } -static gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) { +gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) { switch (plane_transform) { case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM: return gfx::OVERLAY_TRANSFORM_NONE; @@ -173,6 +172,16 @@ static gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) { } } +template <typename MANAGER_TYPE, typename OBJECT_TYPE> +GLuint GetClientId(const MANAGER_TYPE* manager, const OBJECT_TYPE* object) { + DCHECK(manager); + GLuint client_id = 0; + if (object) { + manager->GetClientId(object->service_id(), &client_id); + } + return client_id; +} + struct Vec4f { explicit Vec4f(const Vec4& data) { data.GetValues(v); @@ -181,6 +190,33 @@ struct Vec4f { GLfloat v[4]; }; +// Returns the union of |rect1| and |rect2| if one of the rectangles is empty, +// contains the other rectangle or shares an edge with the other rectangle. +bool CombineAdjacentRects(const gfx::Rect& rect1, + const gfx::Rect& rect2, + gfx::Rect* result) { + // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|. + if (rect1.IsEmpty() || rect2.Contains(rect1)) { + *result = rect2; + return true; + } + + // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|. + if (rect2.IsEmpty() || rect1.Contains(rect2)) { + *result = rect1; + return true; + } + + // Return the union of |rect1| and |rect2| if they share an edge. + if (rect1.SharesEdgeWith(rect2)) { + *result = gfx::UnionRects(rect1, rect2); + return true; + } + + // Return false if it's not possible to combine |rect1| and |rect2|. + return false; +} + } // namespace class GLES2DecoderImpl; @@ -675,7 +711,6 @@ class GLES2DecoderImpl : public GLES2Decoder, void SetAsyncPixelTransferManagerForTest( AsyncPixelTransferManager* manager) override; void SetIgnoreCachedStateForTest(bool ignore) override; - void SetAllowExit(bool allow_exit) override; void ProcessFinishedAsyncTransfers(); bool GetServiceTextureId(uint32 client_texture_id, @@ -831,6 +866,10 @@ class GLES2DecoderImpl : public GLES2Decoder, return true; } + bool IsWebGLContext() const { + return webgl_version_ == 1 || webgl_version_ == 2; + } + bool IsOffscreenBufferMultisampled() const { return offscreen_target_samples_ > 1; } @@ -964,6 +1003,20 @@ class GLES2DecoderImpl : public GLES2Decoder, GLenum type, const void * data); + // Wrapper for TexSubImage3D. + error::Error DoTexSubImage3D( + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLenum format, + GLenum type, + const void * data); + // Extra validation for async tex(Sub)Image2D. bool ValidateAsyncTransfer( const char* function_name, @@ -984,13 +1037,27 @@ class GLES2DecoderImpl : public GLES2Decoder, GLuint source_id, GLuint dest_id, GLenum internal_format, - GLenum dest_type); + GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha); void DoCopySubTextureCHROMIUM(GLenum target, GLuint source_id, GLuint dest_id, GLint xoffset, - GLint yoffset); + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha); + + void DoCompressedCopyTextureCHROMIUM(GLenum target, + GLuint source_id, + GLuint dest_id); // Wrapper for TexStorage2DEXT. void DoTexStorage2DEXT( @@ -1032,6 +1099,8 @@ class GLES2DecoderImpl : public GLES2Decoder, void DoLoseContextCHROMIUM(GLenum current, GLenum other); + void DoFlushDriverCachesCHROMIUM(void); + void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix); void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode); @@ -1243,12 +1312,12 @@ class GLES2DecoderImpl : public GLES2Decoder, bool ClearLevel(Texture* texture, unsigned target, int level, - unsigned internal_format, unsigned format, unsigned type, + int xoffset, + int yoffset, int width, - int height, - bool is_texture_immutable) override; + int height) override; // Restore all GL state that affects clearing. void RestoreClearState(); @@ -1715,6 +1784,10 @@ class GLES2DecoderImpl : public GLES2Decoder, void ReleaseIOSurfaceForTexture(GLuint texture_id); #endif + bool GetCompressedTexSizeInBytes( + const char* function_name, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLsizei* size_in_bytes); + bool ValidateCompressedTexDimensions( const char* function_name, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum format); @@ -1731,6 +1804,10 @@ class GLES2DecoderImpl : public GLES2Decoder, TextureRef* source_texture_ref, TextureRef* dest_texture_ref, GLenum dest_internal_format); + bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name, + GLenum target, + TextureRef* source_texture_ref, + TextureRef* dest_texture_ref); void RenderWarning(const char* filename, int line, const std::string& msg); void PerformanceWarning( @@ -1816,13 +1893,6 @@ class GLES2DecoderImpl : public GLES2Decoder, // Util to help with GL. GLES2Util util_; - // unpack flip y as last set by glPixelStorei - bool unpack_flip_y_; - - // unpack (un)premultiply alpha as last set by glPixelStorei - bool unpack_premultiply_alpha_; - bool unpack_unpremultiply_alpha_; - // The buffer we bind to attrib 0 since OpenGL requires it (ES does not). GLuint attrib_0_buffer_id_; @@ -1917,12 +1987,17 @@ class GLES2DecoderImpl : public GLES2Decoder, bool reset_by_robustness_extension_; bool supports_post_sub_buffer_; + // Indicates whether this is a context for WebGL1, WebGL2, or others. + // 0: other types + // 1: WebGL 1 + // 2: WebGL 2 + unsigned webgl_version_; + // These flags are used to override the state of the shared feature_info_ // member. Because the same FeatureInfo instance may be shared among many // contexts, the assumptions on the availablity of extensions in WebGL // contexts may be broken. These flags override the shared state to preserve // WebGL semantics. - bool force_webgl_glsl_validation_; bool derivatives_explicitly_enabled_; bool frag_depth_explicitly_enabled_; bool draw_buffers_explicitly_enabled_; @@ -1970,8 +2045,6 @@ class GLES2DecoderImpl : public GLES2Decoder, GLuint validation_fbo_multisample_; GLuint validation_fbo_; - bool allow_exit_; - typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)( uint32 immediate_data_size, const void* data); @@ -2432,9 +2505,6 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) group_(group), logger_(&debug_marker_manager_), state_(group_->feature_info(), this, &logger_), - unpack_flip_y_(false), - unpack_premultiply_alpha_(false), - unpack_unpremultiply_alpha_(false), attrib_0_buffer_id_(0), attrib_0_buffer_matches_value_(true), attrib_0_size_(0), @@ -2461,7 +2531,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) context_was_lost_(false), reset_by_robustness_extension_(false), supports_post_sub_buffer_(false), - force_webgl_glsl_validation_(false), + webgl_version_(0), derivatives_explicitly_enabled_(false), frag_depth_explicitly_enabled_(false), draw_buffers_explicitly_enabled_(false), @@ -2474,7 +2544,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) viewport_max_height_(0), texture_state_(group_->feature_info() ->workarounds() - .texsubimage2d_faster_than_teximage2d), + .texsubimage_faster_than_teximage), cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( TRACE_DISABLED_BY_DEFAULT("cb_command"))), gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( @@ -2484,8 +2554,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) gpu_debug_commands_(false), validation_texture_(0), validation_fbo_multisample_(0), - validation_fbo_(0), - allow_exit_(false) { + validation_fbo_(0) { DCHECK(group); // The shader translator is used for WebGL even when running on EGL @@ -2518,6 +2587,7 @@ bool GLES2DecoderImpl::Initialize( ContextCreationAttribHelper attrib_parser; if (!attrib_parser.Parse(attribs)) return false; + webgl_version_ = attrib_parser.webgl_version; surfaceless_ = surface->IsSurfaceless() && !offscreen; @@ -2546,6 +2616,12 @@ bool GLES2DecoderImpl::Initialize( // Create GPU Tracer for timing values. gpu_tracer_.reset(new GPUTracer(this)); + if (feature_info_->workarounds().disable_timestamp_queries) { + // Forcing time elapsed query for any GPU Timing Client forces it for all + // clients in the context. + GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery(); + } + // Save the loseContextWhenOutOfMemory context creation attribute. lose_context_when_out_of_memory_ = attrib_parser.lose_context_when_out_of_memory; @@ -2559,23 +2635,30 @@ bool GLES2DecoderImpl::Initialize( return false; } - if (!group_->Initialize(this, disallowed_features)) { - LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group " - << "failed to initialize."; + disallowed_features_ = disallowed_features; + if (webgl_version_ == 1) { + disallowed_features_.npot_support = true; + } + + if (!group_->Initialize(this, + ContextGroup::GetContextType(webgl_version_), + disallowed_features_)) { group_ = NULL; // Must not destroy ContextGroup if it is not initialized. Destroy(true); return false; } CHECK_GL_ERROR(); - if (attrib_parser.es3_context_required && - feature_info_->IsES3Capable()) { + if (webgl_version_ == 2) { + if (!feature_info_->IsES3Capable()) { + LOG(ERROR) << "Underlying driver does not support ES3."; + Destroy(true); + return false; + } feature_info_->EnableES3Validators(); set_unsafe_es3_apis_enabled(true); } - disallowed_features_ = disallowed_features; - state_.attrib_values.resize(group_->max_vertex_attribs()); vertex_array_manager_.reset(new VertexArrayManager()); @@ -2973,14 +3056,14 @@ Capabilities GLES2DecoderImpl::GetCapabilities() { DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps.max_3d_texture_size); DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps.max_array_texture_layers); DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps.max_color_attachments); - DoGetIntegerv(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, - &caps.max_combined_fragment_uniform_components); + DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, + &caps.max_combined_fragment_uniform_components); DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &caps.max_combined_uniform_blocks); - DoGetIntegerv(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, - &caps.max_combined_vertex_uniform_components); + DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, + &caps.max_combined_vertex_uniform_components); DoGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.max_draw_buffers); - DoGetIntegerv(GL_MAX_ELEMENT_INDEX, &caps.max_element_index); + DoGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps.max_element_index); DoGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps.max_elements_indices); DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps.max_elements_vertices); DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, @@ -2991,14 +3074,19 @@ Capabilities GLES2DecoderImpl::GetCapabilities() { &caps.max_fragment_uniform_components); DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET, &caps.max_program_texel_offset); - DoGetIntegerv(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout); + DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout); + // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is + // returned. + if (caps.max_server_wait_timeout < 0) + caps.max_server_wait_timeout = 0; + DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps.max_texture_lod_bias); DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &caps.max_transform_feedback_interleaved_components); DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &caps.max_transform_feedback_separate_attribs); DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &caps.max_transform_feedback_separate_components); - DoGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size); + DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size); DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &caps.max_uniform_buffer_bindings); DoGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps.max_varying_components); @@ -3058,6 +3146,14 @@ Capabilities GLES2DecoderImpl::GetCapabilities() { caps.blend_equation_advanced_coherent = feature_info_->feature_flags().blend_equation_advanced_coherent; caps.texture_rg = feature_info_->feature_flags().ext_texture_rg; + caps.max_copy_texture_chromium_size = + feature_info_->workarounds().max_copy_texture_chromium_size; + caps.render_buffer_format_bgra8888 = + feature_info_->feature_flags().ext_render_buffer_format_bgra8888; + caps.occlusion_query_boolean = + feature_info_->feature_flags().occlusion_query_boolean; + caps.timer_queries = + query_manager_->GPUTimingAvailable(); return caps; } @@ -3097,7 +3193,7 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { resources.FragmentPrecisionHigh = PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision); - if (force_webgl_glsl_validation_) { + if (IsWebGLContext()) { resources.OES_standard_derivatives = derivatives_explicitly_enabled_; resources.EXT_frag_depth = frag_depth_explicitly_enabled_; resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_; @@ -3124,8 +3220,8 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { } ShShaderSpec shader_spec; - if (force_webgl_glsl_validation_) { - shader_spec = unsafe_es3_apis_enabled() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC; + if (IsWebGLContext()) { + shader_spec = webgl_version_ == 2 ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC; } else { shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC; } @@ -3153,6 +3249,8 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS; if (workarounds().regenerate_struct_names) driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES; + if (workarounds().remove_pow_with_constant_exponent) + driver_bug_workarounds |= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT; if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEmulateShaderPrecision)) @@ -3261,10 +3359,7 @@ void GLES2DecoderImpl::DeleteBuffersHelper( Buffer* buffer = GetBuffer(client_ids[ii]); if (buffer && !buffer->IsDeleted()) { buffer->RemoveMappedRange(); - state_.vertex_attrib_manager->Unbind(buffer); - if (state_.bound_array_buffer.get() == buffer) { - state_.bound_array_buffer = NULL; - } + state_.RemoveBoundBuffer(buffer); RemoveBuffer(client_ids[ii]); } } @@ -3659,17 +3754,12 @@ void GLES2DecoderImpl::UpdateParentTextureInfo() { GLenum target = offscreen_saved_color_texture_info_->texture()->target(); glBindTexture(target, offscreen_saved_color_texture_info_->service_id()); texture_manager()->SetLevelInfo( - offscreen_saved_color_texture_info_.get(), - GL_TEXTURE_2D, + offscreen_saved_color_texture_info_.get(), GL_TEXTURE_2D, 0, // level - GL_RGBA, - offscreen_size_.width(), - offscreen_size_.height(), + GL_RGBA, offscreen_size_.width(), offscreen_size_.height(), 1, // depth 0, // border - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(offscreen_size_)); texture_manager()->SetParameteri( "UpdateParentTextureInfo", GetErrorState(), @@ -3786,6 +3876,12 @@ void GLES2DecoderImpl::Destroy(bool have_context) { state_.default_vertex_attrib_manager = NULL; state_.texture_units.clear(); state_.bound_array_buffer = NULL; + state_.bound_copy_read_buffer = NULL; + state_.bound_copy_write_buffer = NULL; + state_.bound_pixel_pack_buffer = NULL; + state_.bound_pixel_unpack_buffer = NULL; + state_.bound_transform_feedback_buffer = NULL; + state_.bound_uniform_buffer = NULL; state_.current_queries.clear(); framebuffer_state_.bound_read_framebuffer = NULL; framebuffer_state_.bound_draw_framebuffer = NULL; @@ -4319,17 +4415,7 @@ void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) { } service_id = buffer->service_id(); } - switch (target) { - case GL_ARRAY_BUFFER: - state_.bound_array_buffer = buffer; - break; - case GL_ELEMENT_ARRAY_BUFFER: - state_.vertex_attrib_manager->SetElementArrayBuffer(buffer); - break; - default: - NOTREACHED(); // Validation should prevent us getting here. - break; - } + state_.SetBoundBuffer(target, buffer); glBindBuffer(target, service_id); } @@ -4470,10 +4556,6 @@ void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) { state_.SetIgnoreCachedStateForTest(ignore); } -void GLES2DecoderImpl::SetAllowExit(bool allow_exit) { - allow_exit_ = allow_exit; -} - void GLES2DecoderImpl::OnFboChanged() const { if (workarounds().restore_scissor_on_fbo_change) state_.fbo_binding_for_scissor_workaround_dirty = true; @@ -4861,6 +4943,28 @@ bool GLES2DecoderImpl::GetHelper( return true; } } + if (unsafe_es3_apis_enabled()) { + switch (pname) { + case GL_MAX_VARYING_COMPONENTS: { + if (feature_info_->gl_version_info().is_es) { + // We can just delegate this query to the driver. + return false; + } + + // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop + // OpenGL core profile, so for simplicity, just compute it + // from GL_MAX_VARYING_VECTORS on non-OpenGL ES + // configurations. + GLint max_varying_vectors = 0; + glGetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors); + *num_written = 1; + if (params) { + *params = max_varying_vectors * 4; + } + return true; + } + } + } switch (pname) { case GL_MAX_VIEWPORT_DIMS: if (offscreen_target_frame_buffer_.get()) { @@ -5039,59 +5143,75 @@ bool GLES2DecoderImpl::GetHelper( case GL_ARRAY_BUFFER_BINDING: *num_written = 1; if (params) { - if (state_.bound_array_buffer.get()) { - GLuint client_id = 0; - buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(), - &client_id); - *params = client_id; - } else { - *params = 0; - } + *params = GetClientId( + buffer_manager(), state_.bound_array_buffer.get()); } return true; case GL_ELEMENT_ARRAY_BUFFER_BINDING: *num_written = 1; if (params) { - if (state_.vertex_attrib_manager->element_array_buffer()) { - GLuint client_id = 0; - buffer_manager()->GetClientId( - state_.vertex_attrib_manager->element_array_buffer()-> - service_id(), &client_id); - *params = client_id; - } else { - *params = 0; - } + *params = GetClientId( + buffer_manager(), + state_.vertex_attrib_manager->element_array_buffer()); + } + return true; + case GL_COPY_READ_BUFFER_BINDING: + *num_written = 1; + if (params) { + *params = GetClientId( + buffer_manager(), state_.bound_copy_read_buffer.get()); + } + return true; + case GL_COPY_WRITE_BUFFER_BINDING: + *num_written = 1; + if (params) { + *params = GetClientId( + buffer_manager(), state_.bound_copy_write_buffer.get()); + } + return true; + case GL_PIXEL_PACK_BUFFER_BINDING: + *num_written = 1; + if (params) { + *params = GetClientId( + buffer_manager(), state_.bound_pixel_pack_buffer.get()); + } + return true; + case GL_PIXEL_UNPACK_BUFFER_BINDING: + *num_written = 1; + if (params) { + *params = GetClientId( + buffer_manager(), state_.bound_pixel_unpack_buffer.get()); + } + return true; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + *num_written = 1; + if (params) { + *params = GetClientId( + buffer_manager(), state_.bound_transform_feedback_buffer.get()); + } + return true; + case GL_UNIFORM_BUFFER_BINDING: + *num_written = 1; + if (params) { + *params = GetClientId( + buffer_manager(), state_.bound_uniform_buffer.get()); } return true; case GL_FRAMEBUFFER_BINDING: // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING) *num_written = 1; if (params) { - Framebuffer* framebuffer = - GetFramebufferInfoForTarget(GL_FRAMEBUFFER); - if (framebuffer) { - GLuint client_id = 0; - framebuffer_manager()->GetClientId( - framebuffer->service_id(), &client_id); - *params = client_id; - } else { - *params = 0; - } + *params = GetClientId( + framebuffer_manager(), + GetFramebufferInfoForTarget(GL_FRAMEBUFFER)); } return true; case GL_READ_FRAMEBUFFER_BINDING_EXT: *num_written = 1; if (params) { - Framebuffer* framebuffer = - GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT); - if (framebuffer) { - GLuint client_id = 0; - framebuffer_manager()->GetClientId( - framebuffer->service_id(), &client_id); - *params = client_id; - } else { - *params = 0; - } + *params = GetClientId( + framebuffer_manager(), + GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT)); } return true; case GL_RENDERBUFFER_BINDING: @@ -5109,14 +5229,7 @@ bool GLES2DecoderImpl::GetHelper( case GL_CURRENT_PROGRAM: *num_written = 1; if (params) { - if (state_.current_program.get()) { - GLuint client_id = 0; - program_manager()->GetClientId( - state_.current_program->service_id(), &client_id); - *params = client_id; - } else { - *params = 0; - } + *params = GetClientId(program_manager(), state_.current_program.get()); } return true; case GL_VERTEX_ARRAY_BINDING_OES: @@ -5177,24 +5290,6 @@ bool GLES2DecoderImpl::GetHelper( } } return true; - case GL_UNPACK_FLIP_Y_CHROMIUM: - *num_written = 1; - if (params) { - params[0] = unpack_flip_y_; - } - return true; - case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM: - *num_written = 1; - if (params) { - params[0] = unpack_premultiply_alpha_; - } - return true; - case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM: - *num_written = 1; - if (params) { - params[0] = unpack_unpremultiply_alpha_; - } - return true; case GL_BIND_GENERATES_RESOURCE_CHROMIUM: *num_written = 1; if (params) { @@ -5276,6 +5371,23 @@ void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) { void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) { DCHECK(params); + if (unsafe_es3_apis_enabled()) { + switch (pname) { + case GL_MAX_ELEMENT_INDEX: { + if (feature_info_->gl_version_info().IsAtLeastGLES(3, 0) || + feature_info_->gl_version_info().IsAtLeastGL(4, 3)) { + glGetInteger64v(GL_MAX_ELEMENT_INDEX, params); + } else { + // Assume that desktop GL implementations can generally support + // 32-bit indices. + if (params) { + *params = std::numeric_limits<unsigned int>::max(); + } + } + return; + } + } + } pname = AdjustGetPname(pname); glGetInteger64v(pname, params); } @@ -5598,9 +5710,10 @@ void GLES2DecoderImpl::RestoreClearState() { state_.color_clear_alpha); glClearStencil(state_.stencil_clear); glClearDepth(state_.depth_clear); - if (state_.enable_flags.scissor_test) { - state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true); - } + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, + state_.enable_flags.scissor_test); + glScissor(state_.scissor_x, state_.scissor_y, state_.scissor_width, + state_.scissor_height); } GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) { @@ -6129,6 +6242,7 @@ void GLES2DecoderImpl::DoRenderbufferStorage( void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram"); + SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime"); Program* program = GetProgramInfoNotShader( program_id, "glLinkProgram"); if (!program) { @@ -8364,15 +8478,6 @@ error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size, return error::kNoError; } break; - case GL_UNPACK_FLIP_Y_CHROMIUM: - unpack_flip_y_ = (param != 0); - return error::kNoError; - case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM: - unpack_premultiply_alpha_ = (param != 0); - return error::kNoError; - case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM: - unpack_unpremultiply_alpha_ = (param != 0); - return error::kNoError; default: break; } @@ -8419,7 +8524,8 @@ error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM( gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer( is_offscreen ? offscreen_size_ : surface_->GetSize()); } - if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) { + if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height) != + gfx::SwapResult::SWAP_FAILED) { return error::kNoError; } else { LOG(ERROR) << "Context lost because PostSubBuffer failed."; @@ -8705,16 +8811,22 @@ error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size, std::string extensions; switch (name) { case GL_VERSION: - str = "OpenGL ES 2.0 Chromium"; + if (unsafe_es3_apis_enabled()) + str = "OpenGL ES 3.0 Chromium"; + else + str = "OpenGL ES 2.0 Chromium"; break; case GL_SHADING_LANGUAGE_VERSION: - str = "OpenGL ES GLSL ES 1.0 Chromium"; + if (unsafe_es3_apis_enabled()) + str = "OpenGL ES GLSL ES 3.0 Chromium"; + else + str = "OpenGL ES GLSL ES 1.0 Chromium"; break; case GL_RENDERER: case GL_VENDOR: // Return the unmasked VENDOR/RENDERER string for WebGL contexts. // They are used by WEBGL_debug_renderer_info. - if (!force_webgl_glsl_validation_) + if (!IsWebGLContext()) str = "Chromium"; else str = reinterpret_cast<const char*>(glGetString(name)); @@ -8723,7 +8835,7 @@ error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size, { // For WebGL contexts, strip out the OES derivatives and // EXT frag depth extensions if they have not been enabled. - if (force_webgl_glsl_validation_) { + if (IsWebGLContext()) { extensions = feature_info_->extensions(); if (!derivatives_explicitly_enabled_) { size_t offset = extensions.find(kOESDerivativeExtension); @@ -8798,16 +8910,15 @@ void GLES2DecoderImpl::DoBufferSubData( &state_, target, offset, size, data); } -bool GLES2DecoderImpl::ClearLevel( - Texture* texture, - unsigned target, - int level, - unsigned internal_format, - unsigned format, - unsigned type, - int width, - int height, - bool is_texture_immutable) { +bool GLES2DecoderImpl::ClearLevel(Texture* texture, + unsigned target, + int level, + unsigned format, + unsigned type, + int xoffset, + int yoffset, + int width, + int height) { uint32 channels = GLES2Util::GetChannelsForFormat(format); if (feature_info_->feature_flags().angle_depth_texture && (channels & GLES2Util::kDepth) != 0) { @@ -8833,7 +8944,8 @@ bool GLES2DecoderImpl::ClearLevel( state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask); glClearDepth(1.0f); state_.SetDeviceDepthMask(GL_TRUE); - state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true); + glScissor(xoffset, yoffset, width, height); glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0)); RestoreClearState(); @@ -8883,17 +8995,11 @@ bool GLES2DecoderImpl::ClearLevel( memset(zero.get(), 0, size); glBindTexture(texture->target(), texture->service_id()); - bool has_images = texture->HasImages(); GLint y = 0; while (y < height) { GLint h = y + tile_height > height ? height - y : tile_height; - if (is_texture_immutable || h != height || has_images) { - glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get()); - } else { - glTexImage2D( - target, level, internal_format, width, h, 0, format, type, - zero.get()); - } + glTexSubImage2D(target, level, xoffset, yoffset + y, width, h, format, type, + zero.get()); y += tile_height; } TextureRef* bound_texture = @@ -8922,9 +9028,9 @@ bool IsValidPVRTCSize(GLint level, GLsizei size) { } // anonymous namespace. -bool GLES2DecoderImpl::ValidateCompressedTexFuncData( +bool GLES2DecoderImpl::GetCompressedTexSizeInBytes( const char* function_name, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei size) { + GLenum format, GLsizei* size_in_bytes) { base::CheckedNumeric<GLsizei> bytes_required(0); switch (format) { @@ -8995,7 +9101,25 @@ bool GLES2DecoderImpl::ValidateCompressedTexFuncData( return false; } - if (!bytes_required.IsValid() || size != bytes_required.ValueOrDefault(0)) { + if (!bytes_required.IsValid()) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "invalid size"); + return false; + } + + *size_in_bytes = bytes_required.ValueOrDefault(0); + return true; +} + +bool GLES2DecoderImpl::ValidateCompressedTexFuncData( + const char* function_name, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLsizei size) { + GLsizei bytes_required = 0; + if (!GetCompressedTexSizeInBytes( + function_name, width, height, depth, format, &bytes_required)) { + return false; + } + + if (size != bytes_required) { LOCAL_SET_GL_ERROR( GL_INVALID_VALUE, function_name, "size is not correct for dimensions"); return false; @@ -9254,9 +9378,9 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D( target, level, internal_format, width, height, border, image_size, data); GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D"); if (error == GL_NO_ERROR) { - texture_manager()->SetLevelInfo( - texture_ref, target, level, internal_format, - width, height, 1, border, 0, 0, true); + texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format, + width, height, 1, border, 0, 0, + gfx::Rect(width, height)); } // This may be a slow command. Exit command processing to allow for @@ -9441,9 +9565,9 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage3D( border, image_size, data); GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D"); if (error == GL_NO_ERROR) { - texture_manager()->SetLevelInfo( - texture_ref, target, level, internal_format, - width, height, depth, border, 0, 0, true); + texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format, + width, height, depth, border, 0, 0, + gfx::Rect(width, height)); } // This may be a slow command. Exit command processing to allow for @@ -9619,7 +9743,7 @@ error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size, TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D", "width", c.width, "height", c.height); // Set as failed for now, but if it successed, this will be set to not failed. - texture_state_.tex_image_2d_failed = true; + texture_state_.tex_image_failed = true; GLenum target = static_cast<GLenum>(c.target); GLint level = static_cast<GLint>(c.level); // TODO(kloveless): Change TexImage2D command to use unsigned integer @@ -9656,11 +9780,11 @@ error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size, return error::kNoError; } - TextureManager::DoTextImage2DArguments args = { - target, level, internal_format, width, height, border, format, type, - pixels, pixels_size}; - texture_manager()->ValidateAndDoTexImage2D( - &texture_state_, &state_, &framebuffer_state_, args); + TextureManager::DoTexImageArguments args = { + target, level, internal_format, width, height, 1, border, format, type, + pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D }; + texture_manager()->ValidateAndDoTexImage( + &texture_state_, &state_, &framebuffer_state_, "glTexImage2D", args); // This may be a slow command. Exit command processing to allow for // context preemption and GPU watchdog checks. @@ -9670,7 +9794,6 @@ error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size, error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size, const void* cmd_data) { - // TODO(zmo): Unsafe ES3 API. if (!unsafe_es3_apis_enabled()) return error::kUnknownCommand; @@ -9678,6 +9801,8 @@ error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size, *static_cast<const gles2::cmds::TexImage3D*>(cmd_data); TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D", "widthXheight", c.width * c.height, "depth", c.depth); + // Set as failed for now, but if it successed, this will be set to not failed. + texture_state_.tex_image_failed = true; GLenum target = static_cast<GLenum>(c.target); GLint level = static_cast<GLint>(c.level); GLenum internal_format = static_cast<GLenum>(c.internalformat); @@ -9704,8 +9829,20 @@ error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size, } } - glTexImage3D(target, level, internal_format, width, height, depth, border, - format, type, pixels); + // For testing only. Allows us to stress the ability to respond to OOM errors. + if (workarounds().simulate_out_of_memory_on_large_textures && + (width * height * depth >= 4096 * 4096)) { + LOCAL_SET_GL_ERROR( + GL_OUT_OF_MEMORY, + "glTexImage3D", "synthetic out of memory"); + return error::kNoError; + } + + TextureManager::DoTexImageArguments args = { + target, level, internal_format, width, height, depth, border, format, type, + pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage3D }; + texture_manager()->ValidateAndDoTexImage( + &texture_state_, &state_, &framebuffer_state_, "glTexImage3D", args); // This may be a slow command. Exit command processing to allow for // context preemption and GPU watchdog checks. @@ -9894,19 +10031,25 @@ void GLES2DecoderImpl::DoCopyTexImage2D( copyY != y || copyWidth != width || copyHeight != height) { - // some part was clipped so clear the texture. - if (!ClearLevel(texture, target, level, internal_format, internal_format, - GL_UNSIGNED_BYTE, width, height, texture->IsImmutable())) { + // some part was clipped so clear the rect. + uint32 pixels_size = 0; + if (!GLES2Util::ComputeImageDataSizes( + width, height, 1, internal_format, GL_UNSIGNED_BYTE, + state_.unpack_alignment, &pixels_size, NULL, NULL)) { LOCAL_SET_GL_ERROR( GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big"); return; } + scoped_ptr<char[]> zero(new char[pixels_size]); + memset(zero.get(), 0, pixels_size); + ScopedModifyPixels modify(texture_ref); + glTexImage2D(target, level, internal_format, width, height, border, + internal_format, GL_UNSIGNED_BYTE, zero.get()); if (copyHeight > 0 && copyWidth > 0) { GLint dx = copyX - x; GLint dy = copyY - y; GLint destX = dx; GLint destY = dy; - ScopedModifyPixels modify(texture_ref); glCopyTexSubImage2D(target, level, destX, destY, copyX, copyY, copyWidth, copyHeight); @@ -9918,9 +10061,9 @@ void GLES2DecoderImpl::DoCopyTexImage2D( } GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D"); if (error == GL_NO_ERROR) { - texture_manager()->SetLevelInfo( - texture_ref, target, level, internal_format, width, height, 1, - border, internal_format, GL_UNSIGNED_BYTE, true); + texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format, + width, height, 1, border, internal_format, + GL_UNSIGNED_BYTE, gfx::Rect(width, height)); } // This may be a slow command. Exit command processing to allow for @@ -10008,11 +10151,22 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( if (xoffset != 0 || yoffset != 0 || width != size.width() || height != size.height()) { - if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, - level)) { - LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", - "dimensions too big"); - return; + gfx::Rect cleared_rect; + if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level), + gfx::Rect(xoffset, yoffset, width, height), + &cleared_rect)) { + DCHECK_GE(cleared_rect.size().GetArea(), + texture->GetLevelClearedRect(target, level).size().GetArea()); + texture_manager()->SetLevelClearedRect(texture_ref, target, level, + cleared_rect); + } else { + // Otherwise clear part of texture level that is not already cleared. + if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, + level)) { + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", + "dimensions too big"); + return; + } } } else { // Write all pixels in below. @@ -10157,11 +10311,22 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D( DCHECK(ok); if (xoffset != 0 || yoffset != 0 || width != tex_width || height != tex_height) { - if (!texture_manager()->ClearTextureLevel(this, texture_ref, - target, level)) { - LOCAL_SET_GL_ERROR( - GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big"); - return error::kNoError; + gfx::Rect cleared_rect; + if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level), + gfx::Rect(xoffset, yoffset, width, height), + &cleared_rect)) { + DCHECK_GE(cleared_rect.size().GetArea(), + texture->GetLevelClearedRect(target, level).size().GetArea()); + texture_manager()->SetLevelClearedRect(texture_ref, target, level, + cleared_rect); + } else { + // Otherwise clear part of texture level that is not already cleared. + if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, + level)) { + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D", + "dimensions too big"); + return error::kNoError; + } } ScopedTextureUploadTimer timer(&texture_state_); glTexSubImage2D( @@ -10169,7 +10334,7 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D( return error::kNoError; } - if (!texture_state_.texsubimage2d_faster_than_teximage2d && + if (!texture_state_.texsubimage_faster_than_teximage && !texture->IsImmutable() && !texture->HasImages()) { ScopedTextureUploadTimer timer(&texture_state_); @@ -10200,7 +10365,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size, TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D", "width", c.width, "height", c.height); GLboolean internal = static_cast<GLboolean>(c.internal); - if (internal == GL_TRUE && texture_state_.tex_image_2d_failed) + if (internal == GL_TRUE && texture_state_.tex_image_failed) return error::kNoError; GLenum target = static_cast<GLenum>(c.target); @@ -10223,9 +10388,44 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size, target, level, xoffset, yoffset, width, height, format, type, pixels); } +error::Error GLES2DecoderImpl::DoTexSubImage3D( + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLenum format, + GLenum type, + const void * data) { + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); + if (!texture_ref) { + LOCAL_SET_GL_ERROR( + GL_INVALID_ENUM, "glTexSubImage3D", "invalid target"); + } + + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D"); + ScopedTextureUploadTimer timer(&texture_state_); + glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, + depth, format, type, data); + GLenum error = LOCAL_PEEK_GL_ERROR("glTexSubImage3D"); + if (error == GL_NO_ERROR) { + // TODO(zmo): This is not 100% correct because only part of the level + // image is cleared. + texture_manager()->SetLevelCleared(texture_ref, target, level, true); + } + + // This may be a slow command. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size, const void* cmd_data) { - // TODO(zmo): Unsafe ES3 API. if (!unsafe_es3_apis_enabled()) return error::kUnknownCommand; @@ -10233,6 +10433,10 @@ error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size, *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data); TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D", "widthXheight", c.width * c.height, "depth", c.depth); + GLboolean internal = static_cast<GLboolean>(c.internal); + if (internal == GL_TRUE && texture_state_.tex_image_failed) + return error::kNoError; + GLenum target = static_cast<GLenum>(c.target); GLint level = static_cast<GLint>(c.level); GLint xoffset = static_cast<GLint>(c.xoffset); @@ -10251,9 +10455,8 @@ error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size, } const void* pixels = GetSharedMemoryAs<const void*>( c.pixels_shm_id, c.pixels_shm_offset, data_size); - glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, - depth, format, type, pixels); - return error::kNoError; + return DoTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, + height, depth, format, type, pixels); } error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv( @@ -10901,7 +11104,7 @@ void GLES2DecoderImpl::DoSwapBuffers() { glFlush(); } } else { - if (!surface_->SwapBuffers()) { + if (surface_->SwapBuffers() == gfx::SwapResult::SWAP_FAILED) { LOG(ERROR) << "Context lost because SwapBuffers failed."; if (!CheckResetStatus()) { MarkContextLost(error::kUnknown); @@ -10958,9 +11161,6 @@ error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM( // needs to be done it seems like refactoring for one to one of those // methods is a very low priority. const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED); - } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) { - force_webgl_glsl_validation_ = true; - InitializeShaderTranslator(); } else { return error::kNoError; } @@ -10996,13 +11196,11 @@ error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM( return error::kInvalidArguments; } - bool desire_webgl_glsl_validation = - feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos; bool desire_standard_derivatives = false; bool desire_frag_depth = false; bool desire_draw_buffers = false; bool desire_shader_texture_lod = false; - if (force_webgl_glsl_validation_) { + if (IsWebGLContext()) { desire_standard_derivatives = feature_str.find("GL_OES_standard_derivatives") != std::string::npos; desire_frag_depth = @@ -11013,11 +11211,10 @@ error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM( feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos; } - if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ || - desire_standard_derivatives != derivatives_explicitly_enabled_ || + if (desire_standard_derivatives != derivatives_explicitly_enabled_ || desire_frag_depth != frag_depth_explicitly_enabled_ || - desire_draw_buffers != draw_buffers_explicitly_enabled_) { - force_webgl_glsl_validation_ |= desire_webgl_glsl_validation; + desire_draw_buffers != draw_buffers_explicitly_enabled_ || + desire_shader_texture_lod != shader_texture_lod_explicitly_enabled_) { derivatives_explicitly_enabled_ |= desire_standard_derivatives; frag_depth_explicitly_enabled_ |= desire_frag_depth; draw_buffers_explicitly_enabled_ |= desire_draw_buffers; @@ -11205,16 +11402,6 @@ void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) { context_lost_reason_ = reason; current_decoder_error_ = error::kLostContext; context_was_lost_ = true; - - // Work around issues with recovery by allowing a new GPU process to launch. - if (workarounds().exit_on_context_lost && allow_exit_) { - LOG(ERROR) << "Exiting GPU process because some drivers cannot recover" - << " from problems."; -#if defined(OS_WIN) - base::win::SetShouldCrashOnProcessDetach(false); -#endif - exit(0); - } } bool GLES2DecoderImpl::CheckResetStatus() { @@ -11384,7 +11571,9 @@ error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size, return error::kNoError; } break; - default: + case GL_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: if (!features().occlusion_query_boolean) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glBeginQueryEXT", @@ -11392,6 +11581,20 @@ error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size, return error::kNoError; } break; + case GL_TIME_ELAPSED: + // TODO(dyen): Also support GL_TIMESTAMP. + if (!query_manager_->GPUTimingAvailable()) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, "glBeginQueryEXT", + "not enabled for timing queries"); + return error::kNoError; + } + break; + default: + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, "glBeginQueryEXT", + "unknown query target"); + return error::kNoError; } if (state_.current_queries.find(target) != state_.current_queries.end()) { @@ -11638,8 +11841,8 @@ void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM( } texture_manager()->SetLevelInfo( - texture_ref, target, 0, GL_RGBA, width, height, 1, 0, - GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true); + texture_ref, target, 0, GL_RGBA, width, height, 1, 0, GL_BGRA, + GL_UNSIGNED_INT_8_8_8_8_REV, gfx::Rect(width, height)); #else LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, @@ -11739,12 +11942,12 @@ bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM( bool valid_dest_format = dest_internal_format == GL_RGB || dest_internal_format == GL_RGBA || dest_internal_format == GL_BGRA_EXT; - bool valid_source_format = source_internal_format == GL_ALPHA || - source_internal_format == GL_RGB || - source_internal_format == GL_RGBA || - source_internal_format == GL_LUMINANCE || - source_internal_format == GL_LUMINANCE_ALPHA || - source_internal_format == GL_BGRA_EXT; + bool valid_source_format = + source_internal_format == GL_R8 || source_internal_format == GL_ALPHA || + source_internal_format == GL_RGB || source_internal_format == GL_RGBA || + source_internal_format == GL_LUMINANCE || + source_internal_format == GL_LUMINANCE_ALPHA || + source_internal_format == GL_BGRA_EXT; if (!valid_source_format || !valid_dest_format) { LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "invalid internal format"); @@ -11753,11 +11956,69 @@ bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM( return true; } -void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target, - GLuint source_id, - GLuint dest_id, - GLenum internal_format, - GLenum dest_type) { +bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM( + const char* function_name, + GLenum target, + TextureRef* source_texture_ref, + TextureRef* dest_texture_ref) { + if (!source_texture_ref || !dest_texture_ref) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id"); + return false; + } + + if (GL_TEXTURE_2D != target) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, + "invalid texture target"); + return false; + } + + Texture* source_texture = source_texture_ref->texture(); + Texture* dest_texture = dest_texture_ref->texture(); + if (source_texture == dest_texture) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "source and destination textures are the same"); + return false; + } + + if (dest_texture->target() != GL_TEXTURE_2D || + (source_texture->target() != GL_TEXTURE_2D && + source_texture->target() != GL_TEXTURE_RECTANGLE_ARB && + source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, + "invalid texture target binding"); + return false; + } + + GLenum source_type = 0; + GLenum source_internal_format = 0; + source_texture->GetLevelType(source_texture->target(), 0, &source_type, + &source_internal_format); + + bool valid_format = + source_internal_format == GL_ATC_RGB_AMD || + source_internal_format == GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD || + source_internal_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || + source_internal_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT || + source_internal_format == GL_ETC1_RGB8_OES; + + if (!valid_format) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "invalid internal format"); + return false; + } + + return true; +} + +void GLES2DecoderImpl::DoCopyTextureCHROMIUM( + GLenum target, + GLuint source_id, + GLuint dest_id, + GLenum internal_format, + GLenum dest_type, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM"); TextureRef* source_texture_ref = GetTexture(source_id); @@ -11862,7 +12123,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target, texture_manager()->SetLevelInfo( dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width, - source_height, 1, 0, internal_format, dest_type, true); + source_height, 1, 0, internal_format, dest_type, + gfx::Rect(source_width, source_height)); } else { texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0, true); @@ -11870,13 +12132,15 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target, ScopedModifyPixels modify(dest_texture_ref); - // Try using GLImage::CopyTexImage when possible. + // Try using GLImage::CopyTexSubImage when possible. bool unpack_premultiply_alpha_change = - unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_; - if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change) { + (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0; + if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) { glBindTexture(GL_TEXTURE_2D, dest_texture->service_id()); - if (image->CopyTexImage(GL_TEXTURE_2D)) + if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0), + gfx::Rect(0, 0, source_width, source_height))) { return; + } } DoWillUseTexImageIfNeeded(source_texture, source_texture->target()); @@ -11888,25 +12152,37 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target, // instead of using kIdentityMatrix crbug.com/226218. copy_texture_CHROMIUM_->DoCopyTextureWithTransform( this, source_texture->target(), source_texture->service_id(), - dest_texture->service_id(), source_width, source_height, unpack_flip_y_, - unpack_premultiply_alpha_, unpack_unpremultiply_alpha_, + dest_texture->service_id(), source_width, source_height, + unpack_flip_y == GL_TRUE, + unpack_premultiply_alpha == GL_TRUE, + unpack_unmultiply_alpha == GL_TRUE, kIdentityMatrix); } else { copy_texture_CHROMIUM_->DoCopyTexture( this, source_texture->target(), source_texture->service_id(), source_internal_format, dest_texture->service_id(), internal_format, - source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_, - unpack_unpremultiply_alpha_); + source_width, source_height, + unpack_flip_y == GL_TRUE, + unpack_premultiply_alpha == GL_TRUE, + unpack_unmultiply_alpha == GL_TRUE); } DoDidUseTexImageIfNeeded(source_texture, source_texture->target()); } -void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target, - GLuint source_id, - GLuint dest_id, - GLint xoffset, - GLint yoffset) { +void GLES2DecoderImpl::DoCopySubTextureCHROMIUM( + GLenum target, + GLuint source_id, + GLuint dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLboolean unpack_flip_y, + GLboolean unpack_premultiply_alpha, + GLboolean unpack_unmultiply_alpha) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM"); TextureRef* source_texture_ref = GetTexture(source_id); @@ -11947,6 +12223,13 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target, GLenum source_internal_format = 0; source_texture->GetLevelType(source_texture->target(), 0, &source_type, &source_internal_format); + if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0, + width, height, 1, source_type)) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM", + "source texture bad dimensions."); + return; + } + GLenum dest_type = 0; GLenum dest_internal_format = 0; bool dest_level_defined = dest_texture->GetLevelType( @@ -11957,8 +12240,7 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target, return; } if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset, - yoffset, 0, source_width, source_height, - 1, dest_type)) { + yoffset, 0, width, height, 1, dest_type)) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM", "destination texture bad dimensions."); return; @@ -11994,13 +12276,24 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target, bool ok = dest_texture->GetLevelSize( GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); DCHECK(ok); - if (xoffset != 0 || yoffset != 0 || source_width != dest_width || - source_height != dest_height) { - if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, - 0)) { - LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", - "destination texture dimensions too big"); - return; + if (xoffset != 0 || yoffset != 0 || width != dest_width || + height != dest_height) { + gfx::Rect cleared_rect; + if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0), + gfx::Rect(xoffset, yoffset, width, height), + &cleared_rect)) { + DCHECK_GE(cleared_rect.size().GetArea(), + dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); + texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, + cleared_rect); + } else { + // Otherwise clear part of texture level that is not already cleared. + if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, + 0)) { + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", + "destination texture dimensions too big"); + return; + } } } else { texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0, @@ -12011,33 +12304,202 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target, // Try using GLImage::CopyTexSubImage when possible. bool unpack_premultiply_alpha_change = - unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_; - if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change && - !xoffset && !yoffset) { + (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0; + if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) { glBindTexture(GL_TEXTURE_2D, dest_texture->service_id()); - if (image->CopyTexImage(GL_TEXTURE_2D)) + if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset), + gfx::Rect(x, y, width, height))) { return; + } } DoWillUseTexImageIfNeeded(source_texture, source_texture->target()); + // TODO(hkuang): get the StreamTexture transform matrix in GPU process. + // crbug.com/226218. + copy_texture_CHROMIUM_->DoCopySubTexture( + this, source_texture->target(), source_texture->service_id(), + source_internal_format, dest_texture->service_id(), dest_internal_format, + xoffset, yoffset, x, y, width, height, dest_width, dest_height, + source_width, source_height, + unpack_flip_y == GL_TRUE, + unpack_premultiply_alpha == GL_TRUE, + unpack_unmultiply_alpha == GL_TRUE); + + DoDidUseTexImageIfNeeded(source_texture, source_texture->target()); +} + +void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target, + GLuint source_id, + GLuint dest_id) { + TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM"); + + TextureRef* source_texture_ref = GetTexture(source_id); + TextureRef* dest_texture_ref = GetTexture(dest_id); + Texture* source_texture = source_texture_ref->texture(); + Texture* dest_texture = dest_texture_ref->texture(); + int source_width = 0; + int source_height = 0; + gfx::GLImage* image = + source_texture->GetLevelImage(source_texture->target(), 0); + if (image) { + gfx::Size size = image->GetSize(); + source_width = size.width(); + source_height = size.height(); + if (source_width <= 0 || source_height <= 0) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, + "glCompressedCopyTextureCHROMIUM", "invalid image size"); + return; + } + } else { + if (!source_texture->GetLevelSize(source_texture->target(), 0, + &source_width, &source_height, nullptr)) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, + "glCompressedCopyTextureCHROMIUM", + "source texture has no level 0"); + return; + } + + // Check that this type of texture is allowed. + if (!texture_manager()->ValidForTarget(source_texture->target(), 0, + source_width, source_height, 1)) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, "glCompressedCopyTextureCHROMIUM", + "Bad dimensions"); + return; + } + } + + GLenum source_type = 0; + GLenum source_internal_format = 0; + source_texture->GetLevelType( + source_texture->target(), 0, &source_type, &source_internal_format); + + if (dest_texture->IsImmutable()) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glCompressedCopyTextureCHROMIUM", + "texture is immutable"); + return; + } + + if (!ValidateCompressedCopyTextureCHROMIUM( + "glCompressedCopyTextureCHROMIUM", + target, + source_texture_ref, dest_texture_ref)) { + return; + } + + // Defer initializing the CopyTextureCHROMIUMResourceManager until it is + // needed because it takes 10s of milliseconds to initialize. + if (!copy_texture_CHROMIUM_.get()) { + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM"); + copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager()); + copy_texture_CHROMIUM_->Initialize(this); + RestoreCurrentFramebufferBindings(); + if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR) + return; + } + + // Clear the source texture if necessary. + if (!texture_manager()->ClearTextureLevel(this, source_texture_ref, + source_texture->target(), 0)) { + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopyTextureCHROMIUM", + "dimensions too big"); + return; + } + + ScopedTextureBinder binder( + &state_, dest_texture->service_id(), GL_TEXTURE_2D); + + ScopedModifyPixels modify(dest_texture_ref); + + // Try using GLImage::CopyTexImage when possible. + if (image) { + GLenum dest_type = 0; + GLenum dest_internal_format = 0; + int dest_width = 0; + int dest_height = 0; + bool dest_level_defined = dest_texture->GetLevelSize( + GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); + + if (dest_level_defined) { + dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type, + &dest_internal_format); + } + + // Resize the destination texture to the dimensions of the source texture. + if (!dest_level_defined || dest_width != source_width || + dest_height != source_height || + dest_internal_format != source_internal_format) { + GLsizei source_size = 0; + + bool did_get_size = GetCompressedTexSizeInBytes( + "glCompressedCopyTextureCHROMIUM", source_width, source_height, + 1, source_internal_format, &source_size); + DCHECK(did_get_size); + + // Ensure that the glCompressedTexImage2D succeeds. + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM"); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, source_internal_format, + source_width, source_height, 0, source_size, + NULL); + GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM"); + if (error != GL_NO_ERROR) { + RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D); + return; + } + + texture_manager()->SetLevelInfo( + dest_texture_ref, GL_TEXTURE_2D, 0, source_internal_format, + source_width, source_height, 1, 0, source_internal_format, + source_type, gfx::Rect(source_width, source_height)); + } else { + texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0, + true); + } + + if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0), + gfx::Rect(0, 0, source_width, source_height))) { + return; + } + } + + TRACE_EVENT0( + "gpu", + "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback"); + + DoWillUseTexImageIfNeeded(source_texture, source_texture->target()); + + // As a fallback, copy into a non-compressed GL_RGBA texture. + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, source_width, source_height, + 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM"); + if (error != GL_NO_ERROR) { + RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D); + return; + } + + texture_manager()->SetLevelInfo( + dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, source_width, + source_height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(source_width, source_height)); + // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix // before presenting. if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) { // TODO(hkuang): get the StreamTexture transform matrix in GPU process // instead of using kIdentityMatrix crbug.com/226218. - copy_texture_CHROMIUM_->DoCopySubTextureWithTransform( + copy_texture_CHROMIUM_->DoCopyTextureWithTransform( this, source_texture->target(), source_texture->service_id(), - dest_texture->service_id(), xoffset, yoffset, dest_width, dest_height, - source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_, - unpack_unpremultiply_alpha_, kIdentityMatrix); + dest_texture->service_id(), source_width, source_height, + false, false, false, kIdentityMatrix); } else { - copy_texture_CHROMIUM_->DoCopySubTexture( + copy_texture_CHROMIUM_->DoCopyTexture( this, source_texture->target(), source_texture->service_id(), - source_internal_format, dest_texture->service_id(), - dest_internal_format, xoffset, yoffset, dest_width, dest_height, - source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_, - unpack_unpremultiply_alpha_); + source_internal_format, dest_texture->service_id(), GL_RGBA, + source_width, source_height, false, false, false); } DoDidUseTexImageIfNeeded(source_texture, source_texture->target()); @@ -12155,9 +12617,9 @@ void GLES2DecoderImpl::DoTexStorage2DEXT( GLsizei level_width = width; GLsizei level_height = height; for (int ii = 0; ii < levels; ++ii) { - texture_manager()->SetLevelInfo( - texture_ref, target, ii, format, - level_width, level_height, 1, 0, format, type, false); + texture_manager()->SetLevelInfo(texture_ref, target, ii, format, + level_width, level_height, 1, 0, format, + type, gfx::Rect()); level_width = std::max(1, level_width >> 1); level_height = std::max(1, level_height >> 1); } @@ -12507,8 +12969,9 @@ void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM( gfx::Size size = gl_image->GetSize(); texture_manager()->SetLevelInfo( - texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0, - GL_RGBA, GL_UNSIGNED_BYTE, true); + texture_ref, target, 0, gl_image->GetInternalFormat(), size.width(), + size.height(), 1, 0, gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, + gfx::Rect(size)); texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image); } @@ -12546,8 +13009,8 @@ void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM( } texture_manager()->SetLevelInfo( - texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0, - GL_RGBA, GL_UNSIGNED_BYTE, false); + texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0, + gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect()); } error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM( @@ -12634,6 +13097,15 @@ void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) { reset_by_robustness_extension_ = true; } +void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) { + // On Adreno Android devices we need to use a workaround to force caches to + // clear. + if (feature_info_->workarounds().unbind_egl_context_to_flush_driver_caches) { + context_->ReleaseCurrent(nullptr); + context_->MakeCurrent(surface_.get()); + } +} + void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix) { DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM || @@ -12778,12 +13250,12 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM( } } - TextureManager::DoTextImage2DArguments args = { - target, level, internal_format, width, height, border, format, type, - pixels, pixels_size}; + TextureManager::DoTexImageArguments args = { + target, level, internal_format, width, height, 1, border, format, type, + pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D }; TextureRef* texture_ref; // All the normal glTexSubImage2D validation. - if (!texture_manager()->ValidateTexImage2D( + if (!texture_manager()->ValidateTexImage( &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) { return error::kNoError; } @@ -13044,6 +13516,59 @@ error::Error GLES2DecoderImpl::HandleWaitSync( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleGetInternalformativ( + uint32_t immediate_data_size, const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::GetInternalformativ& c = + *static_cast<const gles2::cmds::GetInternalformativ*>(cmd_data); + GLenum target = static_cast<GLenum>(c.target); + GLenum format = static_cast<GLenum>(c.format); + GLenum pname = static_cast<GLenum>(c.pname); + if (!validators_->render_buffer_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target, "target"); + return error::kNoError; + } + if (!validators_->render_buffer_format.IsValid(format)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format, "format"); + return error::kNoError; + } + if (!validators_->internal_format_parameter.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname, "pname"); + return error::kNoError; + } + typedef cmds::GetInternalformativ::Result Result; + GLsizei num_values = 0; + switch (pname) { + case GL_NUM_SAMPLE_COUNTS: + num_values = 1; + break; + case GL_SAMPLES: + { + GLint value = 0; + glGetInternalformativ(target, format, GL_NUM_SAMPLE_COUNTS, 1, &value); + num_values = static_cast<GLsizei>(value); + } + break; + default: + NOTREACHED(); + break; + } + Result* result = GetSharedMemoryAs<Result*>( + c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values)); + GLint* params = result ? result->GetData() : NULL; + if (params == NULL) { + return error::kOutOfBounds; + } + // Check that the client initialized the result. + if (result->size != 0) { + return error::kInvalidArguments; + } + glGetInternalformativ(target, format, pname, num_values, params); + result->SetNumResults(num_values); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleMapBufferRange( uint32_t immediate_data_size, const void* cmd_data) { if (!unsafe_es3_apis_enabled()) { diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h index 3fc86237978..79ecb2c21bc 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -7,26 +7,29 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_H_ +#include <string> #include <vector> -#include "base/callback.h" +#include "base/basictypes.h" +#include "base/callback_forward.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "build/build_config.h" #include "gpu/command_buffer/common/capabilities.h" +#include "gpu/command_buffer/common/constants.h" #include "gpu/command_buffer/service/common_decoder.h" -#include "gpu/command_buffer/service/logger.h" -#include "ui/gfx/geometry/size.h" -#include "ui/gl/gl_context.h" +#include "gpu/gpu_export.h" namespace gfx { class GLContext; class GLSurface; +class Size; } namespace gpu { -class AsyncPixelTransferDelegate; class AsyncPixelTransferManager; struct Mailbox; @@ -45,10 +48,12 @@ struct ContextState; struct DisallowedFeatures { DisallowedFeatures() - : gpu_memory_manager(false) { + : gpu_memory_manager(false), + npot_support(false) { } bool gpu_memory_manager; + bool npot_support; }; typedef base::Callback<void(const std::string& key, @@ -171,10 +176,6 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, virtual void SetIgnoreCachedStateForTest(bool ignore) = 0; - // Allow the decoder to exit the current process. - // Defaults to |false|. - virtual void SetAllowExit(bool allow_exit) = 0; - // Gets the QueryManager for this context. virtual QueryManager* GetQueryManager() = 0; @@ -214,18 +215,17 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, // Provides detail about a lost context if one occurred. virtual error::ContextLostReason GetContextLostReason() = 0; - // Clears a level of a texture + // Clears a level sub area of a texture // Returns false if a GL error should be generated. - virtual bool ClearLevel( - Texture* texture, - unsigned target, - int level, - unsigned internal_format, - unsigned format, - unsigned type, - int width, - int height, - bool is_texture_immutable) = 0; + virtual bool ClearLevel(Texture* texture, + unsigned target, + int level, + unsigned format, + unsigned type, + int xoffset, + int yoffset, + int width, + int height) = 0; virtual ErrorState* GetErrorState() = 0; diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 46cb85edc31..27e66c30388 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -1381,11 +1381,9 @@ error::Error GLES2DecoderImpl::HandleGetBooleanv(uint32_t immediate_data_size, return error::kInvalidArguments; } DoGetBooleanv(pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetBooleanv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetBooleanv", ""); } return error::kNoError; } @@ -1463,11 +1461,9 @@ error::Error GLES2DecoderImpl::HandleGetFloatv(uint32_t immediate_data_size, return error::kInvalidArguments; } DoGetFloatv(pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetFloatv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetFloatv", ""); } return error::kNoError; } @@ -1512,11 +1508,9 @@ error::Error GLES2DecoderImpl::HandleGetFramebufferAttachmentParameteriv( return error::kInvalidArguments; } DoGetFramebufferAttachmentParameteriv(target, attachment, pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetFramebufferAttachmentParameteriv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetFramebufferAttachmentParameteriv", ""); } return error::kNoError; } @@ -1544,11 +1538,9 @@ error::Error GLES2DecoderImpl::HandleGetInteger64v(uint32_t immediate_data_size, return error::kInvalidArguments; } DoGetInteger64v(pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetInteger64v"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetInteger64v", ""); } return error::kNoError; } @@ -1577,11 +1569,9 @@ error::Error GLES2DecoderImpl::HandleGetIntegeri_v(uint32_t immediate_data_size, return error::kInvalidArguments; } glGetIntegeri_v(pname, index, data); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetIntegeri_v"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetIntegeri_v", ""); } return error::kNoError; } @@ -1611,11 +1601,9 @@ error::Error GLES2DecoderImpl::HandleGetInteger64i_v( return error::kInvalidArguments; } glGetInteger64i_v(pname, index, data); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetInteger64i_v"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetInteger64i_v", ""); } return error::kNoError; } @@ -1645,47 +1633,9 @@ error::Error GLES2DecoderImpl::HandleGetIntegerv(uint32_t immediate_data_size, return error::kInvalidArguments; } DoGetIntegerv(pname, params); - GLenum error = glGetError(); - if (error == GL_NO_ERROR) { - result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetIntegerv", ""); - } - return error::kNoError; -} - -error::Error GLES2DecoderImpl::HandleGetInternalformativ( - uint32_t immediate_data_size, - const void* cmd_data) { - if (!unsafe_es3_apis_enabled()) - return error::kUnknownCommand; - const gles2::cmds::GetInternalformativ& c = - *static_cast<const gles2::cmds::GetInternalformativ*>(cmd_data); - (void)c; - GLenum target = static_cast<GLenum>(c.target); - GLenum format = static_cast<GLenum>(c.format); - GLenum pname = static_cast<GLenum>(c.pname); - GLsizei bufSize = static_cast<GLsizei>(c.bufSize); - typedef cmds::GetInternalformativ::Result Result; - GLsizei num_values = 0; - GetNumValuesReturnedForGLGet(pname, &num_values); - Result* result = GetSharedMemoryAs<Result*>( - c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values)); - GLint* params = result ? result->GetData() : NULL; - if (params == NULL) { - return error::kOutOfBounds; - } - LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetInternalformativ"); - // Check that the client initialized the result. - if (result->size != 0) { - return error::kInvalidArguments; - } - glGetInternalformativ(target, format, pname, bufSize, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetIntegerv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetInternalformativ", ""); } return error::kNoError; } @@ -1716,11 +1666,9 @@ error::Error GLES2DecoderImpl::HandleGetProgramiv(uint32_t immediate_data_size, return error::kInvalidArguments; } DoGetProgramiv(program, pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetProgramiv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetProgramiv", ""); } return error::kNoError; } @@ -1758,11 +1706,9 @@ error::Error GLES2DecoderImpl::HandleGetRenderbufferParameteriv( return error::kInvalidArguments; } DoGetRenderbufferParameteriv(target, pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetRenderbufferParameteriv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetRenderbufferParameteriv", ""); } return error::kNoError; } @@ -1797,11 +1743,9 @@ error::Error GLES2DecoderImpl::HandleGetSamplerParameterfv( return error::kNoError; } glGetSamplerParameterfv(sampler, pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetSamplerParameterfv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetSamplerParameterfv", ""); } return error::kNoError; } @@ -1836,11 +1780,9 @@ error::Error GLES2DecoderImpl::HandleGetSamplerParameteriv( return error::kNoError; } glGetSamplerParameteriv(sampler, pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetSamplerParameteriv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetSamplerParameteriv", ""); } return error::kNoError; } @@ -1871,11 +1813,9 @@ error::Error GLES2DecoderImpl::HandleGetShaderiv(uint32_t immediate_data_size, return error::kInvalidArguments; } DoGetShaderiv(shader, pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetShaderiv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetShaderiv", ""); } return error::kNoError; } @@ -1909,11 +1849,9 @@ error::Error GLES2DecoderImpl::HandleGetSynciv(uint32_t immediate_data_size, return error::kNoError; } glGetSynciv(service_sync, pname, num_values, nullptr, values); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetSynciv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetSynciv", ""); } return error::kNoError; } @@ -1949,11 +1887,9 @@ error::Error GLES2DecoderImpl::HandleGetTexParameterfv( return error::kInvalidArguments; } DoGetTexParameterfv(target, pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetTexParameterfv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetTexParameterfv", ""); } return error::kNoError; } @@ -1989,11 +1925,9 @@ error::Error GLES2DecoderImpl::HandleGetTexParameteriv( return error::kInvalidArguments; } DoGetTexParameteriv(target, pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetTexParameteriv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetTexParameteriv", ""); } return error::kNoError; } @@ -2025,11 +1959,9 @@ error::Error GLES2DecoderImpl::HandleGetVertexAttribfv( return error::kInvalidArguments; } DoGetVertexAttribfv(index, pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetVertexAttribfv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetVertexAttribfv", ""); } return error::kNoError; } @@ -2061,11 +1993,9 @@ error::Error GLES2DecoderImpl::HandleGetVertexAttribiv( return error::kInvalidArguments; } DoGetVertexAttribiv(index, pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetVertexAttribiv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetVertexAttribiv", ""); } return error::kNoError; } @@ -2095,11 +2025,9 @@ error::Error GLES2DecoderImpl::HandleGetVertexAttribIiv( return error::kInvalidArguments; } DoGetVertexAttribIiv(index, pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetVertexAttribIiv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetVertexAttribIiv", ""); } return error::kNoError; } @@ -2129,11 +2057,9 @@ error::Error GLES2DecoderImpl::HandleGetVertexAttribIuiv( return error::kInvalidArguments; } DoGetVertexAttribIuiv(index, pname, params); - GLenum error = glGetError(); + GLenum error = LOCAL_PEEK_GL_ERROR("GetVertexAttribIuiv"); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); - } else { - LOCAL_SET_GL_ERROR(error, "GetVertexAttribIuiv", ""); } return error::kNoError; } @@ -4235,7 +4161,7 @@ error::Error GLES2DecoderImpl::HandleTexStorage2DEXT( GLenum internalFormat = static_cast<GLenum>(c.internalFormat); GLsizei width = static_cast<GLsizei>(c.width); GLsizei height = static_cast<GLsizei>(c.height); - if (!validators_->texture_target.IsValid(target)) { + if (!validators_->texture_bind_target.IsValid(target)) { LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexStorage2DEXT", target, "target"); return error::kNoError; } @@ -4528,6 +4454,11 @@ error::Error GLES2DecoderImpl::HandleCopyTextureCHROMIUM( GLenum dest_id = static_cast<GLenum>(c.dest_id); GLint internalformat = static_cast<GLint>(c.internalformat); GLenum dest_type = static_cast<GLenum>(c.dest_type); + GLboolean unpack_flip_y = static_cast<GLboolean>(c.unpack_flip_y); + GLboolean unpack_premultiply_alpha = + static_cast<GLboolean>(c.unpack_premultiply_alpha); + GLboolean unpack_unmultiply_alpha = + static_cast<GLboolean>(c.unpack_unmultiply_alpha); if (!validators_->texture_internal_format.IsValid(internalformat)) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "internalformat GL_INVALID_VALUE"); @@ -4538,7 +4469,9 @@ error::Error GLES2DecoderImpl::HandleCopyTextureCHROMIUM( "dest_type"); return error::kNoError; } - DoCopyTextureCHROMIUM(target, source_id, dest_id, internalformat, dest_type); + DoCopyTextureCHROMIUM(target, source_id, dest_id, internalformat, dest_type, + unpack_flip_y, unpack_premultiply_alpha, + unpack_unmultiply_alpha); return error::kNoError; } @@ -4553,7 +4486,41 @@ error::Error GLES2DecoderImpl::HandleCopySubTextureCHROMIUM( GLenum dest_id = static_cast<GLenum>(c.dest_id); GLint xoffset = static_cast<GLint>(c.xoffset); GLint yoffset = static_cast<GLint>(c.yoffset); - DoCopySubTextureCHROMIUM(target, source_id, dest_id, xoffset, yoffset); + GLint x = static_cast<GLint>(c.x); + GLint y = static_cast<GLint>(c.y); + GLsizei width = static_cast<GLsizei>(c.width); + GLsizei height = static_cast<GLsizei>(c.height); + GLboolean unpack_flip_y = static_cast<GLboolean>(c.unpack_flip_y); + GLboolean unpack_premultiply_alpha = + static_cast<GLboolean>(c.unpack_premultiply_alpha); + GLboolean unpack_unmultiply_alpha = + static_cast<GLboolean>(c.unpack_unmultiply_alpha); + if (width < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM", + "width < 0"); + return error::kNoError; + } + if (height < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM", + "height < 0"); + return error::kNoError; + } + DoCopySubTextureCHROMIUM(target, source_id, dest_id, xoffset, yoffset, x, y, + width, height, unpack_flip_y, + unpack_premultiply_alpha, unpack_unmultiply_alpha); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleCompressedCopyTextureCHROMIUM( + uint32_t immediate_data_size, + const void* cmd_data) { + const gles2::cmds::CompressedCopyTextureCHROMIUM& c = + *static_cast<const gles2::cmds::CompressedCopyTextureCHROMIUM*>(cmd_data); + (void)c; + GLenum target = static_cast<GLenum>(c.target); + GLenum source_id = static_cast<GLenum>(c.source_id); + GLenum dest_id = static_cast<GLenum>(c.dest_id); + DoCompressedCopyTextureCHROMIUM(target, source_id, dest_id); return error::kNoError; } @@ -4923,6 +4890,16 @@ error::Error GLES2DecoderImpl::HandleSwapInterval(uint32_t immediate_data_size, return error::kNoError; } +error::Error GLES2DecoderImpl::HandleFlushDriverCachesCHROMIUM( + uint32_t immediate_data_size, + const void* cmd_data) { + const gles2::cmds::FlushDriverCachesCHROMIUM& c = + *static_cast<const gles2::cmds::FlushDriverCachesCHROMIUM*>(cmd_data); + (void)c; + DoFlushDriverCachesCHROMIUM(); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleMatrixLoadfCHROMIUMImmediate( uint32_t immediate_data_size, const void* cmd_data) { diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h index 1e5357dae48..0c71d48b38f 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -9,7 +9,7 @@ #include <vector> -#include "base/callback_forward.h" +#include "base/callback.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "testing/gmock/include/gmock/gmock.h" @@ -21,6 +21,8 @@ class GLSurface; } namespace gpu { +class AsyncPixelTransferDelegate; + namespace gles2 { class ContextGroup; @@ -102,16 +104,16 @@ class MockGLES2Decoder : public GLES2Decoder { uint32* service_texture_id)); MOCK_METHOD0(GetContextLostReason, error::ContextLostReason()); MOCK_CONST_METHOD1(GetCommandName, const char*(unsigned int command_id)); - MOCK_METHOD9(ClearLevel, bool( - Texture* texture, - unsigned target, - int level, - unsigned internal_format, - unsigned format, - unsigned type, - int width, - int height, - bool is_texture_immutable)); + MOCK_METHOD9(ClearLevel, + bool(Texture* texture, + unsigned target, + int level, + unsigned format, + unsigned type, + int x_offset, + int y_offset, + int width, + int height)); MOCK_METHOD0(GetErrorState, ErrorState *()); MOCK_METHOD0(GetLogger, Logger*()); diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index 1dd2fdc2874..a76346f3088 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -44,7 +44,6 @@ using ::testing::Pointee; using ::testing::Return; using ::testing::SaveArg; using ::testing::SetArrayArgument; -using ::testing::SetArgumentPointee; using ::testing::SetArgPointee; using ::testing::StrEq; using ::testing::StrictMock; @@ -96,6 +95,7 @@ void GLES3DecoderTest::SetUp() { InitState init; init.gl_version = "OpenGL ES 3.0"; init.bind_generates_resource = true; + init.webgl_version = 2; InitDecoderWithCommandLine(init, &command_line); } @@ -282,7 +282,53 @@ TEST_P(GLES2DecoderTest, IsTexture) { EXPECT_FALSE(DoIsTexture(client_texture_id_)); } -TEST_P(GLES2DecoderTest, ClientWaitSyncValid) { +TEST_P(GLES3DecoderTest, GetInternalformativValidArgsSamples) { + const GLint kNumSampleCounts = 8; + typedef cmds::GetInternalformativ::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, + GL_NUM_SAMPLE_COUNTS, 1, _)) + .WillOnce(SetArgPointee<4>(kNumSampleCounts)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, + GL_SAMPLES, kNumSampleCounts, + result->GetData())) + .Times(1) + .RetiresOnSaturation(); + result->size = 0; + cmds::GetInternalformativ cmd; + cmd.Init(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, + shared_memory_id_, shared_memory_offset_); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(kNumSampleCounts, result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); +} + +TEST_P(GLES3DecoderTest, GetInternalformativValidArgsNumSampleCounts) { + const GLint kNumSampleCounts = 8; + typedef cmds::GetInternalformativ::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, + GL_NUM_SAMPLE_COUNTS, 1, _)) + .WillOnce(SetArgPointee<4>(kNumSampleCounts)) + .RetiresOnSaturation(); + result->size = 0; + cmds::GetInternalformativ cmd; + cmd.Init(GL_RENDERBUFFER, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, + shared_memory_id_, shared_memory_offset_); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + EXPECT_EQ(kNumSampleCounts, result->GetData()[0]); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); +} + +TEST_P(GLES3DecoderTest, ClientWaitSyncValid) { typedef cmds::ClientWaitSync::Result Result; Result* result = static_cast<Result*>(shared_memory_address_); cmds::ClientWaitSync cmd; @@ -461,7 +507,7 @@ TEST_P(GLES2DecoderManualInitTest, BeginEndQueryEXT) { // Test valid parameters work. EXPECT_CALL(*gl_, GenQueries(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)) + .WillOnce(SetArgPointee<1>(kNewServiceId)) .RetiresOnSaturation(); EXPECT_CALL(*gl_, BeginQuery(GL_ANY_SAMPLES_PASSED_EXT, kNewServiceId)) .Times(1) @@ -527,6 +573,7 @@ const QueryType kQueryTypes[] = { {GL_GET_ERROR_QUERY_CHROMIUM, false}, {GL_COMMANDS_COMPLETED_CHROMIUM, false}, {GL_ANY_SAMPLES_PASSED_EXT, true}, + {GL_TIME_ELAPSED, true}, }; static void CheckBeginEndQueryBadMemoryFails(GLES2DecoderTestBase* test, @@ -538,7 +585,9 @@ static void CheckBeginEndQueryBadMemoryFails(GLES2DecoderTestBase* test, // We need to reset the decoder on each iteration, because we lose the // context every time. GLES2DecoderTestBase::InitState init; - init.extensions = "GL_EXT_occlusion_query_boolean GL_ARB_sync"; + init.extensions = "GL_EXT_occlusion_query_boolean" + " GL_ARB_sync" + " GL_ARB_timer_query"; init.gl_version = "opengl es 2.0"; init.has_alpha = true; init.request_alpha = true; @@ -552,7 +601,7 @@ static void CheckBeginEndQueryBadMemoryFails(GLES2DecoderTestBase* test, if (query_type.is_gl) { EXPECT_CALL(*gl, GenQueries(1, _)) - .WillOnce(SetArgumentPointee<1>(service_id)) + .WillOnce(SetArgPointee<1>(service_id)) .RetiresOnSaturation(); EXPECT_CALL(*gl, BeginQuery(query_type.type, service_id)) .Times(1) @@ -593,11 +642,18 @@ static void CheckBeginEndQueryBadMemoryFails(GLES2DecoderTestBase* test, if (query_type.is_gl) { EXPECT_CALL( *gl, GetQueryObjectuiv(service_id, GL_QUERY_RESULT_AVAILABLE_EXT, _)) - .WillOnce(SetArgumentPointee<2>(1)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, GetQueryObjectuiv(service_id, GL_QUERY_RESULT_EXT, _)) - .WillOnce(SetArgumentPointee<2>(1)) + .WillOnce(SetArgPointee<2>(1)) .RetiresOnSaturation(); + if (query_type.type == GL_TIME_ELAPSED) { + EXPECT_CALL(*gl, GetQueryObjectui64v(service_id, GL_QUERY_RESULT_EXT, _)) + .WillOnce(SetArgPointee<2>(1)) + .RetiresOnSaturation(); + } else { + EXPECT_CALL(*gl, GetQueryObjectuiv(service_id, GL_QUERY_RESULT_EXT, _)) + .WillOnce(SetArgPointee<2>(1)) + .RetiresOnSaturation(); + } + EXPECT_CALL(*gl, DeleteQueries(1, _)).Times(1).RetiresOnSaturation(); } if (query_type.type == GL_COMMANDS_COMPLETED_CHROMIUM) { #if DCHECK_IS_ON() @@ -608,6 +664,12 @@ static void CheckBeginEndQueryBadMemoryFails(GLES2DecoderTestBase* test, EXPECT_CALL(*gl, ClientWaitSync(kGlSync, _, _)) .WillOnce(Return(GL_ALREADY_SIGNALED)) .RetiresOnSaturation(); +#if DCHECK_IS_ON() + EXPECT_CALL(*gl, IsSync(kGlSync)) + .WillOnce(Return(GL_TRUE)) + .RetiresOnSaturation(); +#endif + EXPECT_CALL(*gl, DeleteSync(kGlSync)).Times(1).RetiresOnSaturation(); } QueryManager* query_manager = test->GetDecoder()->GetQueryManager(); @@ -616,18 +678,6 @@ static void CheckBeginEndQueryBadMemoryFails(GLES2DecoderTestBase* test, EXPECT_TRUE(error1 != error::kNoError || error2 != error::kNoError || !process_success); - - if (query_type.is_gl) { - EXPECT_CALL(*gl, DeleteQueries(1, _)).Times(1).RetiresOnSaturation(); - } - if (query_type.type == GL_COMMANDS_COMPLETED_CHROMIUM) { -#if DCHECK_IS_ON() - EXPECT_CALL(*gl, IsSync(kGlSync)) - .WillOnce(Return(GL_TRUE)) - .RetiresOnSaturation(); -#endif - EXPECT_CALL(*gl, DeleteSync(kGlSync)).Times(1).RetiresOnSaturation(); - } test->ResetDecoder(); } @@ -800,6 +850,47 @@ TEST_P(GLES2DecoderManualInitTest, BeginEndQueryEXTCommandsCompletedCHROMIUM) { ResetDecoder(); } +TEST_P(GLES2DecoderManualInitTest, BeginInvalidTargetQueryFails) { + InitState init; + init.extensions = ""; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); + + GenHelper<GenQueriesEXTImmediate>(kNewClientId); + + BeginQueryEXT begin_cmd; + begin_cmd.Init(GL_COMMANDS_COMPLETED_CHROMIUM, + kNewClientId, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + begin_cmd.Init(GL_ANY_SAMPLES_PASSED, + kNewClientId, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + begin_cmd.Init(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, + kNewClientId, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + begin_cmd.Init(0xdeadbeef, + kNewClientId, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + TEST_P(GLES2DecoderTest, IsEnabledReturnsCachedValue) { // NOTE: There are no expectations because no GL functions should be // called for DEPTH_TEST or STENCIL_TEST diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h index 7881a55c8aa..32e1dcc8ed2 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h @@ -1552,31 +1552,7 @@ TEST_P(GLES2DecoderTest1, GetIntegervInvalidArgs1_1) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } - -TEST_P(GLES2DecoderTest1, GetInternalformativValidArgs) { - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - SpecializedSetup<cmds::GetInternalformativ, 0>(true); - typedef cmds::GetInternalformativ::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL( - *gl_, GetInternalformativ(GL_RENDERBUFFER, GL_RGBA4, GL_NUM_SAMPLE_COUNTS, - 4, result->GetData())); - result->size = 0; - cmds::GetInternalformativ cmd; - cmd.Init(GL_RENDERBUFFER, GL_RGBA4, GL_NUM_SAMPLE_COUNTS, 4, - shared_memory_id_, shared_memory_offset_); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_NUM_SAMPLE_COUNTS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); -} +// TODO(gman): GetInternalformativ TEST_P(GLES2DecoderTest1, GetProgramivValidArgs) { SpecializedSetup<cmds::GetProgramiv, 0>(true); diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h index e09d54020fc..7c0638e0cca 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h @@ -392,6 +392,7 @@ TEST_P(GLES2DecoderTest3, PopGroupMarkerEXTValidArgs) { // TODO(gman): TexImageIOSurface2DCHROMIUM // TODO(gman): CopyTextureCHROMIUM // TODO(gman): CopySubTextureCHROMIUM +// TODO(gman): CompressedCopyTextureCHROMIUM // TODO(gman): DrawArraysInstancedANGLE // TODO(gman): DrawElementsInstancedANGLE // TODO(gman): VertexAttribDivisorANGLE @@ -450,4 +451,5 @@ TEST_P(GLES2DecoderTest3, IsValuebufferCHROMIUMInvalidArgsBadSharedMemoryId) { // TODO(gman): ScheduleOverlayPlaneCHROMIUM // TODO(gman): SwapInterval +// TODO(gman): FlushDriverCachesCHROMIUM #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 6bd61561fed..276cb7ded57 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -63,7 +63,7 @@ void NormalizeInitState(gpu::gles2::GLES2DecoderTestBase::InitState* init) { return; if (!init->extensions.empty()) init->extensions += " "; - if (StartsWithASCII(init->gl_version, "opengl es", false)) { + if (base::StartsWithASCII(init->gl_version, "opengl es", false)) { init->extensions += kVAOExtensions[0]; } else { #if !defined(OS_MACOSX) @@ -157,7 +157,8 @@ GLES2DecoderTestBase::InitState::InitState() request_stencil(false), bind_generates_resource(false), lose_context_when_out_of_memory(false), - use_native_vao(true) { + use_native_vao(true), + webgl_version(0) { } void GLES2DecoderTestBase::InitDecoder(const InitState& init) { @@ -227,10 +228,13 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( EXPECT_CALL(*mock_decoder_, DoCommands(_, _, _, _)).WillRepeatedly( Invoke(mock_decoder_.get(), &MockGLES2Decoder::FakeDoCommands)); - EXPECT_TRUE( - group_->Initialize(mock_decoder_.get(), DisallowedFeatures())); - if (group_->feature_info()->IsES3Capable()) { + EXPECT_TRUE(group_->Initialize( + mock_decoder_.get(), + ContextGroup::GetContextType(init.webgl_version), + DisallowedFeatures())); + + if (init.webgl_version == 2) { EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_COLOR_ATTACHMENTS, _)) .WillOnce(SetArgumentPointee<1>(kMaxColorAttachments)) .RetiresOnSaturation(); @@ -400,9 +404,7 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( shared_memory_base_ = buffer->memory(); static const int32 kLoseContextWhenOutOfMemory = 0x10002; - static const int32 kES3ContextRequired = 0x10003; - - bool es3_context_required = group_->feature_info()->IsES3Capable(); + static const int32 kWebGLVersion = 0x10003; int32 attributes[] = { EGL_ALPHA_SIZE, @@ -413,8 +415,8 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( normalized_init.request_stencil ? 8 : 0, kLoseContextWhenOutOfMemory, normalized_init.lose_context_when_out_of_memory ? 1 : 0, - kES3ContextRequired, - es3_context_required ? 1 : 0 + kWebGLVersion, + init.webgl_version }; std::vector<int32> attribs(attributes, attributes + arraysize(attributes)); @@ -657,22 +659,23 @@ void GLES2DecoderTestBase::SetBucketAsCStrings( ClearSharedMemory(); } -void GLES2DecoderTestBase::SetupClearTextureExpectations( - GLuint service_id, - GLuint old_service_id, - GLenum bind_target, - GLenum target, - GLint level, - GLenum internal_format, - GLenum format, - GLenum type, - GLsizei width, - GLsizei height) { +void GLES2DecoderTestBase::SetupClearTextureExpectations(GLuint service_id, + GLuint old_service_id, + GLenum bind_target, + GLenum target, + GLint level, + GLenum internal_format, + GLenum format, + GLenum type, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height) { EXPECT_CALL(*gl_, BindTexture(bind_target, service_id)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, TexImage2D( - target, level, internal_format, width, height, 0, format, type, _)) + EXPECT_CALL(*gl_, TexSubImage2D(target, level, xoffset, yoffset, width, + height, format, type, _)) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl_, BindTexture(bind_target, old_service_id)) @@ -689,19 +692,16 @@ void GLES2DecoderTestBase::SetupExpectationsForFramebufferClearing( GLclampf restore_alpha, GLuint restore_stencil, GLclampf restore_depth, - bool restore_scissor_test) { + bool restore_scissor_test, + GLint restore_scissor_x, + GLint restore_scissor_y, + GLsizei restore_scissor_width, + GLsizei restore_scissor_height) { SetupExpectationsForFramebufferClearingMulti( - 0, - 0, - target, - clear_bits, - restore_red, - restore_green, - restore_blue, - restore_alpha, - restore_stencil, - restore_depth, - restore_scissor_test); + 0, 0, target, clear_bits, restore_red, restore_green, restore_blue, + restore_alpha, restore_stencil, restore_depth, restore_scissor_test, + restore_scissor_x, restore_scissor_y, restore_scissor_width, + restore_scissor_height); } void GLES2DecoderTestBase::SetupExpectationsForRestoreClearState( @@ -711,7 +711,11 @@ void GLES2DecoderTestBase::SetupExpectationsForRestoreClearState( GLclampf restore_alpha, GLuint restore_stencil, GLclampf restore_depth, - bool restore_scissor_test) { + bool restore_scissor_test, + GLint restore_scissor_x, + GLint restore_scissor_y, + GLsizei restore_scissor_width, + GLsizei restore_scissor_height) { EXPECT_CALL(*gl_, ClearColor( restore_red, restore_green, restore_blue, restore_alpha)) .Times(1) @@ -722,11 +726,11 @@ void GLES2DecoderTestBase::SetupExpectationsForRestoreClearState( EXPECT_CALL(*gl_, ClearDepth(restore_depth)) .Times(1) .RetiresOnSaturation(); - if (restore_scissor_test) { - EXPECT_CALL(*gl_, Enable(GL_SCISSOR_TEST)) - .Times(1) - .RetiresOnSaturation(); - } + SetupExpectationsForEnableDisable(GL_SCISSOR_TEST, restore_scissor_test); + EXPECT_CALL(*gl_, Scissor(restore_scissor_x, restore_scissor_y, + restore_scissor_width, restore_scissor_height)) + .Times(1) + .RetiresOnSaturation(); } void GLES2DecoderTestBase::SetupExpectationsForFramebufferClearingMulti( @@ -740,7 +744,11 @@ void GLES2DecoderTestBase::SetupExpectationsForFramebufferClearingMulti( GLclampf restore_alpha, GLuint restore_stencil, GLclampf restore_depth, - bool restore_scissor_test) { + bool restore_scissor_test, + GLint restore_scissor_x, + GLint restore_scissor_y, + GLsizei restore_scissor_width, + GLsizei restore_scissor_height) { // TODO(gman): Figure out why InSequence stopped working. // InSequence sequence; EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(target)) @@ -780,8 +788,9 @@ void GLES2DecoderTestBase::SetupExpectationsForFramebufferClearingMulti( .Times(1) .RetiresOnSaturation(); SetupExpectationsForRestoreClearState( - restore_red, restore_green, restore_blue, restore_alpha, - restore_stencil, restore_depth, restore_scissor_test); + restore_red, restore_green, restore_blue, restore_alpha, restore_stencil, + restore_depth, restore_scissor_test, restore_scissor_x, restore_scissor_y, + restore_scissor_width, restore_scissor_height); if (target == GL_READ_FRAMEBUFFER_EXT) { EXPECT_CALL(*gl_, BindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, read_framebuffer_service_id)) @@ -1673,6 +1682,18 @@ void GLES2DecoderTestBase::DoBufferSubData( EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); } +void GLES2DecoderTestBase::DoScissor(GLint x, + GLint y, + GLsizei width, + GLsizei height) { + EXPECT_CALL(*gl_, Scissor(x, y, width, height)) + .Times(1) + .RetiresOnSaturation(); + cmds::Scissor cmd; + cmd.Init(x, y, width, height); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + void GLES2DecoderTestBase::SetupVertexBuffer() { DoEnableVertexAttribArray(1); DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index 7719cdf3960..42a44e29611 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -199,6 +199,7 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { bool bind_generates_resource; bool lose_context_when_out_of_memory; bool use_native_vao; // default is true. + unsigned webgl_version; // default to 0, i.e., not WebGL context. }; void InitDecoder(const InitState& init); @@ -326,6 +327,8 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { void DoBufferSubData( GLenum target, GLint offset, GLsizei size, const void* data); + void DoScissor(GLint x, GLint y, GLsizei width, GLsizei height); + void SetupVertexBuffer(); void SetupAllNeededVertexBuffers(); @@ -335,37 +338,44 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { void DeleteIndexBuffer(); - void SetupClearTextureExpectations( - GLuint service_id, - GLuint old_service_id, - GLenum bind_target, - GLenum target, - GLint level, - GLenum internal_format, - GLenum format, - GLenum type, - GLsizei width, - GLsizei height); - - void SetupExpectationsForRestoreClearState( - GLclampf restore_red, - GLclampf restore_green, - GLclampf restore_blue, - GLclampf restore_alpha, - GLuint restore_stencil, - GLclampf restore_depth, - bool restore_scissor_test); - - void SetupExpectationsForFramebufferClearing( - GLenum target, - GLuint clear_bits, - GLclampf restore_red, - GLclampf restore_green, - GLclampf restore_blue, - GLclampf restore_alpha, - GLuint restore_stencil, - GLclampf restore_depth, - bool restore_scissor_test); + void SetupClearTextureExpectations(GLuint service_id, + GLuint old_service_id, + GLenum bind_target, + GLenum target, + GLint level, + GLenum internal_format, + GLenum format, + GLenum type, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height); + + void SetupExpectationsForRestoreClearState(GLclampf restore_red, + GLclampf restore_green, + GLclampf restore_blue, + GLclampf restore_alpha, + GLuint restore_stencil, + GLclampf restore_depth, + bool restore_scissor_test, + GLint restore_scissor_x, + GLint restore_scissor_y, + GLsizei restore_scissor_width, + GLsizei restore_scissor_height); + + void SetupExpectationsForFramebufferClearing(GLenum target, + GLuint clear_bits, + GLclampf restore_red, + GLclampf restore_green, + GLclampf restore_blue, + GLclampf restore_alpha, + GLuint restore_stencil, + GLclampf restore_depth, + bool restore_scissor_test, + GLint restore_scissor_x, + GLint restore_scissor_y, + GLsizei restore_scissor_width, + GLsizei restore_scissor_height); void SetupExpectationsForFramebufferClearingMulti( GLuint read_framebuffer_service_id, @@ -378,7 +388,11 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { GLclampf restore_alpha, GLuint restore_stencil, GLclampf restore_depth, - bool restore_scissor_test); + bool restore_scissor_test, + GLint restore_scissor_x, + GLint restore_scissor_y, + GLsizei restore_scissor_width, + GLsizei restore_scissor_height); void SetupExpectationsForDepthMask(bool mask); void SetupExpectationsForEnableDisable(GLenum cap, bool enable); diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc index bb0286d2a83..579e84b81e0 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc @@ -1820,26 +1820,12 @@ TEST_P(GLES2DecoderWithShaderTest, DrawArraysClearsAfterTexImage2DNULL) { DoTexImage2D( GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); // Expect 2 levels will be cleared. - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, - GL_TEXTURE_2D, - GL_TEXTURE_2D, - 0, - GL_RGBA, - GL_RGBA, - GL_UNSIGNED_BYTE, - 2, - 2); - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, - GL_TEXTURE_2D, - GL_TEXTURE_2D, - 1, - GL_RGBA, - GL_RGBA, - GL_UNSIGNED_BYTE, - 1, - 1); + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, + GL_TEXTURE_2D, GL_TEXTURE_2D, 0, GL_RGBA, + GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 2, 2); + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, + GL_TEXTURE_2D, GL_TEXTURE_2D, 1, GL_RGBA, + GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 1, 1); SetupExpectationsForApplyingDefaultDirtyState(); EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) .Times(1) @@ -1867,26 +1853,12 @@ TEST_P(GLES2DecoderWithShaderTest, DrawElementsClearsAfterTexImage2DNULL) { DoTexImage2D( GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); // Expect 2 levels will be cleared. - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, - GL_TEXTURE_2D, - GL_TEXTURE_2D, - 0, - GL_RGBA, - GL_RGBA, - GL_UNSIGNED_BYTE, - 2, - 2); - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, - GL_TEXTURE_2D, - GL_TEXTURE_2D, - 1, - GL_RGBA, - GL_RGBA, - GL_UNSIGNED_BYTE, - 1, - 1); + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, + GL_TEXTURE_2D, GL_TEXTURE_2D, 0, GL_RGBA, + GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 2, 2); + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, + GL_TEXTURE_2D, GL_TEXTURE_2D, 1, GL_RGBA, + GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 1, 1); SetupExpectationsForApplyingDefaultDirtyState(); EXPECT_CALL(*gl_, @@ -1940,19 +1912,20 @@ TEST_P(GLES2DecoderWithShaderTest, DrawClearsAfterTexImage2DNULLInFBO) { kFBOServiceTextureId, 0, GL_NO_ERROR); + DoEnableDisable(GL_SCISSOR_TEST, false); + DoScissor(0, 0, 1, 1); // Setup "render from" texture. SetupTexture(); SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target GL_COLOR_BUFFER_BIT, // clear bits - 0, - 0, - 0, - 0, // color - 0, // stencil - 1.0f, // depth - false); // scissor test + 0, 0, 0, + 0, // color + 0, // stencil + 1.0f, // depth + false, // scissor test + 0, 0, 1, 1); SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB false, // Framebuffer has depth @@ -2031,16 +2004,17 @@ TEST_P(GLES2DecoderWithShaderTest, DrawClearsAfterRenderbufferStorageInFBO) { client_renderbuffer_id_, kServiceRenderbufferId, GL_NO_ERROR); + DoEnableDisable(GL_SCISSOR_TEST, false); + DoScissor(0, 0, 1, 1); SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target GL_COLOR_BUFFER_BIT, // clear bits - 0, - 0, - 0, - 0, // color - 0, // stencil - 1.0f, // depth - false); // scissor test + 0, 0, 0, + 0, // color + 0, // stencil + 1.0f, // depth + false, // scissor test + 0, 0, 1, 1); AddExpectationsForSimulatedAttrib0(kNumVertices, 0); SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB @@ -2107,26 +2081,14 @@ TEST_P(GLES2DecoderManualInitTest, DrawArraysClearsAfterTexImage2DNULLCubemap) { shm_offset); } // Expect 2 levels will be cleared. - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, GL_TEXTURE_CUBE_MAP, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - 0, - GL_RGBA, - GL_RGBA, - GL_UNSIGNED_BYTE, - 2, - 2); - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, + GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 2, 2); + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, GL_TEXTURE_CUBE_MAP, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - 1, - GL_RGBA, - GL_RGBA, - GL_UNSIGNED_BYTE, - 1, - 1); + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 1, GL_RGBA, + GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 1, 1); AddExpectationsForSimulatedAttrib0(kNumVertices, 0); SetupExpectationsForApplyingDefaultDirtyState(); EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) @@ -2178,18 +2140,18 @@ TEST_P(GLES2DecoderWithShaderTest, client_renderbuffer_id_, kServiceRenderbufferId, GL_NO_ERROR); - + DoEnableDisable(GL_SCISSOR_TEST, false); + DoScissor(0, 0, 1, 1); SetupTexture(); SetupExpectationsForFramebufferClearing( GL_FRAMEBUFFER, // target GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, // clear bits - 0, - 0, - 0, - 0, // color - 0, // stencil - 1.0f, // depth - false); // scissor test + 0, 0, 0, + 0, // color + 0, // stencil + 1.0f, // depth + false, // scissor test + 0, 0, 1, 1); AddExpectationsForSimulatedAttrib0(kNumVertices, 0); SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB @@ -2310,9 +2272,10 @@ TEST_P(GLES2DecoderManualInitTest, DrawClearsDepthTexture) { 0, 0); - // Enable GL_SCISSOR_TEST to make sure we disable it in the clear, - // then re-enable it. - DoEnableDisable(GL_SCISSOR_TEST, true); + // Set scissor rect and disable GL_SCISSOR_TEST to make sure we enable it in + // the clear, then disable it and restore the rect again. + DoScissor(0, 0, 32, 32); + DoEnableDisable(GL_SCISSOR_TEST, false); EXPECT_CALL(*gl_, GenFramebuffersEXT(1, _)).Times(1).RetiresOnSaturation(); EXPECT_CALL(*gl_, BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, _)) @@ -2336,11 +2299,13 @@ TEST_P(GLES2DecoderManualInitTest, DrawClearsDepthTexture) { GLES2Decoder::kDefaultStencilMask); EXPECT_CALL(*gl_, ClearDepth(1.0f)).Times(1).RetiresOnSaturation(); SetupExpectationsForDepthMask(true); - SetupExpectationsForEnableDisable(GL_SCISSOR_TEST, false); + SetupExpectationsForEnableDisable(GL_SCISSOR_TEST, true); + EXPECT_CALL(*gl_, Scissor(0, 0, 1, 1)).Times(1).RetiresOnSaturation(); EXPECT_CALL(*gl_, Clear(GL_DEPTH_BUFFER_BIT)).Times(1).RetiresOnSaturation(); - SetupExpectationsForRestoreClearState(0.0f, 0.0f, 0.0f, 0.0f, 0, 1.0f, true); + SetupExpectationsForRestoreClearState(0.0f, 0.0f, 0.0f, 0.0f, 0, 1.0f, false, + 0, 0, 32, 32); EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, _)).Times(1).RetiresOnSaturation(); EXPECT_CALL(*gl_, BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0)) diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc index 4255ffaa180..6e47194f472 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc @@ -1675,19 +1675,22 @@ TEST_P(GLES2DecoderWithShaderTest, UnClearedAttachmentsGetClearedOnClear) { kFBOServiceTextureId, 0, GL_NO_ERROR); + // Set scissor rect and enable GL_SCISSOR_TEST to make sure we re-enable it + // and restore the rect again after the clear. + DoEnableDisable(GL_SCISSOR_TEST, true); + DoScissor(0, 0, 64, 64); // Setup "render from" texture. SetupTexture(); SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target GL_COLOR_BUFFER_BIT, // clear bits - 0, - 0, - 0, - 0, // color - 0, // stencil - 1.0f, // depth - false); // scissor test + 0, 0, 0, + 0, // color + 0, // stencil + 1.0f, // depth + true, // scissor test + 0, 0, 64, 64); SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB false, // Framebuffer has depth false, // Framebuffer has stencil @@ -1729,19 +1732,20 @@ TEST_P(GLES2DecoderWithShaderTest, UnClearedAttachmentsGetClearedOnReadPixels) { kFBOServiceTextureId, 0, GL_NO_ERROR); + DoEnableDisable(GL_SCISSOR_TEST, false); + DoScissor(0, 0, 1, 1); // Setup "render from" texture. SetupTexture(); SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target GL_COLOR_BUFFER_BIT, // clear bits - 0, - 0, - 0, - 0, // color - 0, // stencil - 1.0f, // depth - false); // scissor test + 0, 0, 0, + 0, // color + 0, // stencil + 1.0f, // depth + false, // scissor test + 0, 0, 1, 1); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -1800,22 +1804,22 @@ TEST_P(GLES2DecoderManualInitTest, 0, GL_NO_ERROR); - // Enable GL_SCISSOR_TEST to make sure we disable it in the clear, - // then re-enable after. - DoEnableDisable(GL_SCISSOR_TEST, true); + // Set scissor rect and disable GL_SCISSOR_TEST to make sure we enable it in + // the clear, then disable it and restore the rect again. + DoScissor(0, 0, 32, 32); + DoEnableDisable(GL_SCISSOR_TEST, false); SetupExpectationsForFramebufferClearingMulti( kServiceFramebufferId, // read framebuffer service id 0, // backbuffer service id GL_READ_FRAMEBUFFER, // target GL_COLOR_BUFFER_BIT, // clear bits - 0, - 0, - 0, + 0, 0, 0, 0, // color 0, // stencil 1.0f, // depth - true); // scissor test + false, // scissor test + 0, 0, 32, 32); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -2201,19 +2205,20 @@ TEST_P(GLES2DecoderManualInitTest, kFBOServiceTextureId, 0, GL_NO_ERROR); + DoEnableDisable(GL_SCISSOR_TEST, false); + DoScissor(0, 0, 1, 1); // Setup "render from" texture. SetupTexture(); SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target GL_COLOR_BUFFER_BIT, // clear bits - 0, - 0, - 0, - 0, // color - 0, // stencil - 1.0f, // depth - false); // scissor test + 0, 0, 0, + 0, // color + 0, // stencil + 1.0f, // depth + false, // scissor test + 0, 0, 1, 1); SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB false, // Framebuffer has depth false, // Framebuffer has stencil diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc index 2d1330111b6..159813d4605 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc @@ -103,16 +103,9 @@ TEST_P(GLES2DecoderTest, GenerateMipmapClearsUnclearedTexture) { DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); DoTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, - GL_TEXTURE_2D, - GL_TEXTURE_2D, - 0, - GL_RGBA, - GL_RGBA, - GL_UNSIGNED_BYTE, - 2, - 2); + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, + GL_TEXTURE_2D, GL_TEXTURE_2D, 0, GL_RGBA, + GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 2, 2); EXPECT_CALL(*gl_, GenerateMipmapEXT(GL_TEXTURE_2D)); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -139,16 +132,9 @@ TEST_P(GLES2DecoderManualInitTest, SetTextureFiltersBeforeGenerateMipmap) { DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); DoTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, - GL_TEXTURE_2D, - GL_TEXTURE_2D, - 0, - GL_RGBA, - GL_RGBA, - GL_UNSIGNED_BYTE, - 2, - 2); + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, + GL_TEXTURE_2D, GL_TEXTURE_2D, 0, GL_RGBA, + GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 2, 2); EXPECT_CALL( *gl_, TexParameteri( @@ -511,16 +497,6 @@ TEST_P(GLES2DecoderTest, TexImage2DRedefinitionSucceeds) { kSharedMemoryId, kSharedMemoryOffset); } else { - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, - GL_TEXTURE_2D, - GL_TEXTURE_2D, - 0, - GL_RGBA, - GL_RGBA, - GL_UNSIGNED_BYTE, - kWidth, - kHeight); cmd.Init(GL_TEXTURE_2D, 0, GL_RGBA, @@ -1776,52 +1752,23 @@ TEST_P(GLES2DecoderManualInitTest, TexSubImage2DClearsAfterTexImage2DNULL) { DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); DoTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, - GL_TEXTURE_2D, - GL_TEXTURE_2D, - 0, - GL_RGBA, - GL_RGBA, - GL_UNSIGNED_BYTE, - 2, - 2); - EXPECT_CALL(*gl_, - TexSubImage2D(GL_TEXTURE_2D, - 0, - 1, - 1, - 1, - 1, - GL_RGBA, - GL_UNSIGNED_BYTE, - shared_memory_address_)) - .Times(1) + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, + GL_TEXTURE_2D, GL_TEXTURE_2D, 0, GL_RGBA, + GL_RGBA, GL_UNSIGNED_BYTE, 0, 1, 2, 1); + EXPECT_CALL(*gl_, TexSubImage2D(GL_TEXTURE_2D, 0, 0, _, _, 1, GL_RGBA, + GL_UNSIGNED_BYTE, shared_memory_address_)) + .Times(2) .RetiresOnSaturation(); TexSubImage2D cmd; - cmd.Init(GL_TEXTURE_2D, - 0, - 1, - 1, - 1, - 1, - GL_RGBA, - GL_UNSIGNED_BYTE, - kSharedMemoryId, - kSharedMemoryOffset, - GL_FALSE); + cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(GL_TEXTURE_2D, 0, 0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); // Test if we call it again it does not clear. - EXPECT_CALL(*gl_, - TexSubImage2D(GL_TEXTURE_2D, - 0, - 1, - 1, - 1, - 1, - GL_RGBA, - GL_UNSIGNED_BYTE, - shared_memory_address_)) + EXPECT_CALL(*gl_, TexSubImage2D(GL_TEXTURE_2D, 0, 0, 1, 1, 1, GL_RGBA, + GL_UNSIGNED_BYTE, shared_memory_address_)) .Times(1) .RetiresOnSaturation(); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); @@ -1888,7 +1835,7 @@ TEST_P( base::CommandLine command_line(0, NULL); command_line.AppendSwitchASCII( switches::kGpuDriverBugWorkarounds, - base::IntToString(gpu::TEXSUBIMAGE2D_FASTER_THAN_TEXIMAGE2D)); + base::IntToString(gpu::TEXSUBIMAGE_FASTER_THAN_TEXIMAGE)); InitState init; init.bind_generates_resource = true; InitDecoderWithCommandLine(init, &command_line); @@ -1978,40 +1925,19 @@ TEST_P(GLES2DecoderTest, TexSubImage2DClearsAfterTexImage2DWithDataThenNULL) { // It won't actually call TexImage2D, just mark it as uncleared. EXPECT_EQ(error::kNoError, ExecuteCmd(tex_cmd)); // Next call to TexSubImage2d should clear. - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, - GL_TEXTURE_2D, - GL_TEXTURE_2D, - 0, - GL_RGBA, - GL_RGBA, - GL_UNSIGNED_BYTE, - 2, - 2); - EXPECT_CALL(*gl_, - TexSubImage2D(GL_TEXTURE_2D, - 0, - 1, - 1, - 1, - 1, - GL_RGBA, - GL_UNSIGNED_BYTE, - shared_memory_address_)) - .Times(1) + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, + GL_TEXTURE_2D, GL_TEXTURE_2D, 0, GL_RGBA, + GL_RGBA, GL_UNSIGNED_BYTE, 0, 1, 2, 1); + EXPECT_CALL(*gl_, TexSubImage2D(GL_TEXTURE_2D, 0, 0, _, _, 1, GL_RGBA, + GL_UNSIGNED_BYTE, shared_memory_address_)) + .Times(2) .RetiresOnSaturation(); TexSubImage2D cmd; - cmd.Init(GL_TEXTURE_2D, - 0, - 1, - 1, - 1, - 1, - GL_RGBA, - GL_UNSIGNED_BYTE, - kSharedMemoryId, - kSharedMemoryOffset, - GL_FALSE); + cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(GL_TEXTURE_2D, 0, 0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); } @@ -2039,27 +1965,67 @@ TEST_P(GLES2DecoderTest, CopyTexImage2DMarksTextureAsCleared) { EXPECT_TRUE(texture->SafeToRenderFrom()); } -TEST_P(GLES2DecoderTest, CopyTexSubImage2DClearsUnclearedTexture) { +TEST_P(GLES2DecoderTest, CopyTexSubImage2DTwiceMarksTextureAsCleared) { DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); DoTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, - GL_TEXTURE_2D, - GL_TEXTURE_2D, - 0, - GL_RGBA, - GL_RGBA, - GL_UNSIGNED_BYTE, - 2, - 2); - EXPECT_CALL(*gl_, CopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1)) - .Times(1) - .RetiresOnSaturation(); - CopyTexSubImage2D cmd; - cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + // This will initialize the top part. + { + EXPECT_CALL(*gl_, CopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 2, 1)) + .Times(1) + .RetiresOnSaturation(); + CopyTexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 2, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + + // This will initialize the bottom part. + { + EXPECT_CALL(*gl_, CopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 1, 0, 0, 2, 1)) + .Times(1) + .RetiresOnSaturation(); + CopyTexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, 0, 0, 1, 0, 0, 2, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + + TextureManager* manager = group().texture_manager(); + TextureRef* texture_ref = manager->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_TRUE(texture->SafeToRenderFrom()); +} + +TEST_P(GLES2DecoderTest, CopyTexSubImage2DTwiceClearsUnclearedTexture) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, + 0); + + // This will initialize the top part. + { + EXPECT_CALL(*gl_, CopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 2, 1)) + .Times(1) + .RetiresOnSaturation(); + CopyTexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 2, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, + GL_TEXTURE_2D, GL_TEXTURE_2D, 0, GL_RGBA, + GL_RGBA, GL_UNSIGNED_BYTE, 0, 1, 2, 1); + + // This will clear the bottom part as a rectangle is not sufficient to keep + // track of the initialized area. + { + EXPECT_CALL(*gl_, CopyTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 0, 0, 1, 1)) + .Times(1) + .RetiresOnSaturation(); + CopyTexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, 0, 1, 1, 0, 0, 1, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } TextureManager* manager = group().texture_manager(); TextureRef* texture_ref = manager->GetTexture(client_texture_id_); @@ -2595,7 +2561,7 @@ TEST_P(GLES2DecoderTest, GLImageAttachedAfterSubTexImage2D) { // Specifically tests that TexSubImage2D is not optimized to TexImage2D // in the presence of image attachments. ASSERT_FALSE( - feature_info()->workarounds().texsubimage2d_faster_than_teximage2d); + feature_info()->workarounds().texsubimage_faster_than_teximage); scoped_refptr<gfx::GLImage> image(new gfx::GLImageStub); GetImageManager()->AddImage(image.get(), 1); @@ -2680,8 +2646,8 @@ TEST_P(GLES2DecoderTest, GLImageAttachedAfterClearLevel) { height, format, type, _)) .Times(1) .RetiresOnSaturation(); - GetDecoder()->ClearLevel(texture, target, level, format, format, type, width, - height, false); + GetDecoder()->ClearLevel(texture, target, level, format, type, 0, 0, width, + height); EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == image.get()); } @@ -2742,10 +2708,12 @@ class MockGLImage : public gfx::GLImage { // Overridden from gfx::GLImage: MOCK_METHOD0(GetSize, gfx::Size()); + MOCK_METHOD0(GetInternalFormat, unsigned()); MOCK_METHOD1(Destroy, void(bool)); MOCK_METHOD1(BindTexImage, bool(unsigned)); MOCK_METHOD1(ReleaseTexImage, void(unsigned)); - MOCK_METHOD1(CopyTexImage, bool(unsigned)); + MOCK_METHOD3(CopyTexSubImage, + bool(unsigned, const gfx::Point&, const gfx::Rect&)); MOCK_METHOD0(WillUseTexImage, void()); MOCK_METHOD0(DidUseTexImage, void()); MOCK_METHOD0(WillModifyTexImage, void()); @@ -2893,17 +2861,9 @@ TEST_P(GLES2DecoderManualInitTest, DrawWithGLImageExternal) { TextureRef* texture_ref = GetTexture(client_texture_id_); scoped_refptr<MockGLImage> image(new MockGLImage); group().texture_manager()->SetTarget(texture_ref, GL_TEXTURE_EXTERNAL_OES); - group().texture_manager()->SetLevelInfo(texture_ref, - GL_TEXTURE_EXTERNAL_OES, - 0, - GL_RGBA, - 0, - 0, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + group().texture_manager()->SetLevelInfo(texture_ref, GL_TEXTURE_EXTERNAL_OES, + 0, GL_RGBA, 0, 0, 1, 0, GL_RGBA, + GL_UNSIGNED_BYTE, gfx::Rect()); group().texture_manager()->SetLevelImage( texture_ref, GL_TEXTURE_EXTERNAL_OES, 0, image.get()); @@ -3056,40 +3016,19 @@ TEST_P(GLES2DecoderManualInitTest, TexSubImage2DFloatDoesClearOnGLES3) { GL_FLOAT, 0, 0); - SetupClearTextureExpectations(kServiceTextureId, - kServiceTextureId, - GL_TEXTURE_2D, - GL_TEXTURE_2D, - 0, - GL_RGBA32F, - GL_RGBA, - GL_FLOAT, - kWidth, - kHeight); - EXPECT_CALL(*gl_, - TexSubImage2D(GL_TEXTURE_2D, - 0, - 1, - 0, - kWidth - 1, - kHeight, - GL_RGBA, - GL_FLOAT, - shared_memory_address_)) - .Times(1) + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, + GL_TEXTURE_2D, GL_TEXTURE_2D, 0, GL_RGBA32F, + GL_RGBA, GL_FLOAT, 0, kHeight - 1, kWidth, 1); + EXPECT_CALL(*gl_, TexSubImage2D(GL_TEXTURE_2D, 0, 0, _, _, _, GL_RGBA, + GL_FLOAT, shared_memory_address_)) + .Times(2) .RetiresOnSaturation(); TexSubImage2D cmd; - cmd.Init(GL_TEXTURE_2D, - 0, - 1, - 0, - kWidth - 1, - kHeight, - GL_RGBA, - GL_FLOAT, - kSharedMemoryId, - kSharedMemoryOffset, - GL_FALSE); + cmd.Init(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight - 1, GL_RGBA, GL_FLOAT, + kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(GL_TEXTURE_2D, 0, 0, kHeight - 1, kWidth - 1, 1, GL_RGBA, GL_FLOAT, + kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index 69cf3c4c7f1..1c4cf97c349 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h @@ -259,9 +259,6 @@ static const GLenum valid_g_l_state_table[] = { GL_TEXTURE_BINDING_2D, GL_TEXTURE_BINDING_CUBE_MAP, GL_UNPACK_ALIGNMENT, - GL_UNPACK_FLIP_Y_CHROMIUM, - GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, - GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, GL_BIND_GENERATES_RESOURCE_CHROMIUM, GL_VERTEX_ARRAY_BINDING_OES, GL_VIEWPORT, @@ -480,9 +477,6 @@ static const GLenum valid_matrix_mode_table[] = { static const GLenum valid_pixel_store_table[] = { GL_PACK_ALIGNMENT, GL_UNPACK_ALIGNMENT, - GL_UNPACK_FLIP_Y_CHROMIUM, - GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, - GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, }; static const GLenum valid_pixel_store_table_es3[] = { @@ -899,6 +893,7 @@ static const GLenum valid_texture_internal_format_storage_table_es3[] = { GL_RG16I, GL_RG32UI, GL_RG32I, + GL_RGB8, GL_SRGB8, GL_RGB8_SNORM, GL_R11F_G11F_B10F, @@ -911,6 +906,7 @@ static const GLenum valid_texture_internal_format_storage_table_es3[] = { GL_RGB16I, GL_RGB32UI, GL_RGB32I, + GL_RGBA8, GL_SRGB8_ALPHA8, GL_RGBA8_SNORM, GL_RGB10_A2, diff --git a/chromium/gpu/command_buffer/service/gpu_scheduler.cc b/chromium/gpu/command_buffer/service/gpu_scheduler.cc index 8570fcded91..2a15dc76f9c 100644 --- a/chromium/gpu/command_buffer/service/gpu_scheduler.cc +++ b/chromium/gpu/command_buffer/service/gpu_scheduler.cc @@ -10,6 +10,7 @@ #include "base/message_loop/message_loop.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" +#include "gpu/command_buffer/service/logger.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_fence.h" #include "ui/gl/gl_switches.h" diff --git a/chromium/gpu/command_buffer/service/gpu_tracer.cc b/chromium/gpu/command_buffer/service/gpu_tracer.cc index e6c1e7fc8ac..868c5ec7299 100644 --- a/chromium/gpu/command_buffer/service/gpu_tracer.cc +++ b/chromium/gpu/command_buffer/service/gpu_tracer.cc @@ -10,12 +10,14 @@ #include "base/location.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/context_group.h" #include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_context.h" #include "ui/gl/gl_version_info.h" #include "ui/gl/gpu_timing.h" @@ -27,6 +29,7 @@ static const char* kGpuTraceSourceNames[] = { "GroupMarker", // kTraceGroupMarker = 0, "TraceCHROMIUM", // kTraceCHROMIUM = 1, "TraceCmd", // kTraceDecoder = 2, + "Disjoint", // kTraceDisjoint = 3, // Used internally. }; static_assert(NUM_TRACER_SOURCES == arraysize(kGpuTraceSourceNames), "Trace source names must match enumeration."); @@ -73,12 +76,15 @@ void TraceOutputter::TraceDevice(GpuTracerSource source, category.c_str(), "channel", kGpuTraceSourceNames[source]); + + // Time stamps are inclusive, since the traces are durations we subtract + // 1 microsecond from the end time to make the trace markers show up cleaner. TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP2( TRACE_DISABLED_BY_DEFAULT("gpu.device"), name.c_str(), local_trace_device_id_, named_thread_.thread_id(), - end_time, + end_time - 1, "gl_category", category.c_str(), "channel", @@ -128,11 +134,8 @@ GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, outputter_(outputter), service_enabled_(tracing_service), device_enabled_(tracing_device) { - if (tracing_device && - gpu_timing_client->IsAvailable() && - gpu_timing_client->IsTimerOffsetAvailable()) { - gpu_timer_ = gpu_timing_client->CreateGPUTimer(); - } + if (tracing_device && gpu_timing_client->IsAvailable()) + gpu_timer_ = gpu_timing_client->CreateGPUTimer(false); } GPUTrace::~GPUTrace() { @@ -167,7 +170,7 @@ bool GPUTrace::IsAvailable() { } void GPUTrace::Process() { - if (gpu_timer_.get()) { + if (gpu_timer_.get() && device_enabled_) { DCHECK(IsAvailable()); int64 start = 0; @@ -182,9 +185,7 @@ GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) TRACE_DISABLED_BY_DEFAULT("gpu.service"))), gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( TRACE_DISABLED_BY_DEFAULT("gpu.device"))), - decoder_(decoder), - gpu_executing_(false), - process_posted_(false) { + decoder_(decoder) { DCHECK(decoder_); gfx::GLContext* context = decoder_->GetGLContext(); if (context) { @@ -192,23 +193,15 @@ GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) } else { gpu_timing_client_ = new gfx::GPUTimingClient(); } + + disjoint_time_ = gpu_timing_client_->GetCurrentCPUTime(); } GPUTracer::~GPUTracer() { } void GPUTracer::Destroy(bool have_context) { - for (int n = 0; n < NUM_TRACER_SOURCES; n++) { - for (size_t i = 0; i < markers_[n].size(); i++) { - TraceMarker& marker = markers_[n][i]; - if (marker.trace_.get()) { - marker.trace_->Destroy(have_context); - marker.trace_ = 0; - } - } - } - - ClearFinishedTraces(have_context); + ClearOngoingTraces(have_context); } bool GPUTracer::BeginDecoding() { @@ -219,17 +212,13 @@ bool GPUTracer::BeginDecoding() { outputter_ = CreateOutputter(gpu_timing_client_->GetTimerTypeName()); } - if (*gpu_trace_dev_category == '\0') { - // If GPU device category is off, invalidate timing sync. - gpu_timing_client_->InvalidateTimerOffset(); - } - gpu_executing_ = true; if (IsTracing()) { - gpu_timing_client_->CheckAndResetTimerErrors(); + CheckDisjointStatus(); // Begin a Trace for all active markers for (int n = 0; n < NUM_TRACER_SOURCES; n++) { for (size_t i = 0; i < markers_[n].size(); i++) { + began_device_traces_ |= (*gpu_trace_dev_category != 0); TraceMarker& trace_marker = markers_[n][i]; trace_marker.trace_ = new GPUTrace(outputter_, gpu_timing_client_.get(), @@ -267,9 +256,6 @@ bool GPUTracer::EndDecoding() { } gpu_executing_ = false; - - // NOTE(vmiura): glFlush() here can help give better trace results, - // but it distorts the normal device behavior. return true; } @@ -285,6 +271,7 @@ bool GPUTracer::Begin(const std::string& category, const std::string& name, // Create trace if (IsTracing()) { + began_device_traces_ |= (*gpu_trace_dev_category != 0); scoped_refptr<GPUTrace> trace = new GPUTrace( outputter_, gpu_timing_client_.get(), source, category, name, *gpu_trace_srv_category != 0, @@ -360,7 +347,10 @@ void GPUTracer::Process() { void GPUTracer::ProcessTraces() { if (!gpu_timing_client_->IsAvailable()) { - ClearFinishedTraces(false); + while (!finished_traces_.empty()) { + finished_traces_.front()->Destroy(false); + finished_traces_.pop_front(); + } return; } @@ -369,34 +359,65 @@ void GPUTracer::ProcessTraces() { // Make owning decoder's GL context current if (!decoder_->MakeCurrent()) { // Skip subsequent GL calls if MakeCurrent fails - ClearFinishedTraces(false); + ClearOngoingTraces(false); return; } - // Check if timers are still valid (e.g: a disjoint operation - // might have occurred.) - if (gpu_timing_client_->CheckAndResetTimerErrors()) { - ClearFinishedTraces(true); + // Check available traces. + int available_traces = 0; + for (scoped_refptr<GPUTrace>& trace : finished_traces_) { + if (trace->IsDeviceTraceEnabled() && !trace->IsAvailable()) { + break; + } + available_traces++; } - while (!finished_traces_.empty()) { - scoped_refptr<GPUTrace>& trace = finished_traces_.front(); - if (trace->IsDeviceTraceEnabled()) { - if (!finished_traces_.front()->IsAvailable()) - break; - finished_traces_.front()->Process(); + // Clear pending traces if there were are any errors including disjoint. + if (CheckDisjointStatus()) { + ClearOngoingTraces(true); + } else { + for (int i = 0; i < available_traces; ++i) { + scoped_refptr<GPUTrace>& trace = finished_traces_.front(); + trace->Process(); + trace->Destroy(true); + finished_traces_.pop_front(); } - finished_traces_.front()->Destroy(true); - finished_traces_.pop_front(); } - // Clear pending traces if there were are any errors - GLenum err = glGetError(); - if (err != GL_NO_ERROR) - ClearFinishedTraces(true); + DCHECK(GL_NO_ERROR == glGetError()); } -void GPUTracer::ClearFinishedTraces(bool have_context) { +bool GPUTracer::CheckDisjointStatus() { + const int64 current_time = gpu_timing_client_->GetCurrentCPUTime(); + if (*gpu_trace_dev_category == 0) + return false; + + bool status = gpu_timing_client_->CheckAndResetTimerErrors(); + if (status && began_device_traces_) { + // Log disjoint event if we have active traces. + const std::string unique_disjoint_name = + base::StringPrintf("DisjointEvent-%p", this); + outputter_->TraceDevice(kTraceDisjoint, + "DisjointEvent", + unique_disjoint_name, + disjoint_time_, + current_time); + } + disjoint_time_ = current_time; + return status; +} + +void GPUTracer::ClearOngoingTraces(bool have_context) { + for (int n = 0; n < NUM_TRACER_SOURCES; n++) { + for (size_t i = 0; i < markers_[n].size(); i++) { + TraceMarker& marker = markers_[n][i]; + if (marker.trace_.get()) { + marker.trace_->Destroy(have_context); + marker.trace_ = 0; + } + } + } + while (!finished_traces_.empty()) { finished_traces_.front()->Destroy(have_context); finished_traces_.pop_front(); diff --git a/chromium/gpu/command_buffer/service/gpu_tracer.h b/chromium/gpu/command_buffer/service/gpu_tracer.h index 2565ab87a0e..610af9deacf 100644 --- a/chromium/gpu/command_buffer/service/gpu_tracer.h +++ b/chromium/gpu/command_buffer/service/gpu_tracer.h @@ -33,9 +33,10 @@ class GPUTrace; enum GpuTracerSource { kTraceGroupInvalid = -1, - kTraceGroupMarker = 0, - kTraceCHROMIUM = 1, - kTraceDecoder = 2, + kTraceGroupMarker, + kTraceCHROMIUM, + kTraceDecoder, + kTraceDisjoint, // Used internally. NUM_TRACER_SOURCES }; @@ -86,7 +87,8 @@ class GPU_EXPORT GPUTracer void Process(); void ProcessTraces(); - void ClearFinishedTraces(bool have_context); + bool CheckDisjointStatus(); + void ClearOngoingTraces(bool have_context); void IssueProcessTask(); @@ -98,9 +100,11 @@ class GPU_EXPORT GPUTracer const unsigned char* gpu_trace_srv_category; const unsigned char* gpu_trace_dev_category; gles2::GLES2Decoder* decoder_; + int64 disjoint_time_ = 0; - bool gpu_executing_; - bool process_posted_; + bool gpu_executing_ = false; + bool process_posted_ = false; + bool began_device_traces_ = false; private: DISALLOW_COPY_AND_ASSIGN(GPUTracer); diff --git a/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc b/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc index 8de31fade1a..9bb59980087 100644 --- a/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc +++ b/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc @@ -2,27 +2,24 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <map> -#include <set> - #include "base/bind.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/gpu_tracer.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_context.h" #include "ui/gl/gl_mock.h" #include "ui/gl/gpu_timing.h" +#include "ui/gl/gpu_timing_fake.h" namespace gpu { namespace gles2 { namespace { using ::testing::_; -using ::testing::AtLeast; using ::testing::AtMost; using ::testing::Exactly; using ::testing::Invoke; -using ::testing::NotNull; using ::testing::Return; int64 g_fakeCPUTime = 0; @@ -50,107 +47,6 @@ class MockOutputter : public Outputter { ~MockOutputter() {} }; -class GlFakeQueries { - public: - GlFakeQueries() {} - - void Reset() { - current_time_ = 0; - next_query_id_ = 23; - alloced_queries_.clear(); - query_timestamp_.clear(); - } - - void SetCurrentGLTime(GLint64 current_time) { current_time_ = current_time; } - void SetDisjoint() { disjointed_ = true; } - - void GenQueries(GLsizei n, GLuint* ids) { - for (GLsizei i = 0; i < n; i++) { - ids[i] = next_query_id_++; - alloced_queries_.insert(ids[i]); - } - } - - void DeleteQueries(GLsizei n, const GLuint* ids) { - for (GLsizei i = 0; i < n; i++) { - alloced_queries_.erase(ids[i]); - query_timestamp_.erase(ids[i]); - } - } - - void GetQueryObjectiv(GLuint id, GLenum pname, GLint* params) { - switch (pname) { - case GL_QUERY_RESULT_AVAILABLE: { - std::map<GLuint, GLint64>::iterator it = query_timestamp_.find(id); - if (it != query_timestamp_.end() && it->second <= current_time_) - *params = 1; - else - *params = 0; - break; - } - default: - FAIL() << "Invalid variable passed to GetQueryObjectiv: " << pname; - } - } - - void QueryCounter(GLuint id, GLenum target) { - switch (target) { - case GL_TIMESTAMP: - ASSERT_TRUE(alloced_queries_.find(id) != alloced_queries_.end()); - query_timestamp_[id] = current_time_; - break; - default: - FAIL() << "Invalid variable passed to QueryCounter: " << target; - } - } - - void GetInteger64v(GLenum pname, GLint64 * data) { - switch (pname) { - case GL_TIMESTAMP: - *data = current_time_; - break; - default: - FAIL() << "Invalid variable passed to GetInteger64v: " << pname; - } - } - - void GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) { - switch (pname) { - case GL_QUERY_RESULT: - ASSERT_TRUE(query_timestamp_.find(id) != query_timestamp_.end()); - *params = query_timestamp_.find(id)->second; - break; - default: - FAIL() << "Invalid variable passed to GetQueryObjectui64v: " << pname; - } - } - - void GetIntegerv(GLenum pname, GLint* params) { - switch (pname) { - case GL_GPU_DISJOINT_EXT: - *params = static_cast<GLint>(disjointed_); - disjointed_ = false; - break; - default: - FAIL() << "Invalid variable passed to GetIntegerv: " << pname; - } - } - - void Finish() { - } - - GLenum GetError() { - return GL_NO_ERROR; - } - - protected: - bool disjointed_ = false; - GLint64 current_time_ = 0; - GLuint next_query_id_ = 0; - std::set<GLuint> alloced_queries_; - std::map<GLuint, GLint64> query_timestamp_; -}; - class GPUTracerTester : public GPUTracer { public: explicit GPUTracerTester(gles2::GLES2Decoder* decoder) @@ -215,13 +111,11 @@ class BaseGpuTest : public GpuServiceTest { GpuServiceTest::SetUpWithGLVersion(gl_version, extensions); // Disjoint check should only be called by kTracerTypeDisjointTimer type. - if (GetTimerType() == gfx::GPUTiming::kTimerTypeDisjoint) { - EXPECT_CALL(*gl_, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(AtLeast(1)) - .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::GetIntegerv)); - } else { - EXPECT_CALL(*gl_, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(Exactly(0)); - } + if (GetTimerType() == gfx::GPUTiming::kTimerTypeDisjoint) + gl_fake_queries_.ExpectDisjointCalls(*gl_); + else + gl_fake_queries_.ExpectNoDisjointCalls(*gl_); + gpu_timing_client_ = GetGLContext()->CreateGPUTimingClient(); gpu_timing_client_->SetCpuTimeForTesting(base::Bind(&FakeCpuTime)); gl_fake_queries_.Reset(); @@ -238,34 +132,10 @@ class BaseGpuTest : public GpuServiceTest { } void ExpectTraceQueryMocks() { - if (gpu_timing_client_->IsAvailable() && - gpu_timing_client_->IsTimerOffsetAvailable()) { + if (gpu_timing_client_->IsAvailable()) { // Delegate query APIs used by GPUTrace to a GlFakeQueries - EXPECT_CALL(*gl_, GenQueries(2, NotNull())).Times(AtLeast(1)) - .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::GenQueries)); - - EXPECT_CALL(*gl_, GetQueryObjectiv(_, GL_QUERY_RESULT_AVAILABLE, - NotNull())) - .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::GetQueryObjectiv)); - - EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, _)) - .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::GetInteger64v)); - - EXPECT_CALL(*gl_, QueryCounter(_, GL_TIMESTAMP)).Times(AtLeast(2)) - .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::QueryCounter)); - - EXPECT_CALL(*gl_, GetQueryObjectui64v(_, GL_QUERY_RESULT, NotNull())) - .WillRepeatedly( - Invoke(&gl_fake_queries_, - &GlFakeQueries::GetQueryObjectui64v)); - - EXPECT_CALL(*gl_, DeleteQueries(2, NotNull())).Times(AtLeast(1)) - .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::DeleteQueries)); + const bool elapsed = (GetTimerType() == gfx::GPUTiming::kTimerTypeEXT); + gl_fake_queries_.ExpectGPUTimerQuery(*gl_, elapsed); } } @@ -282,9 +152,12 @@ class BaseGpuTest : public GpuServiceTest { const std::string& category, const std::string& name, int64 expect_start_time, int64 expect_end_time, + bool trace_service, bool trace_device) { - EXPECT_CALL(*outputter, - TraceServiceEnd(source, category, name)); + if (trace_service) { + EXPECT_CALL(*outputter, + TraceServiceEnd(source, category, name)); + } if (trace_device) { EXPECT_CALL(*outputter, @@ -298,36 +171,49 @@ class BaseGpuTest : public GpuServiceTest { } } + void ExpectDisjointOutputMocks(MockOutputter* outputter, + int64 expect_start_time, + int64 expect_end_time) { + EXPECT_CALL(*outputter, + TraceDevice(kTraceDisjoint, "DisjointEvent", _, + expect_start_time, expect_end_time)) + .Times(Exactly(1)); + } + + void ExpectNoDisjointOutputMocks(MockOutputter* outputter) { + EXPECT_CALL(*outputter, + TraceDevice(kTraceDisjoint, "DisjointEvent", _, _, _)) + .Times(Exactly(0)); + } + void ExpectOutputterMocks(MockOutputter* outputter, + bool tracing_service, bool tracing_device, GpuTracerSource source, const std::string& category, const std::string& name, int64 expect_start_time, int64 expect_end_time) { - ExpectOutputterBeginMocks(outputter, source, category, name); - bool valid_timer = tracing_device && - gpu_timing_client_->IsAvailable() && - gpu_timing_client_->IsTimerOffsetAvailable(); + if (tracing_service) + ExpectOutputterBeginMocks(outputter, source, category, name); + const bool valid_timer = tracing_device && + gpu_timing_client_->IsAvailable(); ExpectOutputterEndMocks(outputter, source, category, name, - expect_start_time, expect_end_time, valid_timer); + expect_start_time, expect_end_time, + tracing_service, valid_timer); } void ExpectTracerOffsetQueryMocks() { if (GetTimerType() != gfx::GPUTiming::kTimerTypeARB) { - EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, NotNull())) - .Times(Exactly(0)); + gl_fake_queries_.ExpectNoOffsetCalculationQuery(*gl_); } else { - EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, NotNull())) - .Times(AtMost(1)) - .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::GetInteger64v)); + gl_fake_queries_.ExpectOffsetCalculationQuery(*gl_); } } gfx::GPUTiming::TimerType GetTimerType() { return test_timer_type_; } gfx::GPUTiming::TimerType test_timer_type_; - GlFakeQueries gl_fake_queries_; + gfx::GPUTimingFake gl_fake_queries_; scoped_refptr<gfx::GPUTimingClient> gpu_timing_client_; scoped_refptr<MockOutputter> outputter_ref_; @@ -353,10 +239,9 @@ class BaseGpuTraceTest : public BaseGpuTest { const int64 expect_end_time = (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time; - if (tracing_service) - ExpectOutputterMocks(outputter_ref_.get(), tracing_device, tracer_source, - category_name, trace_name, - expect_start_time, expect_end_time); + ExpectOutputterMocks(outputter_ref_.get(), tracing_service, tracing_device, + tracer_source, category_name, trace_name, + expect_start_time, expect_end_time); if (tracing_device) ExpectTraceQueryMocks(); @@ -380,11 +265,13 @@ class BaseGpuTraceTest : public BaseGpuTest { // Shouldn't be available until the queries complete gl_fake_queries_.SetCurrentGLTime(end_timestamp - base::Time::kNanosecondsPerMicrosecond); + g_fakeCPUTime = expect_end_time - 1; if (tracing_device) EXPECT_FALSE(trace->IsAvailable()); // Now it should be available gl_fake_queries_.SetCurrentGLTime(end_timestamp); + g_fakeCPUTime = expect_end_time; EXPECT_TRUE(trace->IsAvailable()); // Proces should output expected Trace results to MockOutputter @@ -462,12 +349,26 @@ class BaseGpuTracerTest : public BaseGpuTest { outputter_ref_ = NULL; } - void DoTracerMarkersTest() { + void DoDisabledTracingTest() { ExpectTracerOffsetQueryMocks(); - EXPECT_CALL(*gl_, GetError()).Times(AtLeast(0)) - .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::GetError)); + const GpuTracerSource source = static_cast<GpuTracerSource>(0); + + MockGLES2Decoder decoder; + EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext())); + GPUTracerTester tracer(&decoder); + tracer.SetTracingEnabled(false); + tracer.SetOutputter(outputter_ref_); + + ASSERT_TRUE(tracer.BeginDecoding()); + ASSERT_TRUE(tracer.Begin("disabled_category", "disabled_name", source)); + ASSERT_TRUE(tracer.End(source)); + ASSERT_TRUE(tracer.EndDecoding()); + } + + void DoTracerMarkersTest() { + ExpectTracerOffsetQueryMocks(); + gl_fake_queries_.ExpectGetErrorCalls(*gl_); const std::string category_name("trace_category"); const std::string trace_name("trace_test"); @@ -512,7 +413,6 @@ class BaseGpuTracerTest : public BaseGpuTest { source_category, source_trace_name); ASSERT_TRUE(tracer.Begin(source_category, source_trace_name, source)); } - for (int i = 0; i < NUM_TRACER_SOURCES; ++i) { // Set times so each source has a different time. gl_fake_queries_.SetCurrentGLTime( @@ -525,35 +425,101 @@ class BaseGpuTracerTest : public BaseGpuTest { std::string source_category = category_name + num_char; std::string source_trace_name = trace_name + num_char; - bool valid_timer = gpu_timing_client_->IsAvailable() && - gpu_timing_client_->IsTimerOffsetAvailable(); + const bool valid_timer = gpu_timing_client_->IsAvailable(); const GpuTracerSource source = static_cast<GpuTracerSource>(i); ExpectOutputterEndMocks(outputter_ref_.get(), source, source_category, source_trace_name, expect_start_time + i, - expect_end_time + i, valid_timer); - + expect_end_time + i, true, valid_timer); // Check if the current category/name are correct for this source. ASSERT_EQ(source_category, tracer.CurrentCategory(source)); ASSERT_EQ(source_trace_name, tracer.CurrentName(source)); ASSERT_TRUE(tracer.End(source)); } + ASSERT_TRUE(tracer.EndDecoding()); + outputter_ref_ = NULL; + } + + void DoOngoingTracerMarkerTest() { + ExpectTracerOffsetQueryMocks(); + gl_fake_queries_.ExpectGetErrorCalls(*gl_); + + const std::string category_name("trace_category"); + const std::string trace_name("trace_test"); + const GpuTracerSource source = static_cast<GpuTracerSource>(0); + const int64 offset_time = 3231; + const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond; + const int64 expect_start_time = + (start_timestamp / base::Time::kNanosecondsPerMicrosecond) + + offset_time; + const bool valid_timer = gpu_timing_client_->IsAvailable(); + + MockGLES2Decoder decoder; + EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext())); + GPUTracerTester tracer(&decoder); + tracer.SetOutputter(outputter_ref_); + // Create trace marker while traces are disabled. + gl_fake_queries_.SetCurrentGLTime(start_timestamp); + g_fakeCPUTime = expect_start_time; + + tracer.SetTracingEnabled(false); + ASSERT_TRUE(tracer.BeginDecoding()); + ASSERT_TRUE(tracer.Begin(category_name, trace_name, source)); ASSERT_TRUE(tracer.EndDecoding()); - outputter_ref_ = NULL; + // Enable traces now. + tracer.SetTracingEnabled(true); + ExpectTraceQueryMocks(); + + // trace should happen when decoding begins, at time start+1. + gl_fake_queries_.SetCurrentGLTime( + start_timestamp + + (1 * base::Time::kNanosecondsPerMicrosecond)); + g_fakeCPUTime = expect_start_time + 1; + ASSERT_TRUE(tracer.BeginDecoding()); + + // End decoding at time start+2. + ExpectOutputterEndMocks(outputter_ref_.get(), source, category_name, + trace_name, expect_start_time + 1, + expect_start_time + 2, true, valid_timer); + gl_fake_queries_.SetCurrentGLTime( + start_timestamp + + (2 * base::Time::kNanosecondsPerMicrosecond)); + g_fakeCPUTime = expect_start_time + 2; + ASSERT_TRUE(tracer.EndDecoding()); + + // Begin decoding again at time start+3. + gl_fake_queries_.SetCurrentGLTime( + start_timestamp + + (3 * base::Time::kNanosecondsPerMicrosecond)); + g_fakeCPUTime = expect_start_time + 3; + ASSERT_TRUE(tracer.BeginDecoding()); + + // End trace at time start+4 + gl_fake_queries_.SetCurrentGLTime( + start_timestamp + + (4 * base::Time::kNanosecondsPerMicrosecond)); + g_fakeCPUTime = expect_start_time + 4; + ExpectOutputterEndMocks(outputter_ref_.get(), source, category_name, + trace_name, expect_start_time + 3, + expect_start_time + 4, true, valid_timer); + ASSERT_TRUE(tracer.End(source)); + + // Increment time before we end decoding to test trace does not stop here. + gl_fake_queries_.SetCurrentGLTime( + start_timestamp + + (5 * base::Time::kNanosecondsPerMicrosecond)); + g_fakeCPUTime = expect_start_time + 5; + ASSERT_TRUE(tracer.EndDecoding()); } void DoDisjointTest() { // Cause a disjoint in a middle of a trace and expect no output calls. ExpectTracerOffsetQueryMocks(); + gl_fake_queries_.ExpectGetErrorCalls(*gl_); - EXPECT_CALL(*gl_, GetError()).Times(AtLeast(0)) - .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::GetError)); - - const GpuTracerSource tracer_source = kTraceGroupMarker; const std::string category_name("trace_category"); const std::string trace_name("trace_test"); const GpuTracerSource source = static_cast<GpuTracerSource>(0); @@ -580,7 +546,7 @@ class BaseGpuTracerTest : public BaseGpuTest { ExpectTraceQueryMocks(); - ExpectOutputterBeginMocks(outputter_ref_.get(), tracer_source, + ExpectOutputterBeginMocks(outputter_ref_.get(), source, category_name, trace_name); ASSERT_TRUE(tracer.Begin(category_name, trace_name, source)); @@ -589,7 +555,7 @@ class BaseGpuTracerTest : public BaseGpuTest { // Create GPUTimingClient to make sure disjoint value is correct. This // should not interfere with the tracer's disjoint value. - scoped_refptr<gfx::GPUTimingClient> disjoint_client = + scoped_refptr<gfx::GPUTimingClient> disjoint_client = GetGLContext()->CreateGPUTimingClient(); // We assert here based on the disjoint_client because if disjoints are not @@ -598,15 +564,72 @@ class BaseGpuTracerTest : public BaseGpuTest { gl_fake_queries_.SetDisjoint(); ASSERT_TRUE(disjoint_client->CheckAndResetTimerErrors()); - ExpectOutputterEndMocks(outputter_ref_.get(), tracer_source, + ExpectDisjointOutputMocks(outputter_ref_.get(), + expect_start_time, expect_end_time); + + ExpectOutputterEndMocks(outputter_ref_.get(), source, category_name, trace_name, - expect_start_time, expect_end_time, false); + expect_start_time, expect_end_time, true, false); ASSERT_TRUE(tracer.End(source)); ASSERT_TRUE(tracer.EndDecoding()); outputter_ref_ = NULL; } + + void DoOutsideDisjointTest() { + ExpectTracerOffsetQueryMocks(); + gl_fake_queries_.ExpectGetErrorCalls(*gl_); + + const std::string category_name("trace_category"); + const std::string trace_name("trace_test"); + const GpuTracerSource source = static_cast<GpuTracerSource>(0); + const int64 offset_time = 3231; + const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond; + const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond; + const int64 expect_start_time = + (start_timestamp / base::Time::kNanosecondsPerMicrosecond) + + offset_time; + const int64 expect_end_time = + (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time; + + MockGLES2Decoder decoder; + EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext())); + EXPECT_CALL(decoder, MakeCurrent()).WillRepeatedly(Return(true)); + GPUTracerTester tracer(&decoder); + tracer.SetOutputter(outputter_ref_); + + // Start a trace before tracing is enabled. + tracer.SetTracingEnabled(false); + ASSERT_TRUE(tracer.BeginDecoding()); + ASSERT_TRUE(tracer.Begin(category_name, trace_name, source)); + ASSERT_TRUE(tracer.EndDecoding()); + + // Enabling traces now, trace should be ongoing. + tracer.SetTracingEnabled(true); + gl_fake_queries_.SetCurrentGLTime(start_timestamp); + g_fakeCPUTime = expect_start_time; + + // Disjoints before we start tracing anything should not do anything. + ExpectNoDisjointOutputMocks(outputter_ref_.get()); + gl_fake_queries_.SetDisjoint(); + + ExpectTraceQueryMocks(); + ExpectOutputterBeginMocks(outputter_ref_.get(), source, + category_name, trace_name); + ASSERT_TRUE(tracer.BeginDecoding()); + + // Set times so each source has a different time. + gl_fake_queries_.SetCurrentGLTime(end_timestamp); + g_fakeCPUTime = expect_end_time; + + ExpectOutputterEndMocks(outputter_ref_.get(), source, category_name, + trace_name, expect_start_time, + expect_end_time, true, true); + + ASSERT_TRUE(tracer.End(source)); + ASSERT_TRUE(tracer.EndDecoding()); + } }; class InvalidTimerTracerTest : public BaseGpuTracerTest { @@ -648,6 +671,22 @@ TEST_F(GpuDisjointTimerTracerTest, DisjointTimerBasicTracerTest) { DoBasicTracerTest(); } +TEST_F(InvalidTimerTracerTest, InvalidTimerDisabledTest) { + DoDisabledTracingTest(); +} + +TEST_F(GpuEXTTimerTracerTest, EXTTimerDisabledTest) { + DoDisabledTracingTest(); +} + +TEST_F(GpuARBTimerTracerTest, ARBTimerDisabledTest) { + DoDisabledTracingTest(); +} + +TEST_F(GpuDisjointTimerTracerTest, DisjointTimerDisabledTest) { + DoDisabledTracingTest(); +} + TEST_F(InvalidTimerTracerTest, InvalidTimerTracerMarkersTest) { DoTracerMarkersTest(); } @@ -656,7 +695,7 @@ TEST_F(GpuEXTTimerTracerTest, EXTTimerTracerMarkersTest) { DoTracerMarkersTest(); } -TEST_F(GpuARBTimerTracerTest, ARBTimerBasicTracerMarkersTest) { +TEST_F(GpuARBTimerTracerTest, ARBTimerTracerMarkersTest) { DoTracerMarkersTest(); } @@ -664,10 +703,30 @@ TEST_F(GpuDisjointTimerTracerTest, DisjointTimerBasicTracerMarkersTest) { DoTracerMarkersTest(); } +TEST_F(InvalidTimerTracerTest, InvalidTimerOngoingTracerMarkersTest) { + DoOngoingTracerMarkerTest(); +} + +TEST_F(GpuEXTTimerTracerTest, EXTTimerOngoingTracerMarkersTest) { + DoOngoingTracerMarkerTest(); +} + +TEST_F(GpuARBTimerTracerTest, ARBTimerBasicOngoingTracerMarkersTest) { + DoOngoingTracerMarkerTest(); +} + +TEST_F(GpuDisjointTimerTracerTest, DisjointTimerOngoingTracerMarkersTest) { + DoOngoingTracerMarkerTest(); +} + TEST_F(GpuDisjointTimerTracerTest, DisjointTimerDisjointTraceTest) { DoDisjointTest(); } +TEST_F(GpuDisjointTimerTracerTest, NonrelevantDisjointTraceTest) { + DoOutsideDisjointTest(); +} + class GPUTracerTest : public GpuServiceTest { protected: void SetUp() override { diff --git a/chromium/gpu/command_buffer/service/image_factory.cc b/chromium/gpu/command_buffer/service/image_factory.cc index ce88f29ed61..f940498abf7 100644 --- a/chromium/gpu/command_buffer/service/image_factory.cc +++ b/chromium/gpu/command_buffer/service/image_factory.cc @@ -84,6 +84,7 @@ bool ImageFactory::IsGpuMemoryBufferFormatSupported( return capabilities.texture_format_etc1; case gfx::GpuMemoryBuffer::R_8: return capabilities.texture_rg; + case gfx::GpuMemoryBuffer::RGBA_4444: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::YUV_420: @@ -108,6 +109,7 @@ bool ImageFactory::IsImageSizeValidForGpuMemoryBufferFormat( // by the block size. return size.width() % 4 == 0 && size.height() % 4 == 0; case gfx::GpuMemoryBuffer::R_8: + case gfx::GpuMemoryBuffer::RGBA_4444: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: case gfx::GpuMemoryBuffer::RGBX_8888: diff --git a/chromium/gpu/command_buffer/service/in_process_command_buffer.cc b/chromium/gpu/command_buffer/service/in_process_command_buffer.cc index 0b1ebb3c59f..12c01c7e285 100644 --- a/chromium/gpu/command_buffer/service/in_process_command_buffer.cc +++ b/chromium/gpu/command_buffer/service/in_process_command_buffer.cc @@ -39,6 +39,7 @@ #include "ui/gfx/geometry/size.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_image.h" +#include "ui/gl/gl_image_shared_memory.h" #include "ui/gl/gl_share_group.h" #if defined(OS_ANDROID) @@ -195,27 +196,7 @@ base::LazyInstance<SyncPointManagerWrapper> g_sync_point_manager = base::SharedMemoryHandle ShareToGpuThread( base::SharedMemoryHandle source_handle) { -#if defined(OS_WIN) - // Windows needs to explicitly duplicate the handle to current process. - base::SharedMemoryHandle target_handle; - if (!DuplicateHandle(GetCurrentProcess(), - source_handle, - GetCurrentProcess(), - &target_handle, - FILE_GENERIC_READ | FILE_GENERIC_WRITE, - FALSE, - 0)) { - return base::SharedMemory::NULLHandle(); - } - - return target_handle; -#else - int duped_handle = HANDLE_EINTR(dup(source_handle.fd)); - if (duped_handle < 0) - return base::SharedMemory::NULLHandle(); - - return base::FileDescriptor(duped_handle, true); -#endif + return base::SharedMemory::DuplicateHandle(source_handle); } gfx::GpuMemoryBufferHandle ShareGpuMemoryBufferToGpuThread( @@ -240,6 +221,21 @@ gfx::GpuMemoryBufferHandle ShareGpuMemoryBufferToGpuThread( } } +scoped_refptr<InProcessCommandBuffer::Service> GetInitialService( + const scoped_refptr<InProcessCommandBuffer::Service>& service) { + if (service) + return service; + + // Call base::ThreadTaskRunnerHandle::IsSet() to ensure that it is + // instantiated before we create the GPU thread, otherwise shutdown order will + // delete the ThreadTaskRunnerHandle before the GPU thread's message loop, + // and when the message loop is shutdown, it will recreate + // ThreadTaskRunnerHandle, which will re-add a new task to the, AtExitManager, + // which causes a deadlock because it's already locked. + base::ThreadTaskRunnerHandle::IsSet(); + return g_default_service.Get().gpu_thread; +} + } // anonyous namespace InProcessCommandBuffer::Service::Service() {} @@ -290,7 +286,7 @@ InProcessCommandBuffer::InProcessCommandBuffer( last_put_offset_(-1), gpu_memory_buffer_manager_(nullptr), flush_event_(false, false), - service_(service.get() ? service : g_default_service.Get().gpu_thread), + service_(GetInitialService(service)), gpu_thread_weak_ptr_factory_(this) { DCHECK(service_.get()); next_image_id_.GetNext(); @@ -395,7 +391,7 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( DCHECK(params.size.width() >= 0 && params.size.height() >= 0); TransferBufferManager* manager = new TransferBufferManager(); - transfer_buffer_manager_.reset(manager); + transfer_buffer_manager_ = manager; manager->Initialize(); scoped_ptr<CommandBufferService> command_buffer( @@ -511,7 +507,6 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( base::Unretained(this))); image_factory_ = params.image_factory; - params.capabilities->image = params.capabilities->image && image_factory_; return true; } @@ -665,17 +660,28 @@ void InProcessCommandBuffer::SetGetBuffer(int32 shm_id) { if (last_state_.error != gpu::error::kNoError) return; - { - base::AutoLock lock(command_buffer_lock_); - command_buffer_->SetGetBuffer(shm_id); - last_put_offset_ = 0; - } + base::WaitableEvent completion(true, false); + base::Closure task = + base::Bind(&InProcessCommandBuffer::SetGetBufferOnGpuThread, + base::Unretained(this), shm_id, &completion); + QueueTask(task); + completion.Wait(); + { base::AutoLock lock(state_after_last_flush_lock_); state_after_last_flush_ = command_buffer_->GetLastState(); } } +void InProcessCommandBuffer::SetGetBufferOnGpuThread( + int32 shm_id, + base::WaitableEvent* completion) { + base::AutoLock lock(command_buffer_lock_); + command_buffer_->SetGetBuffer(shm_id); + last_put_offset_ = 0; + completion->Signal(); +} + scoped_refptr<Buffer> InProcessCommandBuffer::CreateTransferBuffer(size_t size, int32* id) { CheckSequencedThread(); @@ -760,17 +766,39 @@ void InProcessCommandBuffer::CreateImageOnGpuThread( return; } - // Note: this assumes that client ID is always 0. - const int kClientId = 0; - - DCHECK(image_factory_); - scoped_refptr<gfx::GLImage> image = - image_factory_->CreateImageForGpuMemoryBuffer( - handle, size, format, internalformat, kClientId); - if (!image.get()) - return; - - image_manager->AddImage(image.get(), id); + switch (handle.type) { + case gfx::SHARED_MEMORY_BUFFER: { + scoped_refptr<gfx::GLImageSharedMemory> image( + new gfx::GLImageSharedMemory(size, internalformat)); + if (!image->Initialize(handle, format)) { + LOG(ERROR) << "Failed to initialize image."; + return; + } + + image_manager->AddImage(image.get(), id); + break; + } + default: { + if (!image_factory_) { + LOG(ERROR) << "Image factory missing but required by buffer type."; + return; + } + + // Note: this assumes that client ID is always 0. + const int kClientId = 0; + + scoped_refptr<gfx::GLImage> image = + image_factory_->CreateImageForGpuMemoryBuffer( + handle, size, format, internalformat, kClientId); + if (!image.get()) { + LOG(ERROR) << "Failed to create image for buffer."; + return; + } + + image_manager->AddImage(image.get(), id); + break; + } + } } void InProcessCommandBuffer::DestroyImage(int32 id) { @@ -910,6 +938,12 @@ uint32 InProcessCommandBuffer::CreateStreamTexture(uint32 texture_id) { void InProcessCommandBuffer::SetLock(base::Lock*) { } +bool InProcessCommandBuffer::IsGpuChannelLost() { + // There is no such channel to lose for in-process contexts. This only + // makes sense for out-of-process command buffers. + return false; +} + uint32 InProcessCommandBuffer::CreateStreamTextureOnGpuThread( uint32 client_texture_id) { #if defined(OS_ANDROID) diff --git a/chromium/gpu/command_buffer/service/in_process_command_buffer.h b/chromium/gpu/command_buffer/service/in_process_command_buffer.h index b3f6eb806d7..bfc0867cea1 100644 --- a/chromium/gpu/command_buffer/service/in_process_command_buffer.h +++ b/chromium/gpu/command_buffer/service/in_process_command_buffer.h @@ -121,6 +121,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, void SetSurfaceVisible(bool visible) override; uint32 CreateStreamTexture(uint32 texture_id) override; void SetLock(base::Lock*) override; + bool IsGpuChannelLost() override; // The serializer interface to the GPU service (i.e. thread). class Service { @@ -209,6 +210,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, gfx::GpuMemoryBuffer::Format format, uint32 internalformat); void DestroyImageOnGpuThread(int32 id); + void SetGetBufferOnGpuThread(int32 shm_id, base::WaitableEvent* completion); // Callbacks: void OnContextLost(); @@ -220,7 +222,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, // Members accessed on the gpu thread (possibly with the exception of // creation): bool context_lost_; - scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; + scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; scoped_ptr<GpuScheduler> gpu_scheduler_; scoped_ptr<gles2::GLES2Decoder> decoder_; scoped_refptr<gfx::GLContext> context_; diff --git a/chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc b/chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc index 0e064d4b488..3e14b76dc71 100644 --- a/chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc @@ -47,29 +47,19 @@ class MailboxManagerTest : public GpuServiceTest { texture->SetTarget(NULL, target, max_level); } - void SetLevelInfo( - Texture* texture, - GLenum target, - GLint level, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLenum format, - GLenum type, - bool cleared) { - texture->SetLevelInfo(NULL, - target, - level, - internal_format, - width, - height, - depth, - border, - format, - type, - cleared); + void SetLevelInfo(Texture* texture, + GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const gfx::Rect& cleared_rect) { + texture->SetLevelInfo(NULL, target, level, internal_format, width, height, + depth, border, format, type, cleared_rect); } void SetLevelCleared(Texture* texture, @@ -211,17 +201,8 @@ class MailboxManagerSyncTest : public MailboxManagerTest { const GLsizei levels_needed = TextureManager::ComputeMipMapCount( GL_TEXTURE_2D, kMaxTextureWidth, kMaxTextureHeight, kMaxTextureDepth); SetTarget(texture, GL_TEXTURE_2D, levels_needed); - SetLevelInfo(texture, - GL_TEXTURE_2D, - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + SetLevelInfo(texture, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, + GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); SetParameter(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR); SetParameter(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR); return texture; @@ -352,17 +333,8 @@ TEST_F(MailboxManagerSyncTest, ProduceConsumeResize) { EXPECT_EQ(kNewTextureId, new_texture->service_id()); // Resize original texture - SetLevelInfo(texture, - GL_TEXTURE_2D, - 0, - GL_RGBA, - 16, - 32, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + SetLevelInfo(texture, GL_TEXTURE_2D, 0, GL_RGBA, 16, 32, 1, 0, GL_RGBA, + GL_UNSIGNED_BYTE, gfx::Rect(16, 32)); // Should have been orphaned EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); @@ -379,17 +351,8 @@ TEST_F(MailboxManagerSyncTest, ProduceConsumeResize) { // Should have gotten a new attachment EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) != NULL); // Resize original texture again.... - SetLevelInfo(texture, - GL_TEXTURE_2D, - 0, - GL_RGBA, - 64, - 64, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + SetLevelInfo(texture, GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 1, 0, GL_RGBA, + GL_UNSIGNED_BYTE, gfx::Rect(64, 64)); // ...and immediately delete the texture which should save the changes. SetupUpdateTexParamExpectations( kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT); @@ -624,17 +587,8 @@ TEST_F(MailboxManagerSyncTest, SyncIncompleteTexture) { EXPECT_FALSE(new_texture->IsDefined()); // Change cleared to false. - SetLevelInfo(texture, - GL_TEXTURE_2D, - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + SetLevelInfo(texture, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, + GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); SetParameter(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR); SetParameter(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR); EXPECT_TRUE(texture->IsDefined()); diff --git a/chromium/gpu/command_buffer/service/memory_program_cache.cc b/chromium/gpu/command_buffer/service/memory_program_cache.cc index cf3b0ca7d8d..74809a98d73 100644 --- a/chromium/gpu/command_buffer/service/memory_program_cache.cc +++ b/chromium/gpu/command_buffer/service/memory_program_cache.cc @@ -5,6 +5,7 @@ #include "gpu/command_buffer/service/memory_program_cache.h" #include "base/base64.h" +#include "base/callback.h" #include "base/command_line.h" #include "base/metrics/histogram.h" #include "base/sha1.h" diff --git a/chromium/gpu/command_buffer/service/program_manager.cc b/chromium/gpu/command_buffer/service/program_manager.cc index 9a15f820515..b1167b69696 100644 --- a/chromium/gpu/command_buffer/service/program_manager.cc +++ b/chromium/gpu/command_buffer/service/program_manager.cc @@ -841,7 +841,7 @@ void Program::GetCorrectedUniformData( found = uniform->findInfoByMappedName(name, &info, original_name); if (found) { const std::string kArraySpec("[0]"); - if (info->arraySize > 0 && !EndsWith(name, kArraySpec, true)) { + if (info->arraySize > 0 && !base::EndsWith(name, kArraySpec, true)) { *corrected_name = name + kArraySpec; *original_name += kArraySpec; } else { @@ -1188,6 +1188,8 @@ bool Program::DetectVaryingsMismatch(std::string* conflicting_name) const { const VaryingMap* vertex_varyings = &(attached_shaders_[0]->varying_map()); const VaryingMap* fragment_varyings = &(attached_shaders_[1]->varying_map()); + int shader_version = attached_shaders_[0]->shader_version(); + for (VaryingMap::const_iterator iter = fragment_varyings->begin(); iter != fragment_varyings->end(); ++iter) { const std::string& name = iter->first; @@ -1203,7 +1205,7 @@ bool Program::DetectVaryingsMismatch(std::string* conflicting_name) const { continue; } - if (!hit->second.isSameVaryingAtLinkTime(iter->second)) { + if (!hit->second.isSameVaryingAtLinkTime(iter->second, shader_version)) { *conflicting_name = name; return true; } diff --git a/chromium/gpu/command_buffer/service/query_manager.cc b/chromium/gpu/command_buffer/service/query_manager.cc index c74a65000c3..3de501a4499 100644 --- a/chromium/gpu/command_buffer/service/query_manager.cc +++ b/chromium/gpu/command_buffer/service/query_manager.cc @@ -16,7 +16,9 @@ #include "gpu/command_buffer/service/error_state.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "ui/gl/gl_context.h" #include "ui/gl/gl_fence.h" +#include "ui/gl/gpu_timing.h" namespace gpu { namespace gles2 { @@ -448,6 +450,61 @@ void CommandsCompletedQuery::Destroy(bool have_context) { CommandsCompletedQuery::~CommandsCompletedQuery() {} +class TimeElapsedQuery : public QueryManager::Query { + public: + TimeElapsedQuery(QueryManager* manager, + GLenum target, + int32 shm_id, + uint32 shm_offset); + + // Overridden from QueryManager::Query: + bool Begin() override; + bool End(base::subtle::Atomic32 submit_count) override; + bool Process(bool did_finish) override; + void Destroy(bool have_context) override; + + protected: + ~TimeElapsedQuery() override; + + private: + scoped_ptr<gfx::GPUTimer> gpu_timer_; +}; + +TimeElapsedQuery::TimeElapsedQuery(QueryManager* manager, + GLenum target, + int32 shm_id, + uint32 shm_offset) + : Query(manager, target, shm_id, shm_offset), + gpu_timer_(manager->CreateGPUTimer(true)) {} + +bool TimeElapsedQuery::Begin() { + gpu_timer_->Start(); + return true; +} + +bool TimeElapsedQuery::End(base::subtle::Atomic32 submit_count) { + gpu_timer_->End(); + return AddToPendingQueue(submit_count); +} + +bool TimeElapsedQuery::Process(bool did_finish) { + if (!gpu_timer_->IsAvailable()) + return true; + + const uint64_t nano_seconds = + gpu_timer_->GetDeltaElapsed() * base::Time::kNanosecondsPerMicrosecond; + return MarkAsCompleted(nano_seconds); +} + +void TimeElapsedQuery::Destroy(bool have_context) { + if (gpu_timer_.get()) { + gpu_timer_->Destroy(have_context); + gpu_timer_.reset(); + } +} + +TimeElapsedQuery::~TimeElapsedQuery() {} + QueryManager::QueryManager( GLES2Decoder* decoder, FeatureInfo* feature_info) @@ -461,6 +518,13 @@ QueryManager::QueryManager( query_count_(0) { DCHECK(!(use_arb_occlusion_query_for_occlusion_query_boolean_ && use_arb_occlusion_query2_for_occlusion_query_boolean_)); + DCHECK(decoder); + gfx::GLContext* context = decoder_->GetGLContext(); + if (context) { + gpu_timing_client_ = context->CreateGPUTimingClient(); + } else { + gpu_timing_client_ = new gfx::GPUTimingClient(); + } } QueryManager::~QueryManager() { @@ -506,6 +570,9 @@ QueryManager::Query* QueryManager::CreateQuery( case GL_COMMANDS_COMPLETED_CHROMIUM: query = new CommandsCompletedQuery(this, target, shm_id, shm_offset); break; + case GL_TIME_ELAPSED: + query = new TimeElapsedQuery(this, target, shm_id, shm_offset); + break; default: { GLuint service_id = 0; glGenQueries(1, &service_id); @@ -521,6 +588,14 @@ QueryManager::Query* QueryManager::CreateQuery( return query.get(); } +scoped_ptr<gfx::GPUTimer> QueryManager::CreateGPUTimer(bool elapsed_time) { + return gpu_timing_client_->CreateGPUTimer(elapsed_time); +} + +bool QueryManager::GPUTimingAvailable() { + return gpu_timing_client_->IsAvailable(); +} + void QueryManager::GenQueries(GLsizei n, const GLuint* queries) { DCHECK_GE(n, 0); for (GLsizei i = 0; i < n; ++i) { diff --git a/chromium/gpu/command_buffer/service/query_manager.h b/chromium/gpu/command_buffer/service/query_manager.h index 5f14929272c..e453d03f818 100644 --- a/chromium/gpu/command_buffer/service/query_manager.h +++ b/chromium/gpu/command_buffer/service/query_manager.h @@ -16,6 +16,11 @@ #include "gpu/command_buffer/service/feature_info.h" #include "gpu/gpu_export.h" +namespace gfx { + class GPUTimer; + class GPUTimingClient; +} + namespace gpu { class GLES2Decoder; @@ -188,6 +193,9 @@ class GPU_EXPORT QueryManager { return decoder_; } + scoped_ptr<gfx::GPUTimer> CreateGPUTimer(bool elapsed_time); + bool GPUTimingAvailable(); + void GenQueries(GLsizei n, const GLuint* queries); bool IsValidQuery(GLuint id); @@ -241,6 +249,9 @@ class GPU_EXPORT QueryManager { // Async pixel transfer queries waiting for completion. QueryQueue pending_transfer_queries_; + // Used for timer queries. + scoped_refptr<gfx::GPUTimingClient> gpu_timing_client_; + DISALLOW_COPY_AND_ASSIGN(QueryManager); }; diff --git a/chromium/gpu/command_buffer/service/shader_translator.cc b/chromium/gpu/command_buffer/service/shader_translator.cc index dd1c710c0fe..04e12276afb 100644 --- a/chromium/gpu/command_buffer/service/shader_translator.cc +++ b/chromium/gpu/command_buffer/service/shader_translator.cc @@ -126,7 +126,7 @@ bool ShaderTranslator::Init( if (shader_spec == SH_WEBGL2_SPEC || gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGLCoreProfile) { - shader_output = SH_GLSL_CORE_OUTPUT; + shader_output = SH_GLSL_410_CORE_OUTPUT; } else { shader_output = SH_GLSL_COMPATIBILITY_OUTPUT; } @@ -195,6 +195,9 @@ bool ShaderTranslator::Translate(const std::string& shader_source, *info_log = ShGetInfoLog(compiler_); } + // We don't need results in the compiler anymore. + ShClearResults(compiler_); + return success; } diff --git a/chromium/gpu/command_buffer/service/shader_translator.h b/chromium/gpu/command_buffer/service/shader_translator.h index ac431e3e615..858014dc049 100644 --- a/chromium/gpu/command_buffer/service/shader_translator.h +++ b/chromium/gpu/command_buffer/service/shader_translator.h @@ -118,7 +118,7 @@ class GPU_EXPORT ShaderTranslator ShHandle compiler_; bool implementation_is_glsl_es_; ShCompileOptions driver_bug_workarounds_; - ObserverList<DestructionObserver> destruction_observers_; + base::ObserverList<DestructionObserver> destruction_observers_; }; } // namespace gles2 diff --git a/chromium/gpu/command_buffer/service/shader_translator_unittest.cc b/chromium/gpu/command_buffer/service/shader_translator_unittest.cc index b9efe24707b..5f6173818f9 100644 --- a/chromium/gpu/command_buffer/service/shader_translator_unittest.cc +++ b/chromium/gpu/command_buffer/service/shader_translator_unittest.cc @@ -282,39 +282,6 @@ TEST_F(ShaderTranslatorTest, GetUniforms) { EXPECT_STREQ("bar[1].foo.color[0]", original_name.c_str()); } -#if defined(OS_MACOSX) -TEST_F(ShaderTranslatorTest, BuiltInFunctionEmulation) { - // This test might become invalid in the future when ANGLE Translator is no - // longer emulate dot(float, float) in Mac, or the emulated function name is - // no longer webgl_dot_emu. - const char* shader = - "void main() {\n" - " gl_Position = vec4(dot(1.0, 1.0), 1.0, 1.0, 1.0);\n" - "}"; - - std::string info_log, translated_source; - int shader_version; - AttributeMap attrib_map; - UniformMap uniform_map; - VaryingMap varying_map; - NameMap name_map; - EXPECT_TRUE(vertex_translator_->Translate(shader, - &info_log, - &translated_source, - &shader_version, - &attrib_map, - &uniform_map, - &varying_map, - &name_map)); - // Info log must be NULL. - EXPECT_TRUE(info_log.empty()); - // Translated shader must be valid and non-empty. - ASSERT_FALSE(translated_source.empty()); - EXPECT_TRUE(strstr(translated_source.c_str(), - "webgl_dot_emu") != NULL); -} -#endif - TEST_F(ShaderTranslatorTest, OptionsString) { scoped_refptr<ShaderTranslator> translator_1 = new ShaderTranslator(); scoped_refptr<ShaderTranslator> translator_2 = new ShaderTranslator(); diff --git a/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc b/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc index 174edaa6ee9..caf3fb671d3 100644 --- a/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc +++ b/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc @@ -25,9 +25,12 @@ class GLImageImpl : public gfx::GLImage { // implement gfx::GLImage void Destroy(bool have_context) override; gfx::Size GetSize() override; + unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override; - bool CopyTexImage(unsigned target) override; + bool CopyTexSubImage(unsigned target, + const gfx::Point& offset, + const gfx::Rect& rect) override; void WillUseTexImage() override; void DidUseTexImage() override {} void WillModifyTexImage() override {} @@ -64,6 +67,10 @@ gfx::Size GLImageImpl::GetSize() { return gfx::Size(); } +unsigned GLImageImpl::GetInternalFormat() { + return GL_RGBA; +} + bool GLImageImpl::BindTexImage(unsigned target) { NOTREACHED(); return false; @@ -73,7 +80,9 @@ void GLImageImpl::ReleaseTexImage(unsigned target) { NOTREACHED(); } -bool GLImageImpl::CopyTexImage(unsigned target) { +bool GLImageImpl::CopyTexSubImage(unsigned target, + const gfx::Point& offset, + const gfx::Rect& rect) { return false; } @@ -126,17 +135,9 @@ GLuint StreamTextureManagerInProcess::CreateStreamTexture( gfx::Size size = gl_image->GetSize(); texture_manager->SetTarget(texture, GL_TEXTURE_EXTERNAL_OES); - texture_manager->SetLevelInfo(texture, - GL_TEXTURE_EXTERNAL_OES, - 0, - GL_RGBA, - size.width(), - size.height(), - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + texture_manager->SetLevelInfo(texture, GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA, + size.width(), size.height(), 1, 0, GL_RGBA, + GL_UNSIGNED_BYTE, gfx::Rect(size)); texture_manager->SetLevelImage( texture, GL_TEXTURE_EXTERNAL_OES, 0, gl_image.get()); diff --git a/chromium/gpu/command_buffer/service/test_helper.cc b/chromium/gpu/command_buffer/service/test_helper.cc index e2fd7463f12..308ab8e8ffd 100644 --- a/chromium/gpu/command_buffer/service/test_helper.cc +++ b/chromium/gpu/command_buffer/service/test_helper.cc @@ -8,6 +8,7 @@ #include <string> #include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" #include "base/strings/string_tokenizer.h" #include "gpu/command_buffer/service/buffer_manager.h" #include "gpu/command_buffer/service/error_state_mock.h" @@ -364,7 +365,8 @@ void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( // Persistent storage is needed for the split extension string. split_extensions_.clear(); if (extensions) { - Tokenize(extensions, " ", &split_extensions_); + split_extensions_ = base::SplitString( + extensions, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); } gfx::GLVersionInfo gl_info(gl_version, gl_renderer, extensions); @@ -723,26 +725,24 @@ void TestHelper::SetupShader( void TestHelper::DoBufferData( ::gfx::MockGLInterface* gl, MockErrorState* error_state, - BufferManager* manager, Buffer* buffer, GLsizeiptr size, GLenum usage, - const GLvoid* data, GLenum error) { + BufferManager* manager, Buffer* buffer, GLenum target, GLsizeiptr size, + GLenum usage, const GLvoid* data, GLenum error) { EXPECT_CALL(*error_state, CopyRealGLErrorsToWrapper(_, _, _)) .Times(1) .RetiresOnSaturation(); if (manager->IsUsageClientSideArray(usage)) { - EXPECT_CALL(*gl, BufferData( - buffer->target(), 0, _, usage)) + EXPECT_CALL(*gl, BufferData(target, 0, _, usage)) .Times(1) .RetiresOnSaturation(); } else { - EXPECT_CALL(*gl, BufferData( - buffer->target(), size, _, usage)) + EXPECT_CALL(*gl, BufferData(target, size, _, usage)) .Times(1) .RetiresOnSaturation(); } EXPECT_CALL(*error_state, PeekGLError(_, _, _)) .WillOnce(Return(error)) .RetiresOnSaturation(); - manager->DoBufferData(error_state, buffer, size, usage, data); + manager->DoBufferData(error_state, buffer, target, size, usage, data); } void TestHelper::SetTexParameteriWithExpectations( diff --git a/chromium/gpu/command_buffer/service/test_helper.h b/chromium/gpu/command_buffer/service/test_helper.h index a074deb8846..a7eaec2afe3 100644 --- a/chromium/gpu/command_buffer/service/test_helper.h +++ b/chromium/gpu/command_buffer/service/test_helper.h @@ -106,8 +106,8 @@ class TestHelper { static void DoBufferData( ::gfx::MockGLInterface* gl, MockErrorState* error_state, - BufferManager* manager, Buffer* buffer, GLsizeiptr size, GLenum usage, - const GLvoid* data, GLenum error); + BufferManager* manager, Buffer* buffer, GLenum target, GLsizeiptr size, + GLenum usage, const GLvoid* data, GLenum error); static void SetTexParameteriWithExpectations( ::gfx::MockGLInterface* gl, MockErrorState* error_state, diff --git a/chromium/gpu/command_buffer/service/texture_definition.cc b/chromium/gpu/command_buffer/service/texture_definition.cc index 311bb41ef6c..c19b5d3d47c 100644 --- a/chromium/gpu/command_buffer/service/texture_definition.cc +++ b/chromium/gpu/command_buffer/service/texture_definition.cc @@ -33,9 +33,12 @@ class GLImageSync : public gfx::GLImage { // Implement GLImage. void Destroy(bool have_context) override; gfx::Size GetSize() override; + unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override; - bool CopyTexImage(unsigned target) override; + bool CopyTexSubImage(unsigned target, + const gfx::Point& offset, + const gfx::Rect& rect) override; void WillUseTexImage() override; void WillModifyTexImage() override; void DidModifyTexImage() override; @@ -75,6 +78,10 @@ gfx::Size GLImageSync::GetSize() { return size_; } +unsigned GLImageSync::GetInternalFormat() { + return GL_RGBA; +} + bool GLImageSync::BindTexImage(unsigned target) { NOTREACHED(); return false; @@ -84,7 +91,9 @@ void GLImageSync::ReleaseTexImage(unsigned target) { NOTREACHED(); } -bool GLImageSync::CopyTexImage(unsigned target) { +bool GLImageSync::CopyTexSubImage(unsigned target, + const gfx::Point& offset, + const gfx::Rect& rect) { return false; } @@ -302,8 +311,7 @@ TextureDefinition::LevelInfo::LevelInfo() depth(0), border(0), format(0), - type(0), - cleared(false) { + type(0) { } TextureDefinition::LevelInfo::LevelInfo(GLenum target, @@ -314,7 +322,7 @@ TextureDefinition::LevelInfo::LevelInfo(GLenum target, GLint border, GLenum format, GLenum type, - bool cleared) + const gfx::Rect& cleared_rect) : target(target), internal_format(internal_format), width(width), @@ -323,7 +331,8 @@ TextureDefinition::LevelInfo::LevelInfo(GLenum target, border(border), format(format), type(type), - cleared(cleared) {} + cleared_rect(cleared_rect) { +} TextureDefinition::LevelInfo::~LevelInfo() {} @@ -370,7 +379,7 @@ TextureDefinition::TextureDefinition( const Texture::LevelInfo& level = first_face.level_infos[0]; level_info_ = LevelInfo(level.target, level.internal_format, level.width, level.height, level.depth, level.border, level.format, - level.type, level.cleared); + level.type, level.cleared_rect); } TextureDefinition::~TextureDefinition() { @@ -412,7 +421,7 @@ void TextureDefinition::UpdateTextureInternal(Texture* texture) const { level_info_.internal_format, level_info_.width, level_info_.height, level_info_.depth, level_info_.border, level_info_.format, - level_info_.type, level_info_.cleared); + level_info_.type, level_info_.cleared_rect); } if (image_buffer_.get()) { @@ -480,7 +489,8 @@ bool TextureDefinition::Matches(const Texture* texture) const { } bool TextureDefinition::SafeToRenderFrom() const { - return level_info_.cleared; + return level_info_.cleared_rect.Contains( + gfx::Rect(level_info_.width, level_info_.height)); } } // namespace gles2 diff --git a/chromium/gpu/command_buffer/service/texture_definition.h b/chromium/gpu/command_buffer/service/texture_definition.h index e5311846295..19c953cb1c4 100644 --- a/chromium/gpu/command_buffer/service/texture_definition.h +++ b/chromium/gpu/command_buffer/service/texture_definition.h @@ -9,6 +9,7 @@ #include "base/memory/ref_counted.h" #include "gpu/command_buffer/service/gl_utils.h" +#include "ui/gfx/geometry/rect.h" namespace gfx { class GLImage; @@ -84,7 +85,7 @@ class TextureDefinition { GLint border, GLenum format, GLenum type, - bool cleared); + const gfx::Rect& cleared_rect); ~LevelInfo(); GLenum target; @@ -95,7 +96,7 @@ class TextureDefinition { GLint border; GLenum format; GLenum type; - bool cleared; + gfx::Rect cleared_rect; }; unsigned int version_; diff --git a/chromium/gpu/command_buffer/service/texture_manager.cc b/chromium/gpu/command_buffer/service/texture_manager.cc index 90b7d2a236b..c7150ee98ee 100644 --- a/chromium/gpu/command_buffer/service/texture_manager.cc +++ b/chromium/gpu/command_buffer/service/texture_manager.cc @@ -5,9 +5,11 @@ #include "gpu/command_buffer/service/texture_manager.h" #include <algorithm> +#include <set> #include <utility> #include "base/bits.h" +#include "base/lazy_instance.h" #include "base/strings/stringprintf.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/context_state.h" @@ -22,8 +24,10 @@ namespace gpu { namespace gles2 { +namespace { + // This should contain everything to uniquely identify a Texture. -static const char TextureTag[] = "|Texture|"; +const char TextureTag[] = "|Texture|"; struct TextureSignature { GLenum target_; GLint level_; @@ -109,6 +113,158 @@ struct TextureSignature { } }; +class FormatTypeValidator { + public: + FormatTypeValidator() { + static const FormatType kSupportedFormatTypes[] = { + // ES2. + { GL_RGB, GL_RGB, GL_UNSIGNED_BYTE }, + { GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 }, + { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE }, + { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE }, + { GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE }, + // Exposed by GL_OES_texture_float and GL_OES_texture_half_float + { GL_RGB, GL_RGB, GL_FLOAT }, + { GL_RGBA, GL_RGBA, GL_FLOAT }, + { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT }, + { GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT }, + { GL_ALPHA, GL_ALPHA, GL_FLOAT }, + { GL_RGB, GL_RGB, GL_HALF_FLOAT_OES }, + { GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES }, + { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES }, + { GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES }, + { GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES }, + // Exposed by GL_ANGLE_depth_texture + { GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, + { GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }, + { GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 }, + // Exposed by GL_EXT_sRGB + { GL_SRGB, GL_SRGB, GL_UNSIGNED_BYTE }, + { GL_SRGB_ALPHA, GL_SRGB_ALPHA, GL_UNSIGNED_BYTE }, + // Exposed by GL_EXT_texture_format_BGRA8888 + { GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE }, + // Exposed by GL_EXT_texture_rg + { GL_RED, GL_RED, GL_UNSIGNED_BYTE }, + { GL_RG, GL_RG, GL_UNSIGNED_BYTE }, + { GL_RED, GL_RED, GL_FLOAT }, + { GL_RG, GL_RG, GL_FLOAT }, + { GL_RED, GL_RED, GL_HALF_FLOAT_OES }, + { GL_RG, GL_RG, GL_HALF_FLOAT_OES }, + + // ES3. + { GL_R8, GL_RED, GL_UNSIGNED_BYTE }, + { GL_R8_SNORM, GL_RED, GL_BYTE }, + { GL_R16F, GL_RED, GL_HALF_FLOAT }, + { GL_R16F, GL_RED, GL_FLOAT }, + { GL_R32F, GL_RED, GL_FLOAT }, + { GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE }, + { GL_R8I, GL_RED_INTEGER, GL_BYTE }, + { GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT }, + { GL_R16I, GL_RED_INTEGER, GL_SHORT }, + { GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT }, + { GL_R32I, GL_RED_INTEGER, GL_INT }, + { GL_RG8, GL_RG, GL_UNSIGNED_BYTE }, + { GL_RG8_SNORM, GL_RG, GL_BYTE }, + { GL_RG16F, GL_RG, GL_HALF_FLOAT }, + { GL_RG16F, GL_RG, GL_FLOAT }, + { GL_RG32F, GL_RG, GL_FLOAT }, + { GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE }, + { GL_RG8I, GL_RG_INTEGER, GL_BYTE }, + { GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT }, + { GL_RG16I, GL_RG_INTEGER, GL_SHORT }, + { GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT }, + { GL_RG32I, GL_RG_INTEGER, GL_INT }, + { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE }, + { GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE }, + { GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE, }, + { GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }, + { GL_RGB8_SNORM, GL_RGB, GL_BYTE }, + { GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV }, + { GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT }, + { GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT }, + { GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV }, + { GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT }, + { GL_RGB9_E5, GL_RGB, GL_FLOAT }, + { GL_RGB16F, GL_RGB, GL_HALF_FLOAT }, + { GL_RGB16F, GL_RGB, GL_FLOAT }, + { GL_RGB32F, GL_RGB, GL_FLOAT }, + { GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE }, + { GL_RGB8I, GL_RGB_INTEGER, GL_BYTE }, + { GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT }, + { GL_RGB16I, GL_RGB_INTEGER, GL_SHORT }, + { GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT }, + { GL_RGB32I, GL_RGB_INTEGER, GL_INT }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }, + { GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE }, + { GL_RGBA8_SNORM, GL_RGBA, GL_BYTE }, + { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE }, + { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 }, + { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV }, + { GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE }, + { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 }, + { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV }, + { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT }, + { GL_RGBA16F, GL_RGBA, GL_FLOAT }, + { GL_RGBA32F, GL_RGBA, GL_FLOAT }, + { GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE }, + { GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE }, + { GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV }, + { GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT }, + { GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT }, + { GL_RGBA32I, GL_RGBA_INTEGER, GL_INT }, + { GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT }, + { GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, + { GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }, + { GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }, + { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT }, + { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 }, + { GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, + GL_FLOAT_32_UNSIGNED_INT_24_8_REV }, + }; + + for (size_t ii = 0; ii < arraysize(kSupportedFormatTypes); ++ii) { + supported_combinations_.insert(kSupportedFormatTypes[ii]); + } + } + + // This may be accessed from multiple threads. + bool IsValid(GLenum internal_format, GLenum format, GLenum type) const { + FormatType query = { internal_format, format, type }; + return supported_combinations_.find(query) != supported_combinations_.end(); + } + + private: + // TODO(zmo): once std::tuple is allowed, switch over to that. + struct FormatType { + GLenum internal_format; + GLenum format; + GLenum type; + }; + + struct FormatTypeCompare { + bool operator() (const FormatType& lhs, const FormatType& rhs) const { + return (lhs.internal_format < rhs.internal_format || + ((lhs.internal_format == rhs.internal_format) && + (lhs.format < rhs.format)) || + ((lhs.internal_format == rhs.internal_format) && + (lhs.format == rhs.format) && + (lhs.type < rhs.type))); + } + }; + + // This class needs to be thread safe, so once supported_combinations_ + // are initialized in the constructor, it should never be modified later. + std::set<FormatType, FormatTypeCompare> supported_combinations_; +}; + +base::LazyInstance<const FormatTypeValidator>::Leaky g_format_type_validator = + LAZY_INSTANCE_INITIALIZER; + +} // namespace anonymous + TextureManager::DestructionObserver::DestructionObserver() {} TextureManager::DestructionObserver::~DestructionObserver() {} @@ -223,8 +379,7 @@ MemoryTypeTracker* Texture::GetMemTracker() { } Texture::LevelInfo::LevelInfo() - : cleared(true), - target(0), + : target(0), level(-1), internal_format(0), width(0), @@ -237,7 +392,7 @@ Texture::LevelInfo::LevelInfo() } Texture::LevelInfo::LevelInfo(const LevelInfo& rhs) - : cleared(rhs.cleared), + : cleared_rect(rhs.cleared_rect), target(rhs.target), level(rhs.level), internal_format(rhs.internal_format), @@ -384,17 +539,9 @@ bool Texture::MarkMipmapsGenerated( width = std::max(1, width >> 1); height = std::max(1, height >> 1); depth = std::max(1, depth >> 1); - SetLevelInfo(feature_info, - target, - level, - level0_info.internal_format, - width, - height, - depth, - level0_info.border, - level0_info.format, - level0_info.type, - true); + SetLevelInfo(feature_info, target, level, level0_info.internal_format, + width, height, depth, level0_info.border, level0_info.format, + level0_info.type, gfx::Rect(width, height)); } } @@ -509,7 +656,9 @@ bool Texture::TextureMipComplete(const Texture::LevelInfo& level0_face, return complete; } -void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { +void Texture::SetLevelClearedRect(GLenum target, + GLint level, + const gfx::Rect& cleared_rect) { DCHECK_GE(level, 0); size_t face_index = GLES2Util::GLTargetToFaceIndex(target); DCHECK_LT(static_cast<size_t>(face_index), @@ -518,7 +667,19 @@ void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { face_infos_[face_index].level_infos.size()); Texture::LevelInfo& info = face_infos_[face_index].level_infos[level]; - UpdateMipCleared(&info, cleared); + UpdateMipCleared(&info, info.width, info.height, cleared_rect); + UpdateCleared(); +} + +void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { + DCHECK_GE(level, 0); + size_t face_index = GLES2Util::GLTargetToFaceIndex(target); + DCHECK_LT(static_cast<size_t>(face_index), face_infos_.size()); + DCHECK_LT(static_cast<size_t>(level), + face_infos_[face_index].level_infos.size()); + Texture::LevelInfo& info = face_infos_[face_index].level_infos[level]; + UpdateMipCleared(&info, info.width, info.height, + cleared ? gfx::Rect(info.width, info.height) : gfx::Rect()); UpdateCleared(); } @@ -547,10 +708,17 @@ void Texture::UpdateSafeToRenderFrom(bool cleared) { (*it)->manager()->UpdateSafeToRenderFrom(delta); } -void Texture::UpdateMipCleared(LevelInfo* info, bool cleared) { - if (info->cleared == cleared) +void Texture::UpdateMipCleared(LevelInfo* info, + GLsizei width, + GLsizei height, + const gfx::Rect& cleared_rect) { + bool was_cleared = info->cleared_rect == gfx::Rect(info->width, info->height); + info->width = width; + info->height = height; + info->cleared_rect = cleared_rect; + bool cleared = info->cleared_rect == gfx::Rect(info->width, info->height); + if (cleared == was_cleared) return; - info->cleared = cleared; int delta = cleared ? -1 : +1; num_uncleared_mips_ += delta; for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) @@ -595,18 +763,17 @@ void Texture::IncAllFramebufferStateChangeCount() { (*it)->manager()->IncFramebufferStateChangeCount(); } -void Texture::SetLevelInfo( - const FeatureInfo* feature_info, - GLenum target, - GLint level, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLenum format, - GLenum type, - bool cleared) { +void Texture::SetLevelInfo(const FeatureInfo* feature_info, + GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const gfx::Rect& cleared_rect) { DCHECK_GE(level, 0); size_t face_index = GLES2Util::GLTargetToFaceIndex(target); DCHECK_LT(static_cast<size_t>(face_index), @@ -651,20 +818,19 @@ void Texture::SetLevelInfo( info.target = target; info.level = level; info.internal_format = internal_format; - info.width = width; - info.height = height; info.depth = depth; info.border = border; info.format = format; info.type = type; info.image = 0; + UpdateMipCleared(&info, width, height, cleared_rect); + estimated_size_ -= info.estimated_size; GLES2Util::ComputeImageDataSizes( width, height, 1, format, type, 4, &info.estimated_size, NULL, NULL); estimated_size_ += info.estimated_size; - UpdateMipCleared(&info, cleared); max_level_set_ = std::max(max_level_set_, level); Update(feature_info); UpdateCleared(); @@ -760,6 +926,12 @@ GLenum Texture::SetParameteri( } switch (pname) { + case GL_TEXTURE_MIN_LOD: + case GL_TEXTURE_MAX_LOD: + { + GLfloat fparam = static_cast<GLfloat>(param); + return SetParameterf(feature_info, pname, fparam); + } case GL_TEXTURE_MIN_FILTER: if (!feature_info->validators()->texture_min_filter_mode.IsValid(param)) { return GL_INVALID_ENUM; @@ -849,8 +1021,13 @@ GLenum Texture::SetParameterf( case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: case GL_TEXTURE_POOL_CHROMIUM: + case GL_TEXTURE_WRAP_R: case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: + case GL_TEXTURE_COMPARE_FUNC: + case GL_TEXTURE_COMPARE_MODE: + case GL_TEXTURE_BASE_LEVEL: + case GL_TEXTURE_MAX_LEVEL: case GL_TEXTURE_USAGE_ANGLE: { GLint iparam = static_cast<GLint>(param); @@ -979,6 +1156,18 @@ bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { return true; } +gfx::Rect Texture::GetLevelClearedRect(GLenum target, GLint level) const { + size_t face_index = GLES2Util::GLTargetToFaceIndex(target); + if (face_index >= face_infos_.size() || + level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) { + return gfx::Rect(); + } + + const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level]; + + return info.cleared_rect; +} + bool Texture::IsLevelCleared(GLenum target, GLint level) const { size_t face_index = GLES2Util::GLTargetToFaceIndex(target); if (face_index >= face_infos_.size() || @@ -988,7 +1177,7 @@ bool Texture::IsLevelCleared(GLenum target, GLint level) const { const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level]; - return info.cleared; + return info.cleared_rect == gfx::Rect(info.width, info.height); } void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) { @@ -1013,21 +1202,41 @@ bool Texture::ClearLevel( DCHECK(target == info.target); if (info.target == 0 || - info.cleared || - info.width == 0 || - info.height == 0 || - info.depth == 0) { + info.cleared_rect == gfx::Rect(info.width, info.height) || + info.width == 0 || info.height == 0 || info.depth == 0) { return true; } - // NOTE: It seems kind of gross to call back into the decoder for this - // but only the decoder knows all the state (like unpack_alignment_) that's - // needed to be able to call GL correctly. - bool cleared = decoder->ClearLevel( - this, info.target, info.level, info.internal_format, info.format, - info.type, info.width, info.height, immutable_); - UpdateMipCleared(&info, cleared); - return info.cleared; + // Clear all remaining sub regions. + const int x[] = { + 0, info.cleared_rect.x(), info.cleared_rect.right(), info.width}; + const int y[] = { + 0, info.cleared_rect.y(), info.cleared_rect.bottom(), info.height}; + + for (size_t j = 0; j < 3; ++j) { + for (size_t i = 0; i < 3; ++i) { + // Center of nine patch is already cleared. + if (j == 1 && i == 1) + continue; + + gfx::Rect rect(x[i], y[j], x[i + 1] - x[i], y[j + 1] - y[j]); + if (rect.IsEmpty()) + continue; + + // NOTE: It seems kind of gross to call back into the decoder for this + // but only the decoder knows all the state (like unpack_alignment_) + // that's needed to be able to call GL correctly. + bool cleared = decoder->ClearLevel(this, info.target, info.level, + info.format, info.type, rect.x(), + rect.y(), rect.width(), rect.height()); + if (!cleared) + return false; + } + } + + UpdateMipCleared(&info, info.width, info.height, + gfx::Rect(info.width, info.height)); + return true; } void Texture::SetLevelImage( @@ -1206,43 +1415,17 @@ scoped_refptr<TextureRef> SetTarget(default_texture.get(), target); if (needs_faces) { for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { - SetLevelInfo(default_texture.get(), - GLES2Util::IndexToGLFaceTarget(ii), - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + SetLevelInfo(default_texture.get(), GLES2Util::IndexToGLFaceTarget(ii), + 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(1, 1)); } } else { if (needs_initialization) { - SetLevelInfo(default_texture.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + SetLevelInfo(default_texture.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); } else { - SetLevelInfo(default_texture.get(), - GL_TEXTURE_EXTERNAL_OES, - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + SetLevelInfo(default_texture.get(), GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA, + 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); } } } @@ -1276,6 +1459,14 @@ void TextureManager::SetTarget(TextureRef* ref, GLenum target) { ->SetTarget(feature_info_.get(), target, MaxLevelsForTarget(target)); } +void TextureManager::SetLevelClearedRect(TextureRef* ref, + GLenum target, + GLint level, + const gfx::Rect& cleared_rect) { + DCHECK(ref); + ref->texture()->SetLevelClearedRect(target, level, cleared_rect); +} + void TextureManager::SetLevelCleared(TextureRef* ref, GLenum target, GLint level, @@ -1303,33 +1494,25 @@ bool TextureManager::ClearTextureLevel( return result; } -void TextureManager::SetLevelInfo( - TextureRef* ref, - GLenum target, - GLint level, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLenum format, - GLenum type, - bool cleared) { +void TextureManager::SetLevelInfo(TextureRef* ref, + GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const gfx::Rect& cleared_rect) { + DCHECK(gfx::Rect(width, height).Contains(cleared_rect)); DCHECK(ref); Texture* texture = ref->texture(); texture->GetMemTracker()->TrackMemFree(texture->estimated_size()); - texture->SetLevelInfo(feature_info_.get(), - target, - level, - internal_format, - width, - height, - depth, - border, - format, - type, - cleared); + texture->SetLevelInfo(feature_info_.get(), target, level, internal_format, + width, height, depth, border, format, type, + cleared_rect); texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size()); } @@ -1567,7 +1750,9 @@ void TextureManager::IncFramebufferStateChangeCount() { bool TextureManager::ValidateFormatAndTypeCombination( ErrorState* error_state, const char* function_name, GLenum format, GLenum type) { - if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) { + // TODO(zmo): now this is only called by GLES2DecoderImpl::DoCopyTexImage2D + // and is incorrect for ES3. Fix this. + if (!g_format_type_validator.Get().IsValid(format, format, type)) { ERRORSTATE_SET_GL_ERROR( error_state, GL_INVALID_OPERATION, function_name, (std::string("invalid type ") + @@ -1592,24 +1777,32 @@ bool TextureManager::ValidateTextureParameters( error_state, function_name, type, "type"); return false; } - if (format != internal_format && - !((internal_format == GL_RGBA32F && format == GL_RGBA) || - (internal_format == GL_RGB32F && format == GL_RGB))) { + if (!g_format_type_validator.Get().IsValid(internal_format, format, type)) { ERRORSTATE_SET_GL_ERROR( error_state, GL_INVALID_OPERATION, function_name, - "format != internalformat"); + "invalid internalformat/format/type combination"); return false; } - uint32 channels = GLES2Util::GetChannelsForFormat(format); - if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) { - ERRORSTATE_SET_GL_ERROR( - error_state, GL_INVALID_OPERATION, function_name, - (std::string("invalid format ") + GLES2Util::GetStringEnum(format) + - " for level != 0").c_str()); + // For TexSubImage calls, internal_format isn't part of the parameters, + // so its validation needs to be after the internal_format/format/type + // combination validation. Otherwise, an unexpected INVALID_ENUM could be + // generated instead of INVALID_OPERATION. + if (!validators->texture_internal_format.IsValid(internal_format)) { + ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( + error_state, function_name, internal_format, "internal_format"); return false; } - return ValidateFormatAndTypeCombination(error_state, function_name, - format, type); + if (!feature_info_->IsES3Enabled()) { + uint32 channels = GLES2Util::GetChannelsForFormat(format); + if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) { + ERRORSTATE_SET_GL_ERROR( + error_state, GL_INVALID_OPERATION, function_name, + (std::string("invalid format ") + GLES2Util::GetStringEnum(format) + + " for level != 0").c_str()); + return false; + } + } + return true; } // Gets the texture id for a given target. @@ -1659,30 +1852,28 @@ TextureRef* TextureManager::GetTextureInfoForTargetUnlessDefault( return texture; } -bool TextureManager::ValidateTexImage2D( +bool TextureManager::ValidateTexImage( ContextState* state, const char* function_name, - const DoTextImage2DArguments& args, + const DoTexImageArguments& args, TextureRef** texture_ref) { ErrorState* error_state = state->GetErrorState(); const Validators* validators = feature_info_->validators(); - if (!validators->texture_target.IsValid(args.target)) { + if (((args.command_type == DoTexImageArguments::kTexImage2D) && + !validators->texture_target.IsValid(args.target)) || + ((args.command_type == DoTexImageArguments::kTexImage3D) && + !validators->texture_3_d_target.IsValid(args.target))) { ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( error_state, function_name, args.target, "target"); return false; } - if (!validators->texture_internal_format.IsValid(args.internal_format)) { - ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( - error_state, function_name, args.internal_format, - "internalformat"); - return false; - } if (!ValidateTextureParameters( error_state, function_name, args.format, args.type, args.internal_format, args.level)) { return false; } - if (!ValidForTarget(args.target, args.level, args.width, args.height, 1) || + if (!ValidForTarget(args.target, args.level, + args.width, args.height, args.depth) || args.border != 0) { ERRORSTATE_SET_GL_ERROR( error_state, GL_INVALID_VALUE, function_name, @@ -1722,18 +1913,19 @@ bool TextureManager::ValidateTexImage2D( return true; } -void TextureManager::ValidateAndDoTexImage2D( +void TextureManager::ValidateAndDoTexImage( DecoderTextureState* texture_state, ContextState* state, DecoderFramebufferState* framebuffer_state, - const DoTextImage2DArguments& args) { + const char* function_name, + const DoTexImageArguments& args) { TextureRef* texture_ref; - if (!ValidateTexImage2D(state, "glTexImage2D", args, &texture_ref)) { + if (!ValidateTexImage(state, function_name, args, &texture_ref)) { return; } - DoTexImage2D(texture_state, state->GetErrorState(), framebuffer_state, - texture_ref, args); + DoTexImage(texture_state, state->GetErrorState(), framebuffer_state, + function_name, texture_ref, args); } GLenum TextureManager::AdjustTexFormat(GLenum format) const { @@ -1748,31 +1940,33 @@ GLenum TextureManager::AdjustTexFormat(GLenum format) const { return format; } -void TextureManager::DoTexImage2D( +void TextureManager::DoTexImage( DecoderTextureState* texture_state, ErrorState* error_state, DecoderFramebufferState* framebuffer_state, + const char* function_name, TextureRef* texture_ref, - const DoTextImage2DArguments& args) { + const DoTexImageArguments& args) { Texture* texture = texture_ref->texture(); GLsizei tex_width = 0; GLsizei tex_height = 0; + GLsizei tex_depth = 0; GLenum tex_type = 0; GLenum tex_format = 0; bool level_is_same = texture->GetLevelSize( - args.target, args.level, &tex_width, &tex_height, nullptr) && + args.target, args.level, &tex_width, &tex_height, &tex_depth) && texture->GetLevelType(args.target, args.level, &tex_type, &tex_format) && args.width == tex_width && args.height == tex_height && - args.type == tex_type && args.format == tex_format; + args.depth == tex_depth && args.type == tex_type && + args.format == tex_format; if (level_is_same && !args.pixels) { // Just set the level texture but mark the texture as uncleared. - SetLevelInfo( - texture_ref, - args.target, args.level, args.internal_format, args.width, args.height, - 1, args.border, args.format, args.type, false); - texture_state->tex_image_2d_failed = false; + SetLevelInfo(texture_ref, args.target, args.level, args.internal_format, + args.width, args.height, args.depth, args.border, args.format, + args.type, gfx::Rect()); + texture_state->tex_image_failed = false; return; } @@ -1780,32 +1974,44 @@ void TextureManager::DoTexImage2D( framebuffer_state->clear_state_dirty = true; } - if (texture_state->texsubimage2d_faster_than_teximage2d && + if (texture_state->texsubimage_faster_than_teximage && level_is_same && args.pixels) { { ScopedTextureUploadTimer timer(texture_state); - glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height, - AdjustTexFormat(args.format), args.type, args.pixels); + if (args.command_type == DoTexImageArguments::kTexImage3D) { + glTexSubImage3D(args.target, args.level, 0, 0, 0, + args.width, args.height, args.depth, + args.format, args.type, args.pixels); + } else { + glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height, + AdjustTexFormat(args.format), args.type, args.pixels); + } } SetLevelCleared(texture_ref, args.target, args.level, true); - texture_state->tex_image_2d_failed = false; + texture_state->tex_image_failed = false; return; } - ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glTexImage2D"); + ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, function_name); { ScopedTextureUploadTimer timer(texture_state); - glTexImage2D( - args.target, args.level, args.internal_format, args.width, args.height, - args.border, AdjustTexFormat(args.format), args.type, args.pixels); + if (args.command_type == DoTexImageArguments::kTexImage3D) { + glTexImage3D(args.target, args.level, args.internal_format, args.width, + args.height, args.depth, args.border, args.format, + args.type, args.pixels); + } else { + glTexImage2D(args.target, args.level, args.internal_format, args.width, + args.height, args.border, AdjustTexFormat(args.format), + args.type, args.pixels); + } } - GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glTexImage2D"); + GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name); if (error == GL_NO_ERROR) { SetLevelInfo( - texture_ref, - args.target, args.level, args.internal_format, args.width, args.height, - 1, args.border, args.format, args.type, args.pixels != NULL); - texture_state->tex_image_2d_failed = false; + texture_ref, args.target, args.level, args.internal_format, args.width, + args.height, args.depth, args.border, args.format, args.type, + args.pixels != NULL ? gfx::Rect(args.width, args.height) : gfx::Rect()); + texture_state->tex_image_failed = false; } } diff --git a/chromium/gpu/command_buffer/service/texture_manager.h b/chromium/gpu/command_buffer/service/texture_manager.h index 5feeadc4d2c..4de5421b1bc 100644 --- a/chromium/gpu/command_buffer/service/texture_manager.h +++ b/chromium/gpu/command_buffer/service/texture_manager.h @@ -17,6 +17,7 @@ #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/gpu_export.h" +#include "ui/gfx/geometry/rect.h" #include "ui/gl/gl_image.h" namespace gpu { @@ -182,6 +183,10 @@ class GPU_EXPORT Texture { return immutable_; } + // Get the cleared rectangle for a particular level. Returns an empty + // rectangle if level does not exist. + gfx::Rect GetLevelClearedRect(GLenum target, GLint level) const; + // Whether a particular level/face is cleared. bool IsLevelCleared(GLenum target, GLint level) const; @@ -227,7 +232,7 @@ class GPU_EXPORT Texture { LevelInfo(const LevelInfo& rhs); ~LevelInfo(); - bool cleared; + gfx::Rect cleared_rect; GLenum target; GLint level; GLenum internal_format; @@ -250,18 +255,17 @@ class GPU_EXPORT Texture { }; // Set the info for a particular level. - void SetLevelInfo( - const FeatureInfo* feature_info, - GLenum target, - GLint level, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLenum format, - GLenum type, - bool cleared); + void SetLevelInfo(const FeatureInfo* feature_info, + GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const gfx::Rect& cleared_rect); // In GLES2 "texture complete" means it has all required mips for filtering // down to a 1x1 pixel texture, they are in the correct order, they are all @@ -281,6 +285,11 @@ class GPU_EXPORT Texture { return npot_; } + // Marks a |rect| of a particular level as cleared. + void SetLevelClearedRect(GLenum target, + GLint level, + const gfx::Rect& cleared_rect); + // Marks a particular level as cleared or uncleared. void SetLevelCleared(GLenum target, GLint level, bool cleared); @@ -374,7 +383,10 @@ class GPU_EXPORT Texture { // Updates the uncleared mip count in all the managers referencing this // texture. - void UpdateMipCleared(LevelInfo* info, bool cleared); + void UpdateMipCleared(LevelInfo* info, + GLsizei width, + GLsizei height, + const gfx::Rect& cleared_rect); // Computes the CanRenderCondition flag. CanRenderCondition GetCanRenderCondition() const; @@ -520,21 +532,22 @@ class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> { struct DecoderTextureState { // total_texture_upload_time automatically initialized to 0 in default // constructor. - explicit DecoderTextureState(bool texsubimage2d_faster_than_teximage2d) - : tex_image_2d_failed(false), + explicit DecoderTextureState(bool texsubimage_faster_than_teximage) + : tex_image_failed(false), texture_upload_count(0), - texsubimage2d_faster_than_teximage2d( - texsubimage2d_faster_than_teximage2d) {} + texsubimage_faster_than_teximage(texsubimage_faster_than_teximage) {} - // This indicates all the following texSubImage2D calls that are part of the - // failed texImage2D call should be ignored. - bool tex_image_2d_failed; + // This indicates all the following texSubImage*D calls that are part of the + // failed texImage*D call should be ignored. The client calls have a lock + // around them, so it will affect only a single texImage*D + texSubImage*D + // group. + bool tex_image_failed; // Command buffer stats. int texture_upload_count; base::TimeDelta total_texture_upload_time; - bool texsubimage2d_faster_than_teximage2d; + bool texsubimage_faster_than_teximage; }; // This class keeps track of the textures and their sizes so we can do NPOT and @@ -649,27 +662,25 @@ class GPU_EXPORT TextureManager { GLenum target); // Set the info for a particular level in a TexureInfo. - void SetLevelInfo( - TextureRef* ref, - GLenum target, - GLint level, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLenum format, - GLenum type, - bool cleared); + void SetLevelInfo(TextureRef* ref, + GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const gfx::Rect& cleared_rect); // Adapter to call above function. void SetLevelInfoFromParams(TextureRef* ref, const gpu::AsyncTexImage2DParams& params) { - SetLevelInfo( - ref, params.target, params.level, params.internal_format, - params.width, params.height, 1 /* depth */, - params.border, params.format, - params.type, true /* cleared */); + SetLevelInfo(ref, params.target, params.level, params.internal_format, + params.width, params.height, 1 /* depth */, params.border, + params.format, params.type, + gfx::Rect(params.width, params.height) /* cleared_rect */); } Texture* Produce(TextureRef* ref); @@ -677,6 +688,12 @@ class GPU_EXPORT TextureManager { // Maps an existing texture into the texture manager, at a given client ID. TextureRef* Consume(GLuint client_id, Texture* texture); + // Sets |rect| of mip as cleared. + void SetLevelClearedRect(TextureRef* ref, + GLenum target, + GLint level, + const gfx::Rect& cleared_rect); + // Sets a mip as cleared. void SetLevelCleared(TextureRef* ref, GLenum target, GLint level, bool cleared); @@ -798,32 +815,40 @@ class GPU_EXPORT TextureManager { NOTREACHED(); } - struct DoTextImage2DArguments { + struct DoTexImageArguments { + enum TexImageCommandType { + kTexImage2D, + kTexImage3D, + }; + GLenum target; GLint level; GLenum internal_format; GLsizei width; GLsizei height; + GLsizei depth; GLint border; GLenum format; GLenum type; const void* pixels; uint32 pixels_size; + TexImageCommandType command_type; }; - bool ValidateTexImage2D( + bool ValidateTexImage( ContextState* state, const char* function_name, - const DoTextImage2DArguments& args, + const DoTexImageArguments& args, // Pointer to TextureRef filled in if validation successful. // Presumes the pointer is valid. TextureRef** texture_ref); - void ValidateAndDoTexImage2D( + void ValidateAndDoTexImage( DecoderTextureState* texture_state, ContextState* state, DecoderFramebufferState* framebuffer_state, - const DoTextImage2DArguments& args); + const char* function_name, + const DoTexImageArguments& args); // TODO(kloveless): Make GetTexture* private once this is no longer called // from gles2_cmd_decoder. @@ -850,12 +875,13 @@ class GPU_EXPORT TextureManager { GLenum target, GLuint* black_texture); - void DoTexImage2D( + void DoTexImage( DecoderTextureState* texture_state, ErrorState* error_state, DecoderFramebufferState* framebuffer_state, + const char* function_name, TextureRef* texture_ref, - const DoTextImage2DArguments& args); + const DoTexImageArguments& args); void StartTracking(TextureRef* texture); void StopTracking(TextureRef* texture); diff --git a/chromium/gpu/command_buffer/service/texture_manager_unittest.cc b/chromium/gpu/command_buffer/service/texture_manager_unittest.cc index b89e5e9579a..ed25a7d4520 100644 --- a/chromium/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/texture_manager_unittest.cc @@ -6,6 +6,7 @@ #include <utility> +#include "base/command_line.h" #include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/error_state_mock.h" #include "gpu/command_buffer/service/feature_info.h" @@ -19,11 +20,12 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_image_stub.h" #include "ui/gl/gl_mock.h" +#include "ui/gl/gl_switches.h" using ::testing::AtLeast; using ::testing::Pointee; using ::testing::Return; -using ::testing::SetArgumentPointee; +using ::testing::SetArgPointee; using ::testing::StrictMock; using ::testing::_; @@ -55,7 +57,13 @@ class TextureManagerTest : public GpuServiceTest { static const GLint kMaxExternalLevels = 1; static const bool kUseDefaultTextures = false; - TextureManagerTest() : feature_info_(new FeatureInfo()) {} + TextureManagerTest() { + // Always run with this command line, but the ES3 features are not + // enabled without FeatureInfo::EnableES3Validators(). + base::CommandLine command_line(0, nullptr); + command_line.AppendSwitch(switches::kEnableUnsafeES3APIs); + feature_info_ = new FeatureInfo(command_line); + } ~TextureManagerTest() override {} @@ -540,87 +548,33 @@ TEST_F(TextureTest, SetTargetTextureExternalOES) { TEST_F(TextureTest, ZeroSizeCanNotRender) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 0, - 0, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); } TEST_F(TextureTest, EstimatedSize) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 8, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(8, 4)); EXPECT_EQ(8u * 4u * 4u, texture_ref_->texture()->estimated_size()); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 2, - GL_RGBA, - 8, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 2, GL_RGBA, 8, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(8, 4)); EXPECT_EQ(8u * 4u * 4u * 2u, texture_ref_->texture()->estimated_size()); } TEST_F(TextureMemoryTrackerTest, EstimatedSize) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 128, MemoryTracker::kUnmanaged); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 8, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(8, 4)); EXPECT_MEMORY_ALLOCATION_CHANGE(128, 0, MemoryTracker::kUnmanaged); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 256, MemoryTracker::kUnmanaged); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 2, - GL_RGBA, - 8, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 2, GL_RGBA, 8, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(8, 4)); // Add expectation for texture deletion. EXPECT_MEMORY_ALLOCATION_CHANGE(256, 0, MemoryTracker::kUnmanaged); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kUnmanaged); @@ -629,17 +583,8 @@ TEST_F(TextureMemoryTrackerTest, EstimatedSize) { TEST_F(TextureMemoryTrackerTest, SetParameterPool) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 128, MemoryTracker::kUnmanaged); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 8, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(8, 4)); EXPECT_MEMORY_ALLOCATION_CHANGE(128, 0, MemoryTracker::kUnmanaged); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 128, MemoryTracker::kManaged); SetParameter(texture_ref_.get(), @@ -657,21 +602,12 @@ TEST_F(TextureTest, POT2D) { Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target()); // Check Setting level 0 to POT - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); - EXPECT_EQ(0, texture->num_uncleared_mips()); + EXPECT_TRUE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); // Set filters to something that will work with a single mip. SetParameter( @@ -692,34 +628,16 @@ TEST_F(TextureTest, POT2D) { EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Change a mip. - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); // Set a level past the number of mips that would get generated. - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 3, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 3, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); // Make mips. EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); @@ -731,17 +649,8 @@ TEST_F(TextureTest, POT2D) { TEST_F(TextureMemoryTrackerTest, MarkMipmapsGenerated) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 64, MemoryTracker::kUnmanaged); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_MEMORY_ALLOCATION_CHANGE(64, 0, MemoryTracker::kUnmanaged); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 84, MemoryTracker::kUnmanaged); EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); @@ -754,51 +663,24 @@ TEST_F(TextureTest, UnusedMips) { Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target()); // Set level zero to large size. - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Set level zero to large smaller (levels unused mips) - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 2, - 2, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Set an unused level to some size - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 4, - GL_RGBA, - 16, - 16, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 4, GL_RGBA, 16, 16, + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(16, 16)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); @@ -810,17 +692,8 @@ TEST_F(TextureTest, NPOT2D) { Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target()); // Check Setting level 0 to NPOT - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 4, - 5, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 5, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 5)); EXPECT_TRUE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); @@ -839,17 +712,8 @@ TEST_F(TextureTest, NPOT2D) { EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Change it to POT. - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); @@ -876,8 +740,8 @@ TEST_F(TextureTest, NPOT2DNPOTOK) { manager.SetTarget(texture_ref, GL_TEXTURE_2D); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target()); // Check Setting level 0 to NPOT - manager.SetLevelInfo(texture_ref, - GL_TEXTURE_2D, 0, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); + manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 4, 5, 1, 0, + GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 5)); EXPECT_TRUE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager.CanGenerateMipmaps(texture_ref)); @@ -895,102 +759,54 @@ TEST_F(TextureTest, POTCubeMap) { Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP), texture->target()); // Check Setting level 0 each face to POT - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_CUBE_MAP_POSITIVE_X, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, + GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, + GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, + GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, + GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, + GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, + GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture)); @@ -1006,33 +822,17 @@ TEST_F(TextureTest, POTCubeMap) { EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Change a mip. - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - 1, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 1, + GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); // Set a level past the number of mips that would get generated. - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - 3, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 3, + GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(4, 4)); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); // Make mips. EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); @@ -1042,17 +842,8 @@ TEST_F(TextureTest, POTCubeMap) { TEST_F(TextureTest, GetLevelSize) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_3D); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_3D, - 1, - GL_RGBA, - 4, - 5, - 6, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_3D, 1, GL_RGBA, 4, 5, 6, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 5)); GLsizei width = -1; GLsizei height = -1; GLsizei depth = -1; @@ -1076,17 +867,8 @@ TEST_F(TextureTest, GetLevelSize) { TEST_F(TextureTest, GetLevelType) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 4, - 5, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 5)); GLenum type = 0; GLenum format = 0; Texture* texture = texture_ref_->texture(); @@ -1104,17 +886,8 @@ TEST_F(TextureTest, GetLevelType) { TEST_F(TextureTest, ValidForTexture) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 4, - 5, - 6, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 6, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 5)); // Check bad face. Texture* texture = texture_ref_->texture(); EXPECT_FALSE(texture->ValidForTexture( @@ -1182,8 +955,8 @@ TEST_F(TextureTest, FloatNotLinear) { manager.SetTarget(texture_ref, GL_TEXTURE_2D); Texture* texture = texture_ref->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target()); - manager.SetLevelInfo(texture_ref, - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT, true); + manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, + GL_RGBA, GL_FLOAT, gfx::Rect(1, 1)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), &manager, @@ -1214,8 +987,8 @@ TEST_F(TextureTest, FloatLinear) { manager.SetTarget(texture_ref, GL_TEXTURE_2D); Texture* texture = texture_ref->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target()); - manager.SetLevelInfo(texture_ref, - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT, true); + manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, + GL_RGBA, GL_FLOAT, gfx::Rect(1, 1)); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); manager.Destroy(false); } @@ -1238,8 +1011,8 @@ TEST_F(TextureTest, HalfFloatNotLinear) { manager.SetTarget(texture_ref, GL_TEXTURE_2D); Texture* texture = texture_ref->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target()); - manager.SetLevelInfo(texture_ref, - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT_OES, true); + manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, + GL_RGBA, GL_HALF_FLOAT_OES, gfx::Rect(1, 1)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), &manager, @@ -1270,8 +1043,8 @@ TEST_F(TextureTest, HalfFloatLinear) { manager.SetTarget(texture_ref, GL_TEXTURE_2D); Texture* texture = texture_ref->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target()); - manager.SetLevelInfo(texture_ref, - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT_OES, true); + manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, + GL_RGBA, GL_HALF_FLOAT_OES, gfx::Rect(1, 1)); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); manager.Destroy(false); } @@ -1314,9 +1087,8 @@ TEST_F(TextureTest, DepthTexture) { TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); manager.SetTarget(texture_ref, GL_TEXTURE_2D); - manager.SetLevelInfo( - texture_ref, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 4, 4, 1, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false); + manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 4, 4, + 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, gfx::Rect()); EXPECT_FALSE(manager.CanGenerateMipmaps(texture_ref)); manager.Destroy(false); } @@ -1330,17 +1102,8 @@ TEST_F(TextureTest, SafeUnsafe) { Texture* texture = texture_ref_->texture(); EXPECT_EQ(0, texture->num_uncleared_mips()); manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); @@ -1350,17 +1113,8 @@ TEST_F(TextureTest, SafeUnsafe) { EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture->num_uncleared_mips()); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 8, - 8, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); @@ -1370,28 +1124,10 @@ TEST_F(TextureTest, SafeUnsafe) { EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture->num_uncleared_mips()); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 8, - 8, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); @@ -1406,17 +1142,8 @@ TEST_F(TextureTest, SafeUnsafe) { EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture->num_uncleared_mips()); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 8, - 8, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); @@ -1436,31 +1163,13 @@ TEST_F(TextureTest, SafeUnsafe) { EXPECT_FALSE(manager_->HaveUnclearedMips()); Texture* texture2 = texture_ref2->texture(); EXPECT_EQ(0, texture2->num_uncleared_mips()); - manager_->SetLevelInfo(texture_ref2.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 8, - 8, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref2.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(8, 8)); EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture2->num_uncleared_mips()); - manager_->SetLevelInfo(texture_ref2.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 8, - 8, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref2.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(1, texture2->num_uncleared_mips()); @@ -1470,17 +1179,8 @@ TEST_F(TextureTest, SafeUnsafe) { manager_->GetTexture(kClient3Id)); ASSERT_TRUE(texture_ref3.get() != NULL); manager_->SetTarget(texture_ref3.get(), GL_TEXTURE_2D); - manager_->SetLevelInfo(texture_ref3.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 8, - 8, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref3.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); Texture* texture3 = texture_ref3->texture(); @@ -1494,28 +1194,10 @@ TEST_F(TextureTest, SafeUnsafe) { EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture3->num_uncleared_mips()); - manager_->SetLevelInfo(texture_ref2.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 8, - 8, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); - manager_->SetLevelInfo(texture_ref3.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 8, - 8, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref2.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1, 1, 1)); + manager_->SetLevelInfo(texture_ref3.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4, 4, 4)); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(1, texture2->num_uncleared_mips()); @@ -1544,28 +1226,10 @@ TEST_F(TextureTest, ClearTexture) { EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _)) .WillRepeatedly(Return(true)); manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); Texture* texture = texture_ref_->texture(); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); @@ -1576,28 +1240,10 @@ TEST_F(TextureTest, ClearTexture) { EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture->num_uncleared_mips()); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 4, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 3)); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); @@ -1621,17 +1267,8 @@ TEST_F(TextureTest, UseDeletedTexture) { static const GLuint kService2Id = 12; // Make the default texture renderable manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Make a new texture manager_->CreateTexture(kClient2Id, kService2Id); @@ -1645,17 +1282,8 @@ TEST_F(TextureTest, UseDeletedTexture) { EXPECT_FALSE(manager_->CanRender(texture_ref.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); // Check that we can still manipulate it and it effects the manager. - manager_->SetLevelInfo(texture_ref.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_TRUE(manager_->CanRender(texture_ref.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService2Id))) @@ -1666,17 +1294,8 @@ TEST_F(TextureTest, UseDeletedTexture) { TEST_F(TextureTest, GetLevelImage) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 2, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); Texture* texture = texture_ref_->texture(); EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); // Set image. @@ -1688,17 +1307,8 @@ TEST_F(TextureTest, GetLevelImage) { EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_2D, 1, image.get()); // Image should be reset when SetLevelInfo is called. - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 2, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); } @@ -1714,17 +1324,8 @@ bool InSet(std::set<std::string>* string_set, const std::string& str) { TEST_F(TextureTest, AddToSignature) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 2, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); std::string signature1; std::string signature2; manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature1); @@ -1733,140 +1334,59 @@ TEST_F(TextureTest, AddToSignature) { EXPECT_FALSE(InSet(&string_set, signature1)); // check changing 1 thing makes a different signature. - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 4, - 2, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 2, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 2)); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); // check putting it back makes the same signature. - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 2, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_EQ(signature1, signature2); // Check setting cleared status does not change signature. - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 2, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_EQ(signature1, signature2); // Check changing other settings changes signature. - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 4, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 2, - 2, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 2, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 2, - 1, - 1, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, + 1, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 2, - 1, - 0, - GL_RGB, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, + 0, GL_RGB, GL_UNSIGNED_BYTE, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 2, - 1, - 0, - GL_RGBA, - GL_FLOAT, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, + 0, GL_RGBA, GL_FLOAT, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); // put it back - manager_->SetLevelInfo(texture_ref_.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 2, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_EQ(signature1, signature2); @@ -1950,7 +1470,7 @@ class ProduceConsumeTextureTest : public TextureTest, GLsizei depth, GLint border, GLenum type, - bool cleared) + const gfx::Rect& cleared_rect) : target(target), format(format), width(width), @@ -1958,7 +1478,7 @@ class ProduceConsumeTextureTest : public TextureTest, depth(depth), border(border), type(type), - cleared(cleared) {} + cleared_rect(cleared_rect) {} LevelInfo() : target(0), @@ -1967,14 +1487,13 @@ class ProduceConsumeTextureTest : public TextureTest, height(-1), depth(1), border(0), - type(0), - cleared(false) {} + type(0) {} bool operator==(const LevelInfo& other) const { return target == other.target && format == other.format && width == other.width && height == other.height && depth == other.depth && border == other.border && - type == other.type && cleared == other.cleared; + type == other.type && cleared_rect == other.cleared_rect; } GLenum target; @@ -1984,23 +1503,15 @@ class ProduceConsumeTextureTest : public TextureTest, GLsizei depth; GLint border; GLenum type; - bool cleared; + gfx::Rect cleared_rect; }; void SetLevelInfo(TextureRef* texture_ref, GLint level, const LevelInfo& info) { - manager_->SetLevelInfo(texture_ref, - info.target, - level, - info.format, - info.width, - info.height, - info.depth, - info.border, - info.format, - info.type, - info.cleared); + manager_->SetLevelInfo(texture_ref, info.target, level, info.format, + info.width, info.height, info.depth, info.border, + info.format, info.type, info.cleared_rect); } static LevelInfo GetLevelInfo(const TextureRef* texture_ref, @@ -2013,7 +1524,7 @@ class ProduceConsumeTextureTest : public TextureTest, &info.height, &info.depth)); EXPECT_TRUE(texture->GetLevelType(target, level, &info.type, &info.format)); - info.cleared = texture->IsLevelCleared(target, level); + info.cleared_rect = texture->GetLevelClearedRect(target, level); return info; } @@ -2041,8 +1552,8 @@ TEST_F(ProduceConsumeTextureTest, ProduceConsume2D) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target()); - LevelInfo level0( - GL_TEXTURE_2D, GL_RGBA, 4, 4, 1, 0, GL_UNSIGNED_BYTE, true); + LevelInfo level0(GL_TEXTURE_2D, GL_RGBA, 4, 4, 1, 0, GL_UNSIGNED_BYTE, + gfx::Rect(4, 4)); SetLevelInfo(texture_ref_.get(), 0, level0); EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); @@ -2054,10 +1565,8 @@ TEST_F(ProduceConsumeTextureTest, ProduceConsume2D) { // Make this texture bigger with more levels, and make sure they get // clobbered correctly during Consume(). manager_->SetTarget(texture2_.get(), GL_TEXTURE_2D); - SetLevelInfo( - texture2_.get(), - 0, - LevelInfo(GL_TEXTURE_2D, GL_RGBA, 16, 16, 1, 0, GL_UNSIGNED_BYTE, false)); + SetLevelInfo(texture2_.get(), 0, LevelInfo(GL_TEXTURE_2D, GL_RGBA, 16, 16, 1, + 0, GL_UNSIGNED_BYTE, gfx::Rect())); EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture2_.get())); texture = texture2_->texture(); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); @@ -2085,8 +1594,8 @@ TEST_F(ProduceConsumeTextureTest, ProduceConsumeClearRectangle) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_RECTANGLE_ARB); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_RECTANGLE_ARB), texture->target()); - LevelInfo level0( - GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, 1, 1, 1, 0, GL_UNSIGNED_BYTE, false); + LevelInfo level0(GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, 1, 1, 1, 0, + GL_UNSIGNED_BYTE, gfx::Rect()); SetLevelInfo(texture_ref_.get(), 0, level0); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); Texture* produced_texture = Produce(texture_ref_.get()); @@ -2113,8 +1622,8 @@ TEST_F(ProduceConsumeTextureTest, ProduceConsumeExternal) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), texture->target()); - LevelInfo level0( - GL_TEXTURE_EXTERNAL_OES, GL_RGBA, 1, 1, 1, 0, GL_UNSIGNED_BYTE, false); + LevelInfo level0(GL_TEXTURE_EXTERNAL_OES, GL_RGBA, 1, 1, 1, 0, + GL_UNSIGNED_BYTE, gfx::Rect()); SetLevelInfo(texture_ref_.get(), 0, level0); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); Texture* produced_texture = Produce(texture_ref_.get()); @@ -2135,17 +1644,8 @@ TEST_P(ProduceConsumeTextureTest, ProduceConsumeTextureWithImage) { Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(target), texture->target()); scoped_refptr<gfx::GLImage> image(new gfx::GLImageStub); - manager_->SetLevelInfo(texture_ref_.get(), - target, - 0, - GL_RGBA, - 0, - 0, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + manager_->SetLevelInfo(texture_ref_.get(), target, 0, GL_RGBA, 0, 0, 1, 0, + GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); manager_->SetLevelImage(texture_ref_.get(), target, 0, image.get()); GLuint service_id = texture->service_id(); Texture* produced_texture = Produce(texture_ref_.get()); @@ -2170,22 +1670,10 @@ TEST_F(ProduceConsumeTextureTest, ProduceConsumeCube) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_CUBE_MAP); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP), texture->target()); - LevelInfo face0(GL_TEXTURE_CUBE_MAP_POSITIVE_X, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_UNSIGNED_BYTE, - true); - LevelInfo face5(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - GL_RGBA, - 3, - 3, - 1, - 0, - GL_UNSIGNED_BYTE, - true); + LevelInfo face0(GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_RGBA, 1, 1, 1, 0, + GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); + LevelInfo face5(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_RGBA, 3, 3, 1, 0, + GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); SetLevelInfo(texture_ref_.get(), 0, face0); SetLevelInfo(texture_ref_.get(), 0, face5); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); @@ -2335,17 +1823,8 @@ TEST_F(SharedTextureTest, TextureSafetyAccounting) { EXPECT_FALSE(texture_manager2_->HaveUnsafeTextures()); EXPECT_FALSE(texture_manager2_->HaveUnclearedMips()); - texture_manager1_->SetLevelInfo(ref1.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + texture_manager1_->SetLevelInfo(ref1.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(texture_manager1_->HaveUnrenderableTextures()); EXPECT_TRUE(texture_manager1_->HaveUnsafeTextures()); EXPECT_TRUE(texture_manager1_->HaveUnclearedMips()); @@ -2385,17 +1864,9 @@ TEST_F(SharedTextureTest, FBOCompletenessCheck) { // Make FBO complete in manager 1. texture_manager1_->SetTarget(ref1.get(), GL_TEXTURE_2D); - texture_manager1_->SetLevelInfo(ref1.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + texture_manager1_->SetLevelInfo(ref1.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(1, 1)); EXPECT_EQ(kCompleteValue, framebuffer1->IsPossiblyComplete()); framebuffer_manager1.MarkAsComplete(framebuffer1.get()); EXPECT_TRUE(framebuffer_manager1.IsComplete(framebuffer1.get())); @@ -2414,17 +1885,9 @@ TEST_F(SharedTextureTest, FBOCompletenessCheck) { EXPECT_TRUE(framebuffer_manager2.IsComplete(framebuffer2.get())); // Change level for texture, both FBOs should be marked incomplete - texture_manager1_->SetLevelInfo(ref1.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + texture_manager1_->SetLevelInfo(ref1.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(1, 1)); EXPECT_FALSE(framebuffer_manager1.IsComplete(framebuffer1.get())); EXPECT_EQ(kCompleteValue, framebuffer1->IsPossiblyComplete()); framebuffer_manager1.MarkAsComplete(framebuffer1.get()); @@ -2453,17 +1916,8 @@ TEST_F(SharedTextureTest, Memory) { // Newly created texture is unrenderable. scoped_refptr<TextureRef> ref1 = texture_manager1_->CreateTexture(10, 10); texture_manager1_->SetTarget(ref1.get(), GL_TEXTURE_2D); - texture_manager1_->SetLevelInfo(ref1.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 10, - 10, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - false); + texture_manager1_->SetLevelInfo(ref1.get(), GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_LT(0u, ref1->texture()->estimated_size()); EXPECT_EQ(initial_memory1 + ref1->texture()->estimated_size(), @@ -2501,17 +1955,9 @@ TEST_F(SharedTextureTest, Images) { texture_manager2_->Consume(20, ref1->texture()); texture_manager1_->SetTarget(ref1.get(), GL_TEXTURE_2D); - texture_manager1_->SetLevelInfo(ref1.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 2, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + texture_manager1_->SetLevelInfo(ref1.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(2, 2)); EXPECT_FALSE(ref1->texture()->HasImages()); EXPECT_FALSE(ref2->texture()->HasImages()); EXPECT_FALSE(texture_manager1_->HaveImages()); @@ -2528,17 +1974,9 @@ TEST_F(SharedTextureTest, Images) { EXPECT_TRUE(ref2->texture()->HasImages()); EXPECT_TRUE(texture_manager1_->HaveImages()); EXPECT_TRUE(texture_manager2_->HaveImages()); - texture_manager1_->SetLevelInfo(ref1.get(), - GL_TEXTURE_2D, - 1, - GL_RGBA, - 2, - 2, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + texture_manager1_->SetLevelInfo(ref1.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(2, 2)); EXPECT_FALSE(ref1->texture()->HasImages()); EXPECT_FALSE(ref2->texture()->HasImages()); EXPECT_FALSE(texture_manager1_->HaveImages()); @@ -2551,5 +1989,263 @@ TEST_F(SharedTextureTest, Images) { texture_manager2_->RemoveTexture(20); } + +class TextureFormatTypeValidationTest : public TextureManagerTest { + public: + TextureFormatTypeValidationTest() {} + ~TextureFormatTypeValidationTest() override {} + + protected: + void SetupFeatureInfo(const char* gl_extensions, const char* gl_version) { + TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( + gl_.get(), gl_extensions, "", gl_version); + feature_info_->Initialize(); + } + + void ExpectValid(GLenum format, GLenum type, GLenum internal_format) { + EXPECT_TRUE(manager_->ValidateTextureParameters( + error_state_.get(), "", format, type, internal_format, 0)); + } + + void ExpectInvalid(GLenum format, GLenum type, GLenum internal_format) { + EXPECT_CALL(*error_state_, + SetGLError(_, _, _, _, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_FALSE(manager_->ValidateTextureParameters( + error_state_.get(), "", format, type, internal_format, 0)); + } + + void ExpectInvalidEnum(GLenum format, GLenum type, GLenum internal_format) { + EXPECT_CALL(*error_state_, + SetGLErrorInvalidEnum(_, _, _, _, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_FALSE(manager_->ValidateTextureParameters( + error_state_.get(), "", format, type, internal_format, 0)); + } +}; + +TEST_F(TextureFormatTypeValidationTest, ES2Basic) { + SetupFeatureInfo("", "OpenGL ES 2.0"); + + ExpectValid(GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA); + ExpectValid(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB); + ExpectValid(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA); + ExpectValid(GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE); + ExpectValid(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE_ALPHA); + + ExpectInvalid(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA); + + // float / half_float. + ExpectInvalidEnum(GL_RGBA, GL_FLOAT, GL_RGBA); + ExpectInvalidEnum(GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA); + + // GL_EXT_bgra + ExpectInvalidEnum(GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA_EXT); + + // depth / stencil + ExpectInvalidEnum(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT); + ExpectInvalidEnum(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH_STENCIL); + + // SRGB + ExpectInvalidEnum(GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB_EXT); + ExpectInvalidEnum(GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB_ALPHA_EXT); + + // ES3 + ExpectInvalidEnum(GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithExtBGRA) { + SetupFeatureInfo("GL_EXT_bgra", "OpenGL ES 2.0"); + + ExpectValid(GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA_EXT); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithExtTextureFormatBGRA8888) { + SetupFeatureInfo("GL_EXT_texture_format_BGRA8888", "OpenGL ES 2.0"); + + ExpectValid(GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA_EXT); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithAppleTextureFormatBGRA8888) { + SetupFeatureInfo("GL_APPLE_texture_format_BGRA8888", "OpenGL ES 2.0"); + + ExpectValid(GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA_EXT); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithArbDepth) { + SetupFeatureInfo("GL_ARB_depth_texture", "OpenGL ES 2.0"); + + ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT); + ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT); + ExpectInvalidEnum(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH_STENCIL); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithOesDepth) { + SetupFeatureInfo("GL_OES_depth_texture", "OpenGL ES 2.0"); + + ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT); + ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT); + ExpectInvalidEnum(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH_STENCIL); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithAngleDepth) { + SetupFeatureInfo("GL_ANGLE_depth_texture", "OpenGL ES 2.0"); + + ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT); + ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT); + ExpectInvalidEnum(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH_STENCIL); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithExtPackedDepthStencil) { + SetupFeatureInfo( + "GL_EXT_packed_depth_stencil GL_ARB_depth_texture", "OpenGL ES 2.0"); + + ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT); + ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT); + ExpectValid(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH_STENCIL); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithRGWithFloat) { + SetupFeatureInfo( + "GL_EXT_texture_rg GL_OES_texture_float GL_OES_texture_half_float", + "OpenGL ES 2.0"); + + ExpectValid(GL_RED_EXT, GL_HALF_FLOAT_OES, GL_RED_EXT); + ExpectValid(GL_RG_EXT, GL_HALF_FLOAT_OES, GL_RG_EXT); + ExpectValid(GL_RED_EXT, GL_UNSIGNED_BYTE, GL_RED_EXT); + ExpectValid(GL_RG_EXT, GL_UNSIGNED_BYTE, GL_RG_EXT); + + ExpectInvalidEnum(GL_RED_EXT, GL_BYTE, GL_RED_EXT); + ExpectInvalidEnum(GL_RG_EXT, GL_BYTE, GL_RG_EXT); + ExpectInvalidEnum(GL_RED_EXT, GL_SHORT, GL_RED_EXT); + ExpectInvalidEnum(GL_RG_EXT, GL_SHORT, GL_RG_EXT); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithRGNoFloat) { + SetupFeatureInfo("GL_ARB_texture_rg", "OpenGL ES 2.0"); + + ExpectValid(GL_RED_EXT, GL_UNSIGNED_BYTE, GL_RED_EXT); + ExpectValid(GL_RG_EXT, GL_UNSIGNED_BYTE, GL_RG_EXT); + + ExpectInvalidEnum(GL_RED_EXT, GL_HALF_FLOAT_OES, GL_RED_EXT); + ExpectInvalidEnum(GL_RG_EXT, GL_HALF_FLOAT_OES, GL_RG_EXT); +} + +TEST_F(TextureFormatTypeValidationTest, ES2OnTopOfES3) { + SetupFeatureInfo("", "OpenGL ES 3.0"); + + ExpectInvalidEnum(GL_RGB, GL_FLOAT, GL_RGB); + ExpectInvalidEnum(GL_RGBA, GL_FLOAT, GL_RGBA); + ExpectInvalidEnum(GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE); + ExpectInvalidEnum(GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA); + ExpectInvalidEnum(GL_ALPHA, GL_FLOAT, GL_ALPHA); + + ExpectInvalidEnum(GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB_EXT); + ExpectInvalidEnum(GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB_ALPHA_EXT); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithOesTextureFloat) { + SetupFeatureInfo("GL_OES_texture_float", "OpenGL ES 2.0"); + + ExpectValid(GL_RGB, GL_FLOAT, GL_RGB); + ExpectValid(GL_RGBA, GL_FLOAT, GL_RGBA); + ExpectValid(GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE); + ExpectValid(GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA); + ExpectValid(GL_ALPHA, GL_FLOAT, GL_ALPHA); + + ExpectInvalidEnum(GL_RGB, GL_HALF_FLOAT_OES, GL_RGB); + ExpectInvalidEnum(GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA); + ExpectInvalidEnum(GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE); + ExpectInvalidEnum(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA); + ExpectInvalidEnum(GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithOesTextureFloatLinear) { + SetupFeatureInfo( + "GL_OES_texture_float GL_OES_texture_float_linear", "OpenGL ES 2.0"); + + ExpectValid(GL_RGB, GL_FLOAT, GL_RGB); + ExpectValid(GL_RGBA, GL_FLOAT, GL_RGBA); + ExpectValid(GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE); + ExpectValid(GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA); + ExpectValid(GL_ALPHA, GL_FLOAT, GL_ALPHA); + + ExpectInvalidEnum(GL_RGB, GL_HALF_FLOAT_OES, GL_RGB); + ExpectInvalidEnum(GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA); + ExpectInvalidEnum(GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE); + ExpectInvalidEnum(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA); + ExpectInvalidEnum(GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithOesTextureHalfFloat) { + SetupFeatureInfo("GL_OES_texture_half_float", "OpenGL ES 2.0"); + + ExpectValid(GL_RGB, GL_HALF_FLOAT_OES, GL_RGB); + ExpectValid(GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA); + ExpectValid(GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE); + ExpectValid(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA); + ExpectValid(GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA); + + ExpectInvalidEnum(GL_RGB, GL_FLOAT, GL_RGB); + ExpectInvalidEnum(GL_RGBA, GL_FLOAT, GL_RGBA); + ExpectInvalidEnum(GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE); + ExpectInvalidEnum(GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA); + ExpectInvalidEnum(GL_ALPHA, GL_FLOAT, GL_ALPHA); +} + +TEST_F(TextureFormatTypeValidationTest, ES2WithOesTextureHalfFloatLinear) { + SetupFeatureInfo( + "GL_OES_texture_half_float GL_OES_texture_half_float_linear", + "OpenGL ES 2.0"); + + ExpectValid(GL_RGB, GL_HALF_FLOAT_OES, GL_RGB); + ExpectValid(GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA); + ExpectValid(GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE); + ExpectValid(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA); + ExpectValid(GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA); + + ExpectInvalidEnum(GL_RGB, GL_FLOAT, GL_RGB); + ExpectInvalidEnum(GL_RGBA, GL_FLOAT, GL_RGBA); + ExpectInvalidEnum(GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE); + ExpectInvalidEnum(GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA); + ExpectInvalidEnum(GL_ALPHA, GL_FLOAT, GL_ALPHA); +} + +TEST_F(TextureFormatTypeValidationTest, ES3Basic) { + SetupFeatureInfo("", "OpenGL ES 3.0"); + EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_COLOR_ATTACHMENTS, _)) + .WillOnce(SetArgPointee<1>(8)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_DRAW_BUFFERS, _)) + .WillOnce(SetArgPointee<1>(8)) + .RetiresOnSaturation(); + feature_info_->EnableES3Validators(); + + ExpectValid(GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA); + ExpectValid(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB); + ExpectValid(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA); + ExpectValid(GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE); + ExpectValid(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE_ALPHA); + + ExpectValid(GL_RG, GL_BYTE, GL_RG8_SNORM); + ExpectValid(GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI); + ExpectValid(GL_RG_INTEGER, GL_SHORT, GL_RG16I); + ExpectValid(GL_RGB, GL_UNSIGNED_BYTE, GL_SRGB8); + ExpectValid(GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F); + ExpectValid(GL_RGBA, GL_FLOAT, GL_RGBA16F); + ExpectValid(GL_RGBA, GL_FLOAT, GL_RGBA32F); + + ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16); + ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT24); + ExpectValid(GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F); + ExpectValid(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8); + ExpectValid(GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, + GL_DEPTH32F_STENCIL8); + + ExpectInvalid(GL_RGB_INTEGER, GL_INT, GL_RGBA8); +} + } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/transfer_buffer_manager.h b/chromium/gpu/command_buffer/service/transfer_buffer_manager.h index f867790d431..8fae98c911f 100644 --- a/chromium/gpu/command_buffer/service/transfer_buffer_manager.h +++ b/chromium/gpu/command_buffer/service/transfer_buffer_manager.h @@ -11,19 +11,24 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/containers/hash_tables.h" +#include "base/memory/ref_counted.h" #include "base/memory/shared_memory.h" #include "gpu/command_buffer/common/command_buffer_shared.h" namespace gpu { -class GPU_EXPORT TransferBufferManagerInterface { +class GPU_EXPORT TransferBufferManagerInterface : + public base::RefCounted<TransferBufferManagerInterface> { public: - virtual ~TransferBufferManagerInterface(); - virtual bool RegisterTransferBuffer(int32 id, scoped_ptr<BufferBacking> buffer) = 0; virtual void DestroyTransferBuffer(int32 id) = 0; virtual scoped_refptr<Buffer> GetTransferBuffer(int32 id) = 0; + + protected: + friend class base::RefCounted<TransferBufferManagerInterface>; + + virtual ~TransferBufferManagerInterface(); }; class GPU_EXPORT TransferBufferManager diff --git a/chromium/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc index 6f35601debd..5dbcfa140d3 100644 --- a/chromium/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc @@ -18,11 +18,11 @@ class TransferBufferManagerTest : public testing::Test { protected: void SetUp() override { TransferBufferManager* manager = new TransferBufferManager(); - transfer_buffer_manager_.reset(manager); + transfer_buffer_manager_ = manager; ASSERT_TRUE(manager->Initialize()); } - scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; + scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; }; TEST_F(TransferBufferManagerTest, ZeroHandleMapsToNull) { diff --git a/chromium/gpu/command_buffer/service/valuebuffer_manager.h b/chromium/gpu/command_buffer/service/valuebuffer_manager.h index d67616a104b..774b3a3289c 100644 --- a/chromium/gpu/command_buffer/service/valuebuffer_manager.h +++ b/chromium/gpu/command_buffer/service/valuebuffer_manager.h @@ -52,7 +52,7 @@ class GPU_EXPORT SubscriptionRefSet RefSet reference_set_; - ObserverList<Observer, true> observers_; + base::ObserverList<Observer, true> observers_; DISALLOW_COPY_AND_ASSIGN(SubscriptionRefSet); }; diff --git a/chromium/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc b/chromium/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc index 81ad6cd2940..9c521949ded 100644 --- a/chromium/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc @@ -134,6 +134,7 @@ TEST_F(VertexAttribManagerTest, HaveFixedAttribs) { } TEST_F(VertexAttribManagerTest, CanAccess) { + const GLenum kTarget = GL_ARRAY_BUFFER; MockErrorState error_state; BufferManager buffer_manager(NULL, NULL); buffer_manager.CreateBuffer(1, 2); @@ -149,15 +150,15 @@ TEST_F(VertexAttribManagerTest, CanAccess) { manager_->SetAttribInfo(1, buffer, 4, GL_FLOAT, GL_FALSE, 0, 16, 0, GL_FALSE); EXPECT_FALSE(attrib->CanAccess(0)); - EXPECT_TRUE(buffer_manager.SetTarget(buffer, GL_ARRAY_BUFFER)); + EXPECT_TRUE(buffer_manager.SetTarget(buffer, kTarget)); TestHelper::DoBufferData( - gl_.get(), &error_state, &buffer_manager, buffer, 15, GL_STATIC_DRAW, - NULL, GL_NO_ERROR); + gl_.get(), &error_state, &buffer_manager, buffer, + kTarget, 15, GL_STATIC_DRAW, NULL, GL_NO_ERROR); EXPECT_FALSE(attrib->CanAccess(0)); TestHelper::DoBufferData( - gl_.get(), &error_state, &buffer_manager, buffer, 16, GL_STATIC_DRAW, - NULL, GL_NO_ERROR); + gl_.get(), &error_state, &buffer_manager, buffer, + kTarget, 16, GL_STATIC_DRAW, NULL, GL_NO_ERROR); EXPECT_TRUE(attrib->CanAccess(0)); EXPECT_FALSE(attrib->CanAccess(1)); @@ -165,8 +166,8 @@ TEST_F(VertexAttribManagerTest, CanAccess) { EXPECT_FALSE(attrib->CanAccess(0)); TestHelper::DoBufferData( - gl_.get(), &error_state, &buffer_manager, buffer, 32, GL_STATIC_DRAW, - NULL, GL_NO_ERROR); + gl_.get(), &error_state, &buffer_manager, buffer, + kTarget, 32, GL_STATIC_DRAW, NULL, GL_NO_ERROR); EXPECT_TRUE(attrib->CanAccess(0)); EXPECT_FALSE(attrib->CanAccess(1)); manager_->SetAttribInfo(1, buffer, 4, GL_FLOAT, GL_FALSE, 0, 16, 0, GL_FALSE); diff --git a/chromium/gpu/config/gpu_control_list.cc b/chromium/gpu/config/gpu_control_list.cc index f71c15f128d..e187b5fc4c8 100644 --- a/chromium/gpu/config/gpu_control_list.cc +++ b/chromium/gpu/config/gpu_control_list.cc @@ -1029,7 +1029,7 @@ bool GpuControlList::GpuControlListEntry::GLVersionInfoMismatch( gl_type = kGLTypeGLES; if (segments.size() > 3 && - StartsWithASCII(segments[3], "(ANGLE", false)) { + base::StartsWithASCII(segments[3], "(ANGLE", false)) { gl_type = kGLTypeANGLE; } } else { @@ -1250,14 +1250,15 @@ bool GpuControlList::GpuControlListEntry::Contains( for (size_t i = 0; i < exceptions_.size(); ++i) { if (exceptions_[i]->Contains(os_type, os_version, gpu_info) && - !exceptions_[i]->NeedsMoreInfo(gpu_info)) + !exceptions_[i]->NeedsMoreInfo(gpu_info, true)) return false; } return true; } bool GpuControlList::GpuControlListEntry::NeedsMoreInfo( - const GPUInfo& gpu_info) const { + const GPUInfo& gpu_info, + bool consider_exceptions) const { // We only check for missing info that might be collected with a gl context. // If certain info is missing due to some error, say, we fail to collect // vendor_id/device_id, then even if we launch GPU process and create a gl @@ -1270,10 +1271,14 @@ bool GpuControlList::GpuControlListEntry::NeedsMoreInfo( return true; if (!gl_renderer_info_.empty() && gpu_info.gl_renderer.empty()) return true; - for (size_t i = 0; i < exceptions_.size(); ++i) { - if (exceptions_[i]->NeedsMoreInfo(gpu_info)) - return true; + + if (consider_exceptions) { + for (size_t i = 0; i < exceptions_.size(); ++i) { + if (exceptions_[i]->NeedsMoreInfo(gpu_info, consider_exceptions)) + return true; + } } + return false; } @@ -1337,8 +1342,7 @@ GpuControlList::~GpuControlList() { bool GpuControlList::LoadList( const std::string& json_context, GpuControlList::OsFilter os_filter) { - scoped_ptr<base::Value> root; - root.reset(base::JSONReader::Read(json_context)); + scoped_ptr<base::Value> root = base::JSONReader::Read(json_context); if (root.get() == NULL || !root->IsType(base::Value::TYPE_DICTIONARY)) return false; @@ -1396,7 +1400,12 @@ std::set<int> GpuControlList::MakeDecision( std::set<int> features; needs_more_info_ = false; - std::set<int> possible_features; + // Has all features permanently in the list without any possibility of + // removal in the future (subset of "features" set). + std::set<int> permanent_features; + // Has all features absent from "features" set that could potentially be + // included later with more information. + std::set<int> potential_features; if (os == kOsAny) os = GetOsType(); @@ -1404,23 +1413,38 @@ std::set<int> GpuControlList::MakeDecision( os_version = base::SysInfo::OperatingSystemVersion(); for (size_t i = 0; i < entries_.size(); ++i) { - if (entries_[i]->Contains(os, os_version, gpu_info)) { - bool needs_more_info = entries_[i]->NeedsMoreInfo(gpu_info); - if (!entries_[i]->disabled()) { + ScopedGpuControlListEntry entry = entries_[i]; + if (entry->Contains(os, os_version, gpu_info)) { + bool needs_more_info_main = entry->NeedsMoreInfo(gpu_info, false); + bool needs_more_info_exception = entry->NeedsMoreInfo(gpu_info, true); + + if (!entry->disabled()) { if (control_list_logging_enabled_) - entries_[i]->LogControlListMatch(control_list_logging_name_); - MergeFeatureSets(&possible_features, entries_[i]->features()); - if (!needs_more_info) - MergeFeatureSets(&features, entries_[i]->features()); + entry->LogControlListMatch(control_list_logging_name_); + // Only look at main entry info when deciding what to add to "features" + // set. If we don't have enough info for an exception, it's safer if we + // just ignore the exception and assume the exception doesn't apply. + for (std::set<int>::const_iterator iter = entry->features().begin(); + iter != entry->features().end(); ++iter) { + if (needs_more_info_main) { + if (!features.count(*iter)) + potential_features.insert(*iter); + } else { + features.insert(*iter); + potential_features.erase(*iter); + if (!needs_more_info_exception) + permanent_features.insert(*iter); + } + } } - if (!needs_more_info) - active_entries_.push_back(entries_[i]); + + if (!needs_more_info_main) + active_entries_.push_back(entry); } } - if (possible_features.size() > features.size()) - needs_more_info_ = true; - + needs_more_info_ = permanent_features.size() < features.size() || + !potential_features.empty(); return features; } diff --git a/chromium/gpu/config/gpu_control_list.h b/chromium/gpu/config/gpu_control_list.h index 3cd7625d99e..32494154bf4 100644 --- a/chromium/gpu/config/gpu_control_list.h +++ b/chromium/gpu/config/gpu_control_list.h @@ -269,7 +269,7 @@ class GPU_EXPORT GpuControlList { // Determines whether we needs more gpu info to make the blacklisting // decision. It should only be checked if Contains() returns true. - bool NeedsMoreInfo(const GPUInfo& gpu_info) const; + bool NeedsMoreInfo(const GPUInfo& gpu_info, bool consider_exceptions) const; // Returns the OsType. OsType GetOsType() const; diff --git a/chromium/gpu/config/gpu_control_list_entry_unittest.cc b/chromium/gpu/config/gpu_control_list_entry_unittest.cc index f955bdb6590..dbe7031a68e 100644 --- a/chromium/gpu/config/gpu_control_list_entry_unittest.cc +++ b/chromium/gpu/config/gpu_control_list_entry_unittest.cc @@ -30,10 +30,9 @@ class GpuControlListEntryTest : public testing::Test { static ScopedEntry GetEntryFromString( const std::string& json, bool supports_feature_type_all) { - scoped_ptr<base::Value> root; - root.reset(base::JSONReader::Read(json)); + scoped_ptr<base::Value> root = base::JSONReader::Read(json); base::DictionaryValue* value = NULL; - if (root.get() == NULL || !root->GetAsDictionary(&value)) + if (!root || !root->GetAsDictionary(&value)) return NULL; GpuControlList::FeatureMap feature_map; @@ -108,7 +107,7 @@ TEST_F(GpuControlListEntryTest, DetailedEntry) { EXPECT_EQ(1950, entry->webkit_bugs()[0]); EXPECT_EQ(1u, entry->features().size()); EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_0)); - EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info())); + EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info(), true)); EXPECT_TRUE(entry->Contains( GpuControlList::kOsMacosx, "10.6.4", gpu_info())); EXPECT_STREQ("test_extension1", entry->disabled_extensions()[0].c_str()); @@ -763,10 +762,10 @@ TEST_F(GpuControlListEntryTest, NeedsMoreInfoEntry) { GPUInfo gpu_info; gpu_info.gpu.vendor_id = 0x8086; - EXPECT_TRUE(entry->NeedsMoreInfo(gpu_info)); + EXPECT_TRUE(entry->NeedsMoreInfo(gpu_info, true)); gpu_info.driver_version = "10.6"; - EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info)); + EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info, true)); } TEST_F(GpuControlListEntryTest, NeedsMoreInfoForExceptionsEntry) { @@ -789,10 +788,11 @@ TEST_F(GpuControlListEntryTest, NeedsMoreInfoForExceptionsEntry) { GPUInfo gpu_info; gpu_info.gpu.vendor_id = 0x8086; - EXPECT_TRUE(entry->NeedsMoreInfo(gpu_info)); + EXPECT_TRUE(entry->NeedsMoreInfo(gpu_info, true)); + EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info, false)); gpu_info.gl_renderer = "mesa"; - EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info)); + EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info, true)); } TEST_F(GpuControlListEntryTest, FeatureTypeAllEntry) { diff --git a/chromium/gpu/config/gpu_control_list_unittest.cc b/chromium/gpu/config/gpu_control_list_unittest.cc index 91b9d81c966..88452fccdce 100644 --- a/chromium/gpu/config/gpu_control_list_unittest.cc +++ b/chromium/gpu/config/gpu_control_list_unittest.cc @@ -370,7 +370,8 @@ TEST_F(GpuControlListTest, NeedsMoreInfoForExceptions) { // The case this entry might apply, but need more info. features = control_list->MakeDecision( GpuControlList::kOsLinux, kOsVersion, gpu_info); - EXPECT_EMPTY_SET(features); + // Ignore exceptions if main entry info matches + EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0); EXPECT_TRUE(control_list->needs_more_info()); // The case we have full info, and the exception applies (so the entry diff --git a/chromium/gpu/config/gpu_driver_bug_list_json.cc b/chromium/gpu/config/gpu_driver_bug_list_json.cc index 7a270dfc20a..b5e9e6da5f7 100644 --- a/chromium/gpu/config/gpu_driver_bug_list_json.cc +++ b/chromium/gpu/config/gpu_driver_bug_list_json.cc @@ -235,8 +235,9 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( "type": "linux" }, "vendor_id": "0x8086", - "features": [ - "disable_ext_occlusion_query" + "disabled_extensions": [ + "GL_ARB_occlusion_query2", + "GL_ARB_occlusion_query" ] }, { @@ -309,8 +310,8 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( }, "vendor_id": "0x8086", "device_id": ["0xa011", "0xa012"], - "features": [ - "disable_oes_standard_derivatives" + "disabled_extensions": [ + "GL_OES_standard_derivatives" ] }, { @@ -593,13 +594,13 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( }, { "id": 51, - "description": "TexSubImage2D() is faster for full uploads on ANGLE", + "description": "TexSubImage is faster for full uploads on ANGLE", "os": { "type": "win" }, "gl_renderer": "ANGLE.*", "features": [ - "texsubimage2d_faster_than_teximage2d" + "texsubimage_faster_than_teximage" ] }, { @@ -814,8 +815,8 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( "type": "android" }, "gl_extensions": ".*GL_VIV_shader_binary.*", - "features": [ - "disable_oes_standard_derivatives" + "disabled_extensions": [ + "GL_OES_standard_derivatives" ] }, { @@ -850,8 +851,8 @@ LONG_STRING_CONST( } }, "gl_vendor": "Qualcomm.*", - "features": [ - "disable_egl_khr_fence_sync" + "disabled_extensions": [ + "EGL_KHR_fence_sync" ] }, { @@ -883,8 +884,8 @@ LONG_STRING_CONST( } }, "gl_vendor": "Imagination Technologies.*", - "features": [ - "disable_egl_khr_fence_sync" + "disabled_extensions": [ + "EGL_KHR_fence_sync" ] }, { @@ -905,8 +906,8 @@ LONG_STRING_CONST( "op": "<", "value": "3.0" }, - "features": [ - "disable_egl_khr_fence_sync" + "disabled_extensions": [ + "EGL_KHR_fence_sync" ] }, { @@ -921,8 +922,8 @@ LONG_STRING_CONST( } }, "gl_vendor": "Broadcom.*", - "features": [ - "disable_egl_khr_fence_sync" + "disabled_extensions": [ + "EGL_KHR_fence_sync" ] }, { @@ -1064,8 +1065,8 @@ LONG_STRING_CONST( "op": "=", "value": "3.1" }, - "features": [ - "disable_egl_khr_wait_sync" + "disabled_extensions": [ + "EGL_KHR_wait_sync" ] }, { @@ -1174,8 +1175,7 @@ LONG_STRING_CONST( "value": "5.0.2" } }, - "gl_vendor": "Qualcomm.*", - "gl_renderer": ".*420", + "gl_renderer": "Adreno \\(TM\\) 4.*", "features": [ "unbind_attachments_on_bound_render_fbo_delete" ] @@ -1187,15 +1187,14 @@ LONG_STRING_CONST( "os": { "type": "android" }, - "gl_vendor": "Qualcomm.*", - "gl_renderer": ".*420", + "gl_renderer": "Adreno \\(TM\\) 4.*", "features": [ "disable_discard_framebuffer" ] }, { "id": 104, - "description": "EXT_occlusion_query hangs on MediaTek MT8135 pre-Lollipop", + "description": "EXT_occlusion_query_boolean hangs on MediaTek MT8135 pre-Lollipop", "os": { "type": "android", "version": { @@ -1205,8 +1204,8 @@ LONG_STRING_CONST( }, "gl_vendor": "Imagination.*", "gl_renderer": "PowerVR Rogue Han", - "features": [ - "disable_ext_occlusion_query" + "disabled_extensions": [ + "GL_EXT_occlusion_query_boolean" ] }, { @@ -1223,17 +1222,14 @@ LONG_STRING_CONST( }, { "id": 106, - "description": "EXT_occlusion_query hangs on PowerVR SGX 544 (IMG) drivers", + "description": "EXT_occlusion_query_boolean hangs on PowerVR SGX 544 (IMG) drivers", "os": { "type": "android" }, "gl_vendor": "Imagination.*", "gl_renderer": "PowerVR SGX 544", - "features": [ - "disable_ext_occlusion_query" - ], "disabled_extensions": [ - "EXT_occlusion_query_boolean" + "GL_EXT_occlusion_query_boolean" ] }, { @@ -1256,8 +1252,10 @@ LONG_STRING_CONST( "value2": "1.4" }, "features": [ - "avoid_egl_image_target_texture_reuse", - "disable_egl_khr_wait_sync" + "avoid_egl_image_target_texture_reuse" + ], + "disabled_extensions": [ + "EGL_KHR_wait_sync" ] }, { @@ -1282,19 +1280,19 @@ LONG_STRING_CONST( }, { "id": 110, - "description": "EGL Sync server causes crashes on Adreno 3xx drivers", + "description": "EGL Sync server causes crashes on Adreno 2xx and 3xx drivers", "cr_bugs": [482298], "os": { "type": "android" }, "gl_vendor": "Qualcomm.*", - "gl_renderer": "Adreno \\(TM\\) 3.*", + "gl_renderer": "Adreno \\(TM\\) [23].*", "driver_version": { "op": "<", "value": "95" }, - "features": [ - "disable_egl_khr_wait_sync" + "disabled_extensions": [ + "EGL_KHR_wait_sync" ] }, { @@ -1311,6 +1309,52 @@ LONG_STRING_CONST( ] }, { + "id": 112, + "cr_bugs": [477514], + "description": "EXT_disjoint_timer_query fails after 2 queries on adreno 3xx in lollypop", + "os": { + "type": "android", + "version": { + "op": ">=", + "value": "5.0.0" + } + }, + "gl_vendor": "Qualcomm.*", + "gl_renderer": "Adreno \\(TM\\) 3.*", + "features": [ + "disable_timestamp_queries" + ] + }, + { + "id": 113, + "cr_bugs": [477514], + "description": "EXT_disjoint_timer_query fails after 256 queries on adreno 4xx", + "os": { + "type": "android" + }, + "gl_renderer": "Adreno \\(TM\\) 4.*", + "disabled_extensions": [ + "GL_EXT_disjoint_timer_query" + ] + }, + { + "id": 115, + "cr_bugs": [462553], + "description": "glGetIntegerv with GL_GPU_DISJOINT_EXT causes GL_INVALID_ENUM error", + "os": { + "type": "android" + }, + "gl_vendor": "NVIDIA.*", + "gl_type": "gles", + "gl_version": { + "op": ">=", + "value": "3.0" + }, + "disabled_extensions": [ + "GL_EXT_disjoint_timer_query" + ] + }, + { "id": 116, "description": "Adreno 420 support for EXT_multisampled_render_to_texture is buggy on Android < 5.1", "cr_bugs": [490379], @@ -1321,8 +1365,7 @@ LONG_STRING_CONST( "value": "5.1" } }, - "gl_vendor": "Qualcomm.*", - "gl_renderer": ".*420", + "gl_renderer": "Adreno \\(TM\\) 4.*", "features": [ "disable_multisampled_render_to_texture" ] @@ -1341,6 +1384,22 @@ LONG_STRING_CONST( ] }, { + "id": 118, + "cr_bugs": [477306], + "description": "NVIDIA 331 series drivers shader compiler may crash when attempting to optimize pow()", + "os": { + "type": "linux" + }, + "driver_version": { + "op": "<=", + "value": "331" + }, + "vendor_id": "0x10de", + "features": [ + "remove_pow_with_constant_exponent" + ] + }, + { "id": 119, "description": "Context lost recovery often fails on Mali-400/450 on Android.", "cr_bugs": [496438], @@ -1354,6 +1413,62 @@ LONG_STRING_CONST( ] }, { + "id": 120, + "description": "CHROMIUM_copy_texture is slow on Mali pre-Lollipop", + "cr_bugs": [498443], + "os": { + "type": "android", + "version": { + "op": "<", + "value": "5.0.0" + } + }, + "gl_vendor": "ARM.*", + "gl_renderer": "Mali.*", + "features": [ + "max_copy_texture_chromium_size_262144" + ] + }, + { + "id": 121, + "description": "NSCGLSurface API is buggy on multi-GPU systems", + "cr_bugs": [496484], + "os": { + "type": "macosx" + }, + "gpu_count": { + "op": ">", + "value": "1" + }, + "features": [ + "disable_ns_cgl_surface_api" + ] + }, + { + "id": 122, + "description": "NSCGLSurface API unsupported on VMWare drivers", + "cr_bugs": [496484], + "os": { + "type": "macosx" + }, + "vendor_id": "0x15ad", + "features": [ + "disable_ns_cgl_surface_api" + ] + }, + { + "id": 123, + "description": "glFinish doesn't clear caches on Android", + "cr_bugs": [509727], + "os": { + "type": "android" + }, + "gl_renderer": "Adreno.*", + "features": [ + "unbind_egl_context_to_flush_driver_caches" + ] + }, + { "id": 124, "description": "Certain Adreno 4xx drivers often crash in glProgramBinary.", "cr_bugs": [486117], diff --git a/chromium/gpu/config/gpu_driver_bug_workaround_type.h b/chromium/gpu/config/gpu_driver_bug_workaround_type.h index 27243563291..41f2918fb27 100644 --- a/chromium/gpu/config/gpu_driver_bug_workaround_type.h +++ b/chromium/gpu/config/gpu_driver_bug_workaround_type.h @@ -20,8 +20,6 @@ count_all_in_varyings_packing) \ GPU_OP(DISABLE_ANGLE_INSTANCED_ARRAYS, \ disable_angle_instanced_arrays) \ - GPU_OP(DISABLE_ARB_SYNC, \ - disable_arb_sync) \ GPU_OP(DISABLE_ASYNC_READPIXELS, \ disable_async_readpixels) \ GPU_OP(DISABLE_BLEND_EQUATION_ADVANCED, \ @@ -32,26 +30,24 @@ disable_d3d11) \ GPU_OP(DISABLE_DEPTH_TEXTURE, \ disable_depth_texture) \ - GPU_OP(DISABLE_EGL_KHR_FENCE_SYNC, \ - disable_egl_khr_fence_sync) \ - GPU_OP(DISABLE_EGL_KHR_WAIT_SYNC, \ - disable_egl_khr_wait_sync) \ GPU_OP(DISABLE_DISCARD_FRAMEBUFFER, \ disable_discard_framebuffer) \ GPU_OP(DISABLE_EXT_DRAW_BUFFERS, \ disable_ext_draw_buffers) \ - GPU_OP(DISABLE_EXT_OCCLUSION_QUERY, \ - disable_ext_occlusion_query) \ + GPU_OP(DISABLE_GL_RGB_FORMAT, \ + disable_gl_rgb_format) \ GPU_OP(DISABLE_MULTIMONITOR_MULTISAMPLING, \ disable_multimonitor_multisampling) \ GPU_OP(DISABLE_MULTISAMPLED_RENDER_TO_TEXTURE, \ disable_multisampled_render_to_texture) \ - GPU_OP(DISABLE_OES_STANDARD_DERIVATIVES, \ - disable_oes_standard_derivatives) \ + GPU_OP(DISABLE_NS_CGL_SURFACE_API, \ + disable_ns_cgl_surface_api) \ GPU_OP(DISABLE_POST_SUB_BUFFERS_FOR_ONSCREEN_SURFACES, \ disable_post_sub_buffers_for_onscreen_surfaces) \ GPU_OP(DISABLE_PROGRAM_CACHE, \ disable_program_cache) \ + GPU_OP(DISABLE_TIMESTAMP_QUERIES, \ + disable_timestamp_queries) \ GPU_OP(ETC1_POWER_OF_TWO_ONLY, \ etc1_power_of_two_only) \ GPU_OP(EXIT_ON_CONTEXT_LOST, \ @@ -76,6 +72,8 @@ init_varyings_without_static_use) \ GPU_OP(INIT_VERTEX_ATTRIBUTES, \ init_vertex_attributes) \ + GPU_OP(MAX_COPY_TEXTURE_CHROMIUM_SIZE_262144, \ + max_copy_texture_chromium_size_262144) \ GPU_OP(MAX_CUBE_MAP_TEXTURE_SIZE_LIMIT_1024, \ max_cube_map_texture_size_limit_1024) \ GPU_OP(MAX_CUBE_MAP_TEXTURE_SIZE_LIMIT_4096, \ @@ -96,6 +94,8 @@ needs_offscreen_buffer_workaround) \ GPU_OP(REGENERATE_STRUCT_NAMES, \ regenerate_struct_names) \ + GPU_OP(REMOVE_POW_WITH_CONSTANT_EXPONENT, \ + remove_pow_with_constant_exponent) \ GPU_OP(RESTORE_SCISSOR_ON_FBO_CHANGE, \ restore_scissor_on_fbo_change) \ GPU_OP(REVERSE_POINT_SPRITE_COORD_ORIGIN, \ @@ -108,8 +108,8 @@ simulate_out_of_memory_on_large_textures) \ GPU_OP(SWIZZLE_RGBA_FOR_ASYNC_READPIXELS, \ swizzle_rgba_for_async_readpixels) \ - GPU_OP(TEXSUBIMAGE2D_FASTER_THAN_TEXIMAGE2D, \ - texsubimage2d_faster_than_teximage2d) \ + GPU_OP(TEXSUBIMAGE_FASTER_THAN_TEXIMAGE, \ + texsubimage_faster_than_teximage) \ GPU_OP(UNBIND_ATTACHMENTS_ON_BOUND_RENDER_FBO_DELETE, \ unbind_attachments_on_bound_render_fbo_delete) \ GPU_OP(UNBIND_FBO_ON_CONTEXT_SWITCH, \ @@ -130,13 +130,13 @@ validate_multisample_buffer_allocation) \ GPU_OP(WAKE_UP_GPU_BEFORE_DRAWING, \ wake_up_gpu_before_drawing) \ - GPU_OP(DISABLE_GL_RGB_FORMAT, \ - disable_gl_rgb_format) \ + GPU_OP(UNBIND_EGL_CONTEXT_TO_FLUSH_DRIVER_CACHES, \ + unbind_egl_context_to_flush_driver_caches) \ namespace gpu { // Provides all types of GPU driver bug workarounds. -enum GPU_EXPORT GpuDriverBugWorkaroundType { +enum GpuDriverBugWorkaroundType { #define GPU_OP(type, name) type, GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) #undef GPU_OP diff --git a/chromium/gpu/config/gpu_info_collector.cc b/chromium/gpu/config/gpu_info_collector.cc index 2403340fb2c..8ef3d3cada5 100644 --- a/chromium/gpu/config/gpu_info_collector.cc +++ b/chromium/gpu/config/gpu_info_collector.cc @@ -12,7 +12,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" -#include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" @@ -104,7 +103,7 @@ CollectInfoResult CollectGraphicsInfoGL(GPUInfo* gpu_info) { std::string glsl_version_string = GetGLString(GL_SHADING_LANGUAGE_VERSION); GLint max_samples = 0; glGetIntegerv(GL_MAX_SAMPLES, &max_samples); - gpu_info->max_msaa_samples = base::StringPrintf("%d", max_samples); + gpu_info->max_msaa_samples = base::IntToString(max_samples); gfx::GLWindowSystemBindingInfo window_system_binding_info; if (GetGLWindowSystemBindingInfo(&window_system_binding_info)) { diff --git a/chromium/gpu/config/gpu_info_collector_android.cc b/chromium/gpu/config/gpu_info_collector_android.cc index 97a79e53eb6..93da6a93723 100644 --- a/chromium/gpu/config/gpu_info_collector_android.cc +++ b/chromium/gpu/config/gpu_info_collector_android.cc @@ -6,32 +6,29 @@ #include "base/android/build_info.h" #include "base/command_line.h" +#include "base/files/file_path.h" #include "base/logging.h" +#include "base/native_library.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "ui/gl/egl_util.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_surface.h" namespace { -std::string GetDriverVersionFromString(const std::string& version_string) { - // Extract driver version from the second number in a string like: - // "OpenGL ES 2.0 V@6.0 AU@ (CL@2946718)" - - // Exclude first "2.0". - size_t begin = version_string.find_first_of("0123456789"); +std::pair<std::string, size_t> GetVersionFromString( + const std::string& version_string, + size_t begin = 0) { + begin = version_string.find_first_of("0123456789", begin); if (begin == std::string::npos) - return "0"; - size_t end = version_string.find_first_not_of("01234567890.", begin); + return std::make_pair("", std::string::npos); - // Extract number of the form "%d.%d" - begin = version_string.find_first_of("0123456789", end); - if (begin == std::string::npos) - return "0"; - end = version_string.find_first_not_of("01234567890.", begin); + size_t end = version_string.find_first_not_of("01234567890.", begin); std::string sub_string; if (end != std::string::npos) sub_string = version_string.substr(begin, end - begin); @@ -39,45 +36,206 @@ std::string GetDriverVersionFromString(const std::string& version_string) { sub_string = version_string.substr(begin); std::vector<std::string> pieces; base::SplitString(sub_string, '.', &pieces); - if (pieces.size() < 2) - return "0"; - return pieces[0] + "." + pieces[1]; + if (pieces.size() >= 2) + return std::make_pair(pieces[0] + "." + pieces[1], end); + else + return std::make_pair("", end); } -class ScopedRestoreNonOwnedEGLContext { - public: - ScopedRestoreNonOwnedEGLContext(); - ~ScopedRestoreNonOwnedEGLContext(); - - private: - EGLContext context_; - EGLDisplay display_; - EGLSurface draw_surface_; - EGLSurface read_surface_; -}; - -ScopedRestoreNonOwnedEGLContext::ScopedRestoreNonOwnedEGLContext() - : context_(EGL_NO_CONTEXT), - display_(EGL_NO_DISPLAY), - draw_surface_(EGL_NO_SURFACE), - read_surface_(EGL_NO_SURFACE) { - // This should only used to restore a context that is not created or owned by - // Chromium native code, but created by Android system itself. - DCHECK(!gfx::GLContext::GetCurrent()); - - context_ = eglGetCurrentContext(); - display_ = eglGetCurrentDisplay(); - draw_surface_ = eglGetCurrentSurface(EGL_DRAW); - read_surface_ = eglGetCurrentSurface(EGL_READ); +std::string GetDriverVersionFromString(const std::string& version_string) { + // We expect that android GL_VERSION strings will be of a form + // similar to: "OpenGL ES 2.0 V@6.0 AU@ (CL@2946718)" where the + // first match to [0-9][0-9.]* is the OpenGL ES version number, and + // the second match to [0-9][0-9.]* is the driver version (in this + // case, 6.0). + // It is currently assumed that the driver version has at least one + // period in it, and only the first two components are significant. + size_t begin = GetVersionFromString(version_string).second; + if (begin == std::string::npos) + return "0"; + + std::pair<std::string, size_t> driver_version = + GetVersionFromString(version_string, begin); + if (driver_version.first == "") + return "0"; + + return driver_version.first; } -ScopedRestoreNonOwnedEGLContext::~ScopedRestoreNonOwnedEGLContext() { - if (context_ == EGL_NO_CONTEXT || display_ == EGL_NO_DISPLAY || - draw_surface_ == EGL_NO_SURFACE || read_surface_ == EGL_NO_SURFACE) - return; +gpu::CollectInfoResult CollectDriverInfo(gpu::GPUInfo* gpu_info) { + // Go through the process of loading GL libs and initializing an EGL + // context so that we can get GL vendor/version/renderer strings. + base::NativeLibrary gles_library, egl_library; + base::NativeLibraryLoadError error; + gles_library = + base::LoadNativeLibrary(base::FilePath("libGLESv2.so"), &error); + if (!gles_library) + LOG(FATAL) << "Failed to load libGLESv2.so"; + + egl_library = base::LoadNativeLibrary(base::FilePath("libEGL.so"), &error); + if (!egl_library) + LOG(FATAL) << "Failed to load libEGL.so"; + + typedef void* (*eglGetProcAddressProc)(const char* name); + + auto eglGetProcAddressFn = reinterpret_cast<eglGetProcAddressProc>( + base::GetFunctionPointerFromNativeLibrary(egl_library, + "eglGetProcAddress")); + if (!eglGetProcAddressFn) + LOG(FATAL) << "eglGetProcAddress not found."; + + auto get_func = [eglGetProcAddressFn, gles_library, egl_library]( + const char* name) { + void *proc; + proc = base::GetFunctionPointerFromNativeLibrary(egl_library, name); + if (proc) + return proc; + proc = base::GetFunctionPointerFromNativeLibrary(gles_library, name); + if (proc) + return proc; + proc = eglGetProcAddressFn(name); + if (proc) + return proc; + LOG(FATAL) << "Failed to look up " << name; + return (void *)nullptr; + }; + +#define LOOKUP_FUNC(x) auto x##Fn = reinterpret_cast<gfx::x##Proc>(get_func(#x)) + + LOOKUP_FUNC(eglGetError); + LOOKUP_FUNC(eglQueryString); + LOOKUP_FUNC(eglGetCurrentContext); + LOOKUP_FUNC(eglGetCurrentDisplay); + LOOKUP_FUNC(eglGetCurrentSurface); + LOOKUP_FUNC(eglGetDisplay); + LOOKUP_FUNC(eglInitialize); + LOOKUP_FUNC(eglChooseConfig); + LOOKUP_FUNC(eglCreateContext); + LOOKUP_FUNC(eglCreatePbufferSurface); + LOOKUP_FUNC(eglMakeCurrent); + LOOKUP_FUNC(eglDestroySurface); + LOOKUP_FUNC(eglDestroyContext); + + LOOKUP_FUNC(glGetString); + LOOKUP_FUNC(glGetIntegerv); + +#undef LOOKUP_FUNC + + EGLDisplay curr_display = eglGetCurrentDisplayFn(); + EGLContext curr_context = eglGetCurrentContextFn(); + EGLSurface curr_draw_surface = eglGetCurrentSurfaceFn(EGL_DRAW); + EGLSurface curr_read_surface = eglGetCurrentSurfaceFn(EGL_READ); + + EGLDisplay temp_display = EGL_NO_DISPLAY; + EGLContext temp_context = EGL_NO_CONTEXT; + EGLSurface temp_surface = EGL_NO_SURFACE; + + const EGLint kConfigAttribs[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_NONE}; + const EGLint kContextAttribs[] = { + EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, + EGL_LOSE_CONTEXT_ON_RESET_EXT, + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE}; + const EGLint kSurfaceAttribs[] = { + EGL_WIDTH, 1, + EGL_HEIGHT, 1, + EGL_NONE}; + + EGLint major, minor; + + EGLConfig config; + EGLint num_configs; + + auto errorstr = [eglGetErrorFn]() { + uint32_t err = eglGetErrorFn(); + return base::StringPrintf("%s (%x)", ui::GetEGLErrorString(err), err); + }; + + temp_display = eglGetDisplayFn(EGL_DEFAULT_DISPLAY); + + if (temp_display == EGL_NO_DISPLAY) { + LOG(FATAL) << "failed to get display. " << errorstr(); + } + + eglInitializeFn(temp_display, &major, &minor); + + bool egl_create_context_robustness_supported = + strstr(reinterpret_cast<const char*>( + eglQueryStringFn(temp_display, EGL_EXTENSIONS)), + "EGL_EXT_create_context_robustness") != NULL; + + if (!eglChooseConfigFn(temp_display, kConfigAttribs, &config, 1, + &num_configs)) { + LOG(FATAL) << "failed to choose an egl config. " << errorstr(); + } + + temp_context = eglCreateContextFn( + temp_display, config, EGL_NO_CONTEXT, + kContextAttribs + (egl_create_context_robustness_supported ? 0 : 2)); + if (temp_context == EGL_NO_CONTEXT) { + LOG(FATAL) + << "failed to create a temporary context for fetching driver strings. " + << errorstr(); + } + + temp_surface = + eglCreatePbufferSurfaceFn(temp_display, config, kSurfaceAttribs); + + if (temp_surface == EGL_NO_SURFACE) { + eglDestroyContextFn(temp_display, temp_context); + LOG(FATAL) + << "failed to create a pbuffer surface for fetching driver strings. " + << errorstr(); + } + + eglMakeCurrentFn(temp_display, temp_surface, temp_surface, temp_context); + + gpu_info->gl_vendor = reinterpret_cast<const char*>(glGetStringFn(GL_VENDOR)); + gpu_info->gl_version = + reinterpret_cast<const char*>(glGetStringFn(GL_VERSION)); + gpu_info->gl_renderer = + reinterpret_cast<const char*>(glGetStringFn(GL_RENDERER)); + gpu_info->gl_extensions = + reinterpret_cast<const char*>(glGetStringFn(GL_EXTENSIONS)); + + GLint max_samples = 0; + glGetIntegervFn(GL_MAX_SAMPLES, &max_samples); + gpu_info->max_msaa_samples = base::IntToString(max_samples); + + bool supports_robustness = + gpu_info->gl_extensions.find("GL_EXT_robustness") != std::string::npos || + gpu_info->gl_extensions.find("GL_KHR_robustness") != std::string::npos || + gpu_info->gl_extensions.find("GL_ARB_robustness") != std::string::npos; + + if (supports_robustness) { + glGetIntegervFn( + GL_RESET_NOTIFICATION_STRATEGY_ARB, + reinterpret_cast<GLint*>(&gpu_info->gl_reset_notification_strategy)); + } + + std::string glsl_version_string = + reinterpret_cast<const char*>(glGetStringFn(GL_SHADING_LANGUAGE_VERSION)); + + std::string glsl_version = GetVersionFromString(glsl_version_string).first; + gpu_info->pixel_shader_version = glsl_version; + gpu_info->vertex_shader_version = glsl_version; + + if (curr_display != EGL_NO_DISPLAY && + curr_context != EGL_NO_CONTEXT) { + eglMakeCurrentFn(curr_display, curr_draw_surface, curr_read_surface, + curr_context); + } else { + eglMakeCurrentFn(temp_display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + } + + eglDestroySurfaceFn(temp_display, temp_surface); + eglDestroyContextFn(temp_display, temp_context); - if (!eglMakeCurrent(display_, draw_surface_, read_surface_, context_)) - LOG(WARNING) << "Failed to restore EGL context"; + return gpu::kCollectInfoSuccess; } } @@ -85,6 +243,10 @@ ScopedRestoreNonOwnedEGLContext::~ScopedRestoreNonOwnedEGLContext() { namespace gpu { CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info) { + /// TODO(tobiasjs) Check if CollectGraphicsInfo in gpu_main.cc + /// really only needs basic graphics info on all platforms, and if + /// so switch it to using that and make this the NOP that it really + /// should be, to avoid potential double collection of info. return CollectBasicGraphicsInfo(gpu_info); } @@ -103,8 +265,9 @@ CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) { // Create a short-lived context on the UI thread to collect the GL strings. // Make sure we restore the existing context if there is one. - ScopedRestoreNonOwnedEGLContext restore_context; - CollectInfoResult result = CollectGraphicsInfoGL(gpu_info); + CollectInfoResult result = CollectDriverInfo(gpu_info); + if (result == kCollectInfoSuccess) + result = CollectDriverInfoGL(gpu_info); gpu_info->basic_info_state = result; gpu_info->context_info_state = result; return result; diff --git a/chromium/gpu/config/gpu_info_collector_linux.cc b/chromium/gpu/config/gpu_info_collector_linux.cc index 023c08b85f1..413e949eda8 100644 --- a/chromium/gpu/config/gpu_info_collector_linux.cc +++ b/chromium/gpu/config/gpu_info_collector_linux.cc @@ -56,7 +56,7 @@ std::string CollectDriverVersionATI() { base::StringTokenizer t(contents, "\r\n"); while (t.GetNext()) { std::string line = t.token(); - if (StartsWithASCII(line, "ReleaseVersion=", true)) { + if (base::StartsWithASCII(line, "ReleaseVersion=", true)) { size_t begin = line.find_first_of("0123456789"); if (begin != std::string::npos) { size_t end = line.find_first_not_of("0123456789.", begin); @@ -244,7 +244,7 @@ CollectInfoResult CollectDriverInfoGL(GPUInfo* gpu_info) { DCHECK(gpu_info); std::string gl_version = gpu_info->gl_version; - if (StartsWithASCII(gl_version, "OpenGL ES", true)) + if (base::StartsWithASCII(gl_version, "OpenGL ES", true)) gl_version = gl_version.substr(10); std::vector<std::string> pieces; base::SplitStringAlongWhitespace(gl_version, &pieces); diff --git a/chromium/gpu/config/gpu_info_collector_unittest.cc b/chromium/gpu/config/gpu_info_collector_unittest.cc index 359461ad927..f89eb4da4a6 100644 --- a/chromium/gpu/config/gpu_info_collector_unittest.cc +++ b/chromium/gpu/config/gpu_info_collector_unittest.cc @@ -151,5 +151,76 @@ TEST_F(GPUInfoCollectorTest, CollectGraphicsInfoGL) { EXPECT_EQ(test_values_.gl_extensions, gpu_info.gl_extensions); } +class CollectDriverInfoGLTest : public testing::Test { + public: + CollectDriverInfoGLTest() {} + ~CollectDriverInfoGLTest() override {} + + void SetUp() override {} + void TearDown() override {} +}; + +TEST_F(CollectDriverInfoGLTest, CollectDriverInfoGL) { + const struct { + const char* gl_renderer; + const char* gl_vendor; + const char* gl_version; + const char* expected_driver_version; + } kTestStrings[] = { +#if defined(OS_ANDROID) + {"Adreno (TM) 320", + "Qualcomm", + "OpenGL ES 2.0 V@14.0 AU@04.02 (CL@3206)", + "14.0"}, + {"Adreno (TM) 420", "Qualcomm", "OpenGL ES 3.0 V@84.0 AU@ (CL@)", "84.0"}, + {"PowerVR Rogue G6430", + "Imagination Technologies", + "OpenGL ES 3.1 build 1.4@3283119", + "1.4"}, + {"Mali-T604", "ARM", "OpenGL ES 3.1", "0"}, + {"NVIDIA Tegra", + "NVIDIA Corporation", + "OpenGL ES 3.1 NVIDIA 343.00", + "343.00"}, + {"NVIDIA Tegra 3", + "NVIDIA Corporation", + "OpenGL ES 2.0 14.01003", + "14.01003"}, + {"random GPU", + "random vendor", + "OpenGL ES 2.0 with_long_version_string=1.2.3.4", + "1.2"}, + {"random GPU", + "random vendor", + "OpenGL ES 2.0 with_short_version_string=1", + "0"}, + {"random GPU", + "random vendor", + "OpenGL ES 2.0 with_no_version_string", + "0"}, +#elif defined(OS_MACOSX) + {"Intel Iris Pro OpenGL Engine", + "Intel Inc.", + "2.1 INTEL-10.6.20", + "10.6.20"}, +#elif defined(OS_LINUX) + {"Quadro K2000/PCIe/SSE2", + "NVIDIA Corporation", + "4.4.0 NVIDIA 331.79", + "331.79"}, +#endif + {NULL, NULL, NULL, NULL} + }; + + GPUInfo gpu_info; + for (int i = 0; kTestStrings[i].gl_renderer != NULL; ++i) { + gpu_info.gl_renderer = kTestStrings[i].gl_renderer; + gpu_info.gl_vendor = kTestStrings[i].gl_vendor; + gpu_info.gl_version = kTestStrings[i].gl_version; + EXPECT_EQ(CollectDriverInfoGL(&gpu_info), kCollectInfoSuccess); + EXPECT_EQ(gpu_info.driver_version, kTestStrings[i].expected_driver_version); + } +} + } // namespace gpu diff --git a/chromium/gpu/config/gpu_test_expectations_parser.cc b/chromium/gpu/config/gpu_test_expectations_parser.cc index 8b3584a3f7e..ca4031d92c3 100644 --- a/chromium/gpu/config/gpu_test_expectations_parser.cc +++ b/chromium/gpu/config/gpu_test_expectations_parser.cc @@ -131,13 +131,13 @@ const char* kErrorMessage[] = { }; Token ParseToken(const std::string& word) { - if (StartsWithASCII(word, "//", false)) + if (base::StartsWithASCII(word, "//", false)) return kTokenComment; - if (StartsWithASCII(word, "0x", false)) + if (base::StartsWithASCII(word, "0x", false)) return kConfigGPUDeviceID; for (int32 i = 0; i < kNumberOfExactMatchTokens; ++i) { - if (LowerCaseEqualsASCII(word, kTokenData[i].name)) + if (base::LowerCaseEqualsASCII(word, kTokenData[i].name)) return static_cast<Token>(i); } return kTokenWord; diff --git a/chromium/gpu/config/software_rendering_list_json.cc b/chromium/gpu/config/software_rendering_list_json.cc index 7a4d6948f73..a4cf2b088fe 100644 --- a/chromium/gpu/config/software_rendering_list_json.cc +++ b/chromium/gpu/config/software_rendering_list_json.cc @@ -18,7 +18,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( { "name": "software rendering list", // Please update the version number whenever you change this file. - "version": "10.8", + "version": "10.9", "entries": [ { "id": 1, @@ -245,6 +245,12 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "os": { "type": "linux" }, + "exceptions": [ + { + "gl_vendor": "Vivante Corporation", + "gl_renderer": "Vivante GC1000" + } + ], "features": [ "accelerated_2d_canvas" ] diff --git a/chromium/gpu/gles2_conform_support/egl/display.cc b/chromium/gpu/gles2_conform_support/egl/display.cc index bd17250e16e..dce6599acf0 100644 --- a/chromium/gpu/gles2_conform_support/egl/display.cc +++ b/chromium/gpu/gles2_conform_support/egl/display.cc @@ -108,7 +108,7 @@ EGLSurface Display::CreateWindowSurface(EGLConfig config, { gpu::TransferBufferManager* manager = new gpu::TransferBufferManager(); - transfer_buffer_manager_.reset(manager); + transfer_buffer_manager_ = manager; manager->Initialize(); } scoped_ptr<gpu::CommandBufferService> command_buffer( @@ -339,4 +339,9 @@ void Display::SetLock(base::Lock*) { NOTIMPLEMENTED(); } +bool Display::IsGpuChannelLost() { + NOTIMPLEMENTED(); + return false; +} + } // namespace egl diff --git a/chromium/gpu/gles2_conform_support/egl/display.h b/chromium/gpu/gles2_conform_support/egl/display.h index 9b349bd3b6f..adf39490f73 100644 --- a/chromium/gpu/gles2_conform_support/egl/display.h +++ b/chromium/gpu/gles2_conform_support/egl/display.h @@ -93,6 +93,7 @@ class Display : private gpu::GpuControl { void SetSurfaceVisible(bool visible) override; uint32 CreateStreamTexture(uint32 texture_id) override; void SetLock(base::Lock*) override; + bool IsGpuChannelLost() override; private: EGLNativeDisplayType display_id_; @@ -102,7 +103,7 @@ class Display : private gpu::GpuControl { int create_offscreen_width_; int create_offscreen_height_; - scoped_ptr<gpu::TransferBufferManagerInterface> transfer_buffer_manager_; + scoped_refptr<gpu::TransferBufferManagerInterface> transfer_buffer_manager_; scoped_ptr<gpu::CommandBufferService> command_buffer_; scoped_ptr<gpu::GpuScheduler> gpu_scheduler_; scoped_ptr<gpu::gles2::GLES2Decoder> decoder_; diff --git a/chromium/gpu/gpu.gyp b/chromium/gpu/gpu.gyp index ac303158c0b..82e3f1347a8 100644 --- a/chromium/gpu/gpu.gyp +++ b/chromium/gpu/gpu.gyp @@ -358,6 +358,7 @@ 'command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc', 'command_buffer/tests/gl_chromium_path_rendering_unittest.cc', 'command_buffer/tests/gl_clear_framebuffer_unittest.cc', + 'command_buffer/tests/gl_compressed_copy_texture_CHROMIUM_unittest.cc', 'command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc', 'command_buffer/tests/gl_depth_texture_unittest.cc', 'command_buffer/tests/gl_gpu_memory_buffer_unittest.cc', @@ -705,7 +706,7 @@ }, ], }], - ['OS == "win"', { + ['OS == "win" or (OS == "linux" and use_x11==1)', { 'targets': [ { # TODO(kbr): port this target to the GN build. @@ -723,6 +724,10 @@ 'angle_end2end_tests_main.cc', ], }, + ], + }], + ['OS == "win"', { + 'targets': [ { # TODO(jmadill): port this target to the GN build. 'target_name': 'angle_perftests', @@ -767,5 +772,28 @@ }, ], }], + ['OS == "win" and archive_gpu_tests==1', { + 'targets': [ + { + # Only build dEQP on test configs. Note that dEQP is test-only code, + # and is only a part of the Chromium build to allow easy integration + # with the GPU bot waterfall. (Note that dEQP uses exceptions, and + # currently can't build with Clang on Windows) + 'target_name': 'angle_deqp_tests', + 'type': '<(gtest_target_type)', + 'dependencies': [ + '../base/base.gyp:base', + '../base/base.gyp:test_support_base', + '../third_party/angle/src/tests/tests.gyp:angle_deqp_gtest_support', + ], + 'includes': [ + '../third_party/angle/build/common_defines.gypi', + ], + 'sources': [ + 'angle_deqp_tests_main.cc', + ], + }, + ], + }] ], } diff --git a/chromium/gpu/ipc/gpu_command_buffer_traits.cc b/chromium/gpu/ipc/gpu_command_buffer_traits.cc index 1de3b414d77..8d2148de0f7 100644 --- a/chromium/gpu/ipc/gpu_command_buffer_traits.cc +++ b/chromium/gpu/ipc/gpu_command_buffer_traits.cc @@ -36,7 +36,7 @@ void ParamTraits<gpu::CommandBuffer::State> ::Write(Message* m, } bool ParamTraits<gpu::CommandBuffer::State> ::Read(const Message* m, - PickleIterator* iter, + base::PickleIterator* iter, param_type* p) { int32 temp; if (ReadParam(m, iter, &p->get_offset) && @@ -59,9 +59,9 @@ void ParamTraits<gpu::Mailbox>::Write(Message* m, const param_type& p) { m->WriteBytes(p.name, sizeof(p.name)); } -bool ParamTraits<gpu::Mailbox>::Read(const Message* m, - PickleIterator* iter, - param_type* p) { +bool ParamTraits<gpu::Mailbox> ::Read(const Message* m, + base::PickleIterator* iter, + param_type* p) { const char* bytes = NULL; if (!iter->ReadBytes(&bytes, sizeof(p->name))) return false; @@ -81,9 +81,9 @@ void ParamTraits<gpu::MailboxHolder>::Write(Message* m, const param_type& p) { WriteParam(m, p.sync_point); } -bool ParamTraits<gpu::MailboxHolder>::Read(const Message* m, - PickleIterator* iter, - param_type* p) { +bool ParamTraits<gpu::MailboxHolder> ::Read(const Message* m, + base::PickleIterator* iter, + param_type* p) { if (!ReadParam(m, iter, &p->mailbox) || !ReadParam(m, iter, &p->texture_target) || !ReadParam(m, iter, &p->sync_point)) @@ -101,9 +101,9 @@ void ParamTraits<gpu::ValueState>::Write(Message* m, const param_type& p) { sizeof(gpu::ValueState)); } -bool ParamTraits<gpu::ValueState>::Read(const Message* m, - PickleIterator* iter, - param_type* p) { +bool ParamTraits<gpu::ValueState> ::Read(const Message* m, + base::PickleIterator* iter, + param_type* p) { int length; const char* data = NULL; if (!iter->ReadData(&data, &length) || length != sizeof(gpu::ValueState)) diff --git a/chromium/gpu/ipc/gpu_command_buffer_traits.h b/chromium/gpu/ipc/gpu_command_buffer_traits.h index 1c7e02e76e5..d99d4654bff 100644 --- a/chromium/gpu/ipc/gpu_command_buffer_traits.h +++ b/chromium/gpu/ipc/gpu_command_buffer_traits.h @@ -22,7 +22,7 @@ template <> struct GPU_EXPORT ParamTraits<gpu::CommandBuffer::State> { typedef gpu::CommandBuffer::State param_type; static void Write(Message* m, const param_type& p); - static bool Read(const Message* m, PickleIterator* iter, param_type* p); + static bool Read(const Message* m, base::PickleIterator* iter, param_type* p); static void Log(const param_type& p, std::string* l); }; @@ -30,7 +30,7 @@ template<> struct GPU_EXPORT ParamTraits<gpu::Mailbox> { typedef gpu::Mailbox param_type; static void Write(Message* m, const param_type& p); - static bool Read(const Message* m, PickleIterator* iter, param_type* p); + static bool Read(const Message* m, base::PickleIterator* iter, param_type* p); static void Log(const param_type& p, std::string* l); }; @@ -38,7 +38,7 @@ template <> struct GPU_EXPORT ParamTraits<gpu::MailboxHolder> { typedef gpu::MailboxHolder param_type; static void Write(Message* m, const param_type& p); - static bool Read(const Message* m, PickleIterator* iter, param_type* p); + static bool Read(const Message* m, base::PickleIterator* iter, param_type* p); static void Log(const param_type& p, std::string* l); }; @@ -46,7 +46,7 @@ template <> struct GPU_EXPORT ParamTraits<gpu::ValueState> { typedef gpu::ValueState param_type; static void Write(Message* m, const param_type& p); - static bool Read(const Message* m, PickleIterator* iter, param_type* p); + static bool Read(const Message* m, base::PickleIterator* iter, param_type* p); static void Log(const param_type& p, std::string* l); }; diff --git a/chromium/gpu/ipc/gpu_command_buffer_traits_multi.h b/chromium/gpu/ipc/gpu_command_buffer_traits_multi.h index ed6ba3a4232..b869327d4fd 100644 --- a/chromium/gpu/ipc/gpu_command_buffer_traits_multi.h +++ b/chromium/gpu/ipc/gpu_command_buffer_traits_multi.h @@ -49,6 +49,7 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::Capabilities) IPC_STRUCT_TRAITS_MEMBER(max_combined_fragment_uniform_components) IPC_STRUCT_TRAITS_MEMBER(max_combined_uniform_blocks) IPC_STRUCT_TRAITS_MEMBER(max_combined_vertex_uniform_components) + IPC_STRUCT_TRAITS_MEMBER(max_copy_texture_chromium_size) IPC_STRUCT_TRAITS_MEMBER(max_draw_buffers) IPC_STRUCT_TRAITS_MEMBER(max_element_index) IPC_STRUCT_TRAITS_MEMBER(max_elements_indices) @@ -59,6 +60,7 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::Capabilities) IPC_STRUCT_TRAITS_MEMBER(max_program_texel_offset) IPC_STRUCT_TRAITS_MEMBER(max_samples) IPC_STRUCT_TRAITS_MEMBER(max_server_wait_timeout) + IPC_STRUCT_TRAITS_MEMBER(max_texture_lod_bias) IPC_STRUCT_TRAITS_MEMBER(max_transform_feedback_interleaved_components) IPC_STRUCT_TRAITS_MEMBER(max_transform_feedback_separate_attribs) IPC_STRUCT_TRAITS_MEMBER(max_transform_feedback_separate_components) @@ -92,6 +94,9 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::Capabilities) IPC_STRUCT_TRAITS_MEMBER(blend_equation_advanced) IPC_STRUCT_TRAITS_MEMBER(blend_equation_advanced_coherent) IPC_STRUCT_TRAITS_MEMBER(texture_rg) + IPC_STRUCT_TRAITS_MEMBER(render_buffer_format_bgra8888) + IPC_STRUCT_TRAITS_MEMBER(occlusion_query_boolean) + IPC_STRUCT_TRAITS_MEMBER(timer_queries) IPC_STRUCT_TRAITS_MEMBER(major_version) IPC_STRUCT_TRAITS_MEMBER(minor_version) diff --git a/chromium/gpu/perftests/measurements.cc b/chromium/gpu/perftests/measurements.cc index 47ef28e286b..b2dac913305 100644 --- a/chromium/gpu/perftests/measurements.cc +++ b/chromium/gpu/perftests/measurements.cc @@ -55,25 +55,25 @@ Measurement::~Measurement() { MeasurementTimers::MeasurementTimers(gfx::GPUTimingClient* gpu_timing_client) : wall_time_start_(), cpu_time_start_(), gpu_timer_() { DCHECK(gpu_timing_client); - wall_time_start_ = base::TimeTicks::NowFromSystemTraceTime(); - if (base::TimeTicks::IsThreadNowSupported()) { - cpu_time_start_ = base::TimeTicks::ThreadNow(); + wall_time_start_ = base::TraceTicks::Now(); + if (base::ThreadTicks::IsSupported()) { + cpu_time_start_ = base::ThreadTicks::Now(); } else { static bool logged_once = false; - LOG_IF(WARNING, !logged_once) << "ThreadNow not supported."; + LOG_IF(WARNING, !logged_once) << "ThreadTicks not supported."; logged_once = true; } if (gpu_timing_client->IsAvailable()) { - gpu_timer_ = gpu_timing_client->CreateGPUTimer(); + gpu_timer_ = gpu_timing_client->CreateGPUTimer(true); gpu_timer_->Start(); } } void MeasurementTimers::Record() { - wall_time_ = base::TimeTicks::NowFromSystemTraceTime() - wall_time_start_; - if (base::TimeTicks::IsThreadNowSupported()) { - cpu_time_ = base::TimeTicks::ThreadNow() - cpu_time_start_; + wall_time_ = base::TraceTicks::Now() - wall_time_start_; + if (base::ThreadTicks::IsSupported()) { + cpu_time_ = base::ThreadTicks::Now() - cpu_time_start_; } if (gpu_timer_.get()) { gpu_timer_->End(); @@ -84,7 +84,7 @@ Measurement MeasurementTimers::GetAsMeasurement(const std::string& name) { DCHECK_NE(base::TimeDelta(), wall_time_); // At least wall_time_ has been set. - if (!base::TimeTicks::IsThreadNowSupported()) { + if (!base::ThreadTicks::IsSupported()) { cpu_time_ = base::TimeDelta::FromMicroseconds(-1); } int64 gpu_time = -1; diff --git a/chromium/gpu/perftests/measurements.h b/chromium/gpu/perftests/measurements.h index 87d0c2aa83e..724baa49388 100644 --- a/chromium/gpu/perftests/measurements.h +++ b/chromium/gpu/perftests/measurements.h @@ -47,8 +47,8 @@ class MeasurementTimers { ~MeasurementTimers(); private: - base::TimeTicks wall_time_start_; - base::TimeTicks cpu_time_start_; + base::TraceTicks wall_time_start_; + base::ThreadTicks cpu_time_start_; scoped_ptr<gfx::GPUTimer> gpu_timer_; base::TimeDelta wall_time_; diff --git a/chromium/gpu/perftests/texture_upload_perftest.cc b/chromium/gpu/perftests/texture_upload_perftest.cc index 27444a4c432..a70e0f1d2ac 100644 --- a/chromium/gpu/perftests/texture_upload_perftest.cc +++ b/chromium/gpu/perftests/texture_upload_perftest.cc @@ -211,7 +211,6 @@ class TextureUploadPerfTest : public testing::Test { if (gpu_timing_client_->IsAvailable()) { LOG(INFO) << "Gpu timing initialized with timer type: " << gpu_timing_client_->GetTimerTypeName(); - gpu_timing_client_->InvalidateTimerOffset(); } else { LOG(WARNING) << "Can't initialize gpu timing"; } diff --git a/chromium/gpu/skia_runner/BUILD.gn b/chromium/gpu/skia_runner/BUILD.gn new file mode 100644 index 00000000000..cd34057cd2b --- /dev/null +++ b/chromium/gpu/skia_runner/BUILD.gn @@ -0,0 +1,29 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/ui.gni") + +# GYP version: //gpu/skia_runner/skia_runner.gyp:skia_runner +executable("skia_runner") { + sources = [ + "in_process_graphics_system.cc", + "sk_picture_rasterizer.cc", + "skia_runner.cc", + ] + + deps = [ + "//base", + "//gpu/command_buffer/common:gles2_utils", + "//gpu/command_buffer/client:gles2_implementation", + "//gpu/command_buffer/client:gl_in_process_context", + "//gpu/skia_bindings", + "//skia", + "//third_party/WebKit/public:blink", + "//ui/gfx", + "//ui/gl", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] +} diff --git a/chromium/gpu/skia_runner/DEPS b/chromium/gpu/skia_runner/DEPS new file mode 100644 index 00000000000..21e329d387c --- /dev/null +++ b/chromium/gpu/skia_runner/DEPS @@ -0,0 +1,6 @@ +include_rules = [ + "+third_party/khronos", + "+third_party/skia", + "+third_party/WebKit/public/platform", + "+skia/ext", +] diff --git a/chromium/gpu/skia_runner/OWNERS b/chromium/gpu/skia_runner/OWNERS new file mode 100644 index 00000000000..292d13329e9 --- /dev/null +++ b/chromium/gpu/skia_runner/OWNERS @@ -0,0 +1 @@ +hendrikw@chromium.org diff --git a/chromium/gpu/skia_runner/in_process_graphics_system.cc b/chromium/gpu/skia_runner/in_process_graphics_system.cc new file mode 100644 index 00000000000..e5294b1777f --- /dev/null +++ b/chromium/gpu/skia_runner/in_process_graphics_system.cc @@ -0,0 +1,150 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/skia_runner/in_process_graphics_system.h" + +#include <iostream> + +#include "base/lazy_instance.h" +#include "base/memory/discardable_memory.h" +#include "base/memory/discardable_memory_allocator.h" +#include "base/thread_task_runner_handle.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/gles2_lib.h" +#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h" +#include "third_party/khronos/GLES2/gl2.h" +#include "third_party/skia/include/gpu/gl/GrGLInterface.h" + +namespace { + +// TODO(hendrikw): Replace TestDiscardableMemoryAllocator and move to base? +class NonDiscardableMemory : public base::DiscardableMemory { + public: + explicit NonDiscardableMemory(size_t size) : data_(new uint8_t[size]) {} + bool Lock() override { return false; } + void Unlock() override {} + void* data() const override { return data_.get(); } + + private: + scoped_ptr<uint8_t[]> data_; +}; + +class NonDiscardableMemoryAllocator : public base::DiscardableMemoryAllocator { + public: + // Overridden from DiscardableMemoryAllocator: + scoped_ptr<base::DiscardableMemory> AllocateLockedDiscardableMemory( + size_t size) override { + return make_scoped_ptr(new NonDiscardableMemory(size)); + } +}; + +// Singleton used to initialize and terminate the gles2 library. +class GLES2Initializer { + public: + GLES2Initializer() { gles2::Initialize(); } + ~GLES2Initializer() { gles2::Terminate(); } + + private: + DISALLOW_COPY_AND_ASSIGN(GLES2Initializer); +}; + +base::LazyInstance<GLES2Initializer> g_gles2_initializer = + LAZY_INSTANCE_INITIALIZER; +base::LazyInstance<NonDiscardableMemoryAllocator> g_discardable; + +} // namespace anonymous + +namespace skia_runner { + +void BindContext3DGLContextCallback(const GrGLInterface* gl_interface) { + gles2::SetGLContext(reinterpret_cast<gpu::GLInProcessContext*>( + gl_interface->fCallbackData)->GetImplementation()); +} + +InProcessGraphicsSystem::InProcessGraphicsSystem() { + base::DiscardableMemoryAllocator::SetInstance(&g_discardable.Get()); + g_gles2_initializer.Get(); + + if (!gfx::GLSurface::InitializeOneOff()) { + LOG(ERROR) << "Unable to initialize gfx::GLSurface."; + return; + } + + // Create the in process context. + in_process_context_ = CreateInProcessContext(); + if (!in_process_context_) { + LOG(ERROR) << "Unable to create in process context."; + return; + } + + // Create and set up skia's GL bindings. + gles2::SetGLContext(in_process_context_->GetImplementation()); + GrGLInterface* bindings = skia_bindings::CreateCommandBufferSkiaGLBinding(); + if (!bindings) { + LOG(ERROR) << "Unable to create skia command buffer bindings."; + return; + } + + bindings->fCallback = BindContext3DGLContextCallback; + bindings->fCallbackData = + reinterpret_cast<GrGLInterfaceCallbackData>(in_process_context_.get()); + + // Create skia's graphics context. + gr_context_ = skia::AdoptRef(GrContext::Create( + kOpenGL_GrBackend, reinterpret_cast<GrBackendContext>(bindings))); + + if (!gr_context_) { + LOG(ERROR) << "Unable to create skia graphics context."; + return; + } + + // Set skia's graphics context cache size. + const int kMaxGaneshResourceCacheCount = 2048; + const size_t kMaxGaneshResourceCacheBytes = 96 * 1024 * 1024; + gr_context_->setResourceCacheLimits(kMaxGaneshResourceCacheCount, + kMaxGaneshResourceCacheBytes); +} + +InProcessGraphicsSystem::~InProcessGraphicsSystem() { +} + +bool InProcessGraphicsSystem::IsSuccessfullyInitialized() const { + return gr_context_; +} + +int InProcessGraphicsSystem::GetMaxTextureSize() const { + int max_texture_size = 0; + in_process_context_->GetImplementation()->GetIntegerv(GL_MAX_TEXTURE_SIZE, + &max_texture_size); + return max_texture_size; +} + +scoped_ptr<gpu::GLInProcessContext> +InProcessGraphicsSystem::CreateInProcessContext() const { + const bool is_offscreen = true; + const bool share_resources = true; + gpu::gles2::ContextCreationAttribHelper attribs; + attribs.alpha_size = 8; + attribs.blue_size = 8; + attribs.green_size = 8; + attribs.red_size = 8; + attribs.depth_size = 24; + attribs.stencil_size = 8; + attribs.samples = 0; + attribs.sample_buffers = 0; + attribs.fail_if_major_perf_caveat = false; + attribs.bind_generates_resource = false; + gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; + + scoped_ptr<gpu::GLInProcessContext> context = + make_scoped_ptr(gpu::GLInProcessContext::Create( + nullptr, nullptr, is_offscreen, gfx::kNullAcceleratedWidget, + gfx::Size(1, 1), nullptr, share_resources, attribs, gpu_preference, + gpu::GLInProcessContextSharedMemoryLimits(), nullptr, nullptr)); + + DCHECK(context); + return context.Pass(); +} + +} // namespace skia_runner diff --git a/chromium/gpu/skia_runner/in_process_graphics_system.h b/chromium/gpu/skia_runner/in_process_graphics_system.h new file mode 100644 index 00000000000..a2366ccc702 --- /dev/null +++ b/chromium/gpu/skia_runner/in_process_graphics_system.h @@ -0,0 +1,29 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/scoped_ptr.h" +#include "gpu/command_buffer/client/gl_in_process_context.h" +#include "skia/ext/refptr.h" +#include "third_party/skia/include/core/SkPicture.h" +#include "third_party/skia/include/gpu/GrContext.h" + +namespace skia_runner { + +class InProcessGraphicsSystem { + public: + InProcessGraphicsSystem(); + ~InProcessGraphicsSystem(); + + bool IsSuccessfullyInitialized() const; + skia::RefPtr<GrContext> GetGrContext() const { return gr_context_; } + int GetMaxTextureSize() const; + + private: + scoped_ptr<gpu::GLInProcessContext> CreateInProcessContext() const; + + scoped_ptr<gpu::GLInProcessContext> in_process_context_; + skia::RefPtr<GrContext> gr_context_; +}; + +} // namespace skia_runner diff --git a/chromium/gpu/skia_runner/sk_picture_rasterizer.cc b/chromium/gpu/skia_runner/sk_picture_rasterizer.cc new file mode 100644 index 00000000000..7087a1369bd --- /dev/null +++ b/chromium/gpu/skia_runner/sk_picture_rasterizer.cc @@ -0,0 +1,90 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/skia_runner/sk_picture_rasterizer.h" + +#include <iostream> + +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkSurface.h" +#include "third_party/skia/include/core/SkSurfaceProps.h" + +namespace skia_runner { + +SkPictureRasterizer::SkPictureRasterizer(skia::RefPtr<GrContext> gr_context, + int max_texture_size) + : use_lcd_text_(false), + use_distance_field_text_(false), + msaa_sample_count_(0), + max_texture_size_(max_texture_size), + gr_context_(gr_context) { +} + +SkPictureRasterizer::~SkPictureRasterizer() { +} + +skia::RefPtr<SkImage> SkPictureRasterizer::RasterizeTile( + const SkPicture* picture, + const SkRect& rect) const { + DCHECK(gr_context_); + + SkImageInfo info = SkImageInfo::MakeN32Premul(rect.width(), rect.height()); + uint32_t flags = 0; + if (use_distance_field_text_) + flags = SkSurfaceProps::kUseDistanceFieldFonts_Flag; + + SkSurfaceProps surface_props = + use_lcd_text_ + ? SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType) + : SkSurfaceProps(flags, kUnknown_SkPixelGeometry); + + skia::RefPtr<SkSurface> sk_surface(skia::AdoptRef( + SkSurface::NewRenderTarget(gr_context_.get(), SkSurface::kYes_Budgeted, + info, msaa_sample_count_, &surface_props))); + if (sk_surface) { + SkCanvas* canvas = sk_surface->getCanvas(); + canvas->translate(-rect.left(), -rect.top()); + canvas->drawPicture(picture); + + return skia::AdoptRef(sk_surface->newImageSnapshot()); + } + return nullptr; +} + +skia::RefPtr<SkImage> SkPictureRasterizer::Rasterize( + const SkPicture* picture) const { + if (!gr_context_) + return nullptr; + + SkRect picture_rect = picture->cullRect(); + if (picture_rect.width() <= max_texture_size_ && + picture_rect.height() <= max_texture_size_) + return RasterizeTile(picture, picture_rect); + + SkImageInfo info = + SkImageInfo::MakeN32Premul(picture_rect.width(), picture_rect.height()); + + skia::RefPtr<SkSurface> sk_surface( + skia::AdoptRef(SkSurface::NewRaster(info))); + SkCanvas* canvas = sk_surface->getCanvas(); + + int num_tiles_x = picture_rect.width() / max_texture_size_ + 1; + int num_tiles_y = picture_rect.height() / max_texture_size_ + 1; + for (int y = 0; y < num_tiles_y; ++y) { + SkRect tile_rect; + tile_rect.fTop = picture_rect.top() + y * max_texture_size_; + tile_rect.fBottom = + std::min(tile_rect.fTop + max_texture_size_, picture_rect.bottom()); + for (int x = 0; x < num_tiles_x; ++x) { + tile_rect.fLeft = picture_rect.left() + x * max_texture_size_; + tile_rect.fRight = + std::min(tile_rect.fLeft + max_texture_size_, picture_rect.right()); + skia::RefPtr<SkImage> tile(RasterizeTile(picture, tile_rect)); + canvas->drawImage(tile.get(), tile_rect.left(), tile_rect.top()); + } + } + return skia::AdoptRef(sk_surface->newImageSnapshot()); +} + +} // namepsace skia_runner diff --git a/chromium/gpu/skia_runner/sk_picture_rasterizer.h b/chromium/gpu/skia_runner/sk_picture_rasterizer.h new file mode 100644 index 00000000000..380bfa0de06 --- /dev/null +++ b/chromium/gpu/skia_runner/sk_picture_rasterizer.h @@ -0,0 +1,40 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/scoped_ptr.h" +#include "gpu/command_buffer/client/gl_in_process_context.h" +#include "skia/ext/refptr.h" +#include "third_party/skia/include/core/SkPicture.h" +#include "third_party/skia/include/gpu/GrContext.h" + +namespace skia_runner { + +class SkPictureRasterizer { + public: + SkPictureRasterizer(skia::RefPtr<GrContext> gr_context, int max_texture_size); + ~SkPictureRasterizer(); + + skia::RefPtr<SkImage> Rasterize(const SkPicture* picture) const; + + void set_msaa_sample_count(int msaa_sample_count) { + msaa_sample_count_ = msaa_sample_count; + } + void set_use_lcd_text(bool use_lcd_text) { use_lcd_text_ = use_lcd_text; } + void set_use_distance_field_text(bool use_distance_field_text) { + use_distance_field_text_ = use_distance_field_text; + } + + private: + skia::RefPtr<SkImage> RasterizeTile(const SkPicture* picture, + const SkRect& rect) const; + + bool use_lcd_text_; + bool use_distance_field_text_; + int msaa_sample_count_; + + int max_texture_size_; + skia::RefPtr<GrContext> gr_context_; +}; + +} // namespace skia_runner diff --git a/chromium/gpu/skia_runner/skia_runner.cc b/chromium/gpu/skia_runner/skia_runner.cc new file mode 100644 index 00000000000..9fcf48e7c15 --- /dev/null +++ b/chromium/gpu/skia_runner/skia_runner.cc @@ -0,0 +1,255 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <iostream> + +#include "base/at_exit.h" +#include "base/command_line.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/time/time.h" +#include "gpu/skia_runner/in_process_graphics_system.h" +#include "gpu/skia_runner/sk_picture_rasterizer.h" +#include "third_party/WebKit/public/platform/WebData.h" +#include "third_party/WebKit/public/platform/WebImage.h" +#include "third_party/WebKit/public/platform/WebSize.h" +#include "third_party/skia/include/core/SkOSFile.h" +#include "third_party/skia/include/core/SkPicture.h" +#include "third_party/skia/include/core/SkStream.h" +#include "ui/gfx/codec/png_codec.h" + +#if defined(OS_MACOSX) +#include "base/mac/scoped_nsautorelease_pool.h" +#endif + +namespace { + +bool WriteSkImagePNG(const SkImage* image, const base::FilePath& path) { + DCHECK(!path.empty()); + + if (!image) { + std::cout << "Unable to write empty bitmap for " << path.value() << ".\n"; + return false; + } + + std::string file_path = path.MaybeAsASCII(); + SkFILEWStream stream(file_path.c_str()); + if (!stream.isValid()) { + std::cout << "Unable to write to " << file_path.c_str() << ".\n"; + return false; + } + + SkImageInfo info = SkImageInfo::Make(image->width(), image->height(), + SkColorType::kBGRA_8888_SkColorType, + SkAlphaType::kPremul_SkAlphaType); + SkImageInfo::MakeN32Premul(image->width(), image->height()); + + const size_t rowBytes = image->width() * sizeof(SkPMColor); + std::vector<SkPMColor> pixels(image->width() * image->height()); + + if (image->readPixels(info, pixels.data(), rowBytes, 0, 0)) { + std::vector<unsigned char> png_data; + + if (gfx::PNGCodec::Encode( + reinterpret_cast<const unsigned char*>(pixels.data()), + gfx::PNGCodec::FORMAT_BGRA, + gfx::Size(image->width(), image->height()), + static_cast<int>(rowBytes), false, + std::vector<gfx::PNGCodec::Comment>(), &png_data)) { + if (stream.write(png_data.data(), png_data.size())) { + return true; + } + } + } + + return false; +} + +bool onDecode(const void* buffer, size_t size, SkBitmap* bm) { + blink::WebData web_data(static_cast<const char*>(buffer), size); + blink::WebImage image = blink::WebImage::fromData(web_data, blink::WebSize()); + if (!image.isNull()) { + *bm = image.getSkBitmap(); + return true; + } + std::cout << "Error decoding image.\n"; + return false; +} + +skia::RefPtr<SkPicture> ReadPicture(const base::FilePath& path) { + skia::RefPtr<SkPicture> picture; + std::string file_path = path.MaybeAsASCII(); + SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(file_path.c_str())); + if (!stream.get()) { + std::cout << "Unable to read " << file_path.c_str() << ".\n"; + return picture; + } + + picture = skia::AdoptRef(SkPicture::CreateFromStream(stream.get(), onDecode)); + if (!picture) { + std::cout << "Unable to load " << file_path.c_str() + << " as an SkPicture.\n"; + } + return picture; +} + +base::FilePath MakeDestinationPNGFilename(base::FilePath source_file, + base::FilePath destination_folder) { + base::FilePath filename = source_file.BaseName().RemoveExtension(); + filename = filename.AddExtension(FILE_PATH_LITERAL("png")); + return destination_folder.AsEndingWithSeparator().Append(filename); +} + +std::vector<std::pair<base::FilePath, base::FilePath>> GetSkpsToRasterize( + base::FilePath input_path, + base::FilePath output_path) { + std::vector<std::pair<base::FilePath, base::FilePath>> files; + + if (base::DirectoryExists(input_path)) { + if (!output_path.empty() && !base::DirectoryExists(output_path)) + return files; + + base::FilePath::StringType extension = FILE_PATH_LITERAL(".skp"); + base::FileEnumerator file_iter(input_path, false, + base::FileEnumerator::FILES); + while (!file_iter.Next().empty()) { + if (file_iter.GetInfo().GetName().MatchesExtension(extension)) { + base::FilePath skp_file = file_iter.GetInfo().GetName(); + skp_file = input_path.AsEndingWithSeparator().Append(skp_file); + base::FilePath png_file; + if (!output_path.empty()) + png_file = MakeDestinationPNGFilename(skp_file, output_path); + files.push_back(std::make_pair(skp_file, png_file)); + } + } + } else { + // Single file passed. If the output file is a folder, make a name. + if (base::DirectoryExists(output_path)) + output_path = MakeDestinationPNGFilename(input_path, output_path); + files.push_back(std::make_pair(input_path, output_path)); + } + return files; +} + +int GetSwitchInt(const base::CommandLine* command_line, + std::string switch_name, + int default_value) { + if (command_line->HasSwitch(switch_name)) { + std::string value = command_line->GetSwitchValueASCII(switch_name); + int result = default_value; + if (base::StringToInt(value, &result)) + return result; + } + return default_value; +} + +static const char kHelpMessage[] = + "This program renders a skia SKP to a PNG using GPU rasterization via the\n" + "command buffer.\n\n" + "following command line flags to control its behavior:\n" + "\n" + " --in-skp=skp[:DIRECTORY_PATH|FILE_PATH]\n" + " Input SKP file. If a directory is provided, all SKP files will be\n" + " converted.\n" + " --out-png=png[:DIRECTORY_PATH|:FILE_PATH]\n" + " Output PNG file. If a directory is provided, the SKP filename is " + "used.\n\n" + " --use-lcd-text\n" + " Turn on lcd text rendering.\n" + " --use-distance-field-text\n" + " Turn on distance field text rendering.\n" + " --msaa-sample-count=(0|2|4|8|16)\n" + " Turn on multi-sample anti-aliasing.\n" + " --use-gl=(desktop|osmesa|egl|swiftshader)\n" + " Specify Gl driver. --swiftshader-path required for swiftshader.\n" + " --repeat-raster-count=N\n" + " Specify the number of times to repeat rasterization for timing.\n"; + +} // namespace anonymous + +int main(int argc, char** argv) { + base::AtExitManager exit_manager; + base::CommandLine::Init(argc, argv); +#if defined(OS_MACOSX) + base::mac::ScopedNSAutoreleasePool autorelease_pool; +#endif + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + base::FilePath input_path(command_line->GetSwitchValuePath("in-skp")); + base::FilePath output_path(command_line->GetSwitchValuePath("out-png")); + + if (input_path.empty()) { + std::cout << kHelpMessage; + return 0; + } + + if (output_path.empty()) + std::cout << "--out-png path not specified. Timing rasterization only.\n"; + + std::vector<std::pair<base::FilePath, base::FilePath>> files = + GetSkpsToRasterize(input_path, output_path); + + if (files.empty()) { + if (!base::DirectoryExists(output_path)) + std::cout << "You must specify an existing directory using '--out-png'\n"; + else + std::cout << "No skp files found at " << input_path.value() << "\n"; + return 0; + } + + skia_runner::InProcessGraphicsSystem graphics_system; + if (!graphics_system.IsSuccessfullyInitialized()) { + LOG(ERROR) << "Unable to initialize rasterizer."; + return 0; + } + + skia_runner::SkPictureRasterizer picture_rasterizer( + graphics_system.GetGrContext(), graphics_system.GetMaxTextureSize()); + + // Set up command-line render options. + picture_rasterizer.set_use_lcd_text(command_line->HasSwitch("use-lcd-text")); + picture_rasterizer.set_use_distance_field_text( + command_line->HasSwitch("use-distance-field-text")); + + int msaa = GetSwitchInt(command_line, "msaa-sample-count", 0); + if (msaa != 0 && msaa != 2 && msaa != 4 && msaa != 8 && msaa != 16) { + std::cout << "Error: msaa sample count must be 0, 2, 4, 8 or 16.\n"; + return 0; + } + picture_rasterizer.set_msaa_sample_count(msaa); + + int repeat_raster_count = + std::max(1, GetSwitchInt(command_line, "repeat-raster-count", 1)); + + // Disable the security precautions to ensure we correctly read the picture. + SkPicture::SetPictureIOSecurityPrecautionsEnabled_Dangerous(false); + + for (auto file_pair : files) { + skia::RefPtr<SkPicture> picture = ReadPicture(file_pair.first); + if (!picture) { + std::cout << "Error reading: " << file_pair.first.value() << "\n"; + continue; + } + + // GPU Rasterize the picture and time it. + base::TimeTicks rasterize_start = base::TimeTicks::Now(); + skia::RefPtr<SkImage> image; + for (int i = 0; i < repeat_raster_count; ++i) { + image = picture_rasterizer.Rasterize(picture.get()); + graphics_system.GetGrContext()->flush(); + } + base::TimeDelta rasterize_time = base::TimeTicks::Now() - rasterize_start; + double average_time = rasterize_time.InSecondsF() / repeat_raster_count; + std::cout << "Average rasterization time for " << file_pair.first.value() + << ": " << average_time << "s (" << 1.0 / average_time + << " fps)\n"; + + if (!file_pair.second.empty()) { + if (!WriteSkImagePNG(image.get(), file_pair.second)) + std::cout << "Error writing: " << file_pair.second.value() << "\n"; + else + std::cout << file_pair.second.value() << " successfully created.\n"; + } + } +} diff --git a/chromium/gpu/skia_runner/skia_runner.gyp b/chromium/gpu/skia_runner/skia_runner.gyp new file mode 100644 index 00000000000..1a07caae94b --- /dev/null +++ b/chromium/gpu/skia_runner/skia_runner.gyp @@ -0,0 +1,36 @@ +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'targets': [ + { + # GN version: //gpu:skia_runner + 'target_name': 'skia_runner', + 'type': 'executable', + 'dependencies': [ + '../../base/base.gyp:base', + '../../gpu/command_buffer/command_buffer.gyp:gles2_utils', + '../../gpu/gpu.gyp:command_buffer_service', + '../../gpu/gpu.gyp:gles2_implementation', + '../../gpu/gpu.gyp:gl_in_process_context', + '../../gpu/skia_bindings/skia_bindings.gyp:gpu_skia_bindings', + '../../skia/skia.gyp:skia', + '../../third_party/WebKit/public/blink.gyp:blink', + '../../ui/gfx/gfx.gyp:gfx', + '../../ui/gl/gl.gyp:gl', + ], + 'sources': [ + # Note: sources list duplicated in GN build. + 'in_process_graphics_system.cc', + 'in_process_graphics_system.h', + 'sk_picture_rasterizer.cc', + 'sk_picture_rasterizer.h', + 'skia_runner.cc', + ], + }, + ], +} diff --git a/chromium/gpu/tools/compositor_model_bench/render_tree.cc b/chromium/gpu/tools/compositor_model_bench/render_tree.cc index 8712a975ef3..f2369df18ef 100644 --- a/chromium/gpu/tools/compositor_model_bench/render_tree.cc +++ b/chromium/gpu/tools/compositor_model_bench/render_tree.cc @@ -442,7 +442,7 @@ RenderNode* InterpretNode(base::DictionaryValue* node) { string outjson; - JSONWriter::WriteWithOptions(node, base::JSONWriter::OPTIONS_PRETTY_PRINT, + JSONWriter::WriteWithOptions(*node, base::JSONWriter::OPTIONS_PRETTY_PRINT, &outjson); LOG(ERROR) << "Unrecognized node type! JSON:\n\n" "-----------------------\n" << @@ -458,14 +458,11 @@ RenderNode* BuildRenderTreeFromFile(const base::FilePath& path) { if (!ReadFileToString(path, &contents)) return NULL; - scoped_ptr<base::Value> root; int error_code = 0; string error_message; - root.reset(JSONReader::ReadAndReturnError(contents, - base::JSON_ALLOW_TRAILING_COMMAS, - &error_code, - &error_message)); - if (!root.get()) { + scoped_ptr<base::Value> root = JSONReader::ReadAndReturnError( + contents, base::JSON_ALLOW_TRAILING_COMMAS, &error_code, &error_message); + if (!root) { LOG(ERROR) << "Failed to parse JSON file " << path.LossyDisplayName() << "\n(" << error_message << ")"; return NULL; |