diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-07-14 17:41:05 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2016-08-04 12:37:36 +0000 |
commit | 399c965b6064c440ddcf4015f5f8e9d131c7a0a6 (patch) | |
tree | 6b06b60ff365abef0e13b3503d593a0df48d20e8 /chromium/gpu | |
parent | 7366110654eec46f21b6824f302356426f48cd74 (diff) | |
download | qtwebengine-chromium-399c965b6064c440ddcf4015f5f8e9d131c7a0a6.tar.gz |
BASELINE: Update Chromium to 52.0.2743.76 and Ninja to 1.7.1
Change-Id: I382f51b959689505a60f8b707255ecb344f7d8b4
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/gpu')
357 files changed, 10377 insertions, 10178 deletions
diff --git a/chromium/gpu/BUILD.gn b/chromium/gpu/BUILD.gn index da3bb213e04..9e96a4a131e 100644 --- a/chromium/gpu/BUILD.gn +++ b/chromium/gpu/BUILD.gn @@ -57,6 +57,8 @@ shared_library("command_buffer_gles2") { # TODO(hendrikw): Move egl out of gles2_conform_support. "gles2_conform_support/egl/config.cc", "gles2_conform_support/egl/config.h", + "gles2_conform_support/egl/context.cc", + "gles2_conform_support/egl/context.h", "gles2_conform_support/egl/display.cc", "gles2_conform_support/egl/display.h", "gles2_conform_support/egl/egl.cc", @@ -64,6 +66,8 @@ shared_library("command_buffer_gles2") { "gles2_conform_support/egl/surface.h", "gles2_conform_support/egl/test_support.cc", "gles2_conform_support/egl/test_support.h", + "gles2_conform_support/egl/thread_state.cc", + "gles2_conform_support/egl/thread_state.h", ] deps = [ @@ -71,6 +75,7 @@ shared_library("command_buffer_gles2") { "//base", "//gpu/command_buffer/client:gles2_c_lib", "//gpu/command_buffer/client:gles2_implementation", + "//gpu/command_buffer/common:gles2_utils", "//ui/gl:gl", ] @@ -117,7 +122,7 @@ test("command_buffer_gles2_tests") { libs += [ "android" ] deps += [ "//ui/android:ui_java" ] } - if (!is_component_build) { + if (is_linux && !is_component_build) { configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] } } @@ -182,6 +187,8 @@ test("gl_tests") { "command_buffer/tests/gl_unittests_android.cc", "command_buffer/tests/gl_virtual_contexts_unittest.cc", "command_buffer/tests/occlusion_query_unittest.cc", + "ipc/client/gpu_context_tests.h", + "ipc/client/gpu_in_process_context_tests.cc", ] defines = [ "GL_GLEXT_PROTOTYPES" ] @@ -194,6 +201,7 @@ test("gl_tests") { "//base", "//base/test:test_support", "//base/third_party/dynamic_annotations", + "//gpu/command_buffer/client:gl_in_process_context", "//gpu/command_buffer/client:gles2_c_lib", "//gpu/command_buffer/client:gles2_implementation", "//gpu/command_buffer/common:gles2_utils", @@ -211,6 +219,8 @@ test("gl_tests") { if (is_android) { libs += [ "android" ] deps += [ "//ui/android:ui_java" ] + } else if (is_mac) { + libs += [ "IOSurface.framework" ] } } @@ -250,6 +260,7 @@ test("gpu_unittests") { "command_buffer/service/framebuffer_manager_unittest.cc", "command_buffer/service/gl_context_mock.cc", "command_buffer/service/gl_context_mock.h", + "command_buffer/service/gl_context_virtual_unittest.cc", "command_buffer/service/gl_surface_mock.cc", "command_buffer/service/gl_surface_mock.h", "command_buffer/service/gles2_cmd_decoder_unittest.cc", @@ -272,11 +283,11 @@ test("gpu_unittests") { "command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc", "command_buffer/service/gles2_cmd_decoder_unittest_programs.cc", "command_buffer/service/gles2_cmd_decoder_unittest_textures.cc", - "command_buffer/service/gles2_cmd_decoder_unittest_valuebuffer.cc", "command_buffer/service/gpu_service_test.cc", "command_buffer/service/gpu_service_test.h", "command_buffer/service/gpu_tracer_unittest.cc", "command_buffer/service/id_manager_unittest.cc", + "command_buffer/service/indexed_buffer_binding_host_unittest.cc", "command_buffer/service/mailbox_manager_unittest.cc", "command_buffer/service/memory_program_cache_unittest.cc", "command_buffer/service/mocks.cc", @@ -294,7 +305,7 @@ test("gpu_unittests") { "command_buffer/service/test_helper.h", "command_buffer/service/texture_manager_unittest.cc", "command_buffer/service/transfer_buffer_manager_unittest.cc", - "command_buffer/service/valuebuffer_manager_unittest.cc", + "command_buffer/service/transform_feedback_manager_unittest.cc", "command_buffer/service/vertex_array_manager_unittest.cc", "command_buffer/service/vertex_attrib_manager_unittest.cc", "config/gpu_blacklist_unittest.cc", @@ -312,6 +323,12 @@ test("gpu_unittests") { "ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc", "ipc/client/gpu_memory_buffer_impl_test_template.h", ] + + if (is_android) { + sources += + [ "ipc/client/gpu_memory_buffer_impl_surface_texture_unittest.cc" ] + } + if (is_mac) { sources += [ "ipc/client/gpu_memory_buffer_impl_io_surface_unittest.cc" ] } @@ -344,6 +361,13 @@ test("gpu_unittests") { "//ui/gl:test_support", ] + if (is_android) { + deps += [ + "//ui/android:ui_java", + "//ui/gl:gl_jni_headers", + ] + } + if (use_ozone) { deps += [ "//ui/ozone" ] sources += @@ -367,5 +391,9 @@ test("gpu_perftests") { "//testing/perf", "//ui/gfx/geometry", "//ui/gl", + "//ui/gl/init", ] + + # This target should not require the Chrome executable to run. + assert_no_deps = [ "//chrome" ] } diff --git a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_gpu_memory_buffer_image.txt b/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_gpu_memory_buffer_image.txt index d185894ade7..93af3d94275 100644 --- a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_gpu_memory_buffer_image.txt +++ b/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_gpu_memory_buffer_image.txt @@ -51,6 +51,14 @@ New Procedures and Functions INVALID_ENUM is generated if <usage> is not READ_WRTIE_CHROMIUM. + On OS X, driver bugs prevent the usage of memory buffers with RGB internal + format. As a workaround, the created GpuMemoryBuffer will always have + internal format RGBA. The caller is responsible for handling this + appropriately. The only support provided by this extension is that calls + that require parameter validation (such as copyTexImage2D and + copyTexSubImage2D) will perform paramter validation as if the internal + format were RGB. + Errors None. @@ -62,3 +70,4 @@ New State Revision History 9/29/2014 Documented the extension. + 4/12/2016 Added details of OS X RGB workaround. diff --git a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_schedule_ca_layer.txt b/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_schedule_ca_layer.txt index 0475c66a8ed..5d1caaec914 100644 --- a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_schedule_ca_layer.txt +++ b/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_schedule_ca_layer.txt @@ -8,7 +8,7 @@ Name Strings Version - Last Modified Date: December 16, 2015 + Last Modified Date: April 12, 2016 Dependencies @@ -47,7 +47,8 @@ New Procedures and Functions const GLfloat* bounds_rect, GLboolean is_clipped, const GLfloat* clip_rect, - const GLfloat* transform); + const GLfloat* transform, + GLuint filter); Set the CALayer parameters to be presented at the time of the next call to swap buffers. The order of the calls schedule CALayers determines their @@ -69,6 +70,8 @@ New Procedures and Functions the rectangle to clip the layer to, if it is to be clipped. <transform> contains sixteen values indicating the row major order 4x4 transformation matrix to apply to the CALayer. + <filter> will be used for both minification and magnification filtering. The + only valid values are GL_LINEAR and GL_NEAREST. Errors @@ -80,6 +83,8 @@ New State Revision History + 4/12/2016 Add a parameter to support minification and magnification + filtering. 12/16/2015 Add clipping and edge anti-aliasing. 11/7/2015 Initial checkin diff --git a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_subscribe_uniform.txt b/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_subscribe_uniform.txt deleted file mode 100644 index 2427d329f3c..00000000000 --- a/chromium/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_subscribe_uniform.txt +++ /dev/null @@ -1,113 +0,0 @@ -Name - - CHROMIUM_subscribe_uniform - -Name Strings - - CHROMIUM_subscribe_uniform - -Version - - Last Modifed Date: October 30, 2014 - -Dependencies - - OpenGL ES 2.0 is required. - -Overview - - Allows clients to subscribe to a set of input uniforms which can - be populated within buffers and used to modify uniform variables within - their programs. - - Decreases percieved latency for operations performed against these - uniforms. - -New Tokens - - Accepted by the <target> parameter of glBindValueBufferCHROMIUM, - glSubscribeValueCHROMIUM, glPopulateSubscribedValuesCHROMIUM and - glUniformValueBufferCHROMIUM - - GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM 0x924B - - Accepted by the <subscription> parameter of glSubscribeValueCHROMIUM and - glUniformValueBufferCHROMIUM: - - GL_MOUSE_POSITION_CHROMIUM 0x924C - -New Procedures and Functions - - The command - - void glGenValuebuffersCHROMIUM(GLsizei n, GLuint* buffers) - - Generates value buffer object names. - <n> Specifies the number of value buffer object names to be generated. - <buffers> Specifies an array in which the generated value buffer object - names are stored. - - The command - - void glDeleteValuebuffersCHROMIUM(GLsizei n, const GLuint* valuebuffers) - - Deletes named value buffer objects. - <n> Specifies the number of value buffer objects to be deleted. - <buffers> Specifies an array of value buffer objects to be deleted. - - The command - - boolean glIsValuebufferCHROMIUM(GLuint buffer); - - Returns whether an object is a value buffer object. - <buffer> Specifies the name of a buffer object. - - The command - - void glBindValuebufferCHROMIUM(GLenum target, GLuint buffer); - - Lets you use a named value buffer object. - <target> Specifies the target to which the buffer object is bound. - <buffer> Specifies the name of a buffer object. - - The command - - void glSubscribeValueCHROMIUM(GLenum target, GLenum subscription) - - Subscribes the currently bound buffer object to a subscription target. - <target> Specifies the target to which the buffer object is bound. - <subscription> Specifies the subscription to which the currently bound - buffer object should be subscribed. - - The command - - void glPopulateSubscribedValuesCHROMIUM(GLenum target) - - Populates the currently bound buffer object with all subscription states - to which it is subscribed. - <target> Specifies the target to which the buffer object is bound. - - The command - - void glUniformValueBufferCHROMIUM(GLint location, GLenum target, - GLenum subscription) - - Populates the uniform specified by location within the currently bound - program with the value in the currently bound buffer for the subscription - target. - <location> Specifies the location of the uniform variable to by modified. - <target> Specifies the target to which the buffer object is bound. - <subscription> Specifies the subscription in the currently bound buffer - whose value should be used to populate the uniform. - -Errors - - None. - -New State - - None. - -Revision History - - 10/30/2014 Documented the extension diff --git a/chromium/gpu/GLES2/gl2chromium_autogen.h b/chromium/gpu/GLES2/gl2chromium_autogen.h index e4bd8f2eeaf..99af8298a9f 100644 --- a/chromium/gpu/GLES2/gl2chromium_autogen.h +++ b/chromium/gpu/GLES2/gl2chromium_autogen.h @@ -309,14 +309,6 @@ #define glCreateAndConsumeTextureCHROMIUM \ GLES2_GET_FUN(CreateAndConsumeTextureCHROMIUM) #define glBindUniformLocationCHROMIUM GLES2_GET_FUN(BindUniformLocationCHROMIUM) -#define glGenValuebuffersCHROMIUM GLES2_GET_FUN(GenValuebuffersCHROMIUM) -#define glDeleteValuebuffersCHROMIUM GLES2_GET_FUN(DeleteValuebuffersCHROMIUM) -#define glIsValuebufferCHROMIUM GLES2_GET_FUN(IsValuebufferCHROMIUM) -#define glBindValuebufferCHROMIUM GLES2_GET_FUN(BindValuebufferCHROMIUM) -#define glSubscribeValueCHROMIUM GLES2_GET_FUN(SubscribeValueCHROMIUM) -#define glPopulateSubscribedValuesCHROMIUM \ - GLES2_GET_FUN(PopulateSubscribedValuesCHROMIUM) -#define glUniformValuebufferCHROMIUM GLES2_GET_FUN(UniformValuebufferCHROMIUM) #define glBindTexImage2DCHROMIUM GLES2_GET_FUN(BindTexImage2DCHROMIUM) #define glReleaseTexImage2DCHROMIUM GLES2_GET_FUN(ReleaseTexImage2DCHROMIUM) #define glTraceBeginCHROMIUM GLES2_GET_FUN(TraceBeginCHROMIUM) diff --git a/chromium/gpu/GLES2/gl2extchromium.h b/chromium/gpu/GLES2/gl2extchromium.h index a5c979c38f6..2fe3ebfacc7 100644 --- a/chromium/gpu/GLES2/gl2extchromium.h +++ b/chromium/gpu/GLES2/gl2extchromium.h @@ -696,35 +696,6 @@ typedef void (GL_APIENTRYP PFNGLWAITSYNCTOKENCHROMIUM) ( #endif #endif /* GL_CHROMIUM_color_buffer_float_rgb */ -/* GL_CHROMIUM_subscribe_uniform */ -#ifndef GL_CHROMIUM_subscribe_uniform -#define GL_CHROMIUM_subscribe_uniform 1 - -#ifndef GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM -#define GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM 0x924B -#endif - -#ifndef GL_MOUSE_POSITION_CHROMIUM -#define GL_MOUSE_POSITION_CHROMIUM 0x924C -#endif - -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY -glGenValuebuffersCHROMIUM(GLsizei n, GLuint* buffers); -GL_APICALL void GL_APIENTRY -glDeleteValuebuffersCHROMIUM(GLsizei n, const GLuint* valuebuffers); -GL_APICALL GLboolean GL_APIENTRY glIsValuebufferCHROMIUM(GLuint valuebuffer); -GL_APICALL void GL_APIENTRY -glBindValuebufferCHROMIUM(GLenum target, GLuint valuebuffer); -GL_APICALL void GL_APIENTRY -glSubscribeValueCHROMIUM(GLenum target, GLenum subscription); -GL_APICALL void GL_APIENTRY glPopulateSubscribedValuesCHROMIUM(GLenum target); -GL_APICALL void GL_APIENTRY glUniformValuebufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription); -#endif -#endif /* GL_CHROMIUM_subscribe_uniform */ - /* GL_CHROMIUM_schedule_overlay_plane */ #ifndef GL_CHROMIUM_schedule_overlay_plane #define GL_CHROMIUM_schedule_overlay_plane 1 @@ -811,7 +782,8 @@ glScheduleCALayerCHROMIUM(GLuint contents_texture_id, GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, - const GLfloat* transform); + const GLfloat* transform, + GLuint filter); #endif typedef void(GL_APIENTRYP PFNGLSCHEDULECALAYERCHROMIUMPROC)( GLuint contents_texture_id, @@ -823,7 +795,8 @@ typedef void(GL_APIENTRYP PFNGLSCHEDULECALAYERCHROMIUMPROC)( GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, - const GLfloat* transform); + const GLfloat* transform, + GLuint filter); #endif /* GL_CHROMIUM_schedule_ca_layer */ /* GL_CHROMIUM_sync_query */ diff --git a/chromium/gpu/blink/BUILD.gn b/chromium/gpu/blink/BUILD.gn deleted file mode 100644 index 8bb98b1188c..00000000000 --- a/chromium/gpu/blink/BUILD.gn +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# GYP version: gpu/blink/gpu_blink.gyp:gpu_blink -component("blink") { - output_name = "gpu_blink" - - sources = [ - "gpu_blink_export.h", - "webgraphicscontext3d_impl.cc", - "webgraphicscontext3d_impl.h", - "webgraphicscontext3d_in_process_command_buffer_impl.cc", - "webgraphicscontext3d_in_process_command_buffer_impl.h", - ] - - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - - defines = [ "GPU_BLINK_IMPLEMENTATION" ] - - deps = [ - "//base", - "//base/third_party/dynamic_annotations", - "//cc", - "//gpu/command_buffer/client:gl_in_process_context", - "//gpu/command_buffer/client:gles2_c_lib", - "//gpu/command_buffer/client:gles2_implementation", - "//gpu/command_buffer/common", - "//gpu/command_buffer/common:gles2_utils", - "//gpu/command_buffer/service", - "//gpu/skia_bindings", - "//skia", - "//third_party/WebKit/public:blink_minimal", - "//third_party/angle:translator", - "//ui/gfx", - "//ui/gfx/geometry", - "//ui/gl", - ] -} diff --git a/chromium/gpu/blink/DEPS b/chromium/gpu/blink/DEPS deleted file mode 100644 index c8199ab3d9f..00000000000 --- a/chromium/gpu/blink/DEPS +++ /dev/null @@ -1,4 +0,0 @@ -include_rules = [ - "+third_party/WebKit/public/platform", - "+third_party/khronos/GLES2", -] diff --git a/chromium/gpu/blink/OWNERS b/chromium/gpu/blink/OWNERS deleted file mode 100644 index d591a3eaa09..00000000000 --- a/chromium/gpu/blink/OWNERS +++ /dev/null @@ -1 +0,0 @@ -kbr@chromium.org diff --git a/chromium/gpu/blink/gpu_blink.gyp b/chromium/gpu/blink/gpu_blink.gyp deleted file mode 100644 index 06a7c122e37..00000000000 --- a/chromium/gpu/blink/gpu_blink.gyp +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'conditions': [ - ['OS != "ios"', { - 'targets': [ - { - # GN version: //gpu/blink - 'target_name': 'gpu_blink', - 'type': '<(component)', - 'variables': { - 'chromium_code': 1, - 'enable_wexit_time_destructors': 1, - }, - 'dependencies': [ - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/cc/cc.gyp:cc', - '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', - '<(DEPTH)/gpu/command_buffer/command_buffer.gyp:gles2_utils', - '<(DEPTH)/gpu/gpu.gyp:command_buffer_service', - '<(DEPTH)/gpu/gpu.gyp:gles2_c_lib', - '<(DEPTH)/gpu/gpu.gyp:gles2_implementation', - '<(DEPTH)/gpu/gpu.gyp:gl_in_process_context', - '<(DEPTH)/gpu/skia_bindings/skia_bindings.gyp:gpu_skia_bindings', - '<(DEPTH)/skia/skia.gyp:skia', - '<(DEPTH)/third_party/WebKit/public/blink.gyp:blink_minimal', - '<(angle_path)/src/angle.gyp:translator', - '<(DEPTH)/ui/gl/gl.gyp:gl', - '<(DEPTH)/ui/gfx/gfx.gyp:gfx', - '<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry', - ], - 'sources': [ - 'gpu_blink_export.h', - 'webgraphicscontext3d_impl.cc', - 'webgraphicscontext3d_impl.h', - 'webgraphicscontext3d_in_process_command_buffer_impl.cc', - 'webgraphicscontext3d_in_process_command_buffer_impl.h', - ], - 'defines': [ - 'GPU_BLINK_IMPLEMENTATION', - ], - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - 'msvs_disabled_warnings': [ 4267, ], - }, - ], - }], - ], -} diff --git a/chromium/gpu/blink/gpu_blink_export.h b/chromium/gpu/blink/gpu_blink_export.h deleted file mode 100644 index ee697500e05..00000000000 --- a/chromium/gpu/blink/gpu_blink_export.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_BLINK_GPU_BLINK_EXPORT_H_ -#define GPU_BLINK_GPU_BLINK_EXPORT_H_ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(GPU_BLINK_IMPLEMENTATION) -#define GPU_BLINK_EXPORT __declspec(dllexport) -#else -#define GPU_BLINK_EXPORT __declspec(dllimport) -#endif // defined(GPU_BLINK_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(GPU_BLINK_IMPLEMENTATION) -#define GPU_BLINK_EXPORT __attribute__((visibility("default"))) -#else -#define GPU_BLINK_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define GPU_BLINK_EXPORT -#endif - -#endif // GPU_BLINK_GPU_BLINK_EXPORT_H_ diff --git a/chromium/gpu/blink/webgraphicscontext3d_impl.cc b/chromium/gpu/blink/webgraphicscontext3d_impl.cc deleted file mode 100644 index 5a5cdbd1fca..00000000000 --- a/chromium/gpu/blink/webgraphicscontext3d_impl.cc +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2012 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/blink/webgraphicscontext3d_impl.h" - -#include <stdint.h> - -#include "base/atomicops.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/sys_info.h" -#include "gpu/GLES2/gl2extchromium.h" -#include "gpu/command_buffer/client/gles2_implementation.h" -#include "gpu/command_buffer/client/gles2_lib.h" -#include "gpu/command_buffer/common/gles2_cmd_utils.h" -#include "gpu/command_buffer/common/sync_token.h" -#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h" - -#include "third_party/khronos/GLES2/gl2.h" -#ifndef GL_GLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES 1 -#endif -#include "third_party/khronos/GLES2/gl2ext.h" - -namespace gpu_blink { - -class WebGraphicsContext3DErrorMessageCallback - : public ::gpu::gles2::GLES2ImplementationErrorMessageCallback { - public: - WebGraphicsContext3DErrorMessageCallback( - WebGraphicsContext3DImpl* context) - : graphics_context_(context) { - } - - void OnErrorMessage(const char* msg, int id) override; - - private: - WebGraphicsContext3DImpl* graphics_context_; - - DISALLOW_COPY_AND_ASSIGN(WebGraphicsContext3DErrorMessageCallback); -}; - -void WebGraphicsContext3DErrorMessageCallback::OnErrorMessage( - const char* msg, int id) { - graphics_context_->OnErrorMessage(msg, id); -} - -WebGraphicsContext3DImpl::WebGraphicsContext3DImpl() - : initialized_(false), - initialize_failed_(false), - context_lost_callback_(0), - error_message_callback_(0), - gl_(NULL) {} - -WebGraphicsContext3DImpl::~WebGraphicsContext3DImpl() { - -} - -void WebGraphicsContext3DImpl::setErrorMessageCallback( - WebGraphicsContext3D::WebGraphicsErrorMessageCallback* cb) { - error_message_callback_ = cb; -} - -void WebGraphicsContext3DImpl::setContextLostCallback( - WebGraphicsContext3D::WebGraphicsContextLostCallback* cb) { - context_lost_callback_ = cb; -} - -::gpu::gles2::GLES2ImplementationErrorMessageCallback* - WebGraphicsContext3DImpl::getErrorMessageCallback() { - if (!client_error_message_callback_) { - client_error_message_callback_.reset( - new WebGraphicsContext3DErrorMessageCallback(this)); - } - return client_error_message_callback_.get(); -} - -void WebGraphicsContext3DImpl::OnErrorMessage( - const std::string& message, int id) { - if (error_message_callback_) { - blink::WebString str = blink::WebString::fromUTF8(message.c_str()); - error_message_callback_->onErrorMessage(str, id); - } -} - -} // namespace gpu_blink diff --git a/chromium/gpu/blink/webgraphicscontext3d_impl.h b/chromium/gpu/blink/webgraphicscontext3d_impl.h deleted file mode 100644 index 0dc5bc58bf3..00000000000 --- a/chromium/gpu/blink/webgraphicscontext3d_impl.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_BLINK_WEBGRAPHICSCONTEXT3D_IMPL_H_ -#define GPU_BLINK_WEBGRAPHICSCONTEXT3D_IMPL_H_ - -#include <stdint.h> - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "gpu/blink/gpu_blink_export.h" -#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" -#include "third_party/WebKit/public/platform/WebString.h" - -namespace gpu { - -namespace gles2 { -class GLES2Interface; -class GLES2ImplementationErrorMessageCallback; -struct ContextCreationAttribHelper; -} -} - -namespace gpu_blink { - -class WebGraphicsContext3DErrorMessageCallback; - -class GPU_BLINK_EXPORT WebGraphicsContext3DImpl - : public NON_EXPORTED_BASE(blink::WebGraphicsContext3D) { - public: - ~WebGraphicsContext3DImpl() override; - - //---------------------------------------------------------------------- - // WebGraphicsContext3D methods - - void setContextLostCallback( - WebGraphicsContext3D::WebGraphicsContextLostCallback* callback); - - void setErrorMessageCallback( - WebGraphicsContext3D::WebGraphicsErrorMessageCallback* callback) override; - - ::gpu::gles2::GLES2Interface* GetGLInterface() { - return gl_; - } - - protected: - friend class WebGraphicsContext3DErrorMessageCallback; - - WebGraphicsContext3DImpl(); - - ::gpu::gles2::GLES2ImplementationErrorMessageCallback* - getErrorMessageCallback(); - virtual void OnErrorMessage(const std::string& message, int id); - - void SetGLInterface(::gpu::gles2::GLES2Interface* gl) { gl_ = gl; } - - bool initialized_; - bool initialize_failed_; - - WebGraphicsContext3D::WebGraphicsContextLostCallback* context_lost_callback_; - - WebGraphicsContext3D::WebGraphicsErrorMessageCallback* - error_message_callback_; - scoped_ptr<WebGraphicsContext3DErrorMessageCallback> - client_error_message_callback_; - - ::gpu::gles2::GLES2Interface* gl_; - bool lose_context_when_out_of_memory_; -}; - -} // namespace gpu_blink - -#endif // GPU_BLINK_WEBGRAPHICSCONTEXT3D_IMPL_H_ diff --git a/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc b/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc deleted file mode 100644 index 9a2a59689c6..00000000000 --- a/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) 2012 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/blink/webgraphicscontext3d_in_process_command_buffer_impl.h" - -#include <GLES2/gl2.h> -#include <utility> -#ifndef GL_GLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES 1 -#endif -#include <GLES2/gl2ext.h> -#include <GLES2/gl2extchromium.h> -#include <stddef.h> - -#include <string> - -#include "base/atomicops.h" -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/logging.h" -#include "gpu/command_buffer/client/gles2_implementation.h" -#include "gpu/command_buffer/common/gles2_cmd_utils.h" -#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h" -#include "ui/gfx/geometry/size.h" -#include "ui/gl/gl_implementation.h" - -using gpu::gles2::GLES2Implementation; -using gpu::GLInProcessContext; - -namespace gpu_blink { - -// static -scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> -WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext( - const gpu::gles2::ContextCreationAttribHelper& attributes) { - bool is_offscreen = true; - return make_scoped_ptr(new WebGraphicsContext3DInProcessCommandBufferImpl( - scoped_ptr<::gpu::GLInProcessContext>(), attributes, is_offscreen, - gfx::kNullAcceleratedWidget)); -} - -scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> -WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext( - scoped_ptr<::gpu::GLInProcessContext> context, - const gpu::gles2::ContextCreationAttribHelper& attributes) { - bool is_offscreen = true; // Not used. - gfx::AcceleratedWidget window = gfx::kNullAcceleratedWidget; // Not used. - return make_scoped_ptr(new WebGraphicsContext3DInProcessCommandBufferImpl( - std::move(context), attributes, is_offscreen, window)); -} - -WebGraphicsContext3DInProcessCommandBufferImpl:: - WebGraphicsContext3DInProcessCommandBufferImpl( - scoped_ptr<::gpu::GLInProcessContext> context, - const gpu::gles2::ContextCreationAttribHelper& attributes, - bool is_offscreen, - gfx::AcceleratedWidget window) - : attributes_(attributes), - is_offscreen_(is_offscreen), - window_(window), - context_(std::move(context)) {} - -WebGraphicsContext3DInProcessCommandBufferImpl:: - ~WebGraphicsContext3DInProcessCommandBufferImpl() { -} - -size_t WebGraphicsContext3DInProcessCommandBufferImpl::GetMappedMemoryLimit() { - return context_->GetMappedMemoryLimit(); -} - -bool WebGraphicsContext3DInProcessCommandBufferImpl::MaybeInitializeGL() { - if (initialized_) - return true; - - if (initialize_failed_) - return false; - - if (!context_) { - // TODO(kbr): More work will be needed in this implementation to - // properly support GPU switching. Like in the out-of-process - // command buffer implementation, all previously created contexts - // will need to be lost either when the first context requesting the - // discrete GPU is created, or the last one is destroyed. - gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; - context_.reset(GLInProcessContext::Create( - NULL, /* service */ - NULL, /* surface */ - is_offscreen_, window_, gfx::Size(1, 1), NULL, /* share_context */ - attributes_, gpu_preference, - ::gpu::GLInProcessContextSharedMemoryLimits(), nullptr, nullptr)); - } - - if (!context_) { - initialize_failed_ = true; - return false; - } - - real_gl_ = context_->GetImplementation(); - SetGLInterface(real_gl_); - - real_gl_->TraceBeginCHROMIUM("WebGraphicsContext3D", - "InProcessContext"); - - initialized_ = true; - return true; -} - -bool -WebGraphicsContext3DInProcessCommandBufferImpl::InitializeOnCurrentThread() { - if (!MaybeInitializeGL()) - return false; - return context_ && - context_->GetImplementation()->GetGraphicsResetStatusKHR() == - GL_NO_ERROR; -} - -void WebGraphicsContext3DInProcessCommandBufferImpl::SetLock(base::Lock* lock) { - context_->SetLock(lock); -} - -::gpu::ContextSupport* -WebGraphicsContext3DInProcessCommandBufferImpl::GetContextSupport() { - return real_gl_; -} - -} // namespace gpu_blink diff --git a/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h b/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h deleted file mode 100644 index 2dd275d5d87..00000000000 --- a/chromium/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_BLINK_WEBGRAPHICSCONTEXT3D_IN_PROCESS_COMMAND_BUFFER_IMPL_H_ -#define GPU_BLINK_WEBGRAPHICSCONTEXT3D_IN_PROCESS_COMMAND_BUFFER_IMPL_H_ - -#include <stddef.h> - -#include <vector> - -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "gpu/blink/gpu_blink_export.h" -#include "gpu/blink/webgraphicscontext3d_impl.h" -#include "gpu/command_buffer/client/gl_in_process_context.h" -#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" -#include "third_party/WebKit/public/platform/WebString.h" -#include "ui/gfx/native_widget_types.h" - -namespace gpu { -class ContextSupport; -class GLInProcessContext; - -namespace gles2 { -class GLES2Interface; -class GLES2Implementation; -struct ContextCreationAttribHelper; -} -} - -namespace gpu_blink { - -class GPU_BLINK_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl - : public WebGraphicsContext3DImpl { - public: - enum MappedMemoryReclaimLimit { - kNoLimit = 0, - }; - - static scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> - CreateOffscreenContext( - const gpu::gles2::ContextCreationAttribHelper& attributes); - - static scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> WrapContext( - scoped_ptr<::gpu::GLInProcessContext> context, - const gpu::gles2::ContextCreationAttribHelper& attributes); - - ~WebGraphicsContext3DInProcessCommandBufferImpl() override; - - size_t GetMappedMemoryLimit(); - - bool InitializeOnCurrentThread(); - void SetLock(base::Lock* lock); - - ::gpu::ContextSupport* GetContextSupport(); - - ::gpu::gles2::GLES2Implementation* GetImplementation() { - return real_gl_; - } - - private: - WebGraphicsContext3DInProcessCommandBufferImpl( - scoped_ptr<::gpu::GLInProcessContext> context, - const gpu::gles2::ContextCreationAttribHelper& attributes, - bool is_offscreen, - gfx::AcceleratedWidget window); - - void OnContextLost(); - - bool MaybeInitializeGL(); - - // Used to try to find bugs in code that calls gl directly through the gl api - // instead of going through WebGraphicsContext3D. - void ClearContext(); - - ::gpu::gles2::ContextCreationAttribHelper attributes_; - - bool is_offscreen_; - // Only used when not offscreen. - gfx::AcceleratedWidget window_; - - // The context we use for OpenGL rendering. - scoped_ptr< ::gpu::GLInProcessContext> context_; - // The GLES2Implementation we use for OpenGL rendering. - ::gpu::gles2::GLES2Implementation* real_gl_; -}; - -} // namespace gpu_blink - -#endif // GPU_BLINK_WEBGRAPHICSCONTEXT3D_IN_PROCESS_COMMAND_BUFFER_IMPL_H_ diff --git a/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py b/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py index 4d94ddfb0b0..41a9d3e31ed 100755 --- a/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -994,7 +994,6 @@ _NAMED_TYPE_INFO = { }, 'ReadBuffer': { 'type': 'GLenum', - 'is_complete': True, 'valid': [ 'GL_NONE', 'GL_BACK', @@ -2147,18 +2146,6 @@ _NAMED_TYPE_INFO = { 'GL_READ_WRITE_CHROMIUM', ], }, - 'ValueBufferTarget': { - 'type': 'GLenum', - 'valid': [ - 'GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM', - ], - }, - 'SubscriptionTarget': { - 'type': 'GLenum', - 'valid': [ - 'GL_MOUSE_POSITION_CHROMIUM', - ], - }, 'UniformParameter': { 'type': 'GLenum', 'is_complete': True, @@ -2425,6 +2412,7 @@ _FUNCTION_INFO = { 'type': 'Bind', 'decoder_func': 'DoBindBufferRange', 'gen_func': 'GenBuffersARB', + 'unit_test': False, 'valid_args': { '3': '4', '4': '4' @@ -2456,12 +2444,15 @@ _FUNCTION_INFO = { 'gen_func': 'GenTextures', # TODO: remove this once client side caching works. 'client_test': False, + 'unit_test': False, 'trace_level': 2, }, 'BindTransformFeedback': { 'type': 'Bind', - 'id_mapping': [ 'TransformFeedback' ], + 'decoder_func': 'DoBindTransformFeedback', 'unsafe': True, + 'use_helper': True, + 'unit_test': False, }, 'BlitFramebufferCHROMIUM': { 'decoder_func': 'DoBlitFramebufferCHROMIUM', @@ -2592,57 +2583,6 @@ _FUNCTION_INFO = { 'chromium': True, 'trace_level': 2, }, - 'GenValuebuffersCHROMIUM': { - 'type': 'GENn', - 'gl_test_func': 'glGenValuebuffersCHROMIUM', - 'resource_type': 'Valuebuffer', - 'resource_types': 'Valuebuffers', - 'unit_test': False, - 'extension': 'CHROMIUM_subscribe_uniform', - 'chromium': True, - }, - 'DeleteValuebuffersCHROMIUM': { - 'type': 'DELn', - 'gl_test_func': 'glDeleteValuebuffersCHROMIUM', - 'resource_type': 'Valuebuffer', - 'resource_types': 'Valuebuffers', - 'unit_test': False, - 'extension': 'CHROMIUM_subscribe_uniform', - 'chromium': True, - }, - 'IsValuebufferCHROMIUM': { - 'type': 'Is', - 'decoder_func': 'DoIsValuebufferCHROMIUM', - 'expectation': False, - 'extension': 'CHROMIUM_subscribe_uniform', - 'chromium': True, - }, - 'BindValuebufferCHROMIUM': { - 'type': 'Bind', - 'decoder_func': 'DoBindValueBufferCHROMIUM', - 'gen_func': 'GenValueBuffersCHROMIUM', - 'unit_test': False, - 'extension': 'CHROMIUM_subscribe_uniform', - 'chromium': True, - }, - 'SubscribeValueCHROMIUM': { - 'decoder_func': 'DoSubscribeValueCHROMIUM', - 'unit_test': False, - 'extension': 'CHROMIUM_subscribe_uniform', - 'chromium': True, - }, - 'PopulateSubscribedValuesCHROMIUM': { - 'decoder_func': 'DoPopulateSubscribedValuesCHROMIUM', - 'unit_test': False, - 'extension': 'CHROMIUM_subscribe_uniform', - 'chromium': True, - }, - 'UniformValuebufferCHROMIUM': { - 'decoder_func': 'DoUniformValueBufferCHROMIUM', - 'unit_test': False, - 'extension': 'CHROMIUM_subscribe_uniform', - 'chromium': True, - }, 'ClearStencil': { 'type': 'StateSet', 'state': 'ClearStencil', @@ -2859,6 +2799,8 @@ _FUNCTION_INFO = { 'resource_type': 'TransformFeedback', 'resource_types': 'TransformFeedbacks', 'unsafe': True, + 'use_helper': True, + 'unit_test': False, }, 'DepthRangef': { 'decoder_func': 'DoDepthRangef', @@ -2949,6 +2891,7 @@ _FUNCTION_INFO = { 'FramebufferTextureLayer': { 'decoder_func': 'DoFramebufferTextureLayer', 'unsafe': True, + 'unit_test': False, 'trace_level': 1, }, 'GenerateMipmap': { @@ -2999,6 +2942,8 @@ _FUNCTION_INFO = { 'resource_type': 'TransformFeedback', 'resource_types': 'TransformFeedbacks', 'unsafe': True, + 'use_helper': True, + 'unit_test': False, }, 'GetActiveAttrib': { 'type': 'Custom', @@ -3143,13 +3088,19 @@ _FUNCTION_INFO = { 'GetInteger64i_v': { 'type': 'GETn', 'result': ['SizedResult<GLint64>'], + 'decoder_func': 'DoGetInteger64i_v', + 'shadowed': True, 'client_test': False, + 'unit_test': False, 'unsafe': True }, 'GetIntegeri_v': { 'type': 'GETn', 'result': ['SizedResult<GLint>'], + 'decoder_func': 'DoGetIntegeri_v', + 'shadowed': True, 'client_test': False, + 'unit_test': False, 'unsafe': True }, 'GetInternalformativ': { @@ -3411,6 +3362,7 @@ _FUNCTION_INFO = { 'InvalidateFramebuffer': { 'type': 'PUTn', 'count': 1, + 'decoder_func': 'DoInvalidateFramebuffer', 'client_test': False, 'unit_test': False, 'unsafe': True, @@ -3418,6 +3370,7 @@ _FUNCTION_INFO = { 'InvalidateSubFramebuffer': { 'type': 'PUTn', 'count': 1, + 'decoder_func': 'DoInvalidateSubFramebuffer', 'client_test': False, 'unit_test': False, 'unsafe': True, @@ -3475,9 +3428,10 @@ _FUNCTION_INFO = { }, 'IsTransformFeedback': { 'type': 'Is', - 'id_mapping': [ 'TransformFeedback' ], + 'decoder_func': 'DoIsTransformFeedback', 'expectation': False, 'unsafe': True, + 'use_helper': True, }, 'GetLastFlushIdCHROMIUM': { 'gen_cmd': False, @@ -3525,6 +3479,8 @@ _FUNCTION_INFO = { 'trace_level': 1, }, 'PauseTransformFeedback': { + 'decoder_func': 'DoPauseTransformFeedback', + 'unit_test': False, 'unsafe': True, }, 'PixelStorei': {'type': 'Manual'}, @@ -3622,6 +3578,8 @@ _FUNCTION_INFO = { 'unit_test': False, }, 'ResumeTransformFeedback': { + 'decoder_func': 'DoResumeTransformFeedback', + 'unit_test': False, 'unsafe': True, }, 'SamplerParameterf': { @@ -4187,6 +4145,8 @@ _FUNCTION_INFO = { 'extension': "occlusion_query_EXT", }, 'BeginTransformFeedback': { + 'decoder_func': 'DoBeginTransformFeedback', + 'unit_test': False, 'unsafe': True, }, 'EndQueryEXT': { @@ -4198,6 +4158,8 @@ _FUNCTION_INFO = { 'extension': "occlusion_query_EXT", }, 'EndTransformFeedback': { + 'decoder_func': 'DoEndTransformFeedback', + 'unit_test': False, 'unsafe': True, }, 'FlushDriverCachesCHROMIUM': { @@ -4458,7 +4420,7 @@ _FUNCTION_INFO = { 'cmd_args': 'GLuint contents_texture_id, GLfloat opacity, ' 'GLuint background_color, GLuint edge_aa_mask, ' 'GLboolean is_clipped, GLint sorting_context_id, ' - 'GLuint shm_id, GLuint shm_offset', + 'GLuint filter, GLuint shm_id, GLuint shm_offset', 'extension': 'CHROMIUM_schedule_ca_layer', 'chromium': True, }, @@ -6159,7 +6121,7 @@ class GENnHandler(TypeHandler): return error::kInvalidArguments; } } - scoped_ptr<GLuint[]> service_ids(new GLuint[n]); + std::unique_ptr<GLuint[]> service_ids(new GLuint[n]); gl%(func_name)s(n, service_ids.get()); for (GLsizei ii = 0; ii < n; ++ii) { group_->Add%(resource_name)sId(%(last_arg_name)s[ii], service_ids[ii]); @@ -7291,7 +7253,7 @@ TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) { def WriteGetDataSizeCode(self, func, f): """Overrriden from TypeHandler.""" code = """ uint32_t data_size; - if (!ComputeDataSize(1, sizeof(%s), %d, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(%s), %d, &data_size)) { return error::kOutOfBounds; } """ @@ -7597,12 +7559,14 @@ TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) { def WriteGetDataSizeCode(self, func, f): """Overrriden from TypeHandler.""" - code = """ uint32_t data_size; - if (!ComputeDataSize(count, sizeof(%s), %d, &data_size)) { + code = """ uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(%s), %d, &data_size)) { return error::kOutOfBounds; } """ - f.write(code % (self.GetArrayType(func), self.GetArrayCount(func))) + f.write(code % (self.GetArrayType(func), + self.GetArrayCount(func))) if func.IsImmediate(): f.write(" if (data_size > immediate_data_size) {\n") f.write(" return error::kOutOfBounds;\n") @@ -8978,8 +8942,6 @@ class SizeArgument(Argument): def WriteValidationCode(self, f, func): """overridden from Argument.""" - if func.IsUnsafe(): - return code = """ if (%(var_name)s < 0) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "gl%(func_name)s", "%(var_name)s < 0"); return error::kNoError; @@ -9033,8 +8995,6 @@ class EnumBaseArgument(Argument): return self.named_type.GetConstantValue() def WriteValidationCode(self, f, func): - if func.IsUnsafe(): - return if self.named_type.IsConstant(): return f.write(" if (!validators_->%s.IsValid(%s)) {\n" % @@ -10928,6 +10888,8 @@ extern const NameToFunc g_gles2_function_table[] = { comment = ("// This file is included by gles2_interface.h to declare the\n" "// GL api functions.\n") code = """ +#include <memory> + #include "gpu/command_buffer/client/gles2_interface.h" #include "mojo/public/c/gles2/gles2.h" diff --git a/chromium/gpu/command_buffer/client/buffer_tracker_unittest.cc b/chromium/gpu/command_buffer/client/buffer_tracker_unittest.cc index c44d3849fab..b8d2a7d51cf 100644 --- a/chromium/gpu/command_buffer/client/buffer_tracker_unittest.cc +++ b/chromium/gpu/command_buffer/client/buffer_tracker_unittest.cc @@ -10,7 +10,9 @@ #include <GLES2/gl2ext.h> #include <stddef.h> #include <stdint.h> -#include "base/memory/scoped_ptr.h" + +#include <memory> + #include "gpu/command_buffer/client/client_test_helper.h" #include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/mapped_memory.h" @@ -67,10 +69,10 @@ class BufferTrackerTest : public testing::Test { command_buffer_.reset(); } - scoped_ptr<MockClientCommandBufferImpl> command_buffer_; - scoped_ptr<GLES2CmdHelper> helper_; - scoped_ptr<MappedMemoryManager> mapped_memory_; - scoped_ptr<BufferTracker> buffer_tracker_; + std::unique_ptr<MockClientCommandBufferImpl> command_buffer_; + std::unique_ptr<GLES2CmdHelper> helper_; + std::unique_ptr<MappedMemoryManager> mapped_memory_; + std::unique_ptr<BufferTracker> buffer_tracker_; }; TEST_F(BufferTrackerTest, Basic) { diff --git a/chromium/gpu/command_buffer/client/client_test_helper.cc b/chromium/gpu/command_buffer/client/client_test_helper.cc index 3e8c43c816f..ff7e0694487 100644 --- a/chromium/gpu/command_buffer/client/client_test_helper.cc +++ b/chromium/gpu/command_buffer/client/client_test_helper.cc @@ -9,6 +9,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "gpu/command_buffer/client/cmd_buffer_helper.h" #include "gpu/command_buffer/common/command_buffer.h" #include "testing/gmock/include/gmock/gmock.h" @@ -24,10 +26,6 @@ MockCommandBufferBase::MockCommandBufferBase() : put_offset_(0) { MockCommandBufferBase::~MockCommandBufferBase() { } -bool MockCommandBufferBase::Initialize() { - return true; -} - CommandBuffer::State MockCommandBufferBase::GetLastState() { return state_; } @@ -72,7 +70,7 @@ scoped_refptr<gpu::Buffer> MockCommandBufferBase::CreateTransferBuffer( *id = GetNextFreeTransferBufferId(); if (*id >= 0) { int32_t ndx = *id - kTransferBufferBaseId; - scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); + std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); shared_memory->CreateAndMapAnonymous(size); transfer_buffer_buffers_[ndx] = MakeBufferFromSharedMemory(std::move(shared_memory), size); diff --git a/chromium/gpu/command_buffer/client/client_test_helper.h b/chromium/gpu/command_buffer/client/client_test_helper.h index 30e3dd9d757..3b85773f397 100644 --- a/chromium/gpu/command_buffer/client/client_test_helper.h +++ b/chromium/gpu/command_buffer/client/client_test_helper.h @@ -10,9 +10,10 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/compiler_specific.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/client/gpu_control.h" #include "gpu/command_buffer/common/cmd_buffer_common.h" #include "gpu/command_buffer/common/gpu_memory_allocation.h" @@ -33,7 +34,6 @@ class MockCommandBufferBase : public CommandBufferServiceBase { MockCommandBufferBase(); ~MockCommandBufferBase() override; - bool Initialize() override; State GetLastState() override; int32_t GetLastToken() override; void WaitForTokenInRange(int32_t start, int32_t end) override; @@ -96,6 +96,7 @@ class MockClientGpuControl : public GpuControl { MockClientGpuControl(); virtual ~MockClientGpuControl(); + MOCK_METHOD1(SetGpuControlClient, void(GpuControlClient*)); MOCK_METHOD0(GetCapabilities, Capabilities()); MOCK_METHOD4(CreateImage, int32_t(ClientBuffer buffer, @@ -112,7 +113,6 @@ class MockClientGpuControl : public GpuControl { void(uint32_t query, const base::Closure& callback)); MOCK_METHOD1(CreateStreamTexture, uint32_t(uint32_t)); MOCK_METHOD1(SetLock, void(base::Lock*)); - MOCK_METHOD0(IsGpuChannelLost, bool()); MOCK_METHOD0(EnsureWorkVisible, void()); MOCK_CONST_METHOD0(GetNamespaceID, CommandBufferNamespace()); MOCK_CONST_METHOD0(GetCommandBufferID, CommandBufferId()); diff --git a/chromium/gpu/command_buffer/client/cmd_buffer_helper.cc b/chromium/gpu/command_buffer/client/cmd_buffer_helper.cc index ab1a47ac47a..e08c78c03cf 100644 --- a/chromium/gpu/command_buffer/client/cmd_buffer_helper.cc +++ b/chromium/gpu/command_buffer/client/cmd_buffer_helper.cc @@ -11,7 +11,7 @@ #include <algorithm> #include "base/logging.h" #include "base/strings/stringprintf.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/trace_event/memory_allocator_dump.h" #include "base/trace_event/memory_dump_manager.h" 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 2fea6ba2664..6b58a2c6fe5 100644 --- a/chromium/gpu/command_buffer/client/cmd_buffer_helper_test.cc +++ b/chromium/gpu/command_buffer/client/cmd_buffer_helper_test.cc @@ -8,6 +8,7 @@ #include <stdint.h> #include <list> +#include <memory> #include "base/bind.h" #include "base/bind_helpers.h" @@ -105,7 +106,6 @@ class CommandBufferHelperTest : public testing::Test { } command_buffer_.reset( new CommandBufferServiceLocked(transfer_buffer_manager_.get())); - EXPECT_TRUE(command_buffer_->Initialize()); executor_.reset( new CommandExecutor(command_buffer_.get(), api_mock_.get(), NULL)); @@ -258,11 +258,11 @@ class CommandBufferHelperTest : public testing::Test { CommandBufferOffset get_helper_put() { return helper_->put_; } - scoped_ptr<AsyncAPIMock> api_mock_; + std::unique_ptr<AsyncAPIMock> api_mock_; scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; - scoped_ptr<CommandBufferServiceLocked> command_buffer_; - scoped_ptr<CommandExecutor> executor_; - scoped_ptr<CommandBufferHelper> helper_; + std::unique_ptr<CommandBufferServiceLocked> command_buffer_; + std::unique_ptr<CommandExecutor> executor_; + std::unique_ptr<CommandBufferHelper> helper_; std::list<linked_ptr<std::vector<CommandBufferEntry> > > test_command_args_; unsigned int test_command_next_id_; Sequence sequence_; diff --git a/chromium/gpu/command_buffer/client/context_support.h b/chromium/gpu/command_buffer/client/context_support.h index 0e7c75c7d8c..c72cf37f16f 100644 --- a/chromium/gpu/command_buffer/client/context_support.h +++ b/chromium/gpu/command_buffer/client/context_support.h @@ -52,6 +52,10 @@ class ContextSupport { // this context's resources belong to. virtual uint64_t ShareGroupTracingGUID() const = 0; + // Sets a callback to be run when an error occurs. + virtual void SetErrorMessageCallback( + const base::Callback<void(const char*, int32_t)>& callback) = 0; + protected: ContextSupport() {} virtual ~ContextSupport() {} diff --git a/chromium/gpu/command_buffer/client/fenced_allocator_test.cc b/chromium/gpu/command_buffer/client/fenced_allocator_test.cc index 6abe1ba2b50..5d23970f3c6 100644 --- a/chromium/gpu/command_buffer/client/fenced_allocator_test.cc +++ b/chromium/gpu/command_buffer/client/fenced_allocator_test.cc @@ -6,6 +6,8 @@ #include <stdint.h> +#include <memory> + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/memory/aligned_memory.h" @@ -52,7 +54,6 @@ class BaseFencedAllocatorTest : public testing::Test { } command_buffer_.reset( new CommandBufferService(transfer_buffer_manager_.get())); - EXPECT_TRUE(command_buffer_->Initialize()); executor_.reset( new CommandExecutor(command_buffer_.get(), api_mock_.get(), NULL)); @@ -69,11 +70,11 @@ class BaseFencedAllocatorTest : public testing::Test { int32_t GetToken() { return command_buffer_->GetLastState().token; } - scoped_ptr<AsyncAPIMock> api_mock_; + std::unique_ptr<AsyncAPIMock> api_mock_; scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; - scoped_ptr<CommandBufferService> command_buffer_; - scoped_ptr<CommandExecutor> executor_; - scoped_ptr<CommandBufferHelper> helper_; + std::unique_ptr<CommandBufferService> command_buffer_; + std::unique_ptr<CommandExecutor> executor_; + std::unique_ptr<CommandBufferHelper> helper_; base::MessageLoop message_loop_; }; @@ -101,7 +102,7 @@ class FencedAllocatorTest : public BaseFencedAllocatorTest { BaseFencedAllocatorTest::TearDown(); } - scoped_ptr<FencedAllocator> allocator_; + std::unique_ptr<FencedAllocator> allocator_; }; // Checks basic alloc and free. @@ -413,8 +414,8 @@ class FencedAllocatorWrapperTest : public BaseFencedAllocatorTest { BaseFencedAllocatorTest::TearDown(); } - scoped_ptr<FencedAllocatorWrapper> allocator_; - scoped_ptr<char, base::AlignedFreeDeleter> buffer_; + std::unique_ptr<FencedAllocatorWrapper> allocator_; + std::unique_ptr<char, base::AlignedFreeDeleter> buffer_; }; // Checks basic alloc and free. 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 c11e01a25ad..cf9faab6896 100644 --- a/chromium/gpu/command_buffer/client/gl_in_process_context.cc +++ b/chromium/gpu/command_buffer/client/gl_in_process_context.cc @@ -7,6 +7,7 @@ #include <stddef.h> #include <stdint.h> +#include <memory> #include <set> #include <utility> #include <vector> @@ -23,11 +24,11 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/macros.h" -#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/shared_memory_limits.h" #include "gpu/command_buffer/client/transfer_buffer.h" #include "gpu/command_buffer/common/command_buffer.h" #include "gpu/command_buffer/common/constants.h" @@ -42,17 +43,11 @@ namespace gpu { namespace { -const int32_t kDefaultCommandBufferSize = 1024 * 1024; -const unsigned int kDefaultStartTransferBufferSize = 4 * 1024 * 1024; -const unsigned int kDefaultMinTransferBufferSize = 1 * 256 * 1024; -const unsigned int kDefaultMaxTransferBufferSize = 16 * 1024 * 1024; - class GLInProcessContextImpl : public GLInProcessContext, public base::SupportsWeakPtr<GLInProcessContextImpl> { public: - explicit GLInProcessContextImpl( - const GLInProcessContextSharedMemoryLimits& mem_limits); + GLInProcessContextImpl(); ~GLInProcessContextImpl() override; bool Initialize(scoped_refptr<gfx::GLSurface> surface, @@ -63,40 +58,27 @@ class GLInProcessContextImpl const gpu::gles2::ContextCreationAttribHelper& attribs, gfx::GpuPreference gpu_preference, const scoped_refptr<InProcessCommandBuffer::Service>& service, + const SharedMemoryLimits& mem_limits, GpuMemoryBufferManager* gpu_memory_buffer_manager, ImageFactory* image_factory); // GLInProcessContext implementation: - void SetContextLostCallback(const base::Closure& callback) override; gles2::GLES2Implementation* GetImplementation() override; - size_t GetMappedMemoryLimit() override; void SetLock(base::Lock* lock) override; -#if defined(OS_ANDROID) - scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture( - uint32_t stream_id) override; - uint32_t CreateStreamTexture(uint32_t texture_id) override; -#endif - private: void Destroy(); - void OnContextLost(); void OnSignalSyncPoint(const base::Closure& callback); - scoped_ptr<gles2::GLES2CmdHelper> gles2_helper_; - scoped_ptr<TransferBuffer> transfer_buffer_; - scoped_ptr<gles2::GLES2Implementation> gles2_implementation_; - scoped_ptr<InProcessCommandBuffer> command_buffer_; - - const GLInProcessContextSharedMemoryLimits mem_limits_; - base::Closure context_lost_callback_; + std::unique_ptr<gles2::GLES2CmdHelper> gles2_helper_; + std::unique_ptr<TransferBuffer> transfer_buffer_; + std::unique_ptr<gles2::GLES2Implementation> gles2_implementation_; + std::unique_ptr<InProcessCommandBuffer> command_buffer_; DISALLOW_COPY_AND_ASSIGN(GLInProcessContextImpl); }; -GLInProcessContextImpl::GLInProcessContextImpl( - const GLInProcessContextSharedMemoryLimits& mem_limits) - : mem_limits_(mem_limits) {} +GLInProcessContextImpl::GLInProcessContextImpl() = default; GLInProcessContextImpl::~GLInProcessContextImpl() { Destroy(); @@ -106,24 +88,10 @@ gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() { return gles2_implementation_.get(); } -size_t GLInProcessContextImpl::GetMappedMemoryLimit() { - return mem_limits_.mapped_memory_reclaim_limit; -} - void GLInProcessContextImpl::SetLock(base::Lock* lock) { NOTREACHED(); } -void GLInProcessContextImpl::SetContextLostCallback( - const base::Closure& callback) { - context_lost_callback_ = callback; -} - -void GLInProcessContextImpl::OnContextLost() { - if (!context_lost_callback_.is_null()) - context_lost_callback_.Run(); -} - bool GLInProcessContextImpl::Initialize( scoped_refptr<gfx::GLSurface> surface, bool is_offscreen, @@ -133,15 +101,11 @@ bool GLInProcessContextImpl::Initialize( const gles2::ContextCreationAttribHelper& attribs, gfx::GpuPreference gpu_preference, const scoped_refptr<InProcessCommandBuffer::Service>& service, + const SharedMemoryLimits& mem_limits, GpuMemoryBufferManager* gpu_memory_buffer_manager, ImageFactory* image_factory) { DCHECK(size.width() >= 0 && size.height() >= 0); - std::vector<int32_t> attrib_vector; - attribs.Serialize(&attrib_vector); - - base::Closure wrapped_callback = - base::Bind(&GLInProcessContextImpl::OnContextLost, AsWeakPtr()); command_buffer_.reset(new InProcessCommandBuffer(service)); scoped_refptr<gles2::ShareGroup> share_group; @@ -159,9 +123,8 @@ bool GLInProcessContextImpl::Initialize( is_offscreen, window, size, - attrib_vector, + attribs, gpu_preference, - wrapped_callback, share_command_buffer, gpu_memory_buffer_manager, image_factory)) { @@ -171,7 +134,7 @@ bool GLInProcessContextImpl::Initialize( // Create the GLES2 helper, which writes the command buffer protocol. gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get())); - if (!gles2_helper_->Initialize(mem_limits_.command_buffer_size)) { + if (!gles2_helper_->Initialize(mem_limits.command_buffer_size)) { LOG(ERROR) << "Failed to initialize GLES2CmdHelper"; Destroy(); return false; @@ -196,10 +159,10 @@ bool GLInProcessContextImpl::Initialize( command_buffer_.get())); if (!gles2_implementation_->Initialize( - mem_limits_.start_transfer_buffer_size, - mem_limits_.min_transfer_buffer_size, - mem_limits_.max_transfer_buffer_size, - mem_limits_.mapped_memory_reclaim_limit)) { + mem_limits.start_transfer_buffer_size, + mem_limits.min_transfer_buffer_size, + mem_limits.max_transfer_buffer_size, + mem_limits.mapped_memory_reclaim_limit)) { return false; } @@ -223,27 +186,8 @@ void GLInProcessContextImpl::Destroy() { command_buffer_.reset(); } -#if defined(OS_ANDROID) -scoped_refptr<gfx::SurfaceTexture> GLInProcessContextImpl::GetSurfaceTexture( - uint32_t stream_id) { - return command_buffer_->GetSurfaceTexture(stream_id); -} - -uint32_t GLInProcessContextImpl::CreateStreamTexture(uint32_t texture_id) { - return command_buffer_->CreateStreamTexture(texture_id); -} -#endif - } // anonymous namespace -GLInProcessContextSharedMemoryLimits::GLInProcessContextSharedMemoryLimits() - : command_buffer_size(kDefaultCommandBufferSize), - start_transfer_buffer_size(kDefaultStartTransferBufferSize), - min_transfer_buffer_size(kDefaultMinTransferBufferSize), - max_transfer_buffer_size(kDefaultMaxTransferBufferSize), - mapped_memory_reclaim_limit(gles2::GLES2Implementation::kNoLimit) { -} - // static GLInProcessContext* GLInProcessContext::Create( scoped_refptr<gpu::InProcessCommandBuffer::Service> service, @@ -254,7 +198,7 @@ GLInProcessContext* GLInProcessContext::Create( GLInProcessContext* share_context, const ::gpu::gles2::ContextCreationAttribHelper& attribs, gfx::GpuPreference gpu_preference, - const GLInProcessContextSharedMemoryLimits& memory_limits, + const SharedMemoryLimits& memory_limits, GpuMemoryBufferManager* gpu_memory_buffer_manager, ImageFactory* image_factory) { if (surface.get()) { @@ -263,18 +207,10 @@ GLInProcessContext* GLInProcessContext::Create( DCHECK_EQ(gfx::kNullAcceleratedWidget, window); } - scoped_ptr<GLInProcessContextImpl> context( - new GLInProcessContextImpl(memory_limits)); - if (!context->Initialize(surface, - is_offscreen, - share_context, - window, - size, - attribs, - gpu_preference, - service, - gpu_memory_buffer_manager, - image_factory)) + std::unique_ptr<GLInProcessContextImpl> context(new GLInProcessContextImpl); + if (!context->Initialize(surface, is_offscreen, share_context, window, size, + attribs, gpu_preference, service, memory_limits, + gpu_memory_buffer_manager, image_factory)) return NULL; return context.release(); diff --git a/chromium/gpu/command_buffer/client/gl_in_process_context.h b/chromium/gpu/command_buffer/client/gl_in_process_context.h index a338f82934d..047aee915e8 100644 --- a/chromium/gpu/command_buffer/client/gl_in_process_context.h +++ b/chromium/gpu/command_buffer/client/gl_in_process_context.h @@ -28,21 +28,12 @@ class SurfaceTexture; #endif namespace gpu { +struct SharedMemoryLimits; namespace gles2 { class GLES2Implementation; } -struct GL_IN_PROCESS_CONTEXT_EXPORT GLInProcessContextSharedMemoryLimits { - GLInProcessContextSharedMemoryLimits(); - - int32_t command_buffer_size; - unsigned int start_transfer_buffer_size; - unsigned int min_transfer_buffer_size; - unsigned int max_transfer_buffer_size; - unsigned int mapped_memory_reclaim_limit; -}; - class GL_IN_PROCESS_CONTEXT_EXPORT GLInProcessContext { public: virtual ~GLInProcessContext() {} @@ -64,25 +55,15 @@ class GL_IN_PROCESS_CONTEXT_EXPORT GLInProcessContext { GLInProcessContext* share_context, const gpu::gles2::ContextCreationAttribHelper& attribs, gfx::GpuPreference gpu_preference, - const GLInProcessContextSharedMemoryLimits& memory_limits, + const SharedMemoryLimits& memory_limits, GpuMemoryBufferManager* gpu_memory_buffer_manager, ImageFactory* image_factory); - virtual void SetContextLostCallback(const base::Closure& callback) = 0; - // Allows direct access to the GLES2 implementation so a GLInProcessContext // can be used without making it current. virtual gles2::GLES2Implementation* GetImplementation() = 0; - virtual size_t GetMappedMemoryLimit() = 0; - virtual void SetLock(base::Lock* lock) = 0; - -#if defined(OS_ANDROID) - virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture( - uint32_t stream_id) = 0; - virtual uint32_t CreateStreamTexture(uint32_t texture_id) = 0; -#endif }; } // namespace gpu 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 67f1e055def..3d3284d37c3 100644 --- a/chromium/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -1412,33 +1412,6 @@ void GL_APIENTRY GLES2BindUniformLocationCHROMIUM(GLuint program, const char* name) { gles2::GetGLContext()->BindUniformLocationCHROMIUM(program, location, name); } -void GL_APIENTRY GLES2GenValuebuffersCHROMIUM(GLsizei n, GLuint* buffers) { - gles2::GetGLContext()->GenValuebuffersCHROMIUM(n, buffers); -} -void GL_APIENTRY GLES2DeleteValuebuffersCHROMIUM(GLsizei n, - const GLuint* valuebuffers) { - gles2::GetGLContext()->DeleteValuebuffersCHROMIUM(n, valuebuffers); -} -GLboolean GL_APIENTRY GLES2IsValuebufferCHROMIUM(GLuint valuebuffer) { - return gles2::GetGLContext()->IsValuebufferCHROMIUM(valuebuffer); -} -void GL_APIENTRY GLES2BindValuebufferCHROMIUM(GLenum target, - GLuint valuebuffer) { - gles2::GetGLContext()->BindValuebufferCHROMIUM(target, valuebuffer); -} -void GL_APIENTRY GLES2SubscribeValueCHROMIUM(GLenum target, - GLenum subscription) { - gles2::GetGLContext()->SubscribeValueCHROMIUM(target, subscription); -} -void GL_APIENTRY GLES2PopulateSubscribedValuesCHROMIUM(GLenum target) { - gles2::GetGLContext()->PopulateSubscribedValuesCHROMIUM(target); -} -void GL_APIENTRY GLES2UniformValuebufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription) { - gles2::GetGLContext()->UniformValuebufferCHROMIUM(location, target, - subscription); -} void GL_APIENTRY GLES2BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { gles2::GetGLContext()->BindTexImage2DCHROMIUM(target, imageId); } @@ -1508,11 +1481,12 @@ void GL_APIENTRY GLES2ScheduleCALayerCHROMIUM(GLuint contents_texture_id, GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, - const GLfloat* transform) { + const GLfloat* transform, + GLuint filter) { gles2::GetGLContext()->ScheduleCALayerCHROMIUM( contents_texture_id, contents_rect, opacity, background_color, edge_aa_mask, bounds_rect, is_clipped, clip_rect, sorting_context_id, - transform); + transform, filter); } void GL_APIENTRY GLES2CommitOverlayPlanesCHROMIUM() { gles2::GetGLContext()->CommitOverlayPlanesCHROMIUM(); @@ -2789,35 +2763,6 @@ extern const NameToFunc g_gles2_function_table[] = { reinterpret_cast<GLES2FunctionPointer>(glBindUniformLocationCHROMIUM), }, { - "glGenValuebuffersCHROMIUM", - reinterpret_cast<GLES2FunctionPointer>(glGenValuebuffersCHROMIUM), - }, - { - "glDeleteValuebuffersCHROMIUM", - reinterpret_cast<GLES2FunctionPointer>(glDeleteValuebuffersCHROMIUM), - }, - { - "glIsValuebufferCHROMIUM", - reinterpret_cast<GLES2FunctionPointer>(glIsValuebufferCHROMIUM), - }, - { - "glBindValuebufferCHROMIUM", - reinterpret_cast<GLES2FunctionPointer>(glBindValuebufferCHROMIUM), - }, - { - "glSubscribeValueCHROMIUM", - reinterpret_cast<GLES2FunctionPointer>(glSubscribeValueCHROMIUM), - }, - { - "glPopulateSubscribedValuesCHROMIUM", - reinterpret_cast<GLES2FunctionPointer>( - glPopulateSubscribedValuesCHROMIUM), - }, - { - "glUniformValuebufferCHROMIUM", - reinterpret_cast<GLES2FunctionPointer>(glUniformValuebufferCHROMIUM), - }, - { "glBindTexImage2DCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(glBindTexImage2DCHROMIUM), }, 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 f8b3dcba877..f4b27ccf77d 100644 --- a/chromium/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -2618,73 +2618,6 @@ void BindUniformLocationCHROMIUMBucket(GLuint program, } } -void GenValuebuffersCHROMIUMImmediate(GLsizei n, GLuint* buffers) { - const uint32_t size = - gles2::cmds::GenValuebuffersCHROMIUMImmediate::ComputeSize(n); - gles2::cmds::GenValuebuffersCHROMIUMImmediate* c = - GetImmediateCmdSpaceTotalSize< - gles2::cmds::GenValuebuffersCHROMIUMImmediate>(size); - if (c) { - c->Init(n, buffers); - } -} - -void DeleteValuebuffersCHROMIUMImmediate(GLsizei n, - const GLuint* valuebuffers) { - const uint32_t size = - gles2::cmds::DeleteValuebuffersCHROMIUMImmediate::ComputeSize(n); - gles2::cmds::DeleteValuebuffersCHROMIUMImmediate* c = - GetImmediateCmdSpaceTotalSize< - gles2::cmds::DeleteValuebuffersCHROMIUMImmediate>(size); - if (c) { - c->Init(n, valuebuffers); - } -} - -void IsValuebufferCHROMIUM(GLuint valuebuffer, - uint32_t result_shm_id, - uint32_t result_shm_offset) { - gles2::cmds::IsValuebufferCHROMIUM* c = - GetCmdSpace<gles2::cmds::IsValuebufferCHROMIUM>(); - if (c) { - c->Init(valuebuffer, result_shm_id, result_shm_offset); - } -} - -void BindValuebufferCHROMIUM(GLenum target, GLuint valuebuffer) { - gles2::cmds::BindValuebufferCHROMIUM* c = - GetCmdSpace<gles2::cmds::BindValuebufferCHROMIUM>(); - if (c) { - c->Init(target, valuebuffer); - } -} - -void SubscribeValueCHROMIUM(GLenum target, GLenum subscription) { - gles2::cmds::SubscribeValueCHROMIUM* c = - GetCmdSpace<gles2::cmds::SubscribeValueCHROMIUM>(); - if (c) { - c->Init(target, subscription); - } -} - -void PopulateSubscribedValuesCHROMIUM(GLenum target) { - gles2::cmds::PopulateSubscribedValuesCHROMIUM* c = - GetCmdSpace<gles2::cmds::PopulateSubscribedValuesCHROMIUM>(); - if (c) { - c->Init(target); - } -} - -void UniformValuebufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription) { - gles2::cmds::UniformValuebufferCHROMIUM* c = - GetCmdSpace<gles2::cmds::UniformValuebufferCHROMIUM>(); - if (c) { - c->Init(location, target, subscription); - } -} - void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { gles2::cmds::BindTexImage2DCHROMIUM* c = GetCmdSpace<gles2::cmds::BindTexImage2DCHROMIUM>(); @@ -2830,13 +2763,14 @@ void ScheduleCALayerCHROMIUM(GLuint contents_texture_id, GLuint edge_aa_mask, GLboolean is_clipped, GLint sorting_context_id, + GLuint filter, GLuint shm_id, GLuint shm_offset) { gles2::cmds::ScheduleCALayerCHROMIUM* c = GetCmdSpace<gles2::cmds::ScheduleCALayerCHROMIUM>(); if (c) { c->Init(contents_texture_id, opacity, background_color, edge_aa_mask, - is_clipped, sorting_context_id, shm_id, shm_offset); + is_clipped, sorting_context_id, filter, shm_id, shm_offset); } } diff --git a/chromium/gpu/command_buffer/client/gles2_implementation.cc b/chromium/gpu/command_buffer/client/gles2_implementation.cc index f8f21373ae3..c7b96402a46 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation.cc +++ b/chromium/gpu/command_buffer/client/gles2_implementation.cc @@ -22,7 +22,7 @@ #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "base/sys_info.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_allocator_dump.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/process_memory_dump.h" @@ -32,6 +32,7 @@ #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/shared_memory_limits.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" @@ -110,7 +111,7 @@ GLES2Implementation::SingleThreadChecker::~SingleThreadChecker() { GLES2Implementation::GLES2Implementation( GLES2CmdHelper* helper, - ShareGroup* share_group, + scoped_refptr<ShareGroup> share_group, TransferBufferInterface* transfer_buffer, bool bind_generates_resource, bool lose_context_when_out_of_memory, @@ -133,7 +134,6 @@ GLES2Implementation::GLES2Implementation( bound_framebuffer_(0), bound_read_framebuffer_(0), bound_renderbuffer_(0), - bound_valuebuffer_(0), current_program_(0), bound_array_buffer_(0), bound_copy_read_buffer_(0), @@ -161,7 +161,6 @@ GLES2Implementation::GLES2Implementation( base::SysInfo::AmountOfPhysicalMemory() / 20) : 0), #endif - error_message_callback_(NULL), current_trace_stack_(0), gpu_control_(gpu_control), capabilities_(gpu_control->GetCapabilities()), @@ -182,7 +181,7 @@ GLES2Implementation::GLES2Implementation( }); share_group_ = - (share_group ? share_group + (share_group ? std::move(share_group) : new ShareGroup( bind_generates_resource, gpu_control_->GetCommandBufferID().GetUnsafeValue())); @@ -201,6 +200,8 @@ bool GLES2Implementation::Initialize( DCHECK_LE(starting_transfer_buffer_size, max_transfer_buffer_size); DCHECK_GE(min_transfer_buffer_size, kStartingOffset); + gpu_control_->SetGpuControlClient(this); + if (!transfer_buffer_->Initialize( starting_transfer_buffer_size, kStartingOffset, @@ -214,7 +215,7 @@ bool GLES2Implementation::Initialize( mapped_memory_.reset(new MappedMemoryManager(helper_, mapped_memory_limit)); unsigned chunk_size = 2 * 1024 * 1024; - if (mapped_memory_limit != kNoLimit) { + if (mapped_memory_limit != SharedMemoryLimits::kNoLimit) { // Use smaller chunks if the client is very memory conscientious. chunk_size = std::min(mapped_memory_limit / 4, chunk_size); } @@ -299,6 +300,10 @@ GLES2Implementation::~GLES2Implementation() { // Make sure the commands make it the service. WaitForCmd(); + + // The gpu_control_ outlives this class, so clear the client on it before we + // self-destruct. + gpu_control_->SetGpuControlClient(nullptr); } GLES2CmdHelper* GLES2Implementation::helper() const { @@ -321,6 +326,28 @@ IdAllocator* GLES2Implementation::GetIdAllocator(int namespace_id) const { return NULL; } +void GLES2Implementation::OnGpuControlLostContext() { + // This should never occur more than once. + DCHECK(!lost_context_callback_run_); + lost_context_callback_run_ = true; + share_group_->Lose(); + if (!lost_context_callback_.is_null()) + lost_context_callback_.Run(); +} + +void GLES2Implementation::OnGpuControlLostContextMaybeReentrant() { + // Queries for lost context state should immediately reflect reality, + // but don't call out to clients yet to avoid them re-entering this + // class. + share_group_->Lose(); +} + +void GLES2Implementation::OnGpuControlErrorMessage(const char* message, + int32_t id) { + if (!error_message_callback_.is_null()) + error_message_callback_.Run(message, id); +} + void* GLES2Implementation::GetResultBuffer() { return transfer_buffer_->GetResultBuffer(); } @@ -346,7 +373,7 @@ void GLES2Implementation::FreeEverything() { } void GLES2Implementation::RunIfContextNotLost(const base::Closure& callback) { - if (!helper_->IsContextLost()) + if (!lost_context_callback_run_) callback.Run(); } @@ -549,10 +576,10 @@ void GLES2Implementation::SetGLError( if (msg) { last_error_ = msg; } - if (error_message_callback_) { + if (!error_message_callback_.is_null()) { std::string temp(GLES2Util::GetStringError(error) + " : " + function_name + ": " + (msg ? msg : "")); - error_message_callback_->OnErrorMessage(temp.c_str(), 0); + error_message_callback_.Run(temp.c_str(), 0); } error_bits_ |= GLES2Util::GLErrorToErrorBit(error); @@ -3961,11 +3988,6 @@ void GLES2Implementation::GenQueriesEXTHelper( GLsizei /* n */, const GLuint* /* queries */) { } -void GLES2Implementation::GenValuebuffersCHROMIUMHelper( - GLsizei /* n */, - const GLuint* /* valuebuffers */) { -} - void GLES2Implementation::GenSamplersHelper( GLsizei /* n */, const GLuint* /* samplers */) { } @@ -4269,35 +4291,6 @@ void GLES2Implementation::BindVertexArrayOESHelper(GLuint array) { } } -void GLES2Implementation::BindValuebufferCHROMIUMHelper(GLenum target, - GLuint valuebuffer) { - bool changed = false; - switch (target) { - case GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM: - if (bound_valuebuffer_ != valuebuffer) { - bound_valuebuffer_ = valuebuffer; - changed = true; - } - break; - default: - changed = true; - break; - } - // TODO(gman): See note #2 above. - if (changed) { - GetIdHandler(id_namespaces::kValuebuffers)->MarkAsUsedForBind( - this, target, valuebuffer, - &GLES2Implementation::BindValuebufferCHROMIUMStub); - } -} - -void GLES2Implementation::BindValuebufferCHROMIUMStub(GLenum target, - GLuint valuebuffer) { - helper_->BindValuebufferCHROMIUM(target, valuebuffer); - if (share_group_->bind_generates_resource()) - helper_->CommandBufferHelper::OrderingBarrier(); -} - void GLES2Implementation::UseProgramHelper(GLuint program) { if (current_program_ != program) { current_program_ = program; @@ -4453,23 +4446,6 @@ void GLES2Implementation::DeleteVertexArraysOESStub( helper_->DeleteVertexArraysOESImmediate(n, arrays); } -void GLES2Implementation::DeleteValuebuffersCHROMIUMHelper( - GLsizei n, - const GLuint* valuebuffers) { - if (!GetIdHandler(id_namespaces::kValuebuffers) - ->FreeIds(this, n, valuebuffers, - &GLES2Implementation::DeleteValuebuffersCHROMIUMStub)) { - SetGLError(GL_INVALID_VALUE, "glDeleteValuebuffersCHROMIUM", - "id not created by this context."); - return; - } - for (GLsizei ii = 0; ii < n; ++ii) { - if (valuebuffers[ii] == bound_valuebuffer_) { - bound_valuebuffer_ = 0; - } - } -} - void GLES2Implementation::DeleteSamplersStub( GLsizei n, const GLuint* samplers) { helper_->DeleteSamplersImmediate(n, samplers); @@ -4503,12 +4479,6 @@ void GLES2Implementation::DeleteTransformFeedbacksHelper( } } -void GLES2Implementation::DeleteValuebuffersCHROMIUMStub( - GLsizei n, - const GLuint* valuebuffers) { - helper_->DeleteValuebuffersCHROMIUMImmediate(n, valuebuffers); -} - void GLES2Implementation::DisableVertexAttribArray(GLuint index) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG( @@ -4673,15 +4643,10 @@ void GLES2Implementation::GetVertexAttribIuiv( 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. + // If any context (including ourselves) has seen itself become lost, + // then it will have told the ShareGroup, so just report its status. + if (share_group_->IsLost()) return GL_UNKNOWN_CONTEXT_RESET_KHR; - } return GL_NO_ERROR; } @@ -4747,7 +4712,8 @@ void GLES2Implementation::ScheduleCALayerCHROMIUM(GLuint contents_texture_id, GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, - const GLfloat* transform) { + const GLfloat* transform, + GLuint filter) { size_t shm_size = 28 * sizeof(GLfloat); ScopedTransferBufferPtr buffer(shm_size, helper_, transfer_buffer_); if (!buffer.valid() || buffer.size() < shm_size) { @@ -4762,7 +4728,7 @@ void GLES2Implementation::ScheduleCALayerCHROMIUM(GLuint contents_texture_id, memcpy(mem + 12, transform, 16 * sizeof(GLfloat)); helper_->ScheduleCALayerCHROMIUM(contents_texture_id, opacity, background_color, edge_aa_mask, is_clipped, - sorting_context_id, buffer.shm_id(), + sorting_context_id, filter, buffer.shm_id(), buffer.offset()); } @@ -5417,11 +5383,6 @@ void GLES2Implementation::EndQueryEXT(GLenum target) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT(" << GLES2Util::GetStringQueryTarget(target) << ")"); - // Don't do anything if the context is lost. - if (helper_->IsContextLost()) { - return; - } - if (query_tracker_->EndQuery(target, this)) CheckGLError(); } @@ -5818,6 +5779,16 @@ uint64_t GLES2Implementation::ShareGroupTracingGUID() const { return share_group_->TracingGUID(); } +void GLES2Implementation::SetErrorMessageCallback( + const base::Callback<void(const char*, int32_t)>& callback) { + error_message_callback_ = callback; +} + +void GLES2Implementation::SetLostContextCallback( + const base::Closure& callback) { + lost_context_callback_ = callback; +} + GLuint64 GLES2Implementation::InsertFenceSyncCHROMIUM() { const uint64_t release = gpu_control_->GenerateFenceSyncRelease(); helper_->InsertFenceSyncCHROMIUM(release); diff --git a/chromium/gpu/command_buffer/client/gles2_implementation.h b/chromium/gpu/command_buffer/client/gles2_implementation.h index 6ee901e2a05..5c7261b35c1 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation.h +++ b/chromium/gpu/command_buffer/client/gles2_implementation.h @@ -10,6 +10,7 @@ #include <list> #include <map> +#include <memory> #include <queue> #include <set> #include <string> @@ -18,7 +19,6 @@ #include "base/compiler_specific.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/trace_event/memory_dump_provider.h" #include "gpu/command_buffer/client/buffer_tracker.h" @@ -26,6 +26,7 @@ #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_impl_export.h" #include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/command_buffer/client/gpu_control_client.h" #include "gpu/command_buffer/client/mapped_memory.h" #include "gpu/command_buffer/client/ref_counted.h" #include "gpu/command_buffer/client/share_group.h" @@ -111,12 +112,6 @@ class GLES2CmdHelper; class VertexArrayObjectManager; class QueryTracker; -class GLES2ImplementationErrorMessageCallback { - public: - virtual ~GLES2ImplementationErrorMessageCallback() { } - virtual void OnErrorMessage(const char* msg, int id) = 0; -}; - // This class emulates GLES2 over command buffers. It can be used by a client // program so that the program does not need deal with shared memory and command // buffer management. See gl2_lib.h. Note that there is a performance gain to @@ -126,12 +121,9 @@ class GLES2ImplementationErrorMessageCallback { class GLES2_IMPL_EXPORT GLES2Implementation : NON_EXPORTED_BASE(public GLES2Interface), NON_EXPORTED_BASE(public ContextSupport), + NON_EXPORTED_BASE(public GpuControlClient), NON_EXPORTED_BASE(public base::trace_event::MemoryDumpProvider) { public: - enum MappedMemoryLimit { - kNoLimit = MappedMemoryManager::kNoLimit, - }; - // Stores GL state that never changes. struct GLES2_IMPL_EXPORT GLStaticState { GLStaticState(); @@ -168,7 +160,7 @@ class GLES2_IMPL_EXPORT GLES2Implementation static const size_t kMaxSwapBuffers = 2; GLES2Implementation(GLES2CmdHelper* helper, - ShareGroup* share_group, + scoped_refptr<ShareGroup> share_group, TransferBufferInterface* transfer_buffer, bool bind_generates_resource, bool lose_context_when_out_of_memory, @@ -212,6 +204,12 @@ class GLES2_IMPL_EXPORT GLES2Implementation const gfx::Rect& display_bounds, const gfx::RectF& uv_rect) override; uint64_t ShareGroupTracingGUID() const override; + void SetErrorMessageCallback( + const base::Callback<void(const char*, int32_t)>& callback) override; + + // TODO(danakj): Move to ContextSupport once ContextProvider doesn't need to + // intercept it. + void SetLostContextCallback(const base::Closure& callback); void GetProgramInfoCHROMIUMHelper(GLuint program, std::vector<int8_t>* result); @@ -264,14 +262,7 @@ class GLES2_IMPL_EXPORT GLES2Implementation bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd) override; - void SetErrorMessageCallback( - GLES2ImplementationErrorMessageCallback* callback) { - error_message_callback_ = callback; - } - - ShareGroup* share_group() const { - return share_group_.get(); - } + const scoped_refptr<ShareGroup>& share_group() const { return share_group_; } const Capabilities& capabilities() const { return capabilities_; @@ -418,6 +409,11 @@ class GLES2_IMPL_EXPORT GLES2Implementation return static_cast<T>(GetResultBuffer()); } + // GpuControlClient implementation. + void OnGpuControlLostContext() final; + void OnGpuControlLostContextMaybeReentrant() final; + void OnGpuControlErrorMessage(const char* message, int32_t id) final; + void* GetResultBuffer(); int32_t GetResultShmId(); uint32_t GetResultShmOffset(); @@ -470,7 +466,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation bool IsTextureReservedId(GLuint id) { return false; } bool IsVertexArrayReservedId(GLuint id) { return false; } bool IsProgramReservedId(GLuint id) { return false; } - bool IsValuebufferReservedId(GLuint id) { return false; } bool IsSamplerReservedId(GLuint id) { return false; } bool IsTransformFeedbackReservedId(GLuint id) { return false; } @@ -484,7 +479,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation void BindTextureHelper(GLenum target, GLuint texture); void BindTransformFeedbackHelper(GLenum target, GLuint transformfeedback); void BindVertexArrayOESHelper(GLuint array); - void BindValuebufferCHROMIUMHelper(GLenum target, GLuint valuebuffer); void UseProgramHelper(GLuint program); void BindBufferStub(GLenum target, GLuint buffer); @@ -494,7 +488,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation void BindFramebufferStub(GLenum target, GLuint framebuffer); void BindRenderbufferStub(GLenum target, GLuint renderbuffer); void BindTextureStub(GLenum target, GLuint texture); - void BindValuebufferCHROMIUMStub(GLenum target, GLuint valuebuffer); void GenBuffersHelper(GLsizei n, const GLuint* buffers); void GenFramebuffersHelper(GLsizei n, const GLuint* framebuffers); @@ -502,7 +495,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation void GenTexturesHelper(GLsizei n, const GLuint* textures); void GenVertexArraysOESHelper(GLsizei n, const GLuint* arrays); void GenQueriesEXTHelper(GLsizei n, const GLuint* queries); - void GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* valuebuffers); void GenSamplersHelper(GLsizei n, const GLuint* samplers); void GenTransformFeedbacksHelper(GLsizei n, const GLuint* transformfeedbacks); @@ -514,7 +506,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation bool DeleteShaderHelper(GLuint shader); void DeleteQueriesEXTHelper(GLsizei n, const GLuint* queries); void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* arrays); - void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* valuebuffers); void DeleteSamplersHelper(GLsizei n, const GLuint* samplers); void DeleteTransformFeedbacksHelper( GLsizei n, const GLuint* transformfeedbacks); @@ -528,7 +519,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation void DeleteProgramStub(GLsizei n, const GLuint* programs); void DeleteShaderStub(GLsizei n, const GLuint* shaders); void DeleteVertexArraysOESStub(GLsizei n, const GLuint* arrays); - void DeleteValuebuffersCHROMIUMStub(GLsizei n, const GLuint* valuebuffers); void DeleteSamplersStub(GLsizei n, const GLuint* samplers); void DeleteTransformFeedbacksStub( GLsizei n, const GLuint* transformfeedbacks); @@ -746,7 +736,7 @@ class GLES2_IMPL_EXPORT GLES2Implementation // unpack skip images as last set by glPixelStorei GLint unpack_skip_images_; - scoped_ptr<TextureUnit[]> texture_units_; + std::unique_ptr<TextureUnit[]> texture_units_; // 0 to gl_state_.max_combined_texture_image_units. GLuint active_texture_unit_; @@ -754,7 +744,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation GLuint bound_framebuffer_; GLuint bound_read_framebuffer_; GLuint bound_renderbuffer_; - GLuint bound_valuebuffer_; // The program in use by glUseProgram GLuint current_program_; @@ -773,7 +762,7 @@ class GLES2_IMPL_EXPORT GLES2Implementation // Client side management for vertex array objects. Needed to correctly // track client side arrays. - scoped_ptr<VertexArrayObjectManager> vertex_array_object_manager_; + std::unique_ptr<VertexArrayObjectManager> vertex_array_object_manager_; GLuint reserved_ids_[2]; @@ -815,17 +804,19 @@ class GLES2_IMPL_EXPORT GLES2Implementation typedef std::map<const void*, MappedTexture> MappedTextureMap; MappedTextureMap mapped_textures_; - scoped_ptr<MappedMemoryManager> mapped_memory_; + std::unique_ptr<MappedMemoryManager> mapped_memory_; scoped_refptr<ShareGroup> share_group_; ShareGroupContextData share_group_context_data_; - scoped_ptr<QueryTracker> query_tracker_; - scoped_ptr<IdAllocator> query_id_allocator_; + std::unique_ptr<QueryTracker> query_tracker_; + std::unique_ptr<IdAllocator> query_id_allocator_; - scoped_ptr<BufferTracker> buffer_tracker_; + std::unique_ptr<BufferTracker> buffer_tracker_; - GLES2ImplementationErrorMessageCallback* error_message_callback_; + base::Callback<void(const char*, int32_t)> error_message_callback_; + base::Closure lost_context_callback_; + bool lost_context_callback_run_ = false; int current_trace_stack_; diff --git a/chromium/gpu/command_buffer/client/gles2_implementation_autogen.h b/chromium/gpu/command_buffer/client/gles2_implementation_autogen.h index bee578d7601..74c5870f5b2 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -981,22 +981,6 @@ void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) override; -void GenValuebuffersCHROMIUM(GLsizei n, GLuint* buffers) override; - -void DeleteValuebuffersCHROMIUM(GLsizei n, const GLuint* valuebuffers) override; - -GLboolean IsValuebufferCHROMIUM(GLuint valuebuffer) override; - -void BindValuebufferCHROMIUM(GLenum target, GLuint valuebuffer) override; - -void SubscribeValueCHROMIUM(GLenum target, GLenum subscription) override; - -void PopulateSubscribedValuesCHROMIUM(GLenum target) override; - -void UniformValuebufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription) override; - void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) override; void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) override; @@ -1048,7 +1032,8 @@ void ScheduleCALayerCHROMIUM(GLuint contents_texture_id, GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, - const GLfloat* transform) override; + const GLfloat* transform, + GLuint filter) override; void CommitOverlayPlanesCHROMIUM() override; 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 0a56dc8465e..c2c10b778f1 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_implementation_impl_autogen.h @@ -228,7 +228,7 @@ void GLES2Implementation::ClearBufferfi(GLenum buffer, GLint stencil) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glClearBufferfi(" - << GLES2Util::GetStringBufferfv(buffer) << ", " + << GLES2Util::GetStringBufferfi(buffer) << ", " << drawbuffers << ", " << depth << ", " << stencil << ")"); helper_->ClearBufferfi(buffer, drawbuffers, depth, stencil); CheckGLError(); @@ -3193,118 +3193,6 @@ void GLES2Implementation::CompressedCopyTextureCHROMIUM(GLenum source_id, CheckGLError(); } -void GLES2Implementation::GenValuebuffersCHROMIUM(GLsizei n, GLuint* buffers) { - GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenValuebuffersCHROMIUM(" << n - << ", " << static_cast<const void*>(buffers) << ")"); - if (n < 0) { - SetGLError(GL_INVALID_VALUE, "glGenValuebuffersCHROMIUM", "n < 0"); - return; - } - GPU_CLIENT_SINGLE_THREAD_CHECK(); - GetIdHandler(id_namespaces::kValuebuffers)->MakeIds(this, 0, n, buffers); - GenValuebuffersCHROMIUMHelper(n, buffers); - helper_->GenValuebuffersCHROMIUMImmediate(n, buffers); - if (share_group_->bind_generates_resource()) - helper_->CommandBufferHelper::Flush(); - GPU_CLIENT_LOG_CODE_BLOCK({ - for (GLsizei i = 0; i < n; ++i) { - GPU_CLIENT_LOG(" " << i << ": " << buffers[i]); - } - }); - CheckGLError(); -} - -void GLES2Implementation::DeleteValuebuffersCHROMIUM( - GLsizei n, - const GLuint* valuebuffers) { - GPU_CLIENT_SINGLE_THREAD_CHECK(); - GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeleteValuebuffersCHROMIUM(" << n - << ", " << static_cast<const void*>(valuebuffers) << ")"); - GPU_CLIENT_LOG_CODE_BLOCK({ - for (GLsizei i = 0; i < n; ++i) { - GPU_CLIENT_LOG(" " << i << ": " << valuebuffers[i]); - } - }); - GPU_CLIENT_DCHECK_CODE_BLOCK({ - for (GLsizei i = 0; i < n; ++i) { - DCHECK(valuebuffers[i] != 0); - } - }); - if (n < 0) { - SetGLError(GL_INVALID_VALUE, "glDeleteValuebuffersCHROMIUM", "n < 0"); - return; - } - DeleteValuebuffersCHROMIUMHelper(n, valuebuffers); - CheckGLError(); -} - -GLboolean GLES2Implementation::IsValuebufferCHROMIUM(GLuint valuebuffer) { - GPU_CLIENT_SINGLE_THREAD_CHECK(); - TRACE_EVENT0("gpu", "GLES2Implementation::IsValuebufferCHROMIUM"); - GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsValuebufferCHROMIUM(" - << valuebuffer << ")"); - typedef cmds::IsValuebufferCHROMIUM::Result Result; - Result* result = GetResultAs<Result*>(); - if (!result) { - return GL_FALSE; - } - *result = 0; - helper_->IsValuebufferCHROMIUM(valuebuffer, GetResultShmId(), - GetResultShmOffset()); - WaitForCmd(); - GLboolean result_value = *result != 0; - GPU_CLIENT_LOG("returned " << result_value); - CheckGLError(); - return result_value; -} - -void GLES2Implementation::BindValuebufferCHROMIUM(GLenum target, - GLuint valuebuffer) { - GPU_CLIENT_SINGLE_THREAD_CHECK(); - GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindValuebufferCHROMIUM(" - << GLES2Util::GetStringValueBufferTarget(target) << ", " - << valuebuffer << ")"); - if (IsValuebufferReservedId(valuebuffer)) { - SetGLError(GL_INVALID_OPERATION, "BindValuebufferCHROMIUM", - "valuebuffer reserved id"); - return; - } - BindValuebufferCHROMIUMHelper(target, valuebuffer); - CheckGLError(); -} - -void GLES2Implementation::SubscribeValueCHROMIUM(GLenum target, - GLenum subscription) { - GPU_CLIENT_SINGLE_THREAD_CHECK(); - GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSubscribeValueCHROMIUM(" - << GLES2Util::GetStringValueBufferTarget(target) << ", " - << GLES2Util::GetStringSubscriptionTarget(subscription) - << ")"); - helper_->SubscribeValueCHROMIUM(target, subscription); - CheckGLError(); -} - -void GLES2Implementation::PopulateSubscribedValuesCHROMIUM(GLenum target) { - GPU_CLIENT_SINGLE_THREAD_CHECK(); - GPU_CLIENT_LOG("[" << GetLogPrefix() - << "] glPopulateSubscribedValuesCHROMIUM(" - << GLES2Util::GetStringValueBufferTarget(target) << ")"); - helper_->PopulateSubscribedValuesCHROMIUM(target); - CheckGLError(); -} - -void GLES2Implementation::UniformValuebufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription) { - GPU_CLIENT_SINGLE_THREAD_CHECK(); - GPU_CLIENT_LOG( - "[" << GetLogPrefix() << "] glUniformValuebufferCHROMIUM(" << location - << ", " << GLES2Util::GetStringValueBufferTarget(target) << ", " - << GLES2Util::GetStringSubscriptionTarget(subscription) << ")"); - helper_->UniformValuebufferCHROMIUM(location, target, subscription); - CheckGLError(); -} - void GLES2Implementation::BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindTexImage2DCHROMIUM(" diff --git a/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc b/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc index dd3d8259a56..ee06435191d 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -10,14 +10,19 @@ #include <GLES2/gl2ext.h> #include <GLES2/gl2extchromium.h> #include <GLES3/gl3.h> + #include <stddef.h> #include <stdint.h> + +#include <memory> + #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/shared_memory_limits.h" #include "gpu/command_buffer/client/transfer_buffer.h" #include "gpu/command_buffer/common/command_buffer.h" #include "gpu/command_buffer/common/sync_token.h" @@ -36,6 +41,7 @@ using testing::InSequence; using testing::Invoke; using testing::Mock; using testing::Pointee; +using testing::SaveArg; using testing::Sequence; using testing::StrictMock; using testing::Truly; @@ -412,7 +418,6 @@ class GLES2ImplementationTest : public testing::Test { static const GLuint kTransformFeedbacksStartId = 1; static const GLuint kQueriesStartId = 1; static const GLuint kVertexArraysStartId = 1; - static const GLuint kValuebuffersStartId = 1; typedef MockTransferBuffer::ExpectedMemoryInfo ExpectedMemoryInfo; @@ -431,8 +436,6 @@ class GLES2ImplementationTest : public testing::Test { int major_version, int minor_version) { command_buffer_.reset(new StrictMock<MockClientCommandBuffer>()); - if (!command_buffer_->Initialize()) - return false; transfer_buffer_.reset( new MockTransferBuffer(command_buffer_.get(), @@ -478,7 +481,7 @@ class GLES2ImplementationTest : public testing::Test { capabilities.major_version = major_version; capabilities.minor_version = minor_version; EXPECT_CALL(*gpu_control_, GetCapabilities()) - .WillOnce(testing::Return(capabilities)); + .WillOnce(Return(capabilities)); { InSequence sequence; @@ -491,16 +494,17 @@ class GLES2ImplementationTest : public testing::Test { lose_context_when_out_of_memory, support_client_side_arrays, gpu_control_.get())); - - if (!gl_->Initialize(kTransferBufferSize, - kTransferBufferSize, - kTransferBufferSize, - GLES2Implementation::kNoLimit)) - return false; } + // The client should be set to something non-null. + EXPECT_CALL(*gpu_control_, SetGpuControlClient(gl_.get())).Times(1); + + if (!gl_->Initialize(kTransferBufferSize, kTransferBufferSize, + kTransferBufferSize, SharedMemoryLimits::kNoLimit)) + return false; + helper_->CommandBufferHelper::Finish(); - ::testing::Mock::VerifyAndClearExpectations(gl_.get()); + Mock::VerifyAndClearExpectations(gl_.get()); scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer(); commands_ = static_cast<CommandBufferEntry*>(ring_buffer->memory()) + @@ -508,7 +512,7 @@ class GLES2ImplementationTest : public testing::Test { ClearCommands(); EXPECT_TRUE(transfer_buffer_->InSync()); - ::testing::Mock::VerifyAndClearExpectations(command_buffer()); + Mock::VerifyAndClearExpectations(command_buffer()); return true; } @@ -518,6 +522,8 @@ class GLES2ImplementationTest : public testing::Test { // For command buffer. EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) .Times(AtLeast(1)); + // The client should be unset. + EXPECT_CALL(*gpu_control_, SetGpuControlClient(nullptr)).Times(1); gl_.reset(); } @@ -532,11 +538,11 @@ class GLES2ImplementationTest : public testing::Test { memset(ring_buffer->memory(), kInitialValue, ring_buffer->size()); } - scoped_ptr<MockClientCommandBuffer> command_buffer_; - scoped_ptr<MockClientGpuControl> gpu_control_; - scoped_ptr<GLES2CmdHelper> helper_; - scoped_ptr<MockTransferBuffer> transfer_buffer_; - scoped_ptr<GLES2Implementation> gl_; + std::unique_ptr<MockClientCommandBuffer> command_buffer_; + std::unique_ptr<MockClientGpuControl> gpu_control_; + std::unique_ptr<GLES2CmdHelper> helper_; + std::unique_ptr<MockTransferBuffer> transfer_buffer_; + std::unique_ptr<GLES2Implementation> gl_; CommandBufferEntry* commands_; int token_; }; @@ -664,7 +670,7 @@ class GLES2ImplementationTest : public testing::Test { // Sets the ProgramInfoManager. The manager will be owned // by the ShareGroup. void SetProgramInfoManager(ProgramInfoManager* manager) { - gl_->share_group()->set_program_info_manager(manager); + gl_->share_group()->SetProgramInfoManagerForTesting(manager); } int CheckError() { @@ -849,18 +855,17 @@ const GLuint GLES2ImplementationTest::kTexturesStartId; const GLuint GLES2ImplementationTest::kTransformFeedbacksStartId; const GLuint GLES2ImplementationTest::kQueriesStartId; const GLuint GLES2ImplementationTest::kVertexArraysStartId; -const GLuint GLES2ImplementationTest::kValuebuffersStartId; #endif TEST_F(GLES2ImplementationTest, Basic) { - EXPECT_TRUE(gl_->share_group() != NULL); + EXPECT_TRUE(gl_->share_group()); } TEST_F(GLES2ImplementationTest, GetBucketContents) { const uint32_t kBucketId = GLES2Implementation::kResultBucketId; const uint32_t kTestSize = MaxTransferBufferSize() + 32; - scoped_ptr<uint8_t[]> buf(new uint8_t[kTestSize]); + std::unique_ptr<uint8_t[]> buf(new uint8_t[kTestSize]); uint8_t* expected_data = buf.get(); for (uint32_t ii = 0; ii < kTestSize; ++ii) { expected_data[ii] = ii * 3; @@ -1727,7 +1732,8 @@ TEST_F(GLES2ImplementationTest, ReadPixels2Reads) { 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, mem2.id, mem2.offset, result2.id, result2.offset, false); expected.set_token2.Init(GetNextToken()); - scoped_ptr<int8_t[]> buffer(new int8_t[kWidth * kHeight * kBytesPerPixel]); + std::unique_ptr<int8_t[]> buffer( + new int8_t[kWidth * kHeight * kBytesPerPixel]); EXPECT_CALL(*command_buffer(), OnFlush()) .WillOnce(SetMemory(result1.ptr, static_cast<uint32_t>(1))) @@ -1759,7 +1765,8 @@ TEST_F(GLES2ImplementationTest, ReadPixelsBadFormatType) { 0, 0, kWidth, kHeight, kFormat, kType, mem1.id, mem1.offset, result1.id, result1.offset, false); expected.set_token.Init(GetNextToken()); - scoped_ptr<int8_t[]> buffer(new int8_t[kWidth * kHeight * kBytesPerPixel]); + std::unique_ptr<int8_t[]> buffer( + new int8_t[kWidth * kHeight * kBytesPerPixel]); EXPECT_CALL(*command_buffer(), OnFlush()) .Times(1) @@ -2429,7 +2436,7 @@ TEST_F(GLES2ImplementationTest, TexImage2DViaMappedMem) { kWidth, kHeight, 1, kFormat, kType, kPixelStoreUnpackAlignment, &size, &unpadded_row_size, &padded_row_size)); - scoped_ptr<uint8_t[]> pixels(new uint8_t[size]); + std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]); for (uint32_t ii = 0; ii < size; ++ii) { pixels[ii] = static_cast<uint8_t>(ii); } @@ -2485,7 +2492,7 @@ TEST_F(GLES2ImplementationTest, TexImage2DViaTexSubImage2D) { kWidth, kHeight / 2, 1, kFormat, kType, kPixelStoreUnpackAlignment, &half_size, NULL, NULL)); - scoped_ptr<uint8_t[]> pixels(new uint8_t[size]); + std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]); for (uint32_t ii = 0; ii < size; ++ii) { pixels[ii] = static_cast<uint8_t>(ii); } @@ -2566,7 +2573,7 @@ TEST_F(GLES2ImplementationTest, SubImage2DUnpack) { ASSERT_TRUE(GLES2Util::ComputeImageDataSizesES3( kSrcWidth, kSrcSubImageY1, 1, kFormat, kType, pixel_params, &pixel_size, nullptr, nullptr, nullptr, nullptr)); - scoped_ptr<uint8_t[]> src_pixels; + std::unique_ptr<uint8_t[]> src_pixels; src_pixels.reset(new uint8_t[pixel_size]); for (size_t i = 0; i < pixel_size; ++i) { src_pixels[i] = static_cast<uint8_t>(i % 255); @@ -2707,7 +2714,7 @@ TEST_F(GLES3ImplementationTest, SubImage3DUnpack) { ASSERT_TRUE(GLES2Util::ComputeImageDataSizesES3( kSrcWidth, kSrcSubImageY1, kSrcSubImageZ1, kFormat, kType, pixel_params, &pixel_size, nullptr, nullptr, nullptr, nullptr)); - scoped_ptr<uint8_t[]> src_pixels; + std::unique_ptr<uint8_t[]> src_pixels; src_pixels.reset(new uint8_t[pixel_size]); for (size_t i = 0; i < pixel_size; ++i) { src_pixels[i] = static_cast<uint8_t>(i % 255); @@ -2922,7 +2929,7 @@ TEST_F(GLES2ImplementationTest, TexImage3DSingleCommand) { kWidth, kHeight, kDepth, kFormat, kType, kPixelStoreUnpackAlignment, &size, NULL, NULL)); - scoped_ptr<uint8_t[]> pixels(new uint8_t[size]); + std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]); for (uint32_t ii = 0; ii < size; ++ii) { pixels[ii] = static_cast<uint8_t>(ii); } @@ -2975,7 +2982,7 @@ TEST_F(GLES2ImplementationTest, TexImage3DViaMappedMem) { kWidth, kHeight, kDepth, kFormat, kType, kPixelStoreUnpackAlignment, &size, NULL, NULL)); - scoped_ptr<uint8_t[]> pixels(new uint8_t[size]); + std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]); for (uint32_t ii = 0; ii < size; ++ii) { pixels[ii] = static_cast<uint8_t>(ii); } @@ -3032,7 +3039,7 @@ TEST_F(GLES2ImplementationTest, TexImage3DViaTexSubImage3D) { EXPECT_EQ(size, first_size + second_size); ExpectedMemoryInfo mem1 = GetExpectedMemory(first_size); ExpectedMemoryInfo mem2 = GetExpectedMemory(second_size); - scoped_ptr<uint8_t[]> pixels(new uint8_t[size]); + std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]); for (uint32_t ii = 0; ii < size; ++ii) { pixels[ii] = static_cast<uint8_t>(ii); } @@ -3092,7 +3099,7 @@ TEST_F(GLES2ImplementationTest, TexSubImage3D4Writes) { uint32_t fourth_size = second_size - (padded_row_size - unpadded_row_size); EXPECT_EQ(size, first_size + second_size + third_size + fourth_size); - scoped_ptr<uint8_t[]> pixels(new uint8_t[size]); + std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]); for (uint32_t ii = 0; ii < size; ++ii) { pixels[ii] = static_cast<uint8_t>(ii); } @@ -3940,7 +3947,7 @@ TEST_F(GLES2ImplementationTest, AllowNestedTracesCHROMIUM) { TEST_F(GLES2ImplementationTest, InsertFenceSyncCHROMIUM) { const GLuint64 kFenceSync = 123u; EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()) - .WillOnce(testing::Return(kFenceSync)); + .WillOnce(Return(kFenceSync)); struct Cmds { cmds::InsertFenceSyncCHROMIUM insert_fence_sync; @@ -3961,31 +3968,31 @@ TEST_F(GLES2ImplementationTest, GenSyncTokenCHROMIUM) { GLbyte sync_token_data[GL_SYNC_TOKEN_SIZE_CHROMIUM]; EXPECT_CALL(*gpu_control_, GetNamespaceID()) - .WillRepeatedly(testing::Return(kNamespaceId)); + .WillRepeatedly(Return(kNamespaceId)); EXPECT_CALL(*gpu_control_, GetCommandBufferID()) - .WillRepeatedly(testing::Return(kCommandBufferId)); + .WillRepeatedly(Return(kCommandBufferId)); EXPECT_CALL(*gpu_control_, GetExtraCommandBufferData()) - .WillRepeatedly(testing::Return(0)); + .WillRepeatedly(Return(0)); gl_->GenSyncTokenCHROMIUM(kFenceSync, nullptr); EXPECT_EQ(GL_INVALID_VALUE, CheckError()); EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(testing::Return(false)); + .WillOnce(Return(false)); gl_->GenSyncTokenCHROMIUM(kFenceSync, sync_token_data); EXPECT_EQ(GL_INVALID_VALUE, CheckError()); EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(testing::Return(true)); + .WillOnce(Return(true)); EXPECT_CALL(*gpu_control_, IsFenceSyncFlushReceived(kFenceSync)) - .WillOnce(testing::Return(false)); + .WillOnce(Return(false)); gl_->GenSyncTokenCHROMIUM(kFenceSync, sync_token_data); EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(testing::Return(true)); + .WillOnce(Return(true)); EXPECT_CALL(*gpu_control_, IsFenceSyncFlushReceived(kFenceSync)) - .WillOnce(testing::Return(true)); + .WillOnce(Return(true)); ClearCommands(); gl_->GenSyncTokenCHROMIUM(kFenceSync, sync_token_data); EXPECT_TRUE(NoCommandsWritten()); @@ -4007,31 +4014,31 @@ TEST_F(GLES2ImplementationTest, GenUnverifiedSyncTokenCHROMIUM) { GLbyte sync_token_data[GL_SYNC_TOKEN_SIZE_CHROMIUM]; EXPECT_CALL(*gpu_control_, GetNamespaceID()) - .WillRepeatedly(testing::Return(kNamespaceId)); + .WillRepeatedly(Return(kNamespaceId)); EXPECT_CALL(*gpu_control_, GetCommandBufferID()) - .WillRepeatedly(testing::Return(kCommandBufferId)); + .WillRepeatedly(Return(kCommandBufferId)); EXPECT_CALL(*gpu_control_, GetExtraCommandBufferData()) - .WillRepeatedly(testing::Return(0)); + .WillRepeatedly(Return(0)); gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync, nullptr); EXPECT_EQ(GL_INVALID_VALUE, CheckError()); EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(testing::Return(false)); + .WillOnce(Return(false)); gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync, sync_token_data); EXPECT_EQ(GL_INVALID_VALUE, CheckError()); EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(testing::Return(true)); + .WillOnce(Return(true)); EXPECT_CALL(*gpu_control_, IsFenceSyncFlushed(kFenceSync)) - .WillOnce(testing::Return(false)); + .WillOnce(Return(false)); gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync, sync_token_data); EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(testing::Return(true)); + .WillOnce(Return(true)); EXPECT_CALL(*gpu_control_, IsFenceSyncFlushed(kFenceSync)) - .WillOnce(testing::Return(true)); + .WillOnce(Return(true)); ClearCommands(); gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync, sync_token_data); EXPECT_TRUE(NoCommandsWritten()); @@ -4060,23 +4067,23 @@ TEST_F(GLES2ImplementationTest, VerifySyncTokensCHROMIUM) { GLbyte* sync_token_datas[] = { sync_token.GetData() }; EXPECT_CALL(*gpu_control_, GetNamespaceID()) - .WillRepeatedly(testing::Return(kNamespaceId)); + .WillRepeatedly(Return(kNamespaceId)); EXPECT_CALL(*gpu_control_, GetCommandBufferID()) - .WillRepeatedly(testing::Return(kCommandBufferId)); + .WillRepeatedly(Return(kCommandBufferId)); EXPECT_CALL(*gpu_control_, GetExtraCommandBufferData()) - .WillRepeatedly(testing::Return(0)); + .WillRepeatedly(Return(0)); EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(testing::Return(true)); + .WillOnce(Return(true)); EXPECT_CALL(*gpu_control_, IsFenceSyncFlushed(kFenceSync)) - .WillOnce(testing::Return(true)); + .WillOnce(Return(true)); gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync, sync_token.GetData()); ASSERT_TRUE(sync_token.HasData()); ASSERT_FALSE(sync_token.verified_flush()); ClearCommands(); EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(_)) - .WillOnce(testing::Return(false)); + .WillOnce(Return(false)); gl_->VerifySyncTokensCHROMIUM(sync_token_datas, 1); EXPECT_TRUE(NoCommandsWritten()); EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); @@ -4084,7 +4091,7 @@ TEST_F(GLES2ImplementationTest, VerifySyncTokensCHROMIUM) { ClearCommands(); EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(_)) - .WillOnce(testing::Return(true)); + .WillOnce(Return(true)); EXPECT_CALL(*gpu_control_, EnsureWorkVisible()); gl_->VerifySyncTokensCHROMIUM(sync_token_datas, arraysize(sync_token_datas)); EXPECT_TRUE(NoCommandsWritten()); @@ -4166,15 +4173,13 @@ TEST_F(GLES2ImplementationTest, WaitSyncTokenCHROMIUM) { GLbyte sync_token[GL_SYNC_TOKEN_SIZE_CHROMIUM]; EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(testing::Return(true)); + .WillOnce(Return(true)); EXPECT_CALL(*gpu_control_, IsFenceSyncFlushReceived(kFenceSync)) - .WillOnce(testing::Return(true)); - EXPECT_CALL(*gpu_control_, GetNamespaceID()) - .WillOnce(testing::Return(kNamespaceId)); + .WillOnce(Return(true)); + EXPECT_CALL(*gpu_control_, GetNamespaceID()).WillOnce(Return(kNamespaceId)); EXPECT_CALL(*gpu_control_, GetCommandBufferID()) - .WillOnce(testing::Return(kCommandBufferId)); - EXPECT_CALL(*gpu_control_, GetExtraCommandBufferData()) - .WillOnce(testing::Return(0)); + .WillOnce(Return(kCommandBufferId)); + EXPECT_CALL(*gpu_control_, GetExtraCommandBufferData()).WillOnce(Return(0)); gl_->GenSyncTokenCHROMIUM(kFenceSync, sync_token); struct Cmds { @@ -4213,7 +4218,7 @@ TEST_F(GLES2ImplementationTest, WaitSyncTokenCHROMIUMErrors) { gpu::SyncToken unverified_sync_token(CommandBufferNamespace::GPU_IO, 0, gpu::CommandBufferId(), 0); EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(_)) - .WillOnce(testing::Return(false)); + .WillOnce(Return(false)); gl_->WaitSyncTokenCHROMIUM(unverified_sync_token.GetConstData()); EXPECT_TRUE(NoCommandsWritten()); EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); @@ -4444,6 +4449,107 @@ TEST_F(GLES2ImplementationTest, GetInternalformativ) { EXPECT_EQ(static_cast<ResultType>(kNumSampleCounts), result); } +static void CountCallback(int* count) { + (*count)++; +} + +TEST_F(GLES2ImplementationTest, SignalSyncToken) { + EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()).WillOnce(Return(1)); + const uint64_t fence_sync = gl_->InsertFenceSyncCHROMIUM(); + gl_->ShallowFlushCHROMIUM(); + + EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(fence_sync)) + .WillOnce(Return(true)); + EXPECT_CALL(*gpu_control_, IsFenceSyncFlushReceived(fence_sync)) + .WillOnce(Return(true)); + EXPECT_CALL(*gpu_control_, GetNamespaceID()).WillOnce(Return(GPU_IO)); + EXPECT_CALL(*gpu_control_, GetExtraCommandBufferData()).WillOnce(Return(0)); + EXPECT_CALL(*gpu_control_, GetCommandBufferID()) + .WillOnce(Return(CommandBufferId::FromUnsafeValue(1))); + gpu::SyncToken sync_token; + gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + + int signaled_count = 0; + + // Request a signal sync token, which gives a callback to the GpuControl to + // run when the sync token is reached. + base::Closure signal_closure; + EXPECT_CALL(*gpu_control_, SignalSyncToken(_, _)) + .WillOnce(SaveArg<1>(&signal_closure)); + gl_->SignalSyncToken(sync_token, base::Bind(&CountCallback, &signaled_count)); + EXPECT_EQ(0, signaled_count); + + // When GpuControl runs the callback, the original callback we gave to + // GLES2Implementation is run. + signal_closure.Run(); + EXPECT_EQ(1, signaled_count); +} + +TEST_F(GLES2ImplementationTest, SignalSyncTokenAfterContextLoss) { + EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()).WillOnce(Return(1)); + const uint64_t fence_sync = gl_->InsertFenceSyncCHROMIUM(); + gl_->ShallowFlushCHROMIUM(); + + EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(fence_sync)) + .WillOnce(Return(true)); + EXPECT_CALL(*gpu_control_, IsFenceSyncFlushReceived(fence_sync)) + .WillOnce(Return(true)); + EXPECT_CALL(*gpu_control_, GetNamespaceID()).WillOnce(Return(GPU_IO)); + EXPECT_CALL(*gpu_control_, GetExtraCommandBufferData()).WillOnce(Return(0)); + EXPECT_CALL(*gpu_control_, GetCommandBufferID()) + .WillOnce(Return(CommandBufferId::FromUnsafeValue(1))); + gpu::SyncToken sync_token; + gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + + int signaled_count = 0; + + // Request a signal sync token, which gives a callback to the GpuControl to + // run when the sync token is reached. + base::Closure signal_closure; + EXPECT_CALL(*gpu_control_, SignalSyncToken(_, _)) + .WillOnce(SaveArg<1>(&signal_closure)); + gl_->SignalSyncToken(sync_token, base::Bind(&CountCallback, &signaled_count)); + EXPECT_EQ(0, signaled_count); + + // Inform the GLES2Implementation that the context is lost. + GpuControlClient* gl_as_client = gl_; + gl_as_client->OnGpuControlLostContext(); + + // When GpuControl runs the callback, the original callback we gave to + // GLES2Implementation is *not* run, since the context is lost and we + // have already run the lost context callback. + signal_closure.Run(); + EXPECT_EQ(0, signaled_count); +} + +TEST_F(GLES2ImplementationTest, ReportLoss) { + GpuControlClient* gl_as_client = gl_; + int lost_count = 0; + gl_->SetLostContextCallback(base::Bind(&CountCallback, &lost_count)); + EXPECT_EQ(0, lost_count); + + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetGraphicsResetStatusKHR()); + gl_as_client->OnGpuControlLostContext(); + EXPECT_NE(static_cast<GLenum>(GL_NO_ERROR), gl_->GetGraphicsResetStatusKHR()); + // The lost context callback should be run when GLES2Implementation is + // notified of the loss. + EXPECT_EQ(1, lost_count); +} + +TEST_F(GLES2ImplementationTest, ReportLossReentrant) { + GpuControlClient* gl_as_client = gl_; + int lost_count = 0; + gl_->SetLostContextCallback(base::Bind(&CountCallback, &lost_count)); + EXPECT_EQ(0, lost_count); + + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetGraphicsResetStatusKHR()); + gl_as_client->OnGpuControlLostContextMaybeReentrant(); + EXPECT_NE(static_cast<GLenum>(GL_NO_ERROR), gl_->GetGraphicsResetStatusKHR()); + // The lost context callback should not be run yet to avoid calling back into + // clients re-entrantly, and having them re-enter GLES2Implementation. + EXPECT_EQ(0, lost_count); +} + 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 13bd0b86512..69615e2e621 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h @@ -200,9 +200,9 @@ TEST_F(GLES2ImplementationTest, ClearBufferfi) { cmds::ClearBufferfi cmd; }; Cmds expected; - expected.cmd.Init(GL_COLOR, 2, 3, 4); + expected.cmd.Init(GL_DEPTH_STENCIL, 2, 3, 4); - gl_->ClearBufferfi(GL_COLOR, 2, 3, 4); + gl_->ClearBufferfi(GL_DEPTH_STENCIL, 2, 3, 4); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } @@ -2756,108 +2756,6 @@ TEST_F(GLES2ImplementationTest, VertexAttribDivisorANGLE) { EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } -TEST_F(GLES2ImplementationTest, GenValuebuffersCHROMIUM) { - GLuint ids[2] = { - 0, - }; - struct Cmds { - cmds::GenValuebuffersCHROMIUMImmediate gen; - GLuint data[2]; - }; - Cmds expected; - expected.gen.Init(arraysize(ids), &ids[0]); - expected.data[0] = kValuebuffersStartId; - expected.data[1] = kValuebuffersStartId + 1; - gl_->GenValuebuffersCHROMIUM(arraysize(ids), &ids[0]); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); - EXPECT_EQ(kValuebuffersStartId, ids[0]); - EXPECT_EQ(kValuebuffersStartId + 1, ids[1]); -} - -TEST_F(GLES2ImplementationTest, DeleteValuebuffersCHROMIUM) { - GLuint ids[2] = {kValuebuffersStartId, kValuebuffersStartId + 1}; - struct Cmds { - cmds::DeleteValuebuffersCHROMIUMImmediate del; - GLuint data[2]; - }; - Cmds expected; - expected.del.Init(arraysize(ids), &ids[0]); - expected.data[0] = kValuebuffersStartId; - expected.data[1] = kValuebuffersStartId + 1; - gl_->DeleteValuebuffersCHROMIUM(arraysize(ids), &ids[0]); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); -} - -TEST_F(GLES2ImplementationTest, IsValuebufferCHROMIUM) { - struct Cmds { - cmds::IsValuebufferCHROMIUM cmd; - }; - - Cmds expected; - ExpectedMemoryInfo result1 = - GetExpectedResultMemory(sizeof(cmds::IsValuebufferCHROMIUM::Result)); - expected.cmd.Init(1, result1.id, result1.offset); - - EXPECT_CALL(*command_buffer(), OnFlush()) - .WillOnce(SetMemory(result1.ptr, uint32_t(GL_TRUE))) - .RetiresOnSaturation(); - - GLboolean result = gl_->IsValuebufferCHROMIUM(1); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); - EXPECT_TRUE(result); -} - -TEST_F(GLES2ImplementationTest, BindValuebufferCHROMIUM) { - struct Cmds { - cmds::BindValuebufferCHROMIUM cmd; - }; - Cmds expected; - expected.cmd.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 2); - - gl_->BindValuebufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 2); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); - ClearCommands(); - gl_->BindValuebufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 2); - EXPECT_TRUE(NoCommandsWritten()); -} - -TEST_F(GLES2ImplementationTest, SubscribeValueCHROMIUM) { - struct Cmds { - cmds::SubscribeValueCHROMIUM cmd; - }; - Cmds expected; - expected.cmd.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, - GL_MOUSE_POSITION_CHROMIUM); - - gl_->SubscribeValueCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, - GL_MOUSE_POSITION_CHROMIUM); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); -} - -TEST_F(GLES2ImplementationTest, PopulateSubscribedValuesCHROMIUM) { - struct Cmds { - cmds::PopulateSubscribedValuesCHROMIUM cmd; - }; - Cmds expected; - expected.cmd.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM); - - gl_->PopulateSubscribedValuesCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); -} - -TEST_F(GLES2ImplementationTest, UniformValuebufferCHROMIUM) { - struct Cmds { - cmds::UniformValuebufferCHROMIUM cmd; - }; - Cmds expected; - expected.cmd.Init(1, GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, - GL_MOUSE_POSITION_CHROMIUM); - - gl_->UniformValuebufferCHROMIUM(1, GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, - GL_MOUSE_POSITION_CHROMIUM); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); -} - TEST_F(GLES2ImplementationTest, BindTexImage2DCHROMIUM) { struct Cmds { cmds::BindTexImage2DCHROMIUM cmd; diff --git a/chromium/gpu/command_buffer/client/gles2_interface_autogen.h b/chromium/gpu/command_buffer/client/gles2_interface_autogen.h index 4ab4116c6c0..076e0859edf 100644 --- a/chromium/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_interface_autogen.h @@ -730,16 +730,6 @@ virtual GLuint CreateAndConsumeTextureCHROMIUM(GLenum target, virtual void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) = 0; -virtual void GenValuebuffersCHROMIUM(GLsizei n, GLuint* buffers) = 0; -virtual void DeleteValuebuffersCHROMIUM(GLsizei n, - const GLuint* valuebuffers) = 0; -virtual GLboolean IsValuebufferCHROMIUM(GLuint valuebuffer) = 0; -virtual void BindValuebufferCHROMIUM(GLenum target, GLuint valuebuffer) = 0; -virtual void SubscribeValueCHROMIUM(GLenum target, GLenum subscription) = 0; -virtual void PopulateSubscribedValuesCHROMIUM(GLenum target) = 0; -virtual void UniformValuebufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription) = 0; virtual void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) = 0; virtual void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) = 0; virtual void TraceBeginCHROMIUM(const char* category_name, @@ -777,7 +767,8 @@ virtual void ScheduleCALayerCHROMIUM(GLuint contents_texture_id, GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, - const GLfloat* transform) = 0; + const GLfloat* transform, + GLuint filter) = 0; virtual void CommitOverlayPlanesCHROMIUM() = 0; virtual void SwapInterval(GLint interval) = 0; virtual void FlushDriverCachesCHROMIUM() = 0; 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 734e02de9d6..11a9af7a87a 100644 --- a/chromium/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_interface_stub_autogen.h @@ -708,15 +708,6 @@ GLuint CreateAndConsumeTextureCHROMIUM(GLenum target, void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) override; -void GenValuebuffersCHROMIUM(GLsizei n, GLuint* buffers) override; -void DeleteValuebuffersCHROMIUM(GLsizei n, const GLuint* valuebuffers) override; -GLboolean IsValuebufferCHROMIUM(GLuint valuebuffer) override; -void BindValuebufferCHROMIUM(GLenum target, GLuint valuebuffer) override; -void SubscribeValueCHROMIUM(GLenum target, GLenum subscription) override; -void PopulateSubscribedValuesCHROMIUM(GLenum target) override; -void UniformValuebufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription) override; void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) override; void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) override; void TraceBeginCHROMIUM(const char* category_name, @@ -754,7 +745,8 @@ void ScheduleCALayerCHROMIUM(GLuint contents_texture_id, GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, - const GLfloat* transform) override; + const GLfloat* transform, + GLuint filter) override; void CommitOverlayPlanesCHROMIUM() override; void SwapInterval(GLint interval) override; void FlushDriverCachesCHROMIUM() override; 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 eeeafb3ba44..ddc0b52e0f1 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 @@ -965,24 +965,6 @@ GLuint GLES2InterfaceStub::CreateAndConsumeTextureCHROMIUM( void GLES2InterfaceStub::BindUniformLocationCHROMIUM(GLuint /* program */, GLint /* location */, const char* /* name */) {} -void GLES2InterfaceStub::GenValuebuffersCHROMIUM(GLsizei /* n */, - GLuint* /* buffers */) {} -void GLES2InterfaceStub::DeleteValuebuffersCHROMIUM( - GLsizei /* n */, - const GLuint* /* valuebuffers */) {} -GLboolean GLES2InterfaceStub::IsValuebufferCHROMIUM(GLuint /* valuebuffer */) { - return 0; -} -void GLES2InterfaceStub::BindValuebufferCHROMIUM(GLenum /* target */, - GLuint /* valuebuffer */) {} -void GLES2InterfaceStub::SubscribeValueCHROMIUM(GLenum /* target */, - GLenum /* subscription */) {} -void GLES2InterfaceStub::PopulateSubscribedValuesCHROMIUM(GLenum /* target */) { -} -void GLES2InterfaceStub::UniformValuebufferCHROMIUM(GLint /* location */, - GLenum /* target */, - GLenum /* subscription */) { -} void GLES2InterfaceStub::BindTexImage2DCHROMIUM(GLenum /* target */, GLint /* imageId */) {} void GLES2InterfaceStub::ReleaseTexImage2DCHROMIUM(GLenum /* target */, @@ -1033,7 +1015,8 @@ void GLES2InterfaceStub::ScheduleCALayerCHROMIUM( GLboolean /* is_clipped */, const GLfloat* /* clip_rect */, GLint /* sorting_context_id */, - const GLfloat* /* transform */) {} + const GLfloat* /* transform */, + GLuint /* filter */) {} void GLES2InterfaceStub::CommitOverlayPlanesCHROMIUM() {} void GLES2InterfaceStub::SwapInterval(GLint /* interval */) {} void GLES2InterfaceStub::FlushDriverCachesCHROMIUM() {} 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 d9679623cc9..dac250a602b 100644 --- a/chromium/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/chromium/gpu/command_buffer/client/gles2_trace_implementation_autogen.h @@ -708,15 +708,6 @@ GLuint CreateAndConsumeTextureCHROMIUM(GLenum target, void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) override; -void GenValuebuffersCHROMIUM(GLsizei n, GLuint* buffers) override; -void DeleteValuebuffersCHROMIUM(GLsizei n, const GLuint* valuebuffers) override; -GLboolean IsValuebufferCHROMIUM(GLuint valuebuffer) override; -void BindValuebufferCHROMIUM(GLenum target, GLuint valuebuffer) override; -void SubscribeValueCHROMIUM(GLenum target, GLenum subscription) override; -void PopulateSubscribedValuesCHROMIUM(GLenum target) override; -void UniformValuebufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription) override; void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) override; void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) override; void TraceBeginCHROMIUM(const char* category_name, @@ -754,7 +745,8 @@ void ScheduleCALayerCHROMIUM(GLuint contents_texture_id, GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, - const GLfloat* transform) override; + const GLfloat* transform, + GLuint filter) override; void CommitOverlayPlanesCHROMIUM() override; void SwapInterval(GLint interval) override; void FlushDriverCachesCHROMIUM() override; 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 eb42f3c82a4..4fd21fcf736 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 @@ -2049,51 +2049,6 @@ void GLES2TraceImplementation::BindUniformLocationCHROMIUM(GLuint program, gl_->BindUniformLocationCHROMIUM(program, location, name); } -void GLES2TraceImplementation::GenValuebuffersCHROMIUM(GLsizei n, - GLuint* buffers) { - TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GenValuebuffersCHROMIUM"); - gl_->GenValuebuffersCHROMIUM(n, buffers); -} - -void GLES2TraceImplementation::DeleteValuebuffersCHROMIUM( - GLsizei n, - const GLuint* valuebuffers) { - TRACE_EVENT_BINARY_EFFICIENT0("gpu", - "GLES2Trace::DeleteValuebuffersCHROMIUM"); - gl_->DeleteValuebuffersCHROMIUM(n, valuebuffers); -} - -GLboolean GLES2TraceImplementation::IsValuebufferCHROMIUM(GLuint valuebuffer) { - TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::IsValuebufferCHROMIUM"); - return gl_->IsValuebufferCHROMIUM(valuebuffer); -} - -void GLES2TraceImplementation::BindValuebufferCHROMIUM(GLenum target, - GLuint valuebuffer) { - TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::BindValuebufferCHROMIUM"); - gl_->BindValuebufferCHROMIUM(target, valuebuffer); -} - -void GLES2TraceImplementation::SubscribeValueCHROMIUM(GLenum target, - GLenum subscription) { - TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::SubscribeValueCHROMIUM"); - gl_->SubscribeValueCHROMIUM(target, subscription); -} - -void GLES2TraceImplementation::PopulateSubscribedValuesCHROMIUM(GLenum target) { - TRACE_EVENT_BINARY_EFFICIENT0("gpu", - "GLES2Trace::PopulateSubscribedValuesCHROMIUM"); - gl_->PopulateSubscribedValuesCHROMIUM(target); -} - -void GLES2TraceImplementation::UniformValuebufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription) { - TRACE_EVENT_BINARY_EFFICIENT0("gpu", - "GLES2Trace::UniformValuebufferCHROMIUM"); - gl_->UniformValuebufferCHROMIUM(location, target, subscription); -} - void GLES2TraceImplementation::BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::BindTexImage2DCHROMIUM"); @@ -2201,12 +2156,13 @@ void GLES2TraceImplementation::ScheduleCALayerCHROMIUM( GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, - const GLfloat* transform) { + const GLfloat* transform, + GLuint filter) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::ScheduleCALayerCHROMIUM"); gl_->ScheduleCALayerCHROMIUM(contents_texture_id, contents_rect, opacity, background_color, edge_aa_mask, bounds_rect, is_clipped, clip_rect, sorting_context_id, - transform); + transform, filter); } void GLES2TraceImplementation::CommitOverlayPlanesCHROMIUM() { diff --git a/chromium/gpu/command_buffer/client/gpu_control.h b/chromium/gpu/command_buffer/client/gpu_control.h index 12ad377b553..813d5630960 100644 --- a/chromium/gpu/command_buffer/client/gpu_control.h +++ b/chromium/gpu/command_buffer/client/gpu_control.h @@ -29,6 +29,7 @@ class GpuMemoryBuffer; } namespace gpu { +class GpuControlClient; struct SyncToken; // Common interface for GpuControl implementations. @@ -37,6 +38,8 @@ class GPU_EXPORT GpuControl { GpuControl() {} virtual ~GpuControl() {} + virtual void SetGpuControlClient(GpuControlClient* gpu_control_client) = 0; + virtual Capabilities GetCapabilities() = 0; // Create an image for a client buffer with the given dimensions and @@ -66,10 +69,6 @@ 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; - // When this function returns it ensures all previously flushed work is // visible by the service. This command does this by sending a synchronous // IPC. Note just because the work is visible to the server does not mean diff --git a/chromium/gpu/command_buffer/client/gpu_control_client.h b/chromium/gpu/command_buffer/client/gpu_control_client.h new file mode 100644 index 00000000000..75d84ecc0da --- /dev/null +++ b/chromium/gpu/command_buffer/client/gpu_control_client.h @@ -0,0 +1,29 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_CLIENT_GPU_CONTROL_CLIENT_H_ +#define GPU_COMMAND_BUFFER_CLIENT_GPU_CONTROL_CLIENT_H_ + +#include <cstdint> + +namespace gpu { + +class GpuControlClient { + public: + // Informs the client that the context was lost. It should inform its own + // clients or take actions as needed. This will only be called a single time + // for any GpuControl. + virtual void OnGpuControlLostContext() = 0; + // This may happen inside calls from the client to the GpuControl, so this + // function is reentrant. It informs the client of loss, but the client will + // also receive a OnGpuControlLostContext (non-re-entrantly) in the future. + // Use this only to update internal state if needed to make lost context be + // visible immediately while unwinding the call stack. + virtual void OnGpuControlLostContextMaybeReentrant() = 0; + virtual void OnGpuControlErrorMessage(const char* message, int32_t id) = 0; +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_CLIENT_GPU_CONTROL_CLIENT_H_ diff --git a/chromium/gpu/command_buffer/client/gpu_memory_buffer_manager.h b/chromium/gpu/command_buffer/client/gpu_memory_buffer_manager.h index a3385325d30..1f56123d03a 100644 --- a/chromium/gpu/command_buffer/client/gpu_memory_buffer_manager.h +++ b/chromium/gpu/command_buffer/client/gpu_memory_buffer_manager.h @@ -5,8 +5,10 @@ #ifndef GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_MANAGER_H_ #define GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_MANAGER_H_ -#include "base/memory/scoped_ptr.h" +#include <memory> + #include "gpu/gpu_export.h" +#include "gpu/ipc/common/surface_handle.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/gpu_memory_buffer.h" @@ -19,14 +21,14 @@ class GPU_EXPORT GpuMemoryBufferManager { GpuMemoryBufferManager(); // Allocates a GpuMemoryBuffer that can be shared with another process. - virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer( + virtual std::unique_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer( const gfx::Size& size, gfx::BufferFormat format, gfx::BufferUsage usage, - int32_t surface_id) = 0; + gpu::SurfaceHandle surface_handle) = 0; // Creates a GpuMemoryBuffer from existing handle. - virtual scoped_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBufferFromHandle( + virtual std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBufferFromHandle( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, gfx::BufferFormat format) = 0; diff --git a/chromium/gpu/command_buffer/client/mapped_memory.cc b/chromium/gpu/command_buffer/client/mapped_memory.cc index c40278e2720..06f1f63e0c9 100644 --- a/chromium/gpu/command_buffer/client/mapped_memory.cc +++ b/chromium/gpu/command_buffer/client/mapped_memory.cc @@ -12,11 +12,13 @@ #include "base/atomic_sequence_num.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/trace_event.h" #include "gpu/command_buffer/client/cmd_buffer_helper.h" +#include "gpu/command_buffer/client/shared_memory_limits.h" #include "gpu/command_buffer/common/buffer.h" namespace gpu { @@ -43,7 +45,7 @@ MappedMemoryManager::MappedMemoryManager(CommandBufferHelper* helper, helper_(helper), allocated_memory_(0), max_free_bytes_(unused_memory_reclaim_limit), - max_allocated_bytes_(kNoLimit), + max_allocated_bytes_(SharedMemoryLimits::kNoLimit), tracing_id_(g_next_mapped_memory_manager_tracing_id.GetNext()) { // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview). // Don't register a dump provider in these cases. @@ -87,7 +89,7 @@ void* MappedMemoryManager::Alloc(unsigned int size, // If there is a memory limit being enforced and total free // memory (allocated_memory_ - total_bytes_in_use) is larger than // the limit try waiting. - if (max_free_bytes_ != kNoLimit && + if (max_free_bytes_ != SharedMemoryLimits::kNoLimit && (allocated_memory_ - total_bytes_in_use) >= max_free_bytes_) { TRACE_EVENT0("gpu", "MappedMemoryManager::Alloc::wait"); for (auto& chunk : chunks_) { @@ -102,7 +104,7 @@ void* MappedMemoryManager::Alloc(unsigned int size, } } - if (max_allocated_bytes_ != kNoLimit && + if (max_allocated_bytes_ != SharedMemoryLimits::kNoLimit && (allocated_memory_ + size) > max_allocated_bytes_) { return nullptr; } @@ -120,7 +122,7 @@ void* MappedMemoryManager::Alloc(unsigned int size, DCHECK(shm.get()); MemoryChunk* mc = new MemoryChunk(id, shm, helper_); allocated_memory_ += mc->GetSize(); - chunks_.push_back(make_scoped_ptr(mc)); + chunks_.push_back(base::WrapUnique(mc)); void* mem = mc->Alloc(size); DCHECK(mem); *shm_id = mc->shm_id(); diff --git a/chromium/gpu/command_buffer/client/mapped_memory.h b/chromium/gpu/command_buffer/client/mapped_memory.h index 70831599045..0af38b56e92 100644 --- a/chromium/gpu/command_buffer/client/mapped_memory.h +++ b/chromium/gpu/command_buffer/client/mapped_memory.h @@ -8,9 +8,10 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/bind.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "base/trace_event/memory_dump_provider.h" #include "gpu/command_buffer/client/fenced_allocator.h" #include "gpu/command_buffer/common/buffer.h" @@ -201,7 +202,7 @@ class GPU_EXPORT MappedMemoryManager } private: - typedef std::vector<scoped_ptr<MemoryChunk>> MemoryChunkVector; + typedef std::vector<std::unique_ptr<MemoryChunk>> MemoryChunkVector; // size a chunk is rounded up to. unsigned int chunk_size_multiple_; diff --git a/chromium/gpu/command_buffer/client/mapped_memory_unittest.cc b/chromium/gpu/command_buffer/client/mapped_memory_unittest.cc index 9846a84d4d8..674d1a14d99 100644 --- a/chromium/gpu/command_buffer/client/mapped_memory_unittest.cc +++ b/chromium/gpu/command_buffer/client/mapped_memory_unittest.cc @@ -8,8 +8,9 @@ #include <stdint.h> #include <list> +#include <memory> + #include "base/bind.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "gpu/command_buffer/client/cmd_buffer_helper.h" #include "gpu/command_buffer/service/command_buffer_service.h" @@ -51,7 +52,6 @@ class MappedMemoryTestBase : public testing::Test { command_buffer_.reset( new CommandBufferService(transfer_buffer_manager_.get())); - EXPECT_TRUE(command_buffer_->Initialize()); executor_.reset( new CommandExecutor(command_buffer_.get(), api_mock_.get(), NULL)); @@ -68,11 +68,11 @@ class MappedMemoryTestBase : public testing::Test { int32_t GetToken() { return command_buffer_->GetLastState().token; } - scoped_ptr<AsyncAPIMock> api_mock_; + std::unique_ptr<AsyncAPIMock> api_mock_; scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; - scoped_ptr<CommandBufferService> command_buffer_; - scoped_ptr<CommandExecutor> executor_; - scoped_ptr<CommandBufferHelper> helper_; + std::unique_ptr<CommandBufferService> command_buffer_; + std::unique_ptr<CommandExecutor> executor_; + std::unique_ptr<CommandBufferHelper> helper_; base::MessageLoop message_loop_; }; @@ -89,7 +89,7 @@ class MemoryChunkTest : public MappedMemoryTestBase { static const int32_t kShmId = 123; void SetUp() override { MappedMemoryTestBase::SetUp(); - scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); + std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); shared_memory->CreateAndMapAnonymous(kBufferSize); buffer_ = MakeBufferFromSharedMemory(std::move(shared_memory), kBufferSize); chunk_.reset(new MemoryChunk(kShmId, buffer_, helper_.get())); @@ -104,7 +104,7 @@ class MemoryChunkTest : public MappedMemoryTestBase { uint8_t* buffer_memory() { return static_cast<uint8_t*>(buffer_->memory()); } - scoped_ptr<MemoryChunk> chunk_; + std::unique_ptr<MemoryChunk> chunk_; scoped_refptr<gpu::Buffer> buffer_; }; @@ -162,7 +162,7 @@ class MappedMemoryManagerTest : public MappedMemoryTestBase { MappedMemoryTestBase::TearDown(); } - scoped_ptr<MappedMemoryManager> manager_; + std::unique_ptr<MappedMemoryManager> manager_; }; TEST_F(MappedMemoryManagerTest, Basic) { diff --git a/chromium/gpu/command_buffer/client/program_info_manager_unittest.cc b/chromium/gpu/command_buffer/client/program_info_manager_unittest.cc index 64d896c6bd6..19aa12efe90 100644 --- a/chromium/gpu/command_buffer/client/program_info_manager_unittest.cc +++ b/chromium/gpu/command_buffer/client/program_info_manager_unittest.cc @@ -5,6 +5,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "gpu/command_buffer/client/program_info_manager.h" #include "testing/gtest/include/gtest/gtest.h" @@ -165,7 +167,7 @@ class ProgramInfoManagerTest : public testing::Test { memcpy(data->name1, kName[1], arraysize(data->name1)); } - scoped_ptr<ProgramInfoManager> program_info_manager_; + std::unique_ptr<ProgramInfoManager> program_info_manager_; Program* program_; }; diff --git a/chromium/gpu/command_buffer/client/query_tracker.cc b/chromium/gpu/command_buffer/client/query_tracker.cc index bf71645d289..4e241d6446a 100644 --- a/chromium/gpu/command_buffer/client/query_tracker.cc +++ b/chromium/gpu/command_buffer/client/query_tracker.cc @@ -175,9 +175,17 @@ void QueryTracker::Query::QueryCounter(GLES2Implementation* gl) { bool QueryTracker::Query::CheckResultsAvailable( CommandBufferHelper* helper) { if (Pending()) { - if (base::subtle::Acquire_Load(&info_.sync->process_count) == - submit_count_ || - helper->IsContextLost()) { + bool processed_all = + base::subtle::Acquire_Load(&info_.sync->process_count) == submit_count_; + // We check lost on the command buffer itself here instead of checking the + // GLES2Implementation because the GLES2Implementation will not hear about + // the loss until we exit out of this call stack (to avoid re-entrancy), and + // we need be able to enter kComplete state on context loss. + // TODO(danakj): If GLES2Implementation can handle being notified of loss + // re-entrantly (without calling its clients re-entrantly), then we could + // call GLES2Implementation::GetGraphicsResetStatusKHR() here and remove + // this method from CommandBufferHelper. + if (processed_all || helper->IsContextLost()) { switch (target()) { case GL_COMMANDS_ISSUED_CHROMIUM: result_ = info_.sync->result; diff --git a/chromium/gpu/command_buffer/client/query_tracker_unittest.cc b/chromium/gpu/command_buffer/client/query_tracker_unittest.cc index a110087c358..78ab936d11d 100644 --- a/chromium/gpu/command_buffer/client/query_tracker_unittest.cc +++ b/chromium/gpu/command_buffer/client/query_tracker_unittest.cc @@ -10,9 +10,9 @@ #include <stddef.h> #include <stdint.h> +#include <memory> #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" #include "gpu/command_buffer/client/mapped_memory.h" @@ -45,10 +45,10 @@ class QuerySyncManagerTest : public testing::Test { command_buffer_.reset(); } - scoped_ptr<CommandBuffer> command_buffer_; - scoped_ptr<GLES2CmdHelper> helper_; - scoped_ptr<MappedMemoryManager> mapped_memory_; - scoped_ptr<QuerySyncManager> sync_manager_; + std::unique_ptr<CommandBuffer> command_buffer_; + std::unique_ptr<GLES2CmdHelper> helper_; + std::unique_ptr<MappedMemoryManager> mapped_memory_; + std::unique_ptr<QuerySyncManager> sync_manager_; }; TEST_F(QuerySyncManagerTest, Basic) { @@ -113,10 +113,10 @@ class QueryTrackerTest : public testing::Test { uint32_t GetFlushGeneration() { return helper_->flush_generation(); } - scoped_ptr<CommandBuffer> command_buffer_; - scoped_ptr<GLES2CmdHelper> helper_; - scoped_ptr<MappedMemoryManager> mapped_memory_; - scoped_ptr<QueryTracker> query_tracker_; + std::unique_ptr<CommandBuffer> command_buffer_; + std::unique_ptr<GLES2CmdHelper> helper_; + std::unique_ptr<MappedMemoryManager> mapped_memory_; + std::unique_ptr<QueryTracker> query_tracker_; }; TEST_F(QueryTrackerTest, Basic) { diff --git a/chromium/gpu/command_buffer/client/ring_buffer_test.cc b/chromium/gpu/command_buffer/client/ring_buffer_test.cc index cf3418f11bd..ed59c33b7e7 100644 --- a/chromium/gpu/command_buffer/client/ring_buffer_test.cc +++ b/chromium/gpu/command_buffer/client/ring_buffer_test.cc @@ -8,6 +8,8 @@ #include <stdint.h> +#include <memory> + #include "base/bind.h" #include "base/bind_helpers.h" #include "gpu/command_buffer/client/cmd_buffer_helper.h" @@ -74,7 +76,6 @@ class BaseRingBufferTest : public testing::Test { } command_buffer_.reset( new CommandBufferService(transfer_buffer_manager_.get())); - EXPECT_TRUE(command_buffer_->Initialize()); executor_.reset( new CommandExecutor(command_buffer_.get(), api_mock_.get(), NULL)); @@ -91,15 +92,15 @@ class BaseRingBufferTest : public testing::Test { int32_t GetToken() { return command_buffer_->GetLastState().token; } - scoped_ptr<AsyncAPIMock> api_mock_; + std::unique_ptr<AsyncAPIMock> api_mock_; scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; - scoped_ptr<CommandBufferService> command_buffer_; - scoped_ptr<CommandExecutor> executor_; - scoped_ptr<CommandBufferHelper> helper_; + std::unique_ptr<CommandBufferService> command_buffer_; + std::unique_ptr<CommandExecutor> executor_; + std::unique_ptr<CommandBufferHelper> helper_; std::vector<const void*> set_token_arguments_; bool delay_set_token_; - scoped_ptr<int8_t[]> buffer_; + std::unique_ptr<int8_t[]> buffer_; int8_t* buffer_start_; base::MessageLoop message_loop_; }; @@ -131,7 +132,7 @@ class RingBufferTest : public BaseRingBufferTest { BaseRingBufferTest::TearDown(); } - scoped_ptr<RingBuffer> allocator_; + std::unique_ptr<RingBuffer> allocator_; }; // Checks basic alloc and free. diff --git a/chromium/gpu/command_buffer/client/share_group.cc b/chromium/gpu/command_buffer/client/share_group.cc index 2ba790a1853..d1041c06e3a 100644 --- a/chromium/gpu/command_buffer/client/share_group.cc +++ b/chromium/gpu/command_buffer/client/share_group.cc @@ -374,7 +374,17 @@ ShareGroup::ShareGroup(bool bind_generates_resource, uint64_t tracing_guid) } } -void ShareGroup::set_program_info_manager(ProgramInfoManager* manager) { +void ShareGroup::Lose() { + base::AutoLock hold(lost_lock_); + lost_ = true; +} + +bool ShareGroup::IsLost() const { + base::AutoLock hold(lost_lock_); + return lost_; +} + +void ShareGroup::SetProgramInfoManagerForTesting(ProgramInfoManager* manager) { program_info_manager_.reset(manager); } diff --git a/chromium/gpu/command_buffer/client/share_group.h b/chromium/gpu/command_buffer/client/share_group.h index 25427e3e12c..091b69f2385 100644 --- a/chromium/gpu/command_buffer/client/share_group.h +++ b/chromium/gpu/command_buffer/client/share_group.h @@ -7,8 +7,11 @@ #include <GLES2/gl2.h> #include <stdint.h> + +#include <memory> + #include "base/macros.h" -#include "base/memory/scoped_ptr.h" +#include "base/synchronization/lock.h" #include "gles2_impl_export.h" #include "gpu/command_buffer/client/ref_counted.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" @@ -144,22 +147,33 @@ class GLES2_IMPL_EXPORT ShareGroup uint64_t TracingGUID() const { return tracing_guid_; } + // Mark the ShareGroup as lost when an error occurs on any context in the + // group. This is thread safe as contexts may be on different threads. + void Lose(); + // Report if any context in the ShareGroup has reported itself lost. This is + // thread safe as contexts may be on different threads. + bool IsLost() const; + private: friend class gpu::RefCountedThreadSafe<ShareGroup>; friend class gpu::gles2::GLES2ImplementationTest; ~ShareGroup(); // Install a new program info manager. Used for testing only; - void set_program_info_manager(ProgramInfoManager* manager); + void SetProgramInfoManagerForTesting(ProgramInfoManager* manager); - scoped_ptr<IdHandlerInterface> id_handlers_[id_namespaces::kNumIdNamespaces]; - scoped_ptr<RangeIdHandlerInterface> + std::unique_ptr<IdHandlerInterface> + id_handlers_[id_namespaces::kNumIdNamespaces]; + std::unique_ptr<RangeIdHandlerInterface> range_id_handlers_[id_namespaces::kNumRangeIdNamespaces]; - scoped_ptr<ProgramInfoManager> program_info_manager_; + std::unique_ptr<ProgramInfoManager> program_info_manager_; bool bind_generates_resource_; uint64_t tracing_guid_; + mutable base::Lock lost_lock_; + bool lost_ = false; + DISALLOW_COPY_AND_ASSIGN(ShareGroup); }; diff --git a/chromium/gpu/command_buffer/client/shared_memory_limits.h b/chromium/gpu/command_buffer/client/shared_memory_limits.h new file mode 100644 index 00000000000..de821732696 --- /dev/null +++ b/chromium/gpu/command_buffer/client/shared_memory_limits.h @@ -0,0 +1,34 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_CLIENT_SHARED_MEMORY_LIMITS_H_ +#define GPU_COMMAND_BUFFER_CLIENT_SHARED_MEMORY_LIMITS_H_ + +#include <stddef.h> + +namespace gpu { + +struct SharedMemoryLimits { + int32_t command_buffer_size = 1024 * 1024; + uint32_t start_transfer_buffer_size = 1 * 1024 * 1024; + uint32_t min_transfer_buffer_size = 1 * 256 * 1024; + uint32_t max_transfer_buffer_size = 16 * 1024 * 1024; + + static constexpr uint32_t kNoLimit = 0; + uint32_t mapped_memory_reclaim_limit = kNoLimit; + + // These are limits for contexts only used for creating textures, mailboxing + // them and dealing with synchronization. + static SharedMemoryLimits ForMailboxContext() { + SharedMemoryLimits limits; + limits.command_buffer_size = 64 * 1024; + limits.start_transfer_buffer_size = 64 * 1024; + limits.min_transfer_buffer_size = 64 * 1024; + return limits; + } +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_CLIENT_SHARED_MEMORY_LIMITS_H_ diff --git a/chromium/gpu/command_buffer/client/transfer_buffer.h b/chromium/gpu/command_buffer/client/transfer_buffer.h index 43fea94efc7..5f6623e0512 100644 --- a/chromium/gpu/command_buffer/client/transfer_buffer.h +++ b/chromium/gpu/command_buffer/client/transfer_buffer.h @@ -8,9 +8,10 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/compiler_specific.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/client/ring_buffer.h" #include "gpu/command_buffer/common/buffer.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" @@ -97,7 +98,7 @@ class GPU_EXPORT TransferBuffer : public TransferBufferInterface { void AllocateRingBuffer(unsigned int size); CommandBufferHelper* helper_; - scoped_ptr<RingBuffer> ring_buffer_; + std::unique_ptr<RingBuffer> ring_buffer_; // size reserved for results unsigned int result_size_; diff --git a/chromium/gpu/command_buffer/client/transfer_buffer_unittest.cc b/chromium/gpu/command_buffer/client/transfer_buffer_unittest.cc index 7a98b804972..369adfd83aa 100644 --- a/chromium/gpu/command_buffer/client/transfer_buffer_unittest.cc +++ b/chromium/gpu/command_buffer/client/transfer_buffer_unittest.cc @@ -9,6 +9,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/compiler_specific.h" #include "gpu/command_buffer/client/client_test_helper.h" #include "gpu/command_buffer/client/cmd_buffer_helper.h" @@ -56,15 +58,14 @@ class TransferBufferTest : public testing::Test { return command_buffer_.get(); } - scoped_ptr<MockClientCommandBufferMockFlush> command_buffer_; - scoped_ptr<CommandBufferHelper> helper_; - scoped_ptr<TransferBuffer> transfer_buffer_; + std::unique_ptr<MockClientCommandBufferMockFlush> command_buffer_; + std::unique_ptr<CommandBufferHelper> helper_; + std::unique_ptr<TransferBuffer> transfer_buffer_; int32_t transfer_buffer_id_; }; void TransferBufferTest::SetUp() { command_buffer_.reset(new StrictMock<MockClientCommandBufferMockFlush>()); - ASSERT_TRUE(command_buffer_->Initialize()); helper_.reset(new CommandBufferHelper(command_buffer())); ASSERT_TRUE(helper_->Initialize(kCommandBufferSizeBytes)); @@ -260,15 +261,14 @@ class TransferBufferExpandContractTest : public testing::Test { return command_buffer_.get(); } - scoped_ptr<MockClientCommandBufferCanFail> command_buffer_; - scoped_ptr<CommandBufferHelper> helper_; - scoped_ptr<TransferBuffer> transfer_buffer_; + std::unique_ptr<MockClientCommandBufferCanFail> command_buffer_; + std::unique_ptr<CommandBufferHelper> helper_; + std::unique_ptr<TransferBuffer> transfer_buffer_; int32_t transfer_buffer_id_; }; void TransferBufferExpandContractTest::SetUp() { command_buffer_.reset(new StrictMock<MockClientCommandBufferCanFail>()); - ASSERT_TRUE(command_buffer_->Initialize()); EXPECT_CALL(*command_buffer(), CreateTransferBuffer(kCommandBufferSizeBytes, _)) diff --git a/chromium/gpu/command_buffer/client/vertex_array_object_manager.h b/chromium/gpu/command_buffer/client/vertex_array_object_manager.h index 6897c9290c5..42ec269ea51 100644 --- a/chromium/gpu/command_buffer/client/vertex_array_object_manager.h +++ b/chromium/gpu/command_buffer/client/vertex_array_object_manager.h @@ -8,9 +8,10 @@ #include <GLES2/gl2.h> #include <stdint.h> +#include <memory> + #include "base/containers/hash_tables.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "gles2_impl_export.h" namespace gpu { @@ -113,7 +114,7 @@ class GLES2_IMPL_EXPORT VertexArrayObjectManager { GLuint element_array_buffer_id_; GLsizei element_array_buffer_size_; GLsizei collection_buffer_size_; - scoped_ptr<int8_t[]> collection_buffer_; + std::unique_ptr<int8_t[]> collection_buffer_; VertexArrayObject* default_vertex_array_object_; VertexArrayObject* bound_vertex_array_object_; diff --git a/chromium/gpu/command_buffer/client/vertex_array_object_manager_unittest.cc b/chromium/gpu/command_buffer/client/vertex_array_object_manager_unittest.cc index b39aab87f38..77b6b4cf395 100644 --- a/chromium/gpu/command_buffer/client/vertex_array_object_manager_unittest.cc +++ b/chromium/gpu/command_buffer/client/vertex_array_object_manager_unittest.cc @@ -6,8 +6,12 @@ #include <GLES2/gl2ext.h> #include <GLES3/gl3.h> + #include <stddef.h> #include <stdint.h> + +#include <memory> + #include "testing/gtest/include/gtest/gtest.h" namespace gpu { @@ -29,7 +33,7 @@ class VertexArrayObjectManagerTest : public testing::Test { } void TearDown() override {} - scoped_ptr<VertexArrayObjectManager> manager_; + std::unique_ptr<VertexArrayObjectManager> manager_; }; // GCC requires these declarations, but MSVC requires they not be present diff --git a/chromium/gpu/command_buffer/cmd_buffer_functions.txt b/chromium/gpu/command_buffer/cmd_buffer_functions.txt index 3f036613622..0f51880efba 100644 --- a/chromium/gpu/command_buffer/cmd_buffer_functions.txt +++ b/chromium/gpu/command_buffer/cmd_buffer_functions.txt @@ -24,7 +24,7 @@ GL_APICALL void GL_APIENTRY glBufferData (GLenumBufferTarget target, GLs GL_APICALL void GL_APIENTRY glBufferSubData (GLenumBufferTarget target, GLintptrNotNegative offset, GLsizeiptr size, const void* data); GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenumFrameBufferTarget target); GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); -GL_APICALL void GL_APIENTRY glClearBufferfi (GLenumBufferfv buffer, GLint drawbuffers, GLfloat depth, GLint stencil); +GL_APICALL void GL_APIENTRY glClearBufferfi (GLenumBufferfi buffer, GLint drawbuffers, GLfloat depth, GLint stencil); GL_APICALL void GL_APIENTRY glClearBufferfv (GLenumBufferfv buffer, GLint drawbuffers, const GLfloat* value); GL_APICALL void GL_APIENTRY glClearBufferiv (GLenumBufferiv buffer, GLint drawbuffers, const GLint* value); GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenumBufferuiv buffer, GLint drawbuffers, const GLuint* value); @@ -125,8 +125,8 @@ GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenumVe GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenumVertexAttribute pname, GLuint* params); GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenumVertexPointer pname, void** pointer); GL_APICALL void GL_APIENTRY glHint (GLenumHintTarget target, GLenumHintMode mode); -GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenumFrameBufferTarget target, GLsizeiNotNegative count, const GLenum* attachments); -GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenumFrameBufferTarget target, GLsizeiNotNegative count, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenumFrameBufferTarget target, GLsizei count, const GLenum* attachments); +GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenumFrameBufferTarget target, GLsizei count, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height); GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLidBuffer buffer); GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenumCapability cap); GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLidFramebuffer framebuffer); @@ -175,39 +175,39 @@ GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenumTextureTarget target, GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenumTexture3DTarget target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenumTextureFormat format, GLenumPixelType type, const void* pixels); GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLidProgram program, GLsizeiNotNegative count, const char* const* varyings, GLenumBufferMode buffermode); GL_APICALL void GL_APIENTRY glUniform1f (GLintUniformLocation location, GLfloat x); -GL_APICALL void GL_APIENTRY glUniform1fv (GLintUniformLocation location, GLsizeiNotNegative count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform1fv (GLintUniformLocation location, GLsizei count, const GLfloat* v); GL_APICALL void GL_APIENTRY glUniform1i (GLintUniformLocation location, GLint x); -GL_APICALL void GL_APIENTRY glUniform1iv (GLintUniformLocation location, GLsizeiNotNegative count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform1iv (GLintUniformLocation location, GLsizei count, const GLint* v); GL_APICALL void GL_APIENTRY glUniform1ui (GLintUniformLocation location, GLuint x); -GL_APICALL void GL_APIENTRY glUniform1uiv (GLintUniformLocation location, GLsizeiNotNegative count, const GLuint* v); +GL_APICALL void GL_APIENTRY glUniform1uiv (GLintUniformLocation location, GLsizei count, const GLuint* v); GL_APICALL void GL_APIENTRY glUniform2f (GLintUniformLocation location, GLfloat x, GLfloat y); -GL_APICALL void GL_APIENTRY glUniform2fv (GLintUniformLocation location, GLsizeiNotNegative count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform2fv (GLintUniformLocation location, GLsizei count, const GLfloat* v); GL_APICALL void GL_APIENTRY glUniform2i (GLintUniformLocation location, GLint x, GLint y); -GL_APICALL void GL_APIENTRY glUniform2iv (GLintUniformLocation location, GLsizeiNotNegative count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform2iv (GLintUniformLocation location, GLsizei count, const GLint* v); GL_APICALL void GL_APIENTRY glUniform2ui (GLintUniformLocation location, GLuint x, GLuint y); -GL_APICALL void GL_APIENTRY glUniform2uiv (GLintUniformLocation location, GLsizeiNotNegative count, const GLuint* v); +GL_APICALL void GL_APIENTRY glUniform2uiv (GLintUniformLocation location, GLsizei count, const GLuint* v); GL_APICALL void GL_APIENTRY glUniform3f (GLintUniformLocation location, GLfloat x, GLfloat y, GLfloat z); -GL_APICALL void GL_APIENTRY glUniform3fv (GLintUniformLocation location, GLsizeiNotNegative count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform3fv (GLintUniformLocation location, GLsizei count, const GLfloat* v); GL_APICALL void GL_APIENTRY glUniform3i (GLintUniformLocation location, GLint x, GLint y, GLint z); -GL_APICALL void GL_APIENTRY glUniform3iv (GLintUniformLocation location, GLsizeiNotNegative count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform3iv (GLintUniformLocation location, GLsizei count, const GLint* v); GL_APICALL void GL_APIENTRY glUniform3ui (GLintUniformLocation location, GLuint x, GLuint y, GLuint z); -GL_APICALL void GL_APIENTRY glUniform3uiv (GLintUniformLocation location, GLsizeiNotNegative count, const GLuint* v); +GL_APICALL void GL_APIENTRY glUniform3uiv (GLintUniformLocation location, GLsizei count, const GLuint* v); GL_APICALL void GL_APIENTRY glUniform4f (GLintUniformLocation location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GL_APICALL void GL_APIENTRY glUniform4fv (GLintUniformLocation location, GLsizeiNotNegative count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform4fv (GLintUniformLocation location, GLsizei count, const GLfloat* v); GL_APICALL void GL_APIENTRY glUniform4i (GLintUniformLocation location, GLint x, GLint y, GLint z, GLint w); -GL_APICALL void GL_APIENTRY glUniform4iv (GLintUniformLocation location, GLsizeiNotNegative count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform4iv (GLintUniformLocation location, GLsizei count, const GLint* v); GL_APICALL void GL_APIENTRY glUniform4ui (GLintUniformLocation location, GLuint x, GLuint y, GLuint z, GLuint w); -GL_APICALL void GL_APIENTRY glUniform4uiv (GLintUniformLocation location, GLsizeiNotNegative count, const GLuint* v); +GL_APICALL void GL_APIENTRY glUniform4uiv (GLintUniformLocation location, GLsizei count, const GLuint* v); GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLidProgram program, GLuint index, GLuint binding); -GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLintUniformLocation location, GLsizeiNotNegative count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLintUniformLocation location, GLsizeiNotNegative count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLintUniformLocation location, GLsizeiNotNegative count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLintUniformLocation location, GLsizeiNotNegative count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLintUniformLocation location, GLsizeiNotNegative count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLintUniformLocation location, GLsizeiNotNegative count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLintUniformLocation location, GLsizeiNotNegative count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLintUniformLocation location, GLsizeiNotNegative count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLintUniformLocation location, GLsizeiNotNegative count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLintUniformLocation location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLintUniformLocation location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLintUniformLocation location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLintUniformLocation location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLintUniformLocation location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLintUniformLocation location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLintUniformLocation location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLintUniformLocation location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLintUniformLocation location, GLsizei count, GLboolean transpose, const GLfloat* value); GL_APICALL void GL_APIENTRY glUseProgram (GLidZeroProgram program); GL_APICALL void GL_APIENTRY glValidateProgram (GLidProgram program); GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x); @@ -291,13 +291,6 @@ GL_APICALL void GL_APIENTRY glProduceTextureDirectCHROMIUM (GLidBindText GL_APICALL void GL_APIENTRY glConsumeTextureCHROMIUM (GLenumTextureBindTarget target, const GLbyte* mailbox); GL_APICALL GLuint GL_APIENTRY glCreateAndConsumeTextureCHROMIUM (GLenumTextureBindTarget target, const GLbyte* mailbox); GL_APICALL void GL_APIENTRY glBindUniformLocationCHROMIUM (GLidProgram program, GLint location, const char* name); -GL_APICALL void GL_APIENTRY glGenValuebuffersCHROMIUM (GLsizeiNotNegative n, GLuint* buffers); -GL_APICALL void GL_APIENTRY glDeleteValuebuffersCHROMIUM (GLsizeiNotNegative n, const GLuint* valuebuffers); -GL_APICALL GLboolean GL_APIENTRY glIsValuebufferCHROMIUM (GLidBindValuebuffer valuebuffer); -GL_APICALL void GL_APIENTRY glBindValuebufferCHROMIUM (GLenumValueBufferTarget target, GLidBindValuebuffer valuebuffer); -GL_APICALL void GL_APIENTRY glSubscribeValueCHROMIUM (GLenumValueBufferTarget target, GLenumSubscriptionTarget subscription); -GL_APICALL void GL_APIENTRY glPopulateSubscribedValuesCHROMIUM (GLenumValueBufferTarget target); -GL_APICALL void GL_APIENTRY glUniformValuebufferCHROMIUM (GLintUniformLocation location, GLenumValueBufferTarget target, GLenumSubscriptionTarget subscription); GL_APICALL void GL_APIENTRY glBindTexImage2DCHROMIUM (GLenumTextureBindTarget target, GLint imageId); GL_APICALL void GL_APIENTRY glReleaseTexImage2DCHROMIUM (GLenumTextureBindTarget target, GLint imageId); GL_APICALL void GL_APIENTRY glTraceBeginCHROMIUM (const char* category_name, const char* trace_name); @@ -312,7 +305,7 @@ GL_APICALL void GL_APIENTRY glWaitSyncTokenCHROMIUM (const GLbyte* sync_ GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei count, const GLenum* bufs); 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 glScheduleCALayerCHROMIUM (GLuint contents_texture_id, const GLfloat* contents_rect, GLfloat opacity, GLuint background_color, GLuint edge_aa_mask, const GLfloat* bounds_rect, GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, const GLfloat* transform); +GL_APICALL void GL_APIENTRY glScheduleCALayerCHROMIUM (GLuint contents_texture_id, const GLfloat* contents_rect, GLfloat opacity, GLuint background_color, GLuint edge_aa_mask, const GLfloat* bounds_rect, GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, const GLfloat* transform, GLuint filter); GL_APICALL void GL_APIENTRY glCommitOverlayPlanesCHROMIUM (void); GL_APICALL void GL_APIENTRY glSwapInterval (GLint interval); GL_APICALL void GL_APIENTRY glFlushDriverCachesCHROMIUM (void); diff --git a/chromium/gpu/command_buffer/common/BUILD.gn b/chromium/gpu/command_buffer/common/BUILD.gn index 445ca0611a3..e42bb736ca3 100644 --- a/chromium/gpu/command_buffer/common/BUILD.gn +++ b/chromium/gpu/command_buffer/common/BUILD.gn @@ -6,7 +6,6 @@ # "command_buffer_common" just forwarding) and goes into a static library in # non-component build. This needs to match the GYP build which was likely an # attempt to make larger components to help with loading. -import("//mojo/public/tools/bindings/mojom.gni") group("common") { if (is_component_build) { @@ -54,8 +53,6 @@ source_set("common_sources") { "sync_token.h", "thread_local.h", "time.h", - "value_state.cc", - "value_state.h", ] configs += [ "//gpu:gpu_implementation" ] @@ -86,17 +83,3 @@ component("gles2_utils") { all_dependent_configs = [ "//third_party/khronos:khronos_headers" ] } - -mojom("interfaces") { - sources = [ - "capabilities.mojom", - "command_buffer.mojom", - "mailbox.mojom", - "mailbox_holder.mojom", - "sync_token.mojom", - "value_state.mojom", - ] - - typemaps = [ "mojo.typemap" ] - typemap_deps = [ "//gpu/ipc/common:command_buffer_traits" ] -} diff --git a/chromium/gpu/command_buffer/common/buffer.cc b/chromium/gpu/command_buffer/common/buffer.cc index 02c7777898d..1bb9523079d 100644 --- a/chromium/gpu/command_buffer/common/buffer.cc +++ b/chromium/gpu/command_buffer/common/buffer.cc @@ -14,7 +14,7 @@ namespace gpu { SharedMemoryBufferBacking::SharedMemoryBufferBacking( - scoped_ptr<base::SharedMemory> shared_memory, + std::unique_ptr<base::SharedMemory> shared_memory, size_t size) : shared_memory_(std::move(shared_memory)), size_(size) {} @@ -26,7 +26,7 @@ void* SharedMemoryBufferBacking::GetMemory() const { size_t SharedMemoryBufferBacking::GetSize() const { return size_; } -Buffer::Buffer(scoped_ptr<BufferBacking> backing) +Buffer::Buffer(std::unique_ptr<BufferBacking> backing) : backing_(std::move(backing)), memory_(backing_->GetMemory()), size_(backing_->GetSize()) { diff --git a/chromium/gpu/command_buffer/common/buffer.h b/chromium/gpu/command_buffer/common/buffer.h index 1e427f27dbb..0aea591f716 100644 --- a/chromium/gpu/command_buffer/common/buffer.h +++ b/chromium/gpu/command_buffer/common/buffer.h @@ -8,9 +8,10 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory.h" #include "base/trace_event/memory_allocator_dump.h" #include "gpu/gpu_export.h" @@ -30,7 +31,7 @@ class GPU_EXPORT BufferBacking { class GPU_EXPORT SharedMemoryBufferBacking : public BufferBacking { public: - SharedMemoryBufferBacking(scoped_ptr<base::SharedMemory> shared_memory, + SharedMemoryBufferBacking(std::unique_ptr<base::SharedMemory> shared_memory, size_t size); ~SharedMemoryBufferBacking() override; void* GetMemory() const override; @@ -38,7 +39,7 @@ class GPU_EXPORT SharedMemoryBufferBacking : public BufferBacking { base::SharedMemory* shared_memory() { return shared_memory_.get(); } private: - scoped_ptr<base::SharedMemory> shared_memory_; + std::unique_ptr<base::SharedMemory> shared_memory_; size_t size_; DISALLOW_COPY_AND_ASSIGN(SharedMemoryBufferBacking); }; @@ -46,7 +47,7 @@ class GPU_EXPORT SharedMemoryBufferBacking : public BufferBacking { // Buffer owns a piece of shared-memory of a certain size. class GPU_EXPORT Buffer : public base::RefCountedThreadSafe<Buffer> { public: - explicit Buffer(scoped_ptr<BufferBacking> backing); + explicit Buffer(std::unique_ptr<BufferBacking> backing); BufferBacking* backing() const { return backing_.get(); } void* memory() const { return memory_; } @@ -59,22 +60,22 @@ class GPU_EXPORT Buffer : public base::RefCountedThreadSafe<Buffer> { friend class base::RefCountedThreadSafe<Buffer>; ~Buffer(); - scoped_ptr<BufferBacking> backing_; + std::unique_ptr<BufferBacking> backing_; void* memory_; size_t size_; DISALLOW_COPY_AND_ASSIGN(Buffer); }; -static inline scoped_ptr<BufferBacking> MakeBackingFromSharedMemory( - scoped_ptr<base::SharedMemory> shared_memory, +static inline std::unique_ptr<BufferBacking> MakeBackingFromSharedMemory( + std::unique_ptr<base::SharedMemory> shared_memory, size_t size) { - return scoped_ptr<BufferBacking>( + return std::unique_ptr<BufferBacking>( new SharedMemoryBufferBacking(std::move(shared_memory), size)); } static inline scoped_refptr<Buffer> MakeBufferFromSharedMemory( - scoped_ptr<base::SharedMemory> shared_memory, + std::unique_ptr<base::SharedMemory> shared_memory, size_t size) { return new Buffer( MakeBackingFromSharedMemory(std::move(shared_memory), size)); diff --git a/chromium/gpu/command_buffer/common/capabilities.cc b/chromium/gpu/command_buffer/common/capabilities.cc index 23d1abb091d..9cf78dc6a87 100644 --- a/chromium/gpu/command_buffer/common/capabilities.cc +++ b/chromium/gpu/command_buffer/common/capabilities.cc @@ -84,6 +84,9 @@ Capabilities::Capabilities() surfaceless(false), flips_vertically(false), msaa_is_slow(false), + disable_webgl_multisampling_color_mask_usage(false), + disable_webgl_rgb_multisampling_usage(false), + chromium_image_rgb_emulation(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 b01ccb8c913..f7ffb7db9b6 100644 --- a/chromium/gpu/command_buffer/common/capabilities.h +++ b/chromium/gpu/command_buffer/common/capabilities.h @@ -144,6 +144,15 @@ struct GPU_EXPORT Capabilities { bool surfaceless; bool flips_vertically; bool msaa_is_slow; + bool disable_webgl_multisampling_color_mask_usage; + bool disable_webgl_rgb_multisampling_usage; + + // When this parameter is true, a CHROMIUM image created with RGB format will + // actually have RGBA format. The client is responsible for handling most of + // the complexities associated with this. See + // gpu/GLES2/extensions/CHROMIUM/CHROMIUM_gpu_memory_buffer_image.txt for more + // details. + bool chromium_image_rgb_emulation; int major_version; int minor_version; diff --git a/chromium/gpu/command_buffer/common/command_buffer.h b/chromium/gpu/command_buffer/common/command_buffer.h index 23cb406428c..dc3f7f7850a 100644 --- a/chromium/gpu/command_buffer/common/command_buffer.h +++ b/chromium/gpu/command_buffer/common/command_buffer.h @@ -75,9 +75,6 @@ class GPU_EXPORT CommandBuffer { return start <= value || value <= end; } - // Initialize the command buffer with the given size. - virtual bool Initialize() = 0; - // Returns the last state without synchronizing with the service. virtual State GetLastState() = 0; diff --git a/chromium/gpu/command_buffer/common/command_buffer_mock.h b/chromium/gpu/command_buffer/common/command_buffer_mock.h index 600ae7e5535..6ece2d051dc 100644 --- a/chromium/gpu/command_buffer/common/command_buffer_mock.h +++ b/chromium/gpu/command_buffer/common/command_buffer_mock.h @@ -25,7 +25,6 @@ class MockCommandBuffer : public CommandBufferServiceBase { MockCommandBuffer(); virtual ~MockCommandBuffer(); - MOCK_METHOD0(Initialize, bool()); MOCK_METHOD0(GetLastState, State()); MOCK_METHOD0(GetLastToken, int32_t()); MOCK_METHOD1(Flush, void(int32_t put_offset)); diff --git a/chromium/gpu/command_buffer/common/command_buffer_shared_test.cc b/chromium/gpu/command_buffer/common/command_buffer_shared_test.cc index dc4bbed218f..4ae60408373 100644 --- a/chromium/gpu/command_buffer/common/command_buffer_shared_test.cc +++ b/chromium/gpu/command_buffer/common/command_buffer_shared_test.cc @@ -8,9 +8,10 @@ #include <stdint.h> +#include <memory> + #include "base/bind.h" #include "base/location.h" -#include "base/memory/scoped_ptr.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread.h" #include "testing/gtest/include/gtest/gtest.h" @@ -24,7 +25,7 @@ class CommandBufferSharedTest : public testing::Test { shared_state_->Initialize(); } - scoped_ptr<CommandBufferSharedState> shared_state_; + std::unique_ptr<CommandBufferSharedState> shared_state_; }; TEST_F(CommandBufferSharedTest, TestBasic) { @@ -57,7 +58,7 @@ void WriteToState(int32_t* buffer, CommandBufferSharedState* shared_state) { } TEST_F(CommandBufferSharedTest, TestConsistency) { - scoped_ptr<int32_t[]> buffer; + std::unique_ptr<int32_t[]> buffer; buffer.reset(new int32_t[kSize]); base::Thread consumer("Reader Thread"); diff --git a/chromium/gpu/command_buffer/common/constants.h b/chromium/gpu/command_buffer/common/constants.h index 77232aaeba7..68f0948eade 100644 --- a/chromium/gpu/command_buffer/common/constants.h +++ b/chromium/gpu/command_buffer/common/constants.h @@ -13,7 +13,6 @@ namespace gpu { typedef int32_t CommandBufferOffset; const CommandBufferOffset kInvalidCommandBufferOffset = -1; -// This enum must stay in sync with NPDeviceContext3DError. namespace error { enum Error { kNoError, diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_format.h b/chromium/gpu/command_buffer/common/gles2_cmd_format.h index e9483825e4f..1ac1d8967db 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_format.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_format.h @@ -68,7 +68,6 @@ enum IdNamespaces { kTextures, kQueries, kVertexArrays, - kValuebuffers, kSamplers, kTransformFeedbacks, kSyncs, 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 3f3fe783115..ddd4182f057 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -12951,288 +12951,6 @@ static_assert( offsetof(BindUniformLocationCHROMIUMBucket, name_bucket_id) == 12, "offset of BindUniformLocationCHROMIUMBucket name_bucket_id should be 12"); -struct GenValuebuffersCHROMIUMImmediate { - typedef GenValuebuffersCHROMIUMImmediate ValueType; - static const CommandId kCmdId = kGenValuebuffersCHROMIUMImmediate; - static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; - static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); - - static uint32_t ComputeDataSize(GLsizei n) { - return static_cast<uint32_t>(sizeof(GLuint) * n); // NOLINT - } - - static uint32_t ComputeSize(GLsizei n) { - return static_cast<uint32_t>(sizeof(ValueType) + - ComputeDataSize(n)); // NOLINT - } - - void SetHeader(GLsizei n) { - header.SetCmdByTotalSize<ValueType>(ComputeSize(n)); - } - - void Init(GLsizei _n, GLuint* _buffers) { - SetHeader(_n); - n = _n; - memcpy(ImmediateDataAddress(this), _buffers, ComputeDataSize(_n)); - } - - void* Set(void* cmd, GLsizei _n, GLuint* _buffers) { - static_cast<ValueType*>(cmd)->Init(_n, _buffers); - const uint32_t size = ComputeSize(_n); - return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size); - } - - gpu::CommandHeader header; - int32_t n; -}; - -static_assert(sizeof(GenValuebuffersCHROMIUMImmediate) == 8, - "size of GenValuebuffersCHROMIUMImmediate should be 8"); -static_assert(offsetof(GenValuebuffersCHROMIUMImmediate, header) == 0, - "offset of GenValuebuffersCHROMIUMImmediate header should be 0"); -static_assert(offsetof(GenValuebuffersCHROMIUMImmediate, n) == 4, - "offset of GenValuebuffersCHROMIUMImmediate n should be 4"); - -struct DeleteValuebuffersCHROMIUMImmediate { - typedef DeleteValuebuffersCHROMIUMImmediate ValueType; - static const CommandId kCmdId = kDeleteValuebuffersCHROMIUMImmediate; - static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; - static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); - - static uint32_t ComputeDataSize(GLsizei n) { - return static_cast<uint32_t>(sizeof(GLuint) * n); // NOLINT - } - - static uint32_t ComputeSize(GLsizei n) { - return static_cast<uint32_t>(sizeof(ValueType) + - ComputeDataSize(n)); // NOLINT - } - - void SetHeader(GLsizei n) { - header.SetCmdByTotalSize<ValueType>(ComputeSize(n)); - } - - void Init(GLsizei _n, const GLuint* _valuebuffers) { - SetHeader(_n); - n = _n; - memcpy(ImmediateDataAddress(this), _valuebuffers, ComputeDataSize(_n)); - } - - void* Set(void* cmd, GLsizei _n, const GLuint* _valuebuffers) { - static_cast<ValueType*>(cmd)->Init(_n, _valuebuffers); - const uint32_t size = ComputeSize(_n); - return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size); - } - - gpu::CommandHeader header; - int32_t n; -}; - -static_assert(sizeof(DeleteValuebuffersCHROMIUMImmediate) == 8, - "size of DeleteValuebuffersCHROMIUMImmediate should be 8"); -static_assert( - offsetof(DeleteValuebuffersCHROMIUMImmediate, header) == 0, - "offset of DeleteValuebuffersCHROMIUMImmediate header should be 0"); -static_assert(offsetof(DeleteValuebuffersCHROMIUMImmediate, n) == 4, - "offset of DeleteValuebuffersCHROMIUMImmediate n should be 4"); - -struct IsValuebufferCHROMIUM { - typedef IsValuebufferCHROMIUM ValueType; - static const CommandId kCmdId = kIsValuebufferCHROMIUM; - static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); - - typedef uint32_t Result; - - static uint32_t ComputeSize() { - return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT - } - - void SetHeader() { header.SetCmd<ValueType>(); } - - void Init(GLuint _valuebuffer, - uint32_t _result_shm_id, - uint32_t _result_shm_offset) { - SetHeader(); - valuebuffer = _valuebuffer; - result_shm_id = _result_shm_id; - result_shm_offset = _result_shm_offset; - } - - void* Set(void* cmd, - GLuint _valuebuffer, - uint32_t _result_shm_id, - uint32_t _result_shm_offset) { - static_cast<ValueType*>(cmd)->Init(_valuebuffer, _result_shm_id, - _result_shm_offset); - return NextCmdAddress<ValueType>(cmd); - } - - gpu::CommandHeader header; - uint32_t valuebuffer; - uint32_t result_shm_id; - uint32_t result_shm_offset; -}; - -static_assert(sizeof(IsValuebufferCHROMIUM) == 16, - "size of IsValuebufferCHROMIUM should be 16"); -static_assert(offsetof(IsValuebufferCHROMIUM, header) == 0, - "offset of IsValuebufferCHROMIUM header should be 0"); -static_assert(offsetof(IsValuebufferCHROMIUM, valuebuffer) == 4, - "offset of IsValuebufferCHROMIUM valuebuffer should be 4"); -static_assert(offsetof(IsValuebufferCHROMIUM, result_shm_id) == 8, - "offset of IsValuebufferCHROMIUM result_shm_id should be 8"); -static_assert(offsetof(IsValuebufferCHROMIUM, result_shm_offset) == 12, - "offset of IsValuebufferCHROMIUM result_shm_offset should be 12"); - -struct BindValuebufferCHROMIUM { - typedef BindValuebufferCHROMIUM ValueType; - static const CommandId kCmdId = kBindValuebufferCHROMIUM; - static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8_t 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, GLuint _valuebuffer) { - SetHeader(); - target = _target; - valuebuffer = _valuebuffer; - } - - void* Set(void* cmd, GLenum _target, GLuint _valuebuffer) { - static_cast<ValueType*>(cmd)->Init(_target, _valuebuffer); - return NextCmdAddress<ValueType>(cmd); - } - - gpu::CommandHeader header; - uint32_t target; - uint32_t valuebuffer; -}; - -static_assert(sizeof(BindValuebufferCHROMIUM) == 12, - "size of BindValuebufferCHROMIUM should be 12"); -static_assert(offsetof(BindValuebufferCHROMIUM, header) == 0, - "offset of BindValuebufferCHROMIUM header should be 0"); -static_assert(offsetof(BindValuebufferCHROMIUM, target) == 4, - "offset of BindValuebufferCHROMIUM target should be 4"); -static_assert(offsetof(BindValuebufferCHROMIUM, valuebuffer) == 8, - "offset of BindValuebufferCHROMIUM valuebuffer should be 8"); - -struct SubscribeValueCHROMIUM { - typedef SubscribeValueCHROMIUM ValueType; - static const CommandId kCmdId = kSubscribeValueCHROMIUM; - static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8_t 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 _subscription) { - SetHeader(); - target = _target; - subscription = _subscription; - } - - void* Set(void* cmd, GLenum _target, GLenum _subscription) { - static_cast<ValueType*>(cmd)->Init(_target, _subscription); - return NextCmdAddress<ValueType>(cmd); - } - - gpu::CommandHeader header; - uint32_t target; - uint32_t subscription; -}; - -static_assert(sizeof(SubscribeValueCHROMIUM) == 12, - "size of SubscribeValueCHROMIUM should be 12"); -static_assert(offsetof(SubscribeValueCHROMIUM, header) == 0, - "offset of SubscribeValueCHROMIUM header should be 0"); -static_assert(offsetof(SubscribeValueCHROMIUM, target) == 4, - "offset of SubscribeValueCHROMIUM target should be 4"); -static_assert(offsetof(SubscribeValueCHROMIUM, subscription) == 8, - "offset of SubscribeValueCHROMIUM subscription should be 8"); - -struct PopulateSubscribedValuesCHROMIUM { - typedef PopulateSubscribedValuesCHROMIUM ValueType; - static const CommandId kCmdId = kPopulateSubscribedValuesCHROMIUM; - static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8_t 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) { - SetHeader(); - target = _target; - } - - void* Set(void* cmd, GLenum _target) { - static_cast<ValueType*>(cmd)->Init(_target); - return NextCmdAddress<ValueType>(cmd); - } - - gpu::CommandHeader header; - uint32_t target; -}; - -static_assert(sizeof(PopulateSubscribedValuesCHROMIUM) == 8, - "size of PopulateSubscribedValuesCHROMIUM should be 8"); -static_assert(offsetof(PopulateSubscribedValuesCHROMIUM, header) == 0, - "offset of PopulateSubscribedValuesCHROMIUM header should be 0"); -static_assert(offsetof(PopulateSubscribedValuesCHROMIUM, target) == 4, - "offset of PopulateSubscribedValuesCHROMIUM target should be 4"); - -struct UniformValuebufferCHROMIUM { - typedef UniformValuebufferCHROMIUM ValueType; - static const CommandId kCmdId = kUniformValuebufferCHROMIUM; - static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8_t 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(GLint _location, GLenum _target, GLenum _subscription) { - SetHeader(); - location = _location; - target = _target; - subscription = _subscription; - } - - void* Set(void* cmd, GLint _location, GLenum _target, GLenum _subscription) { - static_cast<ValueType*>(cmd)->Init(_location, _target, _subscription); - return NextCmdAddress<ValueType>(cmd); - } - - gpu::CommandHeader header; - int32_t location; - uint32_t target; - uint32_t subscription; -}; - -static_assert(sizeof(UniformValuebufferCHROMIUM) == 16, - "size of UniformValuebufferCHROMIUM should be 16"); -static_assert(offsetof(UniformValuebufferCHROMIUM, header) == 0, - "offset of UniformValuebufferCHROMIUM header should be 0"); -static_assert(offsetof(UniformValuebufferCHROMIUM, location) == 4, - "offset of UniformValuebufferCHROMIUM location should be 4"); -static_assert(offsetof(UniformValuebufferCHROMIUM, target) == 8, - "offset of UniformValuebufferCHROMIUM target should be 8"); -static_assert(offsetof(UniformValuebufferCHROMIUM, subscription) == 12, - "offset of UniformValuebufferCHROMIUM subscription should be 12"); - struct BindTexImage2DCHROMIUM { typedef BindTexImage2DCHROMIUM ValueType; static const CommandId kCmdId = kBindTexImage2DCHROMIUM; @@ -13894,6 +13612,7 @@ struct ScheduleCALayerCHROMIUM { GLuint _edge_aa_mask, GLboolean _is_clipped, GLint _sorting_context_id, + GLuint _filter, GLuint _shm_id, GLuint _shm_offset) { SetHeader(); @@ -13903,6 +13622,7 @@ struct ScheduleCALayerCHROMIUM { edge_aa_mask = _edge_aa_mask; is_clipped = _is_clipped; sorting_context_id = _sorting_context_id; + filter = _filter; shm_id = _shm_id; shm_offset = _shm_offset; } @@ -13914,11 +13634,12 @@ struct ScheduleCALayerCHROMIUM { GLuint _edge_aa_mask, GLboolean _is_clipped, GLint _sorting_context_id, + GLuint _filter, GLuint _shm_id, GLuint _shm_offset) { static_cast<ValueType*>(cmd)->Init( _contents_texture_id, _opacity, _background_color, _edge_aa_mask, - _is_clipped, _sorting_context_id, _shm_id, _shm_offset); + _is_clipped, _sorting_context_id, _filter, _shm_id, _shm_offset); return NextCmdAddress<ValueType>(cmd); } @@ -13929,12 +13650,13 @@ struct ScheduleCALayerCHROMIUM { uint32_t edge_aa_mask; uint32_t is_clipped; int32_t sorting_context_id; + uint32_t filter; uint32_t shm_id; uint32_t shm_offset; }; -static_assert(sizeof(ScheduleCALayerCHROMIUM) == 36, - "size of ScheduleCALayerCHROMIUM should be 36"); +static_assert(sizeof(ScheduleCALayerCHROMIUM) == 40, + "size of ScheduleCALayerCHROMIUM should be 40"); static_assert(offsetof(ScheduleCALayerCHROMIUM, header) == 0, "offset of ScheduleCALayerCHROMIUM header should be 0"); static_assert( @@ -13952,10 +13674,12 @@ static_assert(offsetof(ScheduleCALayerCHROMIUM, is_clipped) == 20, static_assert( offsetof(ScheduleCALayerCHROMIUM, sorting_context_id) == 24, "offset of ScheduleCALayerCHROMIUM sorting_context_id should be 24"); -static_assert(offsetof(ScheduleCALayerCHROMIUM, shm_id) == 28, - "offset of ScheduleCALayerCHROMIUM shm_id should be 28"); -static_assert(offsetof(ScheduleCALayerCHROMIUM, shm_offset) == 32, - "offset of ScheduleCALayerCHROMIUM shm_offset should be 32"); +static_assert(offsetof(ScheduleCALayerCHROMIUM, filter) == 28, + "offset of ScheduleCALayerCHROMIUM filter should be 28"); +static_assert(offsetof(ScheduleCALayerCHROMIUM, shm_id) == 32, + "offset of ScheduleCALayerCHROMIUM shm_id should be 32"); +static_assert(offsetof(ScheduleCALayerCHROMIUM, shm_offset) == 36, + "offset of ScheduleCALayerCHROMIUM shm_offset should be 36"); struct CommitOverlayPlanesCHROMIUM { typedef CommitOverlayPlanesCHROMIUM ValueType; 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 cee9167164c..cbfccdd9964 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 @@ -4513,111 +4513,6 @@ TEST_F(GLES2FormatTest, BindUniformLocationCHROMIUMBucket) { CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } -TEST_F(GLES2FormatTest, GenValuebuffersCHROMIUMImmediate) { - static GLuint ids[] = { - 12, 23, 34, - }; - cmds::GenValuebuffersCHROMIUMImmediate& cmd = - *GetBufferAs<cmds::GenValuebuffersCHROMIUMImmediate>(); - void* next_cmd = cmd.Set(&cmd, static_cast<GLsizei>(arraysize(ids)), ids); - EXPECT_EQ( - static_cast<uint32_t>(cmds::GenValuebuffersCHROMIUMImmediate::kCmdId), - cmd.header.command); - EXPECT_EQ(sizeof(cmd) + RoundSizeToMultipleOfEntries(cmd.n * 4u), - cmd.header.size * 4u); - EXPECT_EQ(static_cast<GLsizei>(arraysize(ids)), cmd.n); - CheckBytesWrittenMatchesExpectedSize( - next_cmd, - sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u)); - EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids))); -} - -TEST_F(GLES2FormatTest, DeleteValuebuffersCHROMIUMImmediate) { - static GLuint ids[] = { - 12, 23, 34, - }; - cmds::DeleteValuebuffersCHROMIUMImmediate& cmd = - *GetBufferAs<cmds::DeleteValuebuffersCHROMIUMImmediate>(); - void* next_cmd = cmd.Set(&cmd, static_cast<GLsizei>(arraysize(ids)), ids); - EXPECT_EQ( - static_cast<uint32_t>(cmds::DeleteValuebuffersCHROMIUMImmediate::kCmdId), - cmd.header.command); - EXPECT_EQ(sizeof(cmd) + RoundSizeToMultipleOfEntries(cmd.n * 4u), - cmd.header.size * 4u); - EXPECT_EQ(static_cast<GLsizei>(arraysize(ids)), cmd.n); - CheckBytesWrittenMatchesExpectedSize( - next_cmd, - sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u)); - EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids))); -} - -TEST_F(GLES2FormatTest, IsValuebufferCHROMIUM) { - cmds::IsValuebufferCHROMIUM& cmd = - *GetBufferAs<cmds::IsValuebufferCHROMIUM>(); - void* next_cmd = - cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12), - static_cast<uint32_t>(13)); - EXPECT_EQ(static_cast<uint32_t>(cmds::IsValuebufferCHROMIUM::kCmdId), - cmd.header.command); - EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); - EXPECT_EQ(static_cast<GLuint>(11), cmd.valuebuffer); - EXPECT_EQ(static_cast<uint32_t>(12), cmd.result_shm_id); - EXPECT_EQ(static_cast<uint32_t>(13), cmd.result_shm_offset); - CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); -} - -TEST_F(GLES2FormatTest, BindValuebufferCHROMIUM) { - cmds::BindValuebufferCHROMIUM& cmd = - *GetBufferAs<cmds::BindValuebufferCHROMIUM>(); - void* next_cmd = - cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<GLuint>(12)); - EXPECT_EQ(static_cast<uint32_t>(cmds::BindValuebufferCHROMIUM::kCmdId), - cmd.header.command); - EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); - EXPECT_EQ(static_cast<GLenum>(11), cmd.target); - EXPECT_EQ(static_cast<GLuint>(12), cmd.valuebuffer); - CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); -} - -TEST_F(GLES2FormatTest, SubscribeValueCHROMIUM) { - cmds::SubscribeValueCHROMIUM& cmd = - *GetBufferAs<cmds::SubscribeValueCHROMIUM>(); - void* next_cmd = - cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<GLenum>(12)); - EXPECT_EQ(static_cast<uint32_t>(cmds::SubscribeValueCHROMIUM::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.subscription); - CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); -} - -TEST_F(GLES2FormatTest, PopulateSubscribedValuesCHROMIUM) { - cmds::PopulateSubscribedValuesCHROMIUM& cmd = - *GetBufferAs<cmds::PopulateSubscribedValuesCHROMIUM>(); - void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11)); - EXPECT_EQ( - static_cast<uint32_t>(cmds::PopulateSubscribedValuesCHROMIUM::kCmdId), - cmd.header.command); - EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); - EXPECT_EQ(static_cast<GLenum>(11), cmd.target); - CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); -} - -TEST_F(GLES2FormatTest, UniformValuebufferCHROMIUM) { - cmds::UniformValuebufferCHROMIUM& cmd = - *GetBufferAs<cmds::UniformValuebufferCHROMIUM>(); - void* next_cmd = cmd.Set(&cmd, static_cast<GLint>(11), - static_cast<GLenum>(12), static_cast<GLenum>(13)); - EXPECT_EQ(static_cast<uint32_t>(cmds::UniformValuebufferCHROMIUM::kCmdId), - cmd.header.command); - EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); - EXPECT_EQ(static_cast<GLint>(11), cmd.location); - EXPECT_EQ(static_cast<GLenum>(12), cmd.target); - EXPECT_EQ(static_cast<GLenum>(13), cmd.subscription); - CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); -} - TEST_F(GLES2FormatTest, BindTexImage2DCHROMIUM) { cmds::BindTexImage2DCHROMIUM& cmd = *GetBufferAs<cmds::BindTexImage2DCHROMIUM>(); @@ -4783,11 +4678,11 @@ TEST_F(GLES2FormatTest, ScheduleOverlayPlaneCHROMIUM) { TEST_F(GLES2FormatTest, ScheduleCALayerCHROMIUM) { cmds::ScheduleCALayerCHROMIUM& cmd = *GetBufferAs<cmds::ScheduleCALayerCHROMIUM>(); - void* next_cmd = - cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLfloat>(12), - static_cast<GLuint>(13), static_cast<GLuint>(14), - static_cast<GLboolean>(15), static_cast<GLint>(16), - static_cast<GLuint>(17), static_cast<GLuint>(18)); + void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11), + static_cast<GLfloat>(12), static_cast<GLuint>(13), + static_cast<GLuint>(14), static_cast<GLboolean>(15), + static_cast<GLint>(16), static_cast<GLuint>(17), + static_cast<GLuint>(18), static_cast<GLuint>(19)); EXPECT_EQ(static_cast<uint32_t>(cmds::ScheduleCALayerCHROMIUM::kCmdId), cmd.header.command); EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); @@ -4797,8 +4692,9 @@ TEST_F(GLES2FormatTest, ScheduleCALayerCHROMIUM) { EXPECT_EQ(static_cast<GLuint>(14), cmd.edge_aa_mask); EXPECT_EQ(static_cast<GLboolean>(15), cmd.is_clipped); EXPECT_EQ(static_cast<GLint>(16), cmd.sorting_context_id); - EXPECT_EQ(static_cast<GLuint>(17), cmd.shm_id); - EXPECT_EQ(static_cast<GLuint>(18), cmd.shm_offset); + EXPECT_EQ(static_cast<GLuint>(17), cmd.filter); + EXPECT_EQ(static_cast<GLuint>(18), cmd.shm_id); + EXPECT_EQ(static_cast<GLuint>(19), cmd.shm_offset); CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } 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 03161998c56..1ac33682a7a 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -280,61 +280,54 @@ OP(ConsumeTextureCHROMIUMImmediate) /* 521 */ \ OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 522 */ \ OP(BindUniformLocationCHROMIUMBucket) /* 523 */ \ - OP(GenValuebuffersCHROMIUMImmediate) /* 524 */ \ - OP(DeleteValuebuffersCHROMIUMImmediate) /* 525 */ \ - OP(IsValuebufferCHROMIUM) /* 526 */ \ - OP(BindValuebufferCHROMIUM) /* 527 */ \ - OP(SubscribeValueCHROMIUM) /* 528 */ \ - OP(PopulateSubscribedValuesCHROMIUM) /* 529 */ \ - OP(UniformValuebufferCHROMIUM) /* 530 */ \ - OP(BindTexImage2DCHROMIUM) /* 531 */ \ - OP(ReleaseTexImage2DCHROMIUM) /* 532 */ \ - OP(TraceBeginCHROMIUM) /* 533 */ \ - OP(TraceEndCHROMIUM) /* 534 */ \ - OP(DiscardFramebufferEXTImmediate) /* 535 */ \ - OP(LoseContextCHROMIUM) /* 536 */ \ - OP(InsertFenceSyncCHROMIUM) /* 537 */ \ - OP(GenSyncTokenCHROMIUMImmediate) /* 538 */ \ - OP(GenUnverifiedSyncTokenCHROMIUMImmediate) /* 539 */ \ - OP(VerifySyncTokensCHROMIUMImmediate) /* 540 */ \ - OP(WaitSyncTokenCHROMIUM) /* 541 */ \ - OP(DrawBuffersEXTImmediate) /* 542 */ \ - OP(DiscardBackbufferCHROMIUM) /* 543 */ \ - OP(ScheduleOverlayPlaneCHROMIUM) /* 544 */ \ - OP(ScheduleCALayerCHROMIUM) /* 545 */ \ - OP(CommitOverlayPlanesCHROMIUM) /* 546 */ \ - OP(SwapInterval) /* 547 */ \ - OP(FlushDriverCachesCHROMIUM) /* 548 */ \ - OP(MatrixLoadfCHROMIUMImmediate) /* 549 */ \ - OP(MatrixLoadIdentityCHROMIUM) /* 550 */ \ - OP(GenPathsCHROMIUM) /* 551 */ \ - OP(DeletePathsCHROMIUM) /* 552 */ \ - OP(IsPathCHROMIUM) /* 553 */ \ - OP(PathCommandsCHROMIUM) /* 554 */ \ - OP(PathParameterfCHROMIUM) /* 555 */ \ - OP(PathParameteriCHROMIUM) /* 556 */ \ - OP(PathStencilFuncCHROMIUM) /* 557 */ \ - OP(StencilFillPathCHROMIUM) /* 558 */ \ - OP(StencilStrokePathCHROMIUM) /* 559 */ \ - OP(CoverFillPathCHROMIUM) /* 560 */ \ - OP(CoverStrokePathCHROMIUM) /* 561 */ \ - OP(StencilThenCoverFillPathCHROMIUM) /* 562 */ \ - OP(StencilThenCoverStrokePathCHROMIUM) /* 563 */ \ - OP(StencilFillPathInstancedCHROMIUM) /* 564 */ \ - OP(StencilStrokePathInstancedCHROMIUM) /* 565 */ \ - OP(CoverFillPathInstancedCHROMIUM) /* 566 */ \ - OP(CoverStrokePathInstancedCHROMIUM) /* 567 */ \ - OP(StencilThenCoverFillPathInstancedCHROMIUM) /* 568 */ \ - OP(StencilThenCoverStrokePathInstancedCHROMIUM) /* 569 */ \ - OP(BindFragmentInputLocationCHROMIUMBucket) /* 570 */ \ - OP(ProgramPathFragmentInputGenCHROMIUM) /* 571 */ \ - OP(CoverageModulationCHROMIUM) /* 572 */ \ - OP(BlendBarrierKHR) /* 573 */ \ - OP(ApplyScreenSpaceAntialiasingCHROMIUM) /* 574 */ \ - OP(BindFragDataLocationIndexedEXTBucket) /* 575 */ \ - OP(BindFragDataLocationEXTBucket) /* 576 */ \ - OP(GetFragDataIndexEXT) /* 577 */ \ - OP(UniformMatrix4fvStreamTextureMatrixCHROMIUMImmediate) /* 578 */ + OP(BindTexImage2DCHROMIUM) /* 524 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 525 */ \ + OP(TraceBeginCHROMIUM) /* 526 */ \ + OP(TraceEndCHROMIUM) /* 527 */ \ + OP(DiscardFramebufferEXTImmediate) /* 528 */ \ + OP(LoseContextCHROMIUM) /* 529 */ \ + OP(InsertFenceSyncCHROMIUM) /* 530 */ \ + OP(GenSyncTokenCHROMIUMImmediate) /* 531 */ \ + OP(GenUnverifiedSyncTokenCHROMIUMImmediate) /* 532 */ \ + OP(VerifySyncTokensCHROMIUMImmediate) /* 533 */ \ + OP(WaitSyncTokenCHROMIUM) /* 534 */ \ + OP(DrawBuffersEXTImmediate) /* 535 */ \ + OP(DiscardBackbufferCHROMIUM) /* 536 */ \ + OP(ScheduleOverlayPlaneCHROMIUM) /* 537 */ \ + OP(ScheduleCALayerCHROMIUM) /* 538 */ \ + OP(CommitOverlayPlanesCHROMIUM) /* 539 */ \ + OP(SwapInterval) /* 540 */ \ + OP(FlushDriverCachesCHROMIUM) /* 541 */ \ + OP(MatrixLoadfCHROMIUMImmediate) /* 542 */ \ + OP(MatrixLoadIdentityCHROMIUM) /* 543 */ \ + OP(GenPathsCHROMIUM) /* 544 */ \ + OP(DeletePathsCHROMIUM) /* 545 */ \ + OP(IsPathCHROMIUM) /* 546 */ \ + OP(PathCommandsCHROMIUM) /* 547 */ \ + OP(PathParameterfCHROMIUM) /* 548 */ \ + OP(PathParameteriCHROMIUM) /* 549 */ \ + OP(PathStencilFuncCHROMIUM) /* 550 */ \ + OP(StencilFillPathCHROMIUM) /* 551 */ \ + OP(StencilStrokePathCHROMIUM) /* 552 */ \ + OP(CoverFillPathCHROMIUM) /* 553 */ \ + OP(CoverStrokePathCHROMIUM) /* 554 */ \ + OP(StencilThenCoverFillPathCHROMIUM) /* 555 */ \ + OP(StencilThenCoverStrokePathCHROMIUM) /* 556 */ \ + OP(StencilFillPathInstancedCHROMIUM) /* 557 */ \ + OP(StencilStrokePathInstancedCHROMIUM) /* 558 */ \ + OP(CoverFillPathInstancedCHROMIUM) /* 559 */ \ + OP(CoverStrokePathInstancedCHROMIUM) /* 560 */ \ + OP(StencilThenCoverFillPathInstancedCHROMIUM) /* 561 */ \ + OP(StencilThenCoverStrokePathInstancedCHROMIUM) /* 562 */ \ + OP(BindFragmentInputLocationCHROMIUMBucket) /* 563 */ \ + OP(ProgramPathFragmentInputGenCHROMIUM) /* 564 */ \ + OP(CoverageModulationCHROMIUM) /* 565 */ \ + OP(BlendBarrierKHR) /* 566 */ \ + OP(ApplyScreenSpaceAntialiasingCHROMIUM) /* 567 */ \ + OP(BindFragDataLocationIndexedEXTBucket) /* 568 */ \ + OP(BindFragDataLocationEXTBucket) /* 569 */ \ + OP(GetFragDataIndexEXT) /* 570 */ \ + OP(UniformMatrix4fvStreamTextureMatrixCHROMIUMImmediate) /* 571 */ 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 8eeaf2488c4..491665d99a8 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_utils.cc +++ b/chromium/gpu/command_buffer/common/gles2_cmd_utils.cc @@ -1067,30 +1067,16 @@ uint32_t GLES2Util::GetGLReadPixelsImplementationType(uint32_t internal_format, case GL_RG32F: case GL_RGB32F: case GL_RGBA32F: - return GL_FLOAT; + case GL_R11F_G11F_B10F: + return GL_UNSIGNED_BYTE; case GL_R16F: case GL_RG16F: - case GL_R11F_G11F_B10F: case GL_RGB16F: case GL_RGBA16F: - // TODO(zmo): Consider return GL_UNSIGNED_INT_10F_11F_11F_REV and - // GL_HALF_FLOAT. - return GL_FLOAT; - case GL_RGBA: - case GL_RGB: - // Unsized internal format, check the type - switch (texture_type) { - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - return GL_FLOAT; - // TODO(zmo): Consider return GL_UNSIGNED_SHORT_5_6_5, - // GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1, and - // GL_UNSIGNED_INT_2_10_10_10_REV. - default: - return GL_UNSIGNED_BYTE; - } + return GL_HALF_FLOAT; default: - return GL_UNSIGNED_BYTE; + // Unsized internal format. + return texture_type; } } @@ -1385,11 +1371,27 @@ bool GLES2Util::IsFloatFormat(uint32_t internal_format) { } } +// static +bool GLES2Util::ComputeDataSize(uint32_t count, + size_t size, + unsigned int elements_per_unit, + uint32_t* dst) { + uint32_t value; + if (!SafeMultiplyUint32(count, static_cast<uint32_t>(size), &value)) { + return false; + } + if (!SafeMultiplyUint32(value, elements_per_unit, &value)) { + return false; + } + *dst = value; + return true; +} + namespace { -// WebGraphicsContext3DCommandBufferImpl configuration attributes. Those in -// the 16-bit range are the same as used by EGL. Those outside the 16-bit range -// are unique to Chromium. Attributes are matched using a closest fit algorithm. +// GL context configuration attributes. Those in the 16-bit range are the same +// as used by EGL. Those outside the 16-bit range are unique to Chromium. +// Attributes are matched using a closest fit algorithm. // From <EGL/egl.h>. #include <stddef.h> @@ -1405,7 +1407,6 @@ const int32_t kSampleBuffers = 0x3032; // EGL_SAMPLE_BUFFERS const int32_t kNone = 0x3038; // EGL_NONE const int32_t kSwapBehavior = 0x3093; // EGL_SWAP_BEHAVIOR const int32_t kBufferPreserved = 0x3094; // EGL_BUFFER_PRESERVED -const int32_t kBufferDestroyed = 0x3095; // EGL_BUFFER_DESTROYED // Chromium only. const int32_t kBindGeneratesResource = 0x10000; @@ -1433,53 +1434,6 @@ ContextCreationAttribHelper::ContextCreationAttribHelper() ContextCreationAttribHelper::ContextCreationAttribHelper( const ContextCreationAttribHelper& other) = default; -void ContextCreationAttribHelper::Serialize( - std::vector<int32_t>* attribs) const { - if (alpha_size != -1) { - attribs->push_back(kAlphaSize); - attribs->push_back(alpha_size); - } - if (blue_size != -1) { - attribs->push_back(kBlueSize); - attribs->push_back(blue_size); - } - if (green_size != -1) { - attribs->push_back(kGreenSize); - attribs->push_back(green_size); - } - if (red_size != -1) { - attribs->push_back(kRedSize); - attribs->push_back(red_size); - } - if (depth_size != -1) { - attribs->push_back(kDepthSize); - attribs->push_back(depth_size); - } - if (stencil_size != -1) { - attribs->push_back(kStencilSize); - attribs->push_back(stencil_size); - } - if (samples != -1) { - attribs->push_back(kSamples); - attribs->push_back(samples); - } - if (sample_buffers != -1) { - attribs->push_back(kSampleBuffers); - attribs->push_back(sample_buffers); - } - attribs->push_back(kSwapBehavior); - attribs->push_back(buffer_preserved ? kBufferPreserved : kBufferDestroyed); - attribs->push_back(kBindGeneratesResource); - attribs->push_back(bind_generates_resource ? 1 : 0); - attribs->push_back(kFailIfMajorPerfCaveat); - 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(kContextType); - attribs->push_back(context_type); - attribs->push_back(kNone); -} - bool ContextCreationAttribHelper::Parse(const std::vector<int32_t>& attribs) { for (size_t i = 0; i < attribs.size(); i += 2) { const int32_t attrib = attribs[i]; diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_utils.h b/chromium/gpu/command_buffer/common/gles2_cmd_utils.h index 9104fcd68b9..155946ab2b4 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_utils.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_utils.h @@ -220,6 +220,12 @@ class GLES2_UTILS_EXPORT GLES2Util { static bool IsIntegerFormat(uint32_t internal_format); static bool IsFloatFormat(uint32_t internal_format); + // Computes the data size for certain gl commands like glUniform. + static bool ComputeDataSize(uint32_t count, + size_t size, + unsigned int elements_per_unit, + uint32_t* dst); + #include "../common/gles2_cmd_utils_autogen.h" private: @@ -267,14 +273,14 @@ enum ContextType { CONTEXT_TYPE_WEBGL1, CONTEXT_TYPE_WEBGL2, CONTEXT_TYPE_OPENGLES2, - CONTEXT_TYPE_OPENGLES3 + CONTEXT_TYPE_OPENGLES3, + CONTEXT_TYPE_LAST = CONTEXT_TYPE_OPENGLES3 }; struct GLES2_UTILS_EXPORT ContextCreationAttribHelper { ContextCreationAttribHelper(); ContextCreationAttribHelper(const ContextCreationAttribHelper& other); - void Serialize(std::vector<int32_t>* attribs) const; bool Parse(const std::vector<int32_t>& attribs); // -1 if invalid or unspecified. diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/chromium/gpu/command_buffer/common/gles2_cmd_utils_autogen.h index fb7fbebde8c..d923c01c173 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_utils_autogen.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_utils_autogen.h @@ -77,7 +77,6 @@ static std::string GetStringShaderType(uint32_t value); static std::string GetStringSrcBlendFactor(uint32_t value); static std::string GetStringStencilOp(uint32_t value); static std::string GetStringStringType(uint32_t value); -static std::string GetStringSubscriptionTarget(uint32_t value); static std::string GetStringSyncCondition(uint32_t value); static std::string GetStringSyncParameter(uint32_t value); static std::string GetStringTexture3DTarget(uint32_t value); @@ -107,7 +106,6 @@ static std::string GetStringTransformFeedbackBindTarget(uint32_t value); static std::string GetStringTransformFeedbackPrimitiveMode(uint32_t value); static std::string GetStringUniformBlockParameter(uint32_t value); static std::string GetStringUniformParameter(uint32_t value); -static std::string GetStringValueBufferTarget(uint32_t value); static std::string GetStringVertexAttribIType(uint32_t value); static std::string GetStringVertexAttribType(uint32_t value); static std::string GetStringVertexAttribute(uint32_t value); 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 a9f0cb8bd5c..f8cb36ac7f4 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 @@ -3004,12 +3004,6 @@ static const GLES2Util::EnumToString enum_to_string_table[] = { 0x924A, "GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM", }, { - 0x924B, "GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM", - }, - { - 0x924C, "GL_MOUSE_POSITION_CHROMIUM", - }, - { 0x9250, "GL_SHADER_BINARY_DMP", }, { @@ -4506,14 +4500,6 @@ std::string GLES2Util::GetStringStringType(uint32_t value) { arraysize(string_table), value); } -std::string GLES2Util::GetStringSubscriptionTarget(uint32_t value) { - static const EnumToString string_table[] = { - {GL_MOUSE_POSITION_CHROMIUM, "GL_MOUSE_POSITION_CHROMIUM"}, - }; - return GLES2Util::GetQualifiedEnumString(string_table, - arraysize(string_table), value); -} - std::string GLES2Util::GetStringSyncCondition(uint32_t value) { static const EnumToString string_table[] = { {GL_SYNC_GPU_COMMANDS_COMPLETE, "GL_SYNC_GPU_COMMANDS_COMPLETE"}, @@ -4974,15 +4960,6 @@ std::string GLES2Util::GetStringUniformParameter(uint32_t value) { arraysize(string_table), value); } -std::string GLES2Util::GetStringValueBufferTarget(uint32_t value) { - static const EnumToString string_table[] = { - {GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, - "GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM"}, - }; - return GLES2Util::GetQualifiedEnumString(string_table, - arraysize(string_table), value); -} - std::string GLES2Util::GetStringVertexAttribIType(uint32_t value) { static const EnumToString string_table[] = { {GL_BYTE, "GL_BYTE"}, {GL_UNSIGNED_BYTE, "GL_UNSIGNED_BYTE"}, diff --git a/chromium/gpu/command_buffer/common/gpu_memory_buffer_support.cc b/chromium/gpu/command_buffer/common/gpu_memory_buffer_support.cc index 78c3e48864c..6434a38e4a9 100644 --- a/chromium/gpu/command_buffer/common/gpu_memory_buffer_support.cc +++ b/chromium/gpu/command_buffer/common/gpu_memory_buffer_support.cc @@ -73,11 +73,13 @@ bool IsImageFormatCompatibleWithGpuMemoryBufferFormat( case gfx::BufferFormat::ETC1: case gfx::BufferFormat::R_8: case gfx::BufferFormat::RGBA_8888: - case gfx::BufferFormat::RGBX_8888: case gfx::BufferFormat::YUV_420: case gfx::BufferFormat::YUV_420_BIPLANAR: case gfx::BufferFormat::UYVY_422: return format == BufferFormatForInternalFormat(internalformat); + case gfx::BufferFormat::BGR_565: + case gfx::BufferFormat::RGBX_8888: + return internalformat == GL_RGB; case gfx::BufferFormat::RGBA_4444: return internalformat == GL_RGBA; } @@ -105,6 +107,7 @@ bool IsGpuMemoryBufferFormatSupported(gfx::BufferFormat format, return capabilities.texture_rg; case gfx::BufferFormat::UYVY_422: return capabilities.image_ycbcr_422; + case gfx::BufferFormat::BGR_565: case gfx::BufferFormat::RGBA_4444: case gfx::BufferFormat::RGBA_8888: case gfx::BufferFormat::RGBX_8888: @@ -130,6 +133,7 @@ bool IsImageSizeValidForGpuMemoryBufferFormat(const gfx::Size& size, // by the block size. return size.width() % 4 == 0 && size.height() % 4 == 0; case gfx::BufferFormat::R_8: + case gfx::BufferFormat::BGR_565: case gfx::BufferFormat::RGBA_4444: case gfx::BufferFormat::RGBA_8888: case gfx::BufferFormat::RGBX_8888: diff --git a/chromium/gpu/command_buffer/common/id_type.h b/chromium/gpu/command_buffer/common/id_type.h index 197736451a1..0d009c61867 100644 --- a/chromium/gpu/command_buffer/common/id_type.h +++ b/chromium/gpu/command_buffer/common/id_type.h @@ -35,7 +35,7 @@ // - it can be used as an argument to DCHECK_EQ or streamed to LOG(ERROR); // - it has the same memory footprint and runtime overhead as int32_t; // - it can be copied by memcpy. -// - it can be used in IPC messages (for now via gpu/ipc/id_type_traits.h) +// - it can be used in IPC messages. // // IdType32<Foo> has the following differences from a bare int32_t: // - it forces coercions to go through GetUnsafeValue and FromUnsafeValue; diff --git a/chromium/gpu/command_buffer/common/mojo.typemap b/chromium/gpu/command_buffer/common/mojo.typemap deleted file mode 100644 index d412acd927e..00000000000 --- a/chromium/gpu/command_buffer/common/mojo.typemap +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2016 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. - -{ - "c++": { - "gpu.mojom.Capabilities": { - "typename": "gpu::Capabilities", - "public_headers": [ - "gpu/command_buffer/common/capabilities.h" - ], - "traits_headers": [ - "gpu/ipc/common/gpu_command_buffer_traits.h" - ] - }, - "gpu.mojom.CommandBufferState": { - "typename": "gpu::CommandBuffer::State", - "public_headers": [ - "gpu/command_buffer/common/command_buffer.h" - ], - "traits_headers": [ - "gpu/ipc/common/gpu_command_buffer_traits.h" - ] - }, - "gpu.mojom.Mailbox": { - "typename": "gpu::Mailbox", - "public_headers": [ - "gpu/command_buffer/common/mailbox.h" - ], - "traits_headers": [ - "gpu/ipc/common/gpu_command_buffer_traits.h" - ] - }, - "gpu.mojom.MailboxHolder": { - "typename": "gpu::MailboxHolder", - "public_headers": [ - "gpu/command_buffer/common/mailbox_holder.h" - ], - "traits_headers": [ - "gpu/ipc/common/gpu_command_buffer_traits.h" - ] - }, - "gpu.mojom.SyncToken": { - "typename": "gpu::SyncToken", - "public_headers": [ - "gpu/command_buffer/common/sync_token.h" - ], - "traits_headers": [ - "gpu/ipc/common/gpu_command_buffer_traits.h" - ] - }, - "gpu.mojom.ValueState": { - "typename": "gpu::ValueState", - "public_headers": [ - "gpu/command_buffer/common/value_state.h" - ], - "traits_headers": [ - "gpu/ipc/common/gpu_command_buffer_traits.h" - ] - } - } -} diff --git a/chromium/gpu/command_buffer/common/unittest_main.cc b/chromium/gpu/command_buffer/common/unittest_main.cc index ed03dca8b6f..6e907d50533 100644 --- a/chromium/gpu/command_buffer/common/unittest_main.cc +++ b/chromium/gpu/command_buffer/common/unittest_main.cc @@ -3,11 +3,48 @@ // found in the LICENSE file. #include "base/bind.h" +#include "base/command_line.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" +#include "build/build_config.h" + +#if defined(OS_ANDROID) +#include "gpu/ipc/client/android/in_process_surface_texture_manager.h" +#endif + +namespace { + +class GpuTestSuite : public base::TestSuite { + public: + GpuTestSuite(int argc, char** argv); + ~GpuTestSuite() override; + + protected: + void Initialize() override; + + private: + DISALLOW_COPY_AND_ASSIGN(GpuTestSuite); +}; + +GpuTestSuite::GpuTestSuite(int argc, char** argv) + : base::TestSuite(argc, argv) {} + +GpuTestSuite::~GpuTestSuite() {} + +void GpuTestSuite::Initialize() { + base::TestSuite::Initialize(); +#if defined(OS_ANDROID) + gpu::SurfaceTextureManager::SetInstance( + gpu::InProcessSurfaceTextureManager::GetInstance()); +#endif +} + +} // namespace int main(int argc, char** argv) { - base::TestSuite test_suite(argc, argv); + base::CommandLine::Init(argc, argv); + GpuTestSuite test_suite(argc, argv); + return base::LaunchUnitTests( argc, argv, base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); diff --git a/chromium/gpu/command_buffer/common/value_state.cc b/chromium/gpu/command_buffer/common/value_state.cc deleted file mode 100644 index d4dcdc22665..00000000000 --- a/chromium/gpu/command_buffer/common/value_state.cc +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gpu/command_buffer/common/value_state.h" - -namespace gpu { - -ValueStateMap::ValueStateMap() { -} - -ValueStateMap::~ValueStateMap() { -} - -const ValueState* ValueStateMap::GetState(unsigned int target) const { - Map::const_iterator it = state_map_.find(target); - return it != state_map_.end() ? &it->second : NULL; -} - -void ValueStateMap::UpdateState(unsigned int target, const ValueState& state) { - state_map_[target] = state; -} - -} // namespace gpu diff --git a/chromium/gpu/command_buffer/common/value_state.h b/chromium/gpu/command_buffer/common/value_state.h deleted file mode 100644 index ca7675fb08a..00000000000 --- a/chromium/gpu/command_buffer/common/value_state.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_COMMAND_BUFFER_COMMON_VALUE_STATE_H_ -#define GPU_COMMAND_BUFFER_COMMON_VALUE_STATE_H_ - -#include "base/containers/hash_tables.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "gpu/gpu_export.h" - -namespace gpu { - -// Used to maintain Valuebuffer state, exposed to browser to -// support passing ValueStates via IPC. -union GPU_EXPORT ValueState { - float float_value[4]; - int int_value[4]; -}; - -// Refcounted wrapper for a hash_map of subscription targets to ValueStates -class GPU_EXPORT ValueStateMap : public base::RefCounted<ValueStateMap> { - public: - ValueStateMap(); - - // Returns NULL if there is not ValueState for the target - const ValueState* GetState(unsigned int target) const; - - void UpdateState(unsigned int target, const ValueState& state); - - protected: - virtual ~ValueStateMap(); - - private: - friend class base::RefCounted<ValueStateMap>; - - typedef base::hash_map<unsigned int, ValueState> Map; - - Map state_map_; - - DISALLOW_COPY_AND_ASSIGN(ValueStateMap); -}; - -} // namespace gpu - -#endif // GPU_COMMAND_BUFFER_COMMON_VALUE_STATE_H_ diff --git a/chromium/gpu/command_buffer/common/value_state.mojom b/chromium/gpu/command_buffer/common/value_state.mojom deleted file mode 100644 index 53b0d56844f..00000000000 --- a/chromium/gpu/command_buffer/common/value_state.mojom +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2016 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. - -module gpu.mojom; - -[Native] -struct ValueState; diff --git a/chromium/gpu/command_buffer/service/BUILD.gn b/chromium/gpu/command_buffer/service/BUILD.gn index 3b833864131..6a904130d7c 100644 --- a/chromium/gpu/command_buffer/service/BUILD.gn +++ b/chromium/gpu/command_buffer/service/BUILD.gn @@ -81,6 +81,8 @@ source_set("service_sources") { "image_manager.h", "in_process_command_buffer.cc", "in_process_command_buffer.h", + "indexed_buffer_binding_host.cc", + "indexed_buffer_binding_host.h", "logger.cc", "logger.h", "mailbox_manager.cc", @@ -109,8 +111,6 @@ source_set("service_sources") { "shader_translator.h", "shader_translator_cache.cc", "shader_translator_cache.h", - "stream_texture_manager_in_process_android.cc", - "stream_texture_manager_in_process_android.h", "sync_point_manager.cc", "sync_point_manager.h", "texture_definition.cc", @@ -119,8 +119,8 @@ source_set("service_sources") { "texture_manager.h", "transfer_buffer_manager.cc", "transfer_buffer_manager.h", - "valuebuffer_manager.cc", - "valuebuffer_manager.h", + "transform_feedback_manager.cc", + "transform_feedback_manager.h", "vertex_array_manager.cc", "vertex_array_manager.h", "vertex_attrib_manager.cc", @@ -155,6 +155,7 @@ source_set("service_sources") { "//ui/gfx", "//ui/gfx/geometry", "//ui/gl", + "//ui/gl/init", ] if (is_mac) { diff --git a/chromium/gpu/command_buffer/service/buffer_manager.cc b/chromium/gpu/command_buffer/service/buffer_manager.cc index b3352192a37..1644f06ffba 100644 --- a/chromium/gpu/command_buffer/service/buffer_manager.cc +++ b/chromium/gpu/command_buffer/service/buffer_manager.cc @@ -10,7 +10,7 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/trace_event.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" @@ -18,8 +18,10 @@ #include "gpu/command_buffer/service/error_state.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/memory_tracking.h" +#include "gpu/command_buffer/service/transform_feedback_manager.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_version_info.h" #include "ui/gl/trace_util.h" namespace gpu { @@ -35,7 +37,7 @@ BufferManager::BufferManager(MemoryTracker* memory_tracker, allow_fixed_attribs_(false), buffer_count_(0), primitive_restart_fixed_index_(0), - have_context_(true), + lost_context_(false), use_client_side_arrays_for_stream_buffers_( feature_info ? feature_info->workarounds() @@ -57,8 +59,11 @@ BufferManager::~BufferManager() { this); } -void BufferManager::Destroy(bool have_context) { - have_context_ = have_context; +void BufferManager::MarkContextLost() { + lost_context_ = true; +} + +void BufferManager::Destroy() { buffers_.clear(); DCHECK_EQ(0u, memory_type_tracker_->GetMemRepresented()); } @@ -128,7 +133,7 @@ Buffer::Buffer(BufferManager* manager, GLuint service_id) Buffer::~Buffer() { if (manager_) { - if (manager_->have_context_) { + if (!manager_->lost_context_) { GLuint id = service_id(); glDeleteBuffersARB(1, &id); } @@ -409,6 +414,12 @@ void BufferManager::ValidateAndDoBufferData( } DoBufferData(error_state, buffer, target, size, usage, data); + + if (context_state->bound_transform_feedback.get()) { + // buffer size might have changed, and on Desktop GL lower than 4.2, + // we might need to reset transform feedback buffer range. + context_state->bound_transform_feedback->OnBufferData(target, buffer); + } } diff --git a/chromium/gpu/command_buffer/service/buffer_manager.h b/chromium/gpu/command_buffer/service/buffer_manager.h index 8ababfa8cd8..9615f80f652 100644 --- a/chromium/gpu/command_buffer/service/buffer_manager.h +++ b/chromium/gpu/command_buffer/service/buffer_manager.h @@ -9,13 +9,13 @@ #include <stdint.h> #include <map> +#include <memory> #include <vector> #include "base/containers/hash_tables.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/common/buffer.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/memory_tracking.h" @@ -205,7 +205,7 @@ class GPU_EXPORT Buffer : public base::RefCounted<Buffer> { GLenum usage_; // Data cached from last glMapBufferRange call. - scoped_ptr<MappedRange> mapped_range_; + std::unique_ptr<MappedRange> mapped_range_; // A map of ranges to the highest value in that range of a certain type. typedef std::map<Range, GLuint, Range::Less> RangeToMaxValueMap; @@ -222,8 +222,10 @@ class GPU_EXPORT BufferManager : public base::trace_event::MemoryDumpProvider { BufferManager(MemoryTracker* memory_tracker, FeatureInfo* feature_info); ~BufferManager() override; + void MarkContextLost(); + // Must call before destruction. - void Destroy(bool have_context); + void Destroy(); // Creates a Buffer for the given buffer. void CreateBuffer(GLuint client_id, GLuint service_id); @@ -293,6 +295,7 @@ class GPU_EXPORT BufferManager : public base::trace_event::MemoryDumpProvider { friend class Buffer; friend class TestHelper; // Needs access to DoBufferData. friend class BufferManagerTestBase; // Needs access to DoBufferSubData. + friend class IndexedBufferBindingHostTest; // Needs access to SetInfo. void StartTracking(Buffer* buffer); void StopTracking(Buffer* buffer); @@ -328,7 +331,7 @@ class GPU_EXPORT BufferManager : public base::trace_event::MemoryDumpProvider { GLenum usage, bool use_shadow); - scoped_ptr<MemoryTypeTracker> memory_type_tracker_; + std::unique_ptr<MemoryTypeTracker> memory_type_tracker_; MemoryTracker* memory_tracker_; scoped_refptr<FeatureInfo> feature_info_; @@ -348,7 +351,7 @@ class GPU_EXPORT BufferManager : public base::trace_event::MemoryDumpProvider { GLuint primitive_restart_fixed_index_; - bool have_context_; + bool lost_context_; bool use_client_side_arrays_for_stream_buffers_; DISALLOW_COPY_AND_ASSIGN(BufferManager); diff --git a/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc index 45e08c80fcc..327e679dc6e 100644 --- a/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc @@ -5,6 +5,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "gpu/command_buffer/service/buffer_manager.h" #include "gpu/command_buffer/service/error_state_mock.h" #include "gpu/command_buffer/service/feature_info.h" @@ -37,7 +39,8 @@ class BufferManagerTestBase : public GpuServiceTest { } void TearDown() override { - manager_->Destroy(false); + manager_->MarkContextLost(); + manager_->Destroy(); manager_.reset(); error_state_.reset(); GpuServiceTest::TearDown(); @@ -226,8 +229,8 @@ class BufferManagerTestBase : public GpuServiceTest { 40, 1, GL_UNSIGNED_INT, enable_primitive_restart, &max_value)); } - scoped_ptr<BufferManager> manager_; - scoped_ptr<MockErrorState> error_state_; + std::unique_ptr<BufferManager> manager_; + std::unique_ptr<MockErrorState> error_state_; }; class BufferManagerTest : public BufferManagerTestBase { @@ -248,9 +251,9 @@ class BufferManagerMemoryTrackerTest : public BufferManagerTestBase { class BufferManagerClientSideArraysTest : public BufferManagerTestBase { protected: void SetUp() override { - feature_info_ = new FeatureInfo(); - feature_info_->workarounds_.use_client_side_arrays_for_stream_buffers = - true; + GpuDriverBugWorkarounds gpu_driver_bug_workarounds; + gpu_driver_bug_workarounds.use_client_side_arrays_for_stream_buffers = true; + feature_info_ = new FeatureInfo(gpu_driver_bug_workarounds); SetUpBase(NULL, feature_info_.get(), ""); } @@ -338,7 +341,7 @@ TEST_F(BufferManagerTest, Destroy) { EXPECT_CALL(*gl_, DeleteBuffersARB(1, ::testing::Pointee(kService1Id))) .Times(1) .RetiresOnSaturation(); - manager_->Destroy(true); + manager_->Destroy(); // Check the resources were released. buffer1 = manager_->GetBuffer(kClient1Id); ASSERT_TRUE(buffer1 == NULL); @@ -363,7 +366,7 @@ TEST_F(BufferManagerTest, DoBufferSubData) { 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_t[]> temp(new uint8_t[size]); + std::unique_ptr<uint8_t[]> temp(new uint8_t[size]); EXPECT_FALSE(DoBufferSubData(buffer, kTarget, 0 - size, size, temp.get())); EXPECT_FALSE(DoBufferSubData(buffer, kTarget, 1, size / 2, temp.get())); } @@ -569,6 +572,21 @@ TEST_F(BufferManagerTest, BindBufferConflicts) { } } +TEST_F(BufferManagerTest, DeleteBufferAfterContextLost) { + const GLuint kClient1Id = 1; + const GLuint kService1Id = 11; + manager_->CreateBuffer(kClient1Id, kService1Id); + Buffer* buffer1 = manager_->GetBuffer(kClient1Id); + ASSERT_TRUE(buffer1 != nullptr); + manager_->MarkContextLost(); + // Removing buffers after MarkContextLost cause no GL calls. + manager_->RemoveBuffer(kClient1Id); + manager_->Destroy(); + // Check the resources were released. + buffer1 = manager_->GetBuffer(kClient1Id); + ASSERT_TRUE(buffer1 == nullptr); +} + } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/cmd_parser_test.cc b/chromium/gpu/command_buffer/service/cmd_parser_test.cc index 7df519d7143..b1ed3a27eb2 100644 --- a/chromium/gpu/command_buffer/service/cmd_parser_test.cc +++ b/chromium/gpu/command_buffer/service/cmd_parser_test.cc @@ -6,8 +6,9 @@ #include <stddef.h> +#include <memory> + #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/cmd_parser.h" #include "gpu/command_buffer/service/mocks.h" #include "testing/gtest/include/gtest/gtest.h" @@ -61,14 +62,14 @@ class CommandParserTest : public testing::Test { CommandBufferEntry *buffer() { return buffer_.get(); } private: unsigned int buffer_entry_count_; - scoped_ptr<AsyncAPIMock> api_mock_; - scoped_ptr<CommandBufferEntry[]> buffer_; + std::unique_ptr<AsyncAPIMock> api_mock_; + std::unique_ptr<CommandBufferEntry[]> buffer_; Sequence sequence_; }; // Tests initialization conditions. TEST_F(CommandParserTest, TestInit) { - scoped_ptr<CommandParser> parser(MakeParser(10)); + std::unique_ptr<CommandParser> parser(MakeParser(10)); EXPECT_EQ(0, parser->get()); EXPECT_EQ(0, parser->put()); EXPECT_TRUE(parser->IsEmpty()); @@ -76,7 +77,7 @@ TEST_F(CommandParserTest, TestInit) { // Tests simple commands. TEST_F(CommandParserTest, TestSimple) { - scoped_ptr<CommandParser> parser(MakeParser(10)); + std::unique_ptr<CommandParser> parser(MakeParser(10)); CommandBufferOffset put = parser->put(); CommandHeader header; @@ -109,7 +110,7 @@ TEST_F(CommandParserTest, TestSimple) { // Tests having multiple commands in the buffer. TEST_F(CommandParserTest, TestMultipleCommands) { - scoped_ptr<CommandParser> parser(MakeParser(10)); + std::unique_ptr<CommandParser> parser(MakeParser(10)); CommandBufferOffset put = parser->put(); CommandHeader header; @@ -161,7 +162,7 @@ TEST_F(CommandParserTest, TestMultipleCommands) { // Tests that the parser will wrap correctly at the end of the buffer. TEST_F(CommandParserTest, TestWrap) { - scoped_ptr<CommandParser> parser(MakeParser(5)); + std::unique_ptr<CommandParser> parser(MakeParser(5)); CommandBufferOffset put = parser->put(); CommandHeader header; @@ -213,7 +214,7 @@ TEST_F(CommandParserTest, TestWrap) { // Tests error conditions. TEST_F(CommandParserTest, TestError) { const unsigned int kNumEntries = 5; - scoped_ptr<CommandParser> parser(MakeParser(kNumEntries)); + std::unique_ptr<CommandParser> parser(MakeParser(kNumEntries)); CommandBufferOffset put = parser->put(); CommandHeader header; @@ -285,7 +286,7 @@ TEST_F(CommandParserTest, TestError) { } TEST_F(CommandParserTest, SetBuffer) { - scoped_ptr<CommandParser> parser(MakeParser(3)); + std::unique_ptr<CommandParser> parser(MakeParser(3)); CommandBufferOffset put = parser->put(); CommandHeader header; @@ -303,7 +304,7 @@ TEST_F(CommandParserTest, SetBuffer) { EXPECT_EQ(2, parser->get()); Mock::VerifyAndClearExpectations(api_mock()); - scoped_ptr<CommandBufferEntry[]> buffer2(new CommandBufferEntry[2]); + std::unique_ptr<CommandBufferEntry[]> buffer2(new CommandBufferEntry[2]); parser->SetBuffer( buffer2.get(), sizeof(CommandBufferEntry) * 2, 0, sizeof(CommandBufferEntry) * 2); diff --git a/chromium/gpu/command_buffer/service/command_buffer_service.cc b/chromium/gpu/command_buffer/service/command_buffer_service.cc index 368bc1c1a02..b4457d585b8 100644 --- a/chromium/gpu/command_buffer/service/command_buffer_service.cc +++ b/chromium/gpu/command_buffer/service/command_buffer_service.cc @@ -8,6 +8,7 @@ #include <stdint.h> #include <limits> +#include <memory> #include "base/logging.h" #include "base/trace_event/trace_event.h" @@ -36,10 +37,6 @@ CommandBufferService::CommandBufferService( CommandBufferService::~CommandBufferService() { } -bool CommandBufferService::Initialize() { - return true; -} - CommandBufferService::State CommandBufferService::GetLastState() { State state; state.get_offset = get_offset_; @@ -105,7 +102,7 @@ void CommandBufferService::SetGetBuffer(int32_t transfer_buffer_id) { } void CommandBufferService::SetSharedStateBuffer( - scoped_ptr<BufferBacking> shared_state_buffer) { + std::unique_ptr<BufferBacking> shared_state_buffer) { shared_state_buffer_ = std::move(shared_state_buffer); DCHECK(shared_state_buffer_->GetSize() >= sizeof(*shared_state_)); @@ -124,7 +121,7 @@ scoped_refptr<Buffer> CommandBufferService::CreateTransferBuffer(size_t size, int32_t* id) { *id = -1; - scoped_ptr<SharedMemory> shared_memory(new SharedMemory()); + std::unique_ptr<SharedMemory> shared_memory(new SharedMemory()); if (!shared_memory->CreateAndMapAnonymous(size)) { if (error_ == error::kNoError) error_ = gpu::error::kOutOfBounds; @@ -162,7 +159,7 @@ scoped_refptr<Buffer> CommandBufferService::GetTransferBuffer(int32_t id) { bool CommandBufferService::RegisterTransferBuffer( int32_t id, - scoped_ptr<BufferBacking> buffer) { + std::unique_ptr<BufferBacking> buffer) { return transfer_buffer_manager_->RegisterTransferBuffer(id, std::move(buffer)); } diff --git a/chromium/gpu/command_buffer/service/command_buffer_service.h b/chromium/gpu/command_buffer/service/command_buffer_service.h index 560bf163326..c3e4b17a411 100644 --- a/chromium/gpu/command_buffer/service/command_buffer_service.h +++ b/chromium/gpu/command_buffer/service/command_buffer_service.h @@ -8,6 +8,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/callback.h" #include "base/macros.h" #include "gpu/command_buffer/common/command_buffer.h" @@ -51,7 +53,6 @@ class GPU_EXPORT CommandBufferService : public CommandBufferServiceBase { ~CommandBufferService() override; // CommandBuffer implementation: - bool Initialize() override; State GetLastState() override; int32_t GetLastToken() override; void Flush(int32_t put_offset) override; @@ -85,19 +86,20 @@ class GPU_EXPORT CommandBufferService : public CommandBufferServiceBase { virtual void SetParseErrorCallback(const base::Closure& callback); // Setup the shared memory that shared state should be copied into. - void SetSharedStateBuffer(scoped_ptr<BufferBacking> shared_state_buffer); + void SetSharedStateBuffer(std::unique_ptr<BufferBacking> shared_state_buffer); // Copy the current state into the shared state transfer buffer. void UpdateState(); // Registers an existing shared memory object and get an ID that can be used // to identify it in the command buffer. - bool RegisterTransferBuffer(int32_t id, scoped_ptr<BufferBacking> buffer); + bool RegisterTransferBuffer(int32_t id, + std::unique_ptr<BufferBacking> buffer); private: int32_t ring_buffer_id_; scoped_refptr<Buffer> ring_buffer_; - scoped_ptr<BufferBacking> shared_state_buffer_; + std::unique_ptr<BufferBacking> shared_state_buffer_; CommandBufferSharedState* shared_state_; int32_t num_entries_; int32_t get_offset_; 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 5b39a969afe..f089f0230de 100644 --- a/chromium/gpu/command_buffer/service/command_buffer_service_unittest.cc +++ b/chromium/gpu/command_buffer/service/command_buffer_service_unittest.cc @@ -5,6 +5,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/threading/thread.h" @@ -33,7 +35,6 @@ class CommandBufferServiceTest : public testing::Test { } command_buffer_.reset( new CommandBufferService(transfer_buffer_manager_.get())); - EXPECT_TRUE(command_buffer_->Initialize()); } int32_t GetGetOffset() { return command_buffer_->GetLastState().get_offset; } @@ -53,7 +54,7 @@ class CommandBufferServiceTest : public testing::Test { } scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; - scoped_ptr<CommandBufferService> command_buffer_; + std::unique_ptr<CommandBufferService> command_buffer_; }; TEST_F(CommandBufferServiceTest, InitializesCommandBuffer) { @@ -84,7 +85,7 @@ class MockCallbackTest : public CallbackTest { TEST_F(CommandBufferServiceTest, CanSyncGetAndPutOffset) { Initialize(1024); - scoped_ptr<StrictMock<MockCallbackTest> > change_callback( + std::unique_ptr<StrictMock<MockCallbackTest>> change_callback( new StrictMock<MockCallbackTest>); command_buffer_->SetPutOffsetChangeCallback( base::Bind( @@ -117,7 +118,7 @@ TEST_F(CommandBufferServiceTest, SetGetBuffer) { command_buffer_->CreateTransferBuffer(1024, &ring_buffer_id); EXPECT_GT(ring_buffer_id, 0); - scoped_ptr<StrictMock<MockCallbackTest> > change_callback( + std::unique_ptr<StrictMock<MockCallbackTest>> change_callback( new StrictMock<MockCallbackTest>); command_buffer_->SetGetBufferChangeCallback( base::Bind( diff --git a/chromium/gpu/command_buffer/service/command_executor.cc b/chromium/gpu/command_buffer/service/command_executor.cc index f3a688afc14..f541a537f80 100644 --- a/chromium/gpu/command_buffer/service/command_executor.cc +++ b/chromium/gpu/command_buffer/service/command_executor.cc @@ -96,11 +96,7 @@ void CommandExecutor::PutChanged() { void CommandExecutor::SetScheduled(bool scheduled) { TRACE_EVENT2("gpu", "CommandExecutor:SetScheduled", "this", this, "scheduled", scheduled); - if (scheduled_ == scheduled) - return; scheduled_ = scheduled; - if (!scheduling_changed_callback_.is_null()) - scheduling_changed_callback_.Run(scheduled); } bool CommandExecutor::HasPendingQueries() const { @@ -113,11 +109,6 @@ void CommandExecutor::ProcessPendingQueries() { decoder_->ProcessPendingQueries(false); } -void CommandExecutor::SetSchedulingChangedCallback( - const SchedulingChangedCallback& callback) { - scheduling_changed_callback_ = callback; -} - scoped_refptr<Buffer> CommandExecutor::GetSharedMemoryBuffer(int32_t shm_id) { return command_buffer_->GetTransferBuffer(shm_id); } diff --git a/chromium/gpu/command_buffer/service/command_executor.h b/chromium/gpu/command_buffer/service/command_executor.h index 8af08151b6c..bd90d6f3b50 100644 --- a/chromium/gpu/command_buffer/service/command_executor.h +++ b/chromium/gpu/command_buffer/service/command_executor.h @@ -7,6 +7,7 @@ #include <stdint.h> +#include <memory> #include <queue> #include "base/atomic_ref_count.h" @@ -15,7 +16,6 @@ #include "base/macros.h" #include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory.h" #include "base/memory/weak_ptr.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" @@ -76,12 +76,6 @@ class GPU_EXPORT CommandExecutor // determine if there's more pending queries after this has been called. void ProcessPendingQueries(); - typedef base::Callback<void(bool /* scheduled */)> SchedulingChangedCallback; - - // Sets a callback that is invoked just before scheduler is rescheduled - // or descheduled. Takes ownership of callback object. - void SetSchedulingChangedCallback(const SchedulingChangedCallback& callback); - // Implementation of CommandBufferEngine. scoped_refptr<Buffer> GetSharedMemoryBuffer(int32_t shm_id) override; void set_token(int32_t token) override; @@ -120,13 +114,11 @@ class GPU_EXPORT CommandExecutor // TODO(apatrick): The CommandExecutor currently creates and owns the parser. // This should be an argument to the constructor. - scoped_ptr<CommandParser> parser_; + std::unique_ptr<CommandParser> parser_; // Whether the scheduler is currently able to process more commands. bool scheduled_; - SchedulingChangedCallback scheduling_changed_callback_; - base::Closure descheduled_callback_; base::Closure command_processed_callback_; // If non-NULL and |preemption_flag_->IsSet()|, exit PutChanged early. diff --git a/chromium/gpu/command_buffer/service/command_executor_unittest.cc b/chromium/gpu/command_buffer/service/command_executor_unittest.cc index 0002fd9275f..bcee267197a 100644 --- a/chromium/gpu/command_buffer/service/command_executor_unittest.cc +++ b/chromium/gpu/command_buffer/service/command_executor_unittest.cc @@ -7,6 +7,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "gpu/command_buffer/common/command_buffer_mock.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" @@ -31,7 +33,7 @@ class CommandExecutorTest : public testing::Test { static const int32_t kTransferBufferId = 123; void SetUp() override { - scoped_ptr<base::SharedMemory> shared_memory(new ::base::SharedMemory); + std::unique_ptr<base::SharedMemory> shared_memory(new ::base::SharedMemory); shared_memory->CreateAndMapAnonymous(kRingBufferSize); buffer_ = static_cast<int32_t*>(shared_memory->memory()); shared_memory_buffer_ = @@ -68,11 +70,11 @@ class CommandExecutorTest : public testing::Test { error::Error GetError() { return command_buffer_->GetLastState().error; } - scoped_ptr<MockCommandBuffer> command_buffer_; + std::unique_ptr<MockCommandBuffer> command_buffer_; scoped_refptr<Buffer> shared_memory_buffer_; int32_t* buffer_; - scoped_ptr<gles2::MockGLES2Decoder> decoder_; - scoped_ptr<CommandExecutor> executor_; + std::unique_ptr<gles2::MockGLES2Decoder> decoder_; + std::unique_ptr<CommandExecutor> executor_; base::MessageLoop message_loop_; }; diff --git a/chromium/gpu/command_buffer/service/common_decoder.h b/chromium/gpu/command_buffer/service/common_decoder.h index 147b7762c87..a8b5d75f933 100644 --- a/chromium/gpu/command_buffer/service/common_decoder.h +++ b/chromium/gpu/command_buffer/service/common_decoder.h @@ -9,11 +9,12 @@ #include <stdint.h> #include <map> +#include <memory> #include <stack> #include <string> + #include "base/macros.h" #include "base/memory/linked_ptr.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/common/buffer.h" #include "gpu/command_buffer/service/cmd_parser.h" #include "gpu/gpu_export.h" @@ -104,7 +105,7 @@ class GPU_EXPORT CommonDecoder : NON_EXPORTED_BASE(public AsyncAPIInterface) { } size_t size_; - ::scoped_ptr<int8_t[]> data_; + ::std::unique_ptr<int8_t[]> data_; DISALLOW_COPY_AND_ASSIGN(Bucket); }; diff --git a/chromium/gpu/command_buffer/service/common_decoder_unittest.cc b/chromium/gpu/command_buffer/service/common_decoder_unittest.cc index ac4ba1cf92c..c647e562748 100644 --- a/chromium/gpu/command_buffer/service/common_decoder_unittest.cc +++ b/chromium/gpu/command_buffer/service/common_decoder_unittest.cc @@ -5,6 +5,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/common_decoder.h" #include "testing/gtest/include/gtest/gtest.h" @@ -83,7 +85,7 @@ class MockCommandBufferEngine : public CommandBufferEngine { : CommandBufferEngine(), token_(), get_offset_(0) { - scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); + std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); shared_memory->CreateAndMapAnonymous(kBufferSize); buffer_ = MakeBufferFromSharedMemory(std::move(shared_memory), kBufferSize); } diff --git a/chromium/gpu/command_buffer/service/context_group.cc b/chromium/gpu/command_buffer/service/context_group.cc index 56f70303af6..3deebc700c1 100644 --- a/chromium/gpu/command_buffer/service/context_group.cc +++ b/chromium/gpu/command_buffer/service/context_group.cc @@ -11,7 +11,6 @@ #include <string> #include "base/command_line.h" -#include "gpu/command_buffer/common/value_state.h" #include "gpu/command_buffer/service/buffer_manager.h" #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/gpu_preferences.h" @@ -23,7 +22,6 @@ #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/transfer_buffer_manager.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_version_info.h" @@ -65,8 +63,6 @@ ContextGroup::ContextGroup( const scoped_refptr<FramebufferCompletenessCache>& framebuffer_completeness_cache, const scoped_refptr<FeatureInfo>& feature_info, - const scoped_refptr<SubscriptionRefSet>& subscription_ref_set, - const scoped_refptr<ValueStateMap>& pending_valuebuffer_state, bool bind_generates_resource) : gpu_preferences_(gpu_preferences), mailbox_manager_(mailbox_manager), @@ -83,8 +79,6 @@ ContextGroup::ContextGroup( #else framebuffer_completeness_cache_(framebuffer_completeness_cache), #endif - subscription_ref_set_(subscription_ref_set), - pending_valuebuffer_state_(pending_valuebuffer_state), enforce_gl_minimums_(gpu_preferences_.enforce_gl_minimums), bind_generates_resource_(bind_generates_resource), max_vertex_attribs_(0u), @@ -101,17 +95,15 @@ ContextGroup::ContextGroup( max_fragment_input_components_(0u), min_program_texel_offset_(0), max_program_texel_offset_(0), + max_transform_feedback_separate_attribs_(0u), + max_uniform_buffer_bindings_(0u), + uniform_buffer_offset_alignment_(1u), program_cache_(NULL), feature_info_(feature_info) { { + DCHECK(feature_info_); if (!mailbox_manager_.get()) mailbox_manager_ = new MailboxManagerImpl; - if (!subscription_ref_set_.get()) - subscription_ref_set_ = new SubscriptionRefSet(); - if (!pending_valuebuffer_state_.get()) - pending_valuebuffer_state_ = new ValueStateMap(); - if (!feature_info.get()) - feature_info_ = new FeatureInfo; transfer_buffer_manager_ = new TransferBufferManager(memory_tracker_.get()); } } @@ -121,8 +113,8 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, const DisallowedFeatures& disallowed_features) { if (HaveContexts()) { if (context_type != feature_info_->context_type()) { - LOG(ERROR) << "ContextGroup::Initialize failed because the type of " - << "the context does not fit with the group."; + DLOG(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. @@ -134,8 +126,8 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, AdjustDisallowedFeatures(context_type, disallowed_features); if (!feature_info_->Initialize(context_type, adjusted_disallowed_features)) { - LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo " - << "initialization failed."; + DLOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo " + << "initialization failed."; return false; } @@ -146,9 +138,9 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, if (!QueryGLFeature( GL_MAX_RENDERBUFFER_SIZE, kMinRenderbufferSize, &max_renderbuffer_size)) { - LOG(ERROR) << "ContextGroup::Initialize failed because maximum " - << "renderbuffer size too small (" << max_renderbuffer_size - << ", should be " << kMinRenderbufferSize << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because maximum " + << "renderbuffer size too small (" << max_renderbuffer_size + << ", should be " << kMinRenderbufferSize << ")."; return false; } GLint max_samples = 0; @@ -176,6 +168,34 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, DCHECK(max_dual_source_draw_buffers_ >= 1); } + if (feature_info_->gl_version_info().IsES3Capable()) { + const GLint kMinTransformFeedbackSeparateAttribs = 4; + if (!QueryGLFeatureU(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, + kMinTransformFeedbackSeparateAttribs, + &max_transform_feedback_separate_attribs_)) { + DLOG(ERROR) << "ContextGroup::Initialize failed because maximum " + << "transform feedback separate attribs is too small (" + << max_transform_feedback_separate_attribs_ << ", should be " + << kMinTransformFeedbackSeparateAttribs << ")."; + return false; + } + + const GLint kMinUniformBufferBindings = 24; + if (!QueryGLFeatureU(GL_MAX_UNIFORM_BUFFER_BINDINGS, + kMinUniformBufferBindings, + &max_uniform_buffer_bindings_)) { + DLOG(ERROR) << "ContextGroup::Initialize failed because maximum " + << "uniform buffer bindings is too small (" + << max_uniform_buffer_bindings_ << ", should be " + << kMinUniformBufferBindings << ")."; + return false; + } + + // TODO(zmo): Should we check max UNIFORM_BUFFER_OFFSET_ALIGNMENT is 256? + GetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, + &uniform_buffer_offset_alignment_); + } + buffer_manager_.reset( new BufferManager(memory_tracker_.get(), feature_info_.get())); framebuffer_manager_.reset(new FramebufferManager( @@ -186,18 +206,15 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, feature_info_.get())); shader_manager_.reset(new ShaderManager()); sampler_manager_.reset(new SamplerManager(feature_info_.get())); - valuebuffer_manager_.reset( - new ValuebufferManager(subscription_ref_set_.get(), - pending_valuebuffer_state_.get())); // Lookup GL things we need to know. const GLint kGLES2RequiredMinimumVertexAttribs = 8u; if (!QueryGLFeatureU( GL_MAX_VERTEX_ATTRIBS, kGLES2RequiredMinimumVertexAttribs, &max_vertex_attribs_)) { - LOG(ERROR) << "ContextGroup::Initialize failed because too few " - << "vertex attributes supported (" << max_vertex_attribs_ - << ", should be " << kGLES2RequiredMinimumVertexAttribs << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because too few " + << "vertex attributes supported (" << max_vertex_attribs_ + << ", should be " << kGLES2RequiredMinimumVertexAttribs << ")."; return false; } @@ -205,9 +222,9 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, if (!QueryGLFeatureU( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kGLES2RequiredMinimumTextureUnits, &max_texture_units_)) { - LOG(ERROR) << "ContextGroup::Initialize failed because too few " - << "texture units supported (" << max_texture_units_ - << ", should be " << kGLES2RequiredMinimumTextureUnits << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because too few " + << "texture units supported (" << max_texture_units_ + << ", should be " << kGLES2RequiredMinimumTextureUnits << ")."; return false; } @@ -215,42 +232,53 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, GLint max_cube_map_texture_size = 0; GLint max_rectangle_texture_size = 0; GLint max_3d_texture_size = 0; + GLint max_array_texture_layers = 0; const GLint kMinTextureSize = 2048; // GL actually says 64!?!? const GLint kMinCubeMapSize = 256; // GL actually says 16!?!? const GLint kMinRectangleTextureSize = 64; const GLint kMin3DTextureSize = 256; + const GLint kMinArrayTextureLayers = 256; if (!QueryGLFeature(GL_MAX_TEXTURE_SIZE, kMinTextureSize, &max_texture_size)) { - LOG(ERROR) << "ContextGroup::Initialize failed because maximum " - << "2d texture size is too small (" << max_texture_size - << ", should be " << kMinTextureSize << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because maximum " + << "2d texture size is too small (" << max_texture_size + << ", should be " << kMinTextureSize << ")."; return false; } if (!QueryGLFeature(GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMinCubeMapSize, &max_cube_map_texture_size)) { - LOG(ERROR) << "ContextGroup::Initialize failed because maximum " - << "cube texture size is too small (" - << max_cube_map_texture_size << ", should be " << kMinCubeMapSize - << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because maximum " + << "cube texture size is too small (" + << max_cube_map_texture_size << ", should be " + << kMinCubeMapSize << ")."; return false; } if (feature_info_->gl_version_info().IsES3Capable() && !QueryGLFeature(GL_MAX_3D_TEXTURE_SIZE, kMin3DTextureSize, &max_3d_texture_size)) { - LOG(ERROR) << "ContextGroup::Initialize failed because maximum " - << "3d texture size is too small (" << max_3d_texture_size - << ", should be " << kMin3DTextureSize << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because maximum " + << "3d texture size is too small (" << max_3d_texture_size + << ", should be " << kMin3DTextureSize << ")."; + return false; + } + if (feature_info_->gl_version_info().IsES3Capable() && + !QueryGLFeature(GL_MAX_ARRAY_TEXTURE_LAYERS, kMinArrayTextureLayers, + &max_array_texture_layers)) { + DLOG(ERROR) << "ContextGroup::Initialize failed because maximum " + << "array texture layers is too small (" + << max_array_texture_layers + << ", should be " << kMinArrayTextureLayers << ")."; return false; } if (feature_info_->feature_flags().arb_texture_rectangle && !QueryGLFeature(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, kMinRectangleTextureSize, &max_rectangle_texture_size)) { - LOG(ERROR) << "ContextGroup::Initialize failed because maximum " - << "rectangle texture size is too small (" - << max_rectangle_texture_size << ", should be " - << kMinRectangleTextureSize << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because maximum " + << "rectangle texture size is too small (" + << max_rectangle_texture_size << ", should be " + << kMinRectangleTextureSize << ")."; return false; } @@ -274,6 +302,7 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, max_cube_map_texture_size, max_rectangle_texture_size, max_3d_texture_size, + max_array_texture_layers, bind_generates_resource_)); texture_manager_->set_framebuffer_manager(framebuffer_manager_.get()); @@ -281,17 +310,18 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, const GLint kMinVertexTextureImageUnits = 0; if (!QueryGLFeatureU(GL_MAX_TEXTURE_IMAGE_UNITS, kMinTextureImageUnits, &max_texture_image_units_)) { - LOG(ERROR) << "ContextGroup::Initialize failed because too few " - << "texture image units supported (" << max_texture_image_units_ - << ", should be " << kMinTextureImageUnits << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because too few " + << "texture image units supported (" + << max_texture_image_units_ + << ", should be " << kMinTextureImageUnits << ")."; } if (!QueryGLFeatureU(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMinVertexTextureImageUnits, &max_vertex_texture_image_units_)) { - LOG(ERROR) << "ContextGroup::Initialize failed because too few " - << "vertex texture image units supported (" - << max_vertex_texture_image_units_ << ", should be " - << kMinTextureImageUnits << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because too few " + << "vertex texture image units supported (" + << max_vertex_texture_image_units_ << ", should be " + << kMinTextureImageUnits << ")."; return false; } @@ -318,8 +348,8 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, !CheckGLFeatureU(kMinVaryingVectors, &max_varying_vectors_) || !CheckGLFeatureU( kMinVertexUniformVectors, &max_vertex_uniform_vectors_)) { - LOG(ERROR) << "ContextGroup::Initialize failed because too few " - << "uniforms or varyings supported."; + DLOG(ERROR) << "ContextGroup::Initialize failed because too few " + << "uniforms or varyings supported."; return false; } @@ -354,27 +384,27 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, if (!QueryGLFeatureU(GL_MAX_VERTEX_OUTPUT_COMPONENTS, kMinVertexOutputComponents, &max_vertex_output_components_)) { - LOG(ERROR) << "ContextGroup::Initialize failed because maximum " - << "vertex output components is too small (" - << max_vertex_output_components_ << ", should be " - << kMinVertexOutputComponents << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because maximum " + << "vertex output components is too small (" + << max_vertex_output_components_ << ", should be " + << kMinVertexOutputComponents << ")."; return false; } if (!QueryGLFeatureU(GL_MAX_FRAGMENT_INPUT_COMPONENTS, kMinFragmentInputComponents, &max_fragment_input_components_)) { - LOG(ERROR) << "ContextGroup::Initialize failed because maximum " - << "fragment input components is too small (" - << max_fragment_input_components_ << ", should be " - << kMinFragmentInputComponents << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because maximum " + << "fragment input components is too small (" + << max_fragment_input_components_ << ", should be " + << kMinFragmentInputComponents << ")."; return false; } if (!QueryGLFeature(GL_MAX_PROGRAM_TEXEL_OFFSET, kMin_MaxProgramTexelOffset, &max_program_texel_offset_)) { - LOG(ERROR) << "ContextGroup::Initialize failed because maximum " - << "program texel offset is too small (" - << max_program_texel_offset_ << ", should be " - << kMin_MaxProgramTexelOffset << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because maximum " + << "program texel offset is too small (" + << max_program_texel_offset_ << ", should be " + << kMin_MaxProgramTexelOffset << ")."; return false; } glGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &min_program_texel_offset_); @@ -383,19 +413,19 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, std::max(min_program_texel_offset_, kMax_MinProgramTexelOffset); } if (min_program_texel_offset_ > kMax_MinProgramTexelOffset) { - LOG(ERROR) << "ContextGroup::Initialize failed because minimum " - << "program texel offset is too big (" - << min_program_texel_offset_ << ", should be " - << kMax_MinProgramTexelOffset << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because minimum " + << "program texel offset is too big (" + << min_program_texel_offset_ << ", should be " + << kMax_MinProgramTexelOffset << ")."; return false; } const GLint kES3MinCubeMapSize = 2048; if (max_cube_map_texture_size < kES3MinCubeMapSize) { - LOG(ERROR) << "ContextGroup::Initialize failed because maximum " - << "cube texture size is too small (" - << max_cube_map_texture_size << ", should be " - << kES3MinCubeMapSize << ")."; + DLOG(ERROR) << "ContextGroup::Initialize failed because maximum " + << "cube texture size is too small (" + << max_cube_map_texture_size << ", should be " + << kES3MinCubeMapSize << ")."; return false; } } @@ -408,8 +438,8 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, feature_info_.get())); if (!texture_manager_->Initialize()) { - LOG(ERROR) << "Context::Group::Initialize failed because texture manager " - << "failed to initialize."; + DLOG(ERROR) << "Context::Group::Initialize failed because texture manager " + << "failed to initialize."; return false; } @@ -453,8 +483,11 @@ void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) { return; } - if (buffer_manager_ != NULL) { - buffer_manager_->Destroy(have_context); + if (buffer_manager_ != nullptr) { + if (!have_context) { + buffer_manager_->MarkContextLost(); + } + buffer_manager_->Destroy(); buffer_manager_.reset(); } @@ -495,11 +528,6 @@ void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) { sampler_manager_.reset(); } - if (valuebuffer_manager_ != NULL) { - valuebuffer_manager_->Destroy(); - valuebuffer_manager_.reset(); - } - memory_tracker_ = NULL; } @@ -520,6 +548,9 @@ void ContextGroup::LoseContexts(error::ContextLostReason reason) { decoders_[ii]->MarkContextLost(reason); } } + if (buffer_manager_ != nullptr) { + buffer_manager_->MarkContextLost(); + } } ContextGroup::~ContextGroup() { diff --git a/chromium/gpu/command_buffer/service/context_group.h b/chromium/gpu/command_buffer/service/context_group.h index b4d861a8f6e..00d74aad007 100644 --- a/chromium/gpu/command_buffer/service/context_group.h +++ b/chromium/gpu/command_buffer/service/context_group.h @@ -7,11 +7,12 @@ #include <stdint.h> +#include <memory> #include <vector> + #include "base/containers/hash_tables.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "gpu/command_buffer/common/constants.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" @@ -26,7 +27,6 @@ namespace gpu { struct GpuPreferences; class TransferBufferManager; -class ValueStateMap; namespace gles2 { @@ -41,8 +41,6 @@ class ProgramManager; class SamplerManager; class ShaderManager; class TextureManager; -class SubscriptionRefSet; -class ValuebufferManager; class MemoryTracker; struct DisallowedFeatures; @@ -58,8 +56,6 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { const scoped_refptr<FramebufferCompletenessCache>& framebuffer_completeness_cache, const scoped_refptr<FeatureInfo>& feature_info, - const scoped_refptr<SubscriptionRefSet>& subscription_ref_set, - const scoped_refptr<ValueStateMap>& pending_valuebuffer_state, bool bind_generates_resource); // This should only be called by GLES2Decoder. This must be paired with a @@ -133,6 +129,18 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { int32_t max_program_texel_offset() const { return max_program_texel_offset_; } + uint32_t max_transform_feedback_separate_attribs() const { + return max_transform_feedback_separate_attribs_; + } + + uint32_t max_uniform_buffer_bindings() const { + return max_uniform_buffer_bindings_; + } + + uint32_t uniform_buffer_offset_alignment() const { + return uniform_buffer_offset_alignment_; + } + FeatureInfo* feature_info() { return feature_info_.get(); } @@ -153,14 +161,6 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { return renderbuffer_manager_.get(); } - ValuebufferManager* valuebuffer_manager() const { - return valuebuffer_manager_.get(); - } - - ValueStateMap* pending_valuebuffer_state() const { - return pending_valuebuffer_state_.get(); - } - TextureManager* texture_manager() const { return texture_manager_.get(); } @@ -198,31 +198,6 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { bool GetBufferServiceId(GLuint client_id, GLuint* service_id) const; - void AddTransformFeedbackId(GLuint client_id, GLuint service_id) { - transformfeedbacks_id_map_[client_id] = service_id; - } - - 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()) - return false; - if (service_id) - *service_id = iter->second; - return true; - } - - void RemoveTransformFeedbackId(GLuint client_id) { - transformfeedbacks_id_map_.erase(client_id); - } - void AddSyncId(GLuint client_id, GLsync service_id) { syncs_id_map_[client_id] = service_id; } @@ -257,8 +232,6 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { scoped_refptr<ShaderTranslatorCache> shader_translator_cache_; scoped_refptr<FramebufferCompletenessCache> framebuffer_completeness_cache_; scoped_refptr<TransferBufferManager> transfer_buffer_manager_; - scoped_refptr<SubscriptionRefSet> subscription_ref_set_; - scoped_refptr<ValueStateMap> pending_valuebuffer_state_; bool enforce_gl_minimums_; bool bind_generates_resource_; @@ -279,32 +252,33 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { int32_t min_program_texel_offset_; int32_t max_program_texel_offset_; - ProgramCache* program_cache_; + uint32_t max_transform_feedback_separate_attribs_; + uint32_t max_uniform_buffer_bindings_; + uint32_t uniform_buffer_offset_alignment_; - scoped_ptr<BufferManager> buffer_manager_; + ProgramCache* program_cache_; - scoped_ptr<FramebufferManager> framebuffer_manager_; + std::unique_ptr<BufferManager> buffer_manager_; - scoped_ptr<RenderbufferManager> renderbuffer_manager_; + std::unique_ptr<FramebufferManager> framebuffer_manager_; - scoped_ptr<TextureManager> texture_manager_; + std::unique_ptr<RenderbufferManager> renderbuffer_manager_; - scoped_ptr<PathManager> path_manager_; + std::unique_ptr<TextureManager> texture_manager_; - scoped_ptr<ProgramManager> program_manager_; + std::unique_ptr<PathManager> path_manager_; - scoped_ptr<ShaderManager> shader_manager_; + std::unique_ptr<ProgramManager> program_manager_; - scoped_ptr<SamplerManager> sampler_manager_; + std::unique_ptr<ShaderManager> shader_manager_; - scoped_ptr<ValuebufferManager> valuebuffer_manager_; + std::unique_ptr<SamplerManager> sampler_manager_; scoped_refptr<FeatureInfo> feature_info_; std::vector<base::WeakPtr<gles2::GLES2Decoder> > decoders_; // Mappings from client side IDs to service side IDs. - base::hash_map<GLuint, GLuint> transformfeedbacks_id_map_; base::hash_map<GLuint, GLsync> syncs_id_map_; DISALLOW_COPY_AND_ASSIGN(ContextGroup); diff --git a/chromium/gpu/command_buffer/service/context_group_unittest.cc b/chromium/gpu/command_buffer/service/context_group_unittest.cc index f343e5e2e58..96dc351e935 100644 --- a/chromium/gpu/command_buffer/service/context_group_unittest.cc +++ b/chromium/gpu/command_buffer/service/context_group_unittest.cc @@ -6,14 +6,13 @@ #include <stdint.h> -#include "base/memory/scoped_ptr.h" -#include "gpu/command_buffer/common/value_state.h" +#include <memory> + #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/test_helper.h" #include "gpu/command_buffer/service/texture_manager.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_mock.h" @@ -42,13 +41,14 @@ class ContextGroupTest : public GpuServiceTest { void SetUp() override { GpuServiceTest::SetUp(); decoder_.reset(new MockGLES2Decoder()); - group_ = scoped_refptr<ContextGroup>(new ContextGroup( - gpu_preferences_, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - kBindGeneratesResource)); + scoped_refptr<FeatureInfo> feature_info = new FeatureInfo; + group_ = scoped_refptr<ContextGroup>( + new ContextGroup(gpu_preferences_, NULL, NULL, NULL, NULL, feature_info, + kBindGeneratesResource)); } GpuPreferences gpu_preferences_; - scoped_ptr<MockGLES2Decoder> decoder_; + std::unique_ptr<MockGLES2Decoder> decoder_; scoped_refptr<ContextGroup> group_; }; @@ -105,7 +105,7 @@ TEST_F(ContextGroupTest, InitializeNoExtensions) { } TEST_F(ContextGroupTest, MultipleContexts) { - scoped_ptr<MockGLES2Decoder> decoder2_(new MockGLES2Decoder()); + std::unique_ptr<MockGLES2Decoder> decoder2_(new MockGLES2Decoder()); TestHelper::SetupContextGroupInitExpectations( gl_.get(), DisallowedFeatures(), "", "", kBindGeneratesResource); EXPECT_TRUE(group_->Initialize(decoder_.get(), CONTEXT_TYPE_OPENGLES2, diff --git a/chromium/gpu/command_buffer/service/context_state.cc b/chromium/gpu/command_buffer/service/context_state.cc index f91e8ccb9b1..ebbbe268d24 100644 --- a/chromium/gpu/command_buffer/service/context_state.cc +++ b/chromium/gpu/command_buffer/service/context_state.cc @@ -14,6 +14,7 @@ #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/renderbuffer_manager.h" +#include "gpu/command_buffer/service/transform_feedback_manager.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_version_info.h" @@ -68,7 +69,8 @@ bool TargetIsSupported(const FeatureInfo* feature_info, GLuint target) { case GL_TEXTURE_RECTANGLE_ARB: return feature_info->feature_flags().arb_texture_rectangle; case GL_TEXTURE_EXTERNAL_OES: - return feature_info->feature_flags().oes_egl_image_external; + return feature_info->feature_flags().oes_egl_image_external || + feature_info->feature_flags().nv_egl_stream_consumer_external; default: NOTREACHED(); return false; @@ -226,7 +228,9 @@ void ContextState::RestoreTextureUnitBindings( bool bind_texture_2d = true; bool bind_texture_cube = true; - bool bind_texture_oes = feature_info_->feature_flags().oes_egl_image_external; + bool bind_texture_oes = + feature_info_->feature_flags().oes_egl_image_external || + feature_info_->feature_flags().nv_egl_stream_consumer_external; bool bind_texture_arb = feature_info_->feature_flags().arb_texture_rectangle; if (prev_state) { @@ -289,8 +293,34 @@ void ContextState::RestoreRenderbufferBindings() { bound_renderbuffer_valid = false; } -void ContextState::RestoreProgramBindings() const { +void ContextState::RestoreProgramSettings( + const ContextState* prev_state, + bool restore_transform_feedback_bindings) const { + bool flag = (restore_transform_feedback_bindings && + feature_info_->IsES3Capable()); + if (flag && prev_state) { + if (prev_state->bound_transform_feedback.get() && + prev_state->bound_transform_feedback->active() && + !prev_state->bound_transform_feedback->paused()) { + glPauseTransformFeedback(); + } + } glUseProgram(current_program.get() ? current_program->service_id() : 0); + if (flag) { + if (bound_transform_feedback.get()) { + bound_transform_feedback->DoBindTransformFeedback(GL_TRANSFORM_FEEDBACK); + } else { + glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); + } + } +} + +void ContextState::RestoreIndexedUniformBufferBindings( + const ContextState* prev_state) { + if (!feature_info_->IsES3Capable()) + return; + indexed_uniform_buffer_bindings->RestoreBindings( + prev_state ? prev_state->indexed_uniform_buffer_bindings.get() : nullptr); } void ContextState::RestoreActiveTexture() const { @@ -425,7 +455,8 @@ void ContextState::RestoreState(const ContextState* prev_state) { RestoreVertexAttribs(); RestoreBufferBindings(); RestoreRenderbufferBindings(); - RestoreProgramBindings(); + RestoreProgramSettings(prev_state, true); + RestoreIndexedUniformBufferBindings(prev_state); RestoreGlobalState(prev_state); } diff --git a/chromium/gpu/command_buffer/service/context_state.h b/chromium/gpu/command_buffer/service/context_state.h index 7f3211cc8c7..f20186ba851 100644 --- a/chromium/gpu/command_buffer/service/context_state.h +++ b/chromium/gpu/command_buffer/service/context_state.h @@ -7,15 +7,15 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_H_ #define GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_H_ +#include <memory> #include <vector> + #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/sampler_manager.h" #include "gpu/command_buffer/service/texture_manager.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" -#include "gpu/command_buffer/service/vertex_attrib_manager.h" #include "gpu/command_buffer/service/vertex_array_manager.h" +#include "gpu/command_buffer/service/vertex_attrib_manager.h" #include "gpu/gpu_export.h" namespace gpu { @@ -26,9 +26,11 @@ class ErrorState; class ErrorStateClient; class FeatureInfo; class Framebuffer; +class IndexedBufferBindingHost; class Logger; class Program; class Renderbuffer; +class TransformFeedback; // State associated with each texture unit. struct GPU_EXPORT TextureUnit { @@ -186,8 +188,10 @@ struct GPU_EXPORT ContextState { void RestoreVertexAttribs() const; void RestoreBufferBindings() const; void RestoreGlobalState(const ContextState* prev_state) const; - void RestoreProgramBindings() const; + void RestoreProgramSettings(const ContextState* prev_state, + bool restore_transform_feedback_bindings) const; void RestoreRenderbufferBindings(); + void RestoreIndexedUniformBufferBindings(const ContextState* prev_state); void RestoreTextureUnitBindings( GLuint unit, const ContextState* prev_state) const; @@ -273,6 +277,16 @@ struct GPU_EXPORT ContextState { // Which samplers are bound to each texture unit; std::vector<scoped_refptr<Sampler>> sampler_units; + // We create a transform feedback as the default one per ES3 enabled context + // instead of using GL's default one to make context switching easier. + // For other context, we will never change the default transform feedback's + // states, so we can just use the GL's default one. + scoped_refptr<TransformFeedback> default_transform_feedback; + + scoped_refptr<TransformFeedback> bound_transform_feedback; + + scoped_refptr<IndexedBufferBindingHost> indexed_uniform_buffer_bindings; + // The values for each attrib. std::vector<Vec4> attrib_values; @@ -287,9 +301,6 @@ struct GPU_EXPORT ContextState { scoped_refptr<Renderbuffer> bound_renderbuffer; bool bound_renderbuffer_valid; - // The currently bound valuebuffer - scoped_refptr<Valuebuffer> bound_valuebuffer; - bool pack_reverse_row_order; bool ignore_cached_state; @@ -308,7 +319,7 @@ struct GPU_EXPORT ContextState { void InitStateManual(const ContextState* prev_state) const; FeatureInfo* feature_info_; - scoped_ptr<ErrorState> error_state_; + std::unique_ptr<ErrorState> error_state_; }; } // namespace gles2 diff --git a/chromium/gpu/command_buffer/service/feature_info.cc b/chromium/gpu/command_buffer/service/feature_info.cc index 58aa147c2a3..31b6c503187 100644 --- a/chromium/gpu/command_buffer/service/feature_info.cc +++ b/chromium/gpu/command_buffer/service/feature_info.cc @@ -80,50 +80,6 @@ class StringSet { std::set<std::string> string_set_; }; -// Process a string of wordaround type IDs (seperated by ',') and set up -// the corresponding Workaround flags. -void StringToWorkarounds( - const std::string& types, FeatureInfo::Workarounds* workarounds) { - DCHECK(workarounds); - for (const base::StringPiece& piece : - base::SplitStringPiece( - types, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { - int number = 0; - bool succeed = base::StringToInt(piece, &number); - DCHECK(succeed); - switch (number) { -#define GPU_OP(type, name) \ - case gpu::type: \ - workarounds->name = true; \ - break; - GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) -#undef GPU_OP - default: - NOTIMPLEMENTED(); - } - } - if (workarounds->max_texture_size_limit_4096) - workarounds->max_texture_size = 4096; - if (workarounds->max_cube_map_texture_size_limit_4096) - workarounds->max_cube_map_texture_size = 4096; - if (workarounds->max_cube_map_texture_size_limit_1024) - workarounds->max_cube_map_texture_size = 1024; - if (workarounds->max_cube_map_texture_size_limit_512) - workarounds->max_cube_map_texture_size = 512; - - if (workarounds->max_fragment_uniform_vectors_32) - workarounds->max_fragment_uniform_vectors = 32; - if (workarounds->max_varying_vectors_16) - 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_1048576) - workarounds->max_copy_texture_chromium_size = 1048576; - if (workarounds->max_copy_texture_chromium_size_262144) - workarounds->max_copy_texture_chromium_size = 262144; -} - } // anonymous namespace. FeatureInfo::FeatureFlags::FeatureFlags() @@ -135,6 +91,7 @@ FeatureInfo::FeatureFlags::FeatureFlags() chromium_screen_space_antialiasing(false), oes_standard_derivatives(false), oes_egl_image_external(false), + nv_egl_stream_consumer_external(false), oes_depth24(false), oes_compressed_etc1_rgb8_texture(false), packed_depth24_stencil8(false), @@ -174,32 +131,30 @@ FeatureInfo::FeatureFlags::FeatureFlags() ext_texture_rg(false), chromium_image_ycbcr_420v(false), chromium_image_ycbcr_422(false), - enable_subscribe_uniform(false), emulate_primitive_restart_fixed_index(false), ext_render_buffer_format_bgra8888(false), ext_multisample_compatibility(false), ext_blend_func_extended(false), ext_read_format_bgra(false) {} -FeatureInfo::Workarounds::Workarounds() : -#define GPU_OP(type, name) name(false), - GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) -#undef GPU_OP - max_texture_size(0), - max_cube_map_texture_size(0), - max_fragment_uniform_vectors(0), - max_varying_vectors(0), - max_vertex_uniform_vectors(0), - max_copy_texture_chromium_size(0) { +FeatureInfo::FeatureInfo() { + InitializeBasicState(base::CommandLine::InitializedForCurrentProcess() + ? base::CommandLine::ForCurrentProcess() + : nullptr); } -FeatureInfo::FeatureInfo() { +FeatureInfo::FeatureInfo( + const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds) + : workarounds_(gpu_driver_bug_workarounds) { InitializeBasicState(base::CommandLine::InitializedForCurrentProcess() ? base::CommandLine::ForCurrentProcess() : nullptr); } -FeatureInfo::FeatureInfo(const base::CommandLine& command_line) { +FeatureInfo::FeatureInfo( + const base::CommandLine& command_line, + const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds) + : workarounds_(gpu_driver_bug_workarounds) { InitializeBasicState(&command_line); } @@ -207,20 +162,12 @@ void FeatureInfo::InitializeBasicState(const base::CommandLine* command_line) { if (!command_line) return; - if (command_line->HasSwitch(switches::kGpuDriverBugWorkarounds)) { - std::string types = command_line->GetSwitchValueASCII( - switches::kGpuDriverBugWorkarounds); - StringToWorkarounds(types, &workarounds_); - } feature_flags_.enable_shader_name_hashing = !command_line->HasSwitch(switches::kDisableShaderNameHashing); feature_flags_.is_swiftshader = (command_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader"); - feature_flags_.enable_subscribe_uniform = - command_line->HasSwitch(switches::kEnableSubscribeUniformExtension); - enable_unsafe_es3_apis_switch_ = command_line->HasSwitch(switches::kEnableUnsafeES3APIs); @@ -393,10 +340,6 @@ void FeatureInfo::InitializeFeatures() { // but there is no need to add them to pixel_store validtor. AddExtensionString("GL_EXT_unpack_subimage"); - if (feature_flags_.enable_subscribe_uniform) { - AddExtensionString("GL_CHROMIUM_subscribe_uniform"); - } - // OES_vertex_array_object is emulated if not present natively, // so the extension string is always exposed. AddExtensionString("GL_OES_vertex_array_object"); @@ -600,9 +543,12 @@ void FeatureInfo::InitializeFeatures() { // sized formats GL_SRGB8 and GL_SRGB8_ALPHA8. Also, SRGB_EXT isn't a valid // <format> in this case. So, even with GLES3 explicitly check for // GL_EXT_sRGB. - if (((gl_version_info_->is_es3 || extensions.Contains("GL_OES_rgb8_rgba8")) && - extensions.Contains("GL_EXT_sRGB")) || - gfx::HasDesktopGLFeatures()) { + if ((((gl_version_info_->is_es3 || + extensions.Contains("GL_OES_rgb8_rgba8")) && + extensions.Contains("GL_EXT_sRGB")) || + gfx::HasDesktopGLFeatures()) && + (context_type_ == CONTEXT_TYPE_WEBGL1 || + context_type_ == CONTEXT_TYPE_OPENGLES2)) { AddExtensionString("GL_EXT_sRGB"); validators_.texture_internal_format.AddValue(GL_SRGB_EXT); validators_.texture_internal_format.AddValue(GL_SRGB_ALPHA_EXT); @@ -611,6 +557,7 @@ void FeatureInfo::InitializeFeatures() { validators_.render_buffer_format.AddValue(GL_SRGB8_ALPHA8_EXT); validators_.frame_buffer_parameter.AddValue( GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT); + validators_.texture_unsized_internal_format.AddValue(GL_SRGB_EXT); validators_.texture_unsized_internal_format.AddValue(GL_SRGB_ALPHA_EXT); } @@ -620,21 +567,26 @@ void FeatureInfo::InitializeFeatures() { bool enable_immutable_texture_format_bgra_on_es3 = extensions.Contains("GL_APPLE_texture_format_BGRA8888"); - // Check if we should allow GL_EXT_texture_format_BGRA8888 + // Check if we should allow GL_EXT_texture_format_BGRA8888. if (extensions.Contains("GL_EXT_texture_format_BGRA8888") || enable_immutable_texture_format_bgra_on_es3 || !gl_version_info_->is_es) { enable_texture_format_bgra8888 = true; } - // Only desktop GL extension GL_EXT_bgra or ANGLE guarantee that we can - // allocate a renderbuffer with this format. - if (extensions.Contains("GL_EXT_bgra") || gl_version_info_->is_angle) { + // On desktop, all devices support BGRA render buffers (note that on desktop + // BGRA internal formats are converted to RGBA in the API implementation). + // For ES, there is no extension that exposes BGRA renderbuffers, however + // Angle does support these. + if (gl_version_info_->is_angle || !gl_version_info_->is_es) { enable_render_buffer_bgra = true; } + // On desktop, all devices support BGRA readback since OpenGL 2.0, which we + // require. On ES, support is indicated by the GL_EXT_read_format_bgra + // extension. if (extensions.Contains("GL_EXT_read_format_bgra") || - extensions.Contains("GL_EXT_bgra")) { + !gl_version_info_->is_es) { enable_read_format_bgra = true; } @@ -924,6 +876,14 @@ void FeatureInfo::InitializeFeatures() { if (extensions.Contains("GL_OES_EGL_image_external")) { AddExtensionString("GL_OES_EGL_image_external"); feature_flags_.oes_egl_image_external = true; + } + if (extensions.Contains("GL_NV_EGL_stream_consumer_external")) { + AddExtensionString("GL_NV_EGL_stream_consumer_external"); + feature_flags_.nv_egl_stream_consumer_external = true; + } + + if (feature_flags_.oes_egl_image_external || + feature_flags_.nv_egl_stream_consumer_external) { validators_.texture_bind_target.AddValue(GL_TEXTURE_EXTERNAL_OES); validators_.get_tex_param_target.AddValue(GL_TEXTURE_EXTERNAL_OES); validators_.texture_parameter.AddValue(GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES); @@ -996,12 +956,8 @@ void FeatureInfo::InitializeFeatures() { #if defined(OS_MACOSX) if (gfx::GetGLImplementation() != gfx::kGLImplementationOSMesaGL) { AddExtensionString("GL_CHROMIUM_iosurface"); - // TODO(dcastagna): Make this format work with GL Core Profile. - // crbug.com/587158 - if (!gl_version_info_->is_desktop_core_profile) { - AddExtensionString("GL_CHROMIUM_ycbcr_420v_image"); - feature_flags_.chromium_image_ycbcr_420v = true; - } + AddExtensionString("GL_CHROMIUM_ycbcr_420v_image"); + feature_flags_.chromium_image_ycbcr_420v = true; } #endif @@ -1034,7 +990,7 @@ void FeatureInfo::InitializeFeatures() { (extensions.Contains("GL_EXT_texture_storage") || extensions.Contains("GL_ARB_texture_storage") || support_texture_storage_on_es3 || - gl_version_info_->is_desktop_core_profile)) { + gl_version_info_->IsAtLeastGL(4, 2))) { feature_flags_.ext_texture_storage = true; AddExtensionString("GL_EXT_texture_storage"); validators_.texture_parameter.AddValue(GL_TEXTURE_IMMUTABLE_FORMAT_EXT); @@ -1365,6 +1321,9 @@ void FeatureInfo::EnableES3Validators() { validators_.attachment.RemoveValues( kColorAttachments + max_color_attachments, kTotalColorAttachmentEnums - max_color_attachments); + validators_.read_buffer.RemoveValues( + kColorAttachments + max_color_attachments, + kTotalColorAttachmentEnums - max_color_attachments); } GLint max_draw_buffers = 0; diff --git a/chromium/gpu/command_buffer/service/feature_info.h b/chromium/gpu/command_buffer/service/feature_info.h index e343dd9f593..b98afab00bc 100644 --- a/chromium/gpu/command_buffer/service/feature_info.h +++ b/chromium/gpu/command_buffer/service/feature_info.h @@ -5,13 +5,14 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_FEATURE_INFO_H_ #define GPU_COMMAND_BUFFER_SERVICE_FEATURE_INFO_H_ +#include <memory> #include <string> + #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gles2_cmd_validation.h" -#include "gpu/config/gpu_driver_bug_workaround_type.h" +#include "gpu/config/gpu_driver_bug_workarounds.h" #include "gpu/gpu_export.h" namespace base { @@ -43,6 +44,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool chromium_screen_space_antialiasing; bool oes_standard_derivatives; bool oes_egl_image_external; + bool nv_egl_stream_consumer_external; bool oes_depth24; bool oes_compressed_etc1_rgb8_texture; bool packed_depth24_stencil8; @@ -82,7 +84,6 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool ext_texture_rg; bool chromium_image_ycbcr_420v; bool chromium_image_ycbcr_422; - bool enable_subscribe_uniform; bool emulate_primitive_restart_fixed_index; bool ext_render_buffer_format_bgra8888; bool ext_multisample_compatibility; @@ -90,27 +91,15 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool ext_read_format_bgra; }; - struct Workarounds { - Workarounds(); - -#define GPU_OP(type, name) bool name; - GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) -#undef GPU_OP - - // Note: 0 here means use driver limit. - GLint max_texture_size; - GLint max_cube_map_texture_size; - GLint max_fragment_uniform_vectors; - GLint max_varying_vectors; - GLint max_vertex_uniform_vectors; - GLint max_copy_texture_chromium_size; - }; + FeatureInfo(); // Constructor with workarounds taken from the current process's CommandLine - FeatureInfo(); + explicit FeatureInfo( + const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds); // Constructor with workarounds taken from |command_line| - FeatureInfo(const base::CommandLine& command_line); + FeatureInfo(const base::CommandLine& command_line, + const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds); // Initializes the feature information. Needs a current GL context. bool Initialize(ContextType context_type, @@ -135,9 +124,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { return feature_flags_; } - const Workarounds& workarounds() const { - return workarounds_; - } + const GpuDriverBugWorkarounds& workarounds() const { return workarounds_; } const DisallowedFeatures& disallowed_features() const { return disallowed_features_; @@ -188,7 +175,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { FeatureFlags feature_flags_; // Flags for Workarounds. - Workarounds workarounds_; + const GpuDriverBugWorkarounds workarounds_; // Whether the command line switch kEnableUnsafeES3APIs is passed in. bool enable_unsafe_es3_apis_switch_; @@ -202,7 +189,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool oes_texture_half_float_linear_available_; bool disable_shader_translator_; - scoped_ptr<gfx::GLVersionInfo> gl_version_info_; + std::unique_ptr<gfx::GLVersionInfo> gl_version_info_; DISALLOW_COPY_AND_ASSIGN(FeatureInfo); }; diff --git a/chromium/gpu/command_buffer/service/feature_info_unittest.cc b/chromium/gpu/command_buffer/service/feature_info_unittest.cc index 62c3a2e0aec..b5b0629a4c4 100644 --- a/chromium/gpu/command_buffer/service/feature_info_unittest.cc +++ b/chromium/gpu/command_buffer/service/feature_info_unittest.cc @@ -6,8 +6,9 @@ #include <stddef.h> +#include <memory> + #include "base/command_line.h" -#include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" #include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/gpu_switches.h" @@ -101,13 +102,15 @@ class FeatureInfoTest GpuServiceTest::SetUpWithGLVersion(version, extensions); TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( gl_.get(), extensions, renderer, version); - info_ = new FeatureInfo(command_line); + GpuDriverBugWorkarounds gpu_driver_bug_workaround(&command_line); + info_ = new FeatureInfo(command_line, gpu_driver_bug_workaround); info_->InitializeForTesting(); } void SetupWithCommandLine(const base::CommandLine& command_line) { GpuServiceTest::SetUp(); - info_ = new FeatureInfo(command_line); + GpuDriverBugWorkarounds gpu_driver_bug_workaround(&command_line); + info_ = new FeatureInfo(command_line, gpu_driver_bug_workaround); } void SetupInitExpectationsWithCommandLine( @@ -116,7 +119,8 @@ class FeatureInfoTest GpuServiceTest::SetUpWithGLVersion("2.0", extensions); TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( gl_.get(), extensions, "", ""); - info_ = new FeatureInfo(command_line); + GpuDriverBugWorkarounds gpu_driver_bug_workaround(&command_line); + info_ = new FeatureInfo(command_line, gpu_driver_bug_workaround); info_->InitializeForTesting(); } @@ -170,6 +174,7 @@ TEST_P(FeatureInfoTest, Basic) { EXPECT_FALSE(info_->feature_flags().enable_texture_float_linear); EXPECT_FALSE(info_->feature_flags().enable_texture_half_float_linear); EXPECT_FALSE(info_->feature_flags().oes_egl_image_external); + EXPECT_FALSE(info_->feature_flags().nv_egl_stream_consumer_external); EXPECT_FALSE(info_->feature_flags().oes_depth24); EXPECT_FALSE(info_->feature_flags().packed_depth24_stencil8); EXPECT_FALSE(info_->feature_flags().angle_translated_shader_source); @@ -253,8 +258,6 @@ TEST_P(FeatureInfoTest, InitializeNoExtensions) { GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG)); EXPECT_FALSE(info_->validators()->compressed_texture_format.IsValid( GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG)); - EXPECT_FALSE(info_->validators()->read_pixel_format.IsValid( - GL_BGRA_EXT)); EXPECT_FALSE(info_->validators()->texture_parameter.IsValid( GL_TEXTURE_MAX_ANISOTROPY_EXT)); EXPECT_FALSE(info_->validators()->g_l_state.IsValid( @@ -362,49 +365,60 @@ TEST_P(FeatureInfoTest, InitializeDXTExtensionGL) { } TEST_P(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GLES2) { - SetupInitExpectations("GL_EXT_texture_format_BGRA8888"); + SetupInitExpectationsWithGLVersion("GL_EXT_texture_format_BGRA8888", "", + "OpenGL ES 2.0"); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_texture_format_BGRA8888")); EXPECT_TRUE(info_->validators()->texture_format.IsValid( GL_BGRA_EXT)); EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( GL_BGRA_EXT)); + + // On GL ES, render buffer and read pixels functionality is unrelated to + // GL_EXT_texture_format_BGRA8888, make sure we don't enable it. EXPECT_FALSE(info_->validators()->render_buffer_format.IsValid( GL_BGRA8_EXT)); EXPECT_FALSE(info_->feature_flags().ext_render_buffer_format_bgra8888); + EXPECT_FALSE(info_->validators()->read_pixel_format.IsValid(GL_BGRA8_EXT)); + EXPECT_FALSE(info_->feature_flags().ext_read_format_bgra); } TEST_P(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GL) { - SetupInitExpectations("GL_EXT_bgra"); + SetupInitExpectationsWithGLVersion("", "", "OpenGL 2.0"); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_texture_format_BGRA8888")); - EXPECT_THAT(info_->extensions(), - 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_->feature_flags().ext_read_format_bgra); 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_->validators()->render_buffer_format.IsValid( - GL_BGRA8_EXT)); } TEST_P(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888Apple) { - SetupInitExpectations("GL_APPLE_texture_format_BGRA8888"); + SetupInitExpectationsWithGLVersion("GL_APPLE_texture_format_BGRA8888", "", + "OpenGL ES 2.0"); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_texture_format_BGRA8888")); EXPECT_TRUE(info_->validators()->texture_format.IsValid( GL_BGRA_EXT)); EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( GL_BGRA_EXT)); + + // On GL ES, render buffer and read pixels functionality is unrelated to + // GL_APPLE_texture_format_BGRA8888, make sure we don't enable it. EXPECT_FALSE(info_->validators()->render_buffer_format.IsValid( GL_BGRA8_EXT)); EXPECT_FALSE(info_->feature_flags().ext_render_buffer_format_bgra8888); + EXPECT_FALSE(info_->validators()->read_pixel_format.IsValid(GL_BGRA8_EXT)); + EXPECT_FALSE(info_->feature_flags().ext_read_format_bgra); +} + +TEST_P(FeatureInfoTest, InitializeGLES_no_EXT_texture_format_BGRA8888GL) { + SetupInitExpectationsWithGLVersion("", "", "OpenGL ES 2.0"); + EXPECT_THAT(info_->extensions(), + Not(HasSubstr("GL_EXT_texture_format_BGRA8888"))); + EXPECT_FALSE(info_->validators()->texture_format.IsValid(GL_BGRA_EXT)); + EXPECT_FALSE( + info_->validators()->texture_internal_format.IsValid(GL_BGRA_EXT)); } TEST_P(FeatureInfoTest, InitializeGLES2EXT_read_format_bgra) { @@ -413,31 +427,33 @@ TEST_P(FeatureInfoTest, InitializeGLES2EXT_read_format_bgra) { EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_read_format_bgra")); EXPECT_TRUE(info_->feature_flags().ext_read_format_bgra); - EXPECT_FALSE(info_->validators()->texture_format.IsValid( - GL_BGRA_EXT)); - EXPECT_FALSE(info_->validators()->texture_internal_format.IsValid( - GL_BGRA_EXT)); EXPECT_TRUE(info_->validators()->read_pixel_format.IsValid( GL_BGRA_EXT)); + + // On GL ES, texture and render buffer functionality is unrelated to + // GL_EXT_read_format_bgra, make sure we don't enable it. EXPECT_FALSE(info_->validators()->render_buffer_format.IsValid( GL_BGRA8_EXT)); EXPECT_FALSE(info_->feature_flags().ext_render_buffer_format_bgra8888); + EXPECT_FALSE(info_->validators()->texture_format.IsValid(GL_BGRA_EXT)); + EXPECT_FALSE( + info_->validators()->texture_internal_format.IsValid(GL_BGRA_EXT)); } -TEST_P(FeatureInfoTest, InitializeEXT_read_format_bgra) { - SetupInitExpectations("GL_EXT_read_format_bgra"); +TEST_P(FeatureInfoTest, InitializeGLEXT_read_format_bgra) { + SetupInitExpectationsWithGLVersion("", "", "OpenGL 2.0"); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_read_format_bgra")); EXPECT_TRUE(info_->feature_flags().ext_read_format_bgra); - 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_FALSE(info_->validators()->render_buffer_format.IsValid( - GL_BGRA8_EXT)); - EXPECT_FALSE(info_->feature_flags().ext_render_buffer_format_bgra8888); +} + +TEST_P(FeatureInfoTest, InitializeGLES_no_EXT_read_format_bgra) { + SetupInitExpectationsWithGLVersion("", "", "OpenGL ES 2.0"); + EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_EXT_read_format_bgra"))); + EXPECT_FALSE(info_->feature_flags().ext_read_format_bgra); + EXPECT_FALSE(info_->validators()->read_pixel_format.IsValid(GL_BGRA_EXT)); } TEST_P(FeatureInfoTest, InitializeEXT_sRGB) { @@ -528,7 +544,8 @@ TEST_P(FeatureInfoTest, InitializeARB_texture_storage) { } TEST_P(FeatureInfoTest, InitializeEXT_texture_storage_BGRA) { - SetupInitExpectations("GL_EXT_texture_storage GL_EXT_bgra"); + SetupInitExpectationsWithGLVersion("GL_EXT_texture_storage", "", + "OpenGL 2.0"); EXPECT_TRUE(info_->feature_flags().ext_texture_storage); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_texture_storage")); EXPECT_TRUE(info_->validators()->texture_internal_format_storage.IsValid( @@ -537,7 +554,8 @@ TEST_P(FeatureInfoTest, InitializeEXT_texture_storage_BGRA) { } TEST_P(FeatureInfoTest, InitializeARB_texture_storage_BGRA) { - SetupInitExpectations("GL_ARB_texture_storage GL_EXT_bgra"); + SetupInitExpectationsWithGLVersion("GL_ARB_texture_storage", "", + "OpenGL 2.0"); EXPECT_TRUE(info_->feature_flags().ext_texture_storage); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_texture_storage")); EXPECT_TRUE(info_->validators()->texture_internal_format_storage.IsValid( @@ -588,6 +606,17 @@ TEST_P(FeatureInfoTest, InitializeEXT_texture_storage_half_float) { GL_LUMINANCE_ALPHA16F_EXT)); } +// Check that desktop (unlike ES, handled below) always supports BGRA render +// buffers. +TEST_P(FeatureInfoTest, InitializeGL_renderbuffer_format_BGRA8888) { + SetupInitExpectationsWithGLVersion("", "", "OpenGL 2.0"); + + 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)); +} + // Check how to handle ES, texture_storage and BGRA combination; 10 tests. // 1- ES2 + GL_EXT_texture_storage -> GL_EXT_texture_storage (and no @@ -1041,6 +1070,21 @@ TEST_P(FeatureInfoTest, InitializeOES_EGL_image_external) { GL_TEXTURE_BINDING_EXTERNAL_OES)); } +TEST_P(FeatureInfoTest, InitializeNV_EGL_stream_consumer_external) { + SetupInitExpectations("GL_NV_EGL_stream_consumer_external"); + EXPECT_THAT(info_->extensions(), + HasSubstr("GL_NV_EGL_stream_consumer_external")); + EXPECT_TRUE(info_->feature_flags().nv_egl_stream_consumer_external); + EXPECT_TRUE(info_->validators()->texture_bind_target.IsValid( + GL_TEXTURE_EXTERNAL_OES)); + EXPECT_TRUE(info_->validators()->get_tex_param_target.IsValid( + GL_TEXTURE_EXTERNAL_OES)); + EXPECT_TRUE(info_->validators()->texture_parameter.IsValid( + GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES)); + EXPECT_TRUE( + info_->validators()->g_l_state.IsValid(GL_TEXTURE_BINDING_EXTERNAL_OES)); +} + TEST_P(FeatureInfoTest, InitializeOES_compressed_ETC1_RGB8_texture) { SetupInitExpectations("GL_OES_compressed_ETC1_RGB8_texture"); EXPECT_THAT(info_->extensions(), diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager.cc b/chromium/gpu/command_buffer/service/framebuffer_manager.cc index ccd593aac22..d64963534a3 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager.cc +++ b/chromium/gpu/command_buffer/service/framebuffer_manager.cc @@ -129,6 +129,8 @@ class RenderbufferAttachment return false; } + bool EmulatingRGB() const override { return false; } + protected: ~RenderbufferAttachment() override {} @@ -277,6 +279,10 @@ class TextureAttachment return texture == texture_ref_.get() && level == level_; } + bool EmulatingRGB() const override { + return texture_ref_->texture()->EmulatingRGB(); + } + protected: ~TextureAttachment() override {} @@ -438,7 +444,7 @@ void Framebuffer::ClearUnclearedIntRenderbufferAttachments( } bool Framebuffer::PrepareDrawBuffersForClear() const { - scoped_ptr<GLenum[]> buffers(new GLenum[manager_->max_draw_buffers_]); + std::unique_ptr<GLenum[]> buffers(new GLenum[manager_->max_draw_buffers_]); for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i) buffers[i] = GL_NONE; for (AttachmentMap::const_iterator it = attachments_.begin(); @@ -537,6 +543,10 @@ GLenum Framebuffer::GetReadBufferInternalFormat() const { return 0; } const Attachment* attachment = it->second.get(); + if (attachment->EmulatingRGB()) { + DCHECK_EQ(static_cast<GLenum>(GL_RGBA), attachment->internal_format()); + return GL_RGB; + } return attachment->internal_format(); } diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager.h b/chromium/gpu/command_buffer/service/framebuffer_manager.h index 67257dafd25..bb0de013a80 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager.h +++ b/chromium/gpu/command_buffer/service/framebuffer_manager.h @@ -8,12 +8,12 @@ #include <stddef.h> #include <stdint.h> +#include <memory> #include <vector> #include "base/containers/hash_tables.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/gpu_export.h" @@ -62,6 +62,7 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { virtual void AddToSignature( TextureManager* texture_manager, std::string* signature) const = 0; virtual bool FormsFeedbackLoop(TextureRef* texture, GLint level) const = 0; + virtual bool EmulatingRGB() const = 0; protected: friend class base::RefCounted<Attachment>; @@ -224,7 +225,7 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { typedef base::hash_map<GLenum, scoped_refptr<Attachment> > AttachmentMap; AttachmentMap attachments_; - scoped_ptr<GLenum[]> draw_buffers_; + std::unique_ptr<GLenum[]> draw_buffers_; GLenum read_buffer_; diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc index c3538c592d7..c5304f1e6c0 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc @@ -27,6 +27,7 @@ const GLint kMaxTextureSize = 64; const GLint kMaxCubemapSize = 64; const GLint kMaxRectangleTextureSize = 64; const GLint kMax3DTextureSize = 256; +const GLint kMaxArrayTextureLayers = 256; const GLint kMaxRenderbufferSize = 64; const GLint kMaxSamples = 4; const uint32_t kMaxDrawBuffers = 16; @@ -46,6 +47,7 @@ class FramebufferManagerTest : public GpuServiceTest { kMaxCubemapSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures)); renderbuffer_manager_.reset(new RenderbufferManager(NULL, kMaxRenderbufferSize, @@ -61,8 +63,8 @@ class FramebufferManagerTest : public GpuServiceTest { protected: FramebufferManager manager_; scoped_refptr<FeatureInfo> feature_info_; - scoped_ptr<TextureManager> texture_manager_; - scoped_ptr<RenderbufferManager> renderbuffer_manager_; + std::unique_ptr<TextureManager> texture_manager_; + std::unique_ptr<RenderbufferManager> renderbuffer_manager_; }; TEST_F(FramebufferManagerTest, Basic) { @@ -126,6 +128,7 @@ class FramebufferInfoTestBase : public GpuServiceTest { kMaxCubemapSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures)); renderbuffer_manager_.reset(new RenderbufferManager(NULL, kMaxRenderbufferSize, @@ -158,10 +161,10 @@ class FramebufferInfoTestBase : public GpuServiceTest { FramebufferManager manager_; Framebuffer* framebuffer_; scoped_refptr<FeatureInfo> feature_info_; - scoped_ptr<TextureManager> texture_manager_; - scoped_ptr<RenderbufferManager> renderbuffer_manager_; - scoped_ptr<MockErrorState> error_state_; - scoped_ptr<MockGLES2Decoder> decoder_; + std::unique_ptr<TextureManager> texture_manager_; + std::unique_ptr<RenderbufferManager> renderbuffer_manager_; + std::unique_ptr<MockErrorState> error_state_; + std::unique_ptr<MockGLES2Decoder> decoder_; }; class FramebufferInfoTest : public FramebufferInfoTestBase { diff --git a/chromium/gpu/command_buffer/service/gl_context_virtual_unittest.cc b/chromium/gpu/command_buffer/service/gl_context_virtual_unittest.cc new file mode 100644 index 00000000000..d1e225cf2a6 --- /dev/null +++ b/chromium/gpu/command_buffer/service/gl_context_virtual_unittest.cc @@ -0,0 +1,63 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gl_context_virtual.h" + +#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" +#include "gpu/command_buffer/service/gpu_service_test.h" +#include "ui/gl/gl_context_stub.h" +#include "ui/gl/gl_share_group.h" +#include "ui/gl/gl_surface.h" + +namespace gpu { +namespace gles2 { +namespace { + +using testing::AnyNumber; +using testing::Return; + +class GLContextVirtualTest : public GpuServiceTest { + public: + GLContextVirtualTest() : decoder_(new gles2::MockGLES2Decoder()) {} + ~GLContextVirtualTest() override {} + + protected: + std::unique_ptr<MockGLES2Decoder> decoder_; +}; + +// Tests that destroying a GLContextVirtual doesn't leave stale state that +// prevents a new one from initializing. +TEST_F(GLContextVirtualTest, Reinitialize) { + EXPECT_CALL(*gl_, GetError()) + .Times(AnyNumber()) + .WillRepeatedly(Return(GL_NO_ERROR)); + EXPECT_CALL(*gl_, GetString(GL_VERSION)) + .Times(AnyNumber()) + .WillRepeatedly(Return(reinterpret_cast<unsigned const char *>("2.0"))); + EXPECT_CALL(*gl_, GetString(GL_EXTENSIONS)) + .Times(AnyNumber()) + .WillRepeatedly(Return(reinterpret_cast<unsigned const char *>(""))); + { + scoped_refptr<gfx::GLContextStub> base_context = new gfx::GLContextStub; + gfx::GLShareGroup* share_group = base_context->share_group(); + share_group->SetSharedContext(base_context.get()); + scoped_refptr<GLContextVirtual> context(new GLContextVirtual( + share_group, base_context.get(), decoder_->AsWeakPtr())); + EXPECT_TRUE(context->Initialize(GetGLSurface(), gfx::PreferIntegratedGpu)); + EXPECT_TRUE(context->MakeCurrent(GetGLSurface())); + } + { + scoped_refptr<gfx::GLContextStub> base_context = new gfx::GLContextStub; + gfx::GLShareGroup* share_group = base_context->share_group(); + share_group->SetSharedContext(base_context.get()); + scoped_refptr<GLContextVirtual> context(new GLContextVirtual( + share_group, base_context.get(), decoder_->AsWeakPtr())); + EXPECT_TRUE(context->Initialize(GetGLSurface(), gfx::PreferIntegratedGpu)); + EXPECT_TRUE(context->MakeCurrent(GetGLSurface())); + } +} + +} // anonymous namespace +} // namespace gles2 +} // namespace gpu 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 dad3d031aa9..53549f41875 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 @@ -160,8 +160,10 @@ std::string GetFragmentShaderSource(bool premultiply_alpha, source += std::string("#define TextureLookup texture2DRect\n"); break; case GL_TEXTURE_EXTERNAL_OES: + source += + std::string("#extension GL_OES_EGL_image_external : enable\n"); source += std::string( - "#extension GL_OES_EGL_image_external : require\n"); + "#extension GL_NV_EGL_stream_consumer_external : enable\n"); source += std::string("#define TextureLookup texture2D\n"); break; default: @@ -368,9 +370,9 @@ void CopyTextureCHROMIUMResourceManager::Initialize( if (vertex_array_object_id_) { glEnableVertexAttribArray(kVertexPositionAttrib); glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); + decoder->RestoreAllAttributes(); } - decoder->RestoreAllAttributes(); decoder->RestoreBufferBindings(); initialized_ = true; diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc index f28cc4387e7..1ea121e7783 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -13,16 +13,17 @@ #include <cmath> #include <list> #include <map> +#include <memory> #include <queue> #include "base/callback.h" #include "base/callback_helpers.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/stringprintf.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_synthetic_delay.h" #include "build/build_config.h" @@ -56,7 +57,7 @@ #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/shader_translator.h" #include "gpu/command_buffer/service/texture_manager.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" +#include "gpu/command_buffer/service/transform_feedback_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" @@ -276,22 +277,6 @@ RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod, NULL; } -// Computes the data size for certain gl commands like glUniform. -bool ComputeDataSize(GLuint count, - size_t size, - unsigned int elements_per_unit, - uint32_t* dst) { - uint32_t value; - if (!SafeMultiplyUint32(count, size, &value)) { - return false; - } - if (!SafeMultiplyUint32(value, elements_per_unit, &value)) { - return false; - } - *dst = value; - return true; -} - // Return true if a character belongs to the ASCII subset as defined in // GLSL ES 1.0 spec section 3.1. static bool CharacterIsValidForGLES(unsigned char c) { @@ -401,7 +386,7 @@ class ScopedFrameBufferReadPixelHelper { private: GLuint temp_texture_id_ = 0; GLuint temp_fbo_id_ = 0; - scoped_ptr<ScopedFrameBufferBinder> fbo_binder_; + std::unique_ptr<ScopedFrameBufferBinder> fbo_binder_; DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferReadPixelHelper); }; @@ -527,7 +512,7 @@ struct FenceCallback { DCHECK(fence); } std::vector<base::Closure> callbacks; - scoped_ptr<gfx::GLFence> fence; + std::unique_ptr<gfx::GLFence> fence; }; // } // anonymous namespace. @@ -591,9 +576,10 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { bool offscreen, const gfx::Size& offscreen_size, const DisallowedFeatures& disallowed_features, - const std::vector<int32_t>& attribs) override; + const ContextCreationAttribHelper& attrib_helper) override; void Destroy(bool have_context) override; void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override; + void ReleaseSurface() override; void ProduceFrontBuffer(const Mailbox& mailbox) override; bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override; void UpdateParentTextureInfo(); @@ -617,7 +603,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { } void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); } void RestoreProgramBindings() const override { - state_.RestoreProgramBindings(); + state_.RestoreProgramSettings(nullptr, false); } void RestoreTextureUnitBindings(unsigned unit) const override { state_.RestoreTextureUnitBindings(unit, NULL); @@ -630,15 +616,14 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { void RestoreAllAttributes() const override; QueryManager* GetQueryManager() override { return query_manager_.get(); } + TransformFeedbackManager* GetTransformFeedbackManager() override { + return transform_feedback_manager_.get(); + } VertexArrayManager* GetVertexArrayManager() override { return vertex_array_manager_.get(); } ImageManager* GetImageManager() override { return image_manager_.get(); } - ValuebufferManager* GetValuebufferManager() override { - return valuebuffer_manager(); - } - bool HasPendingQueries() const override; void ProcessPendingQueries(bool did_finish) override; @@ -723,6 +708,17 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { friend class ScopedResolvedFrameBufferBinder; friend class BackFramebuffer; + enum FramebufferOperation { + kFramebufferDiscard, + kFramebufferInvalidate, + kFramebufferInvalidateSub + }; + + enum BindIndexedBufferFunctionType { + kBindBufferBase, + kBindBufferRange + }; + // Initialize or re-initialize the shader translator. bool InitializeShaderTranslator(); @@ -737,8 +733,6 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids); bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids); void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids); - bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids); - void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids); bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids); void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids); bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids); @@ -747,6 +741,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { bool DeletePathsCHROMIUMHelper(GLuint first_client_id, GLsizei range); bool GenSamplersHelper(GLsizei n, const GLuint* client_ids); void DeleteSamplersHelper(GLsizei n, const GLuint* client_ids); + bool GenTransformFeedbacksHelper(GLsizei n, const GLuint* client_ids); + void DeleteTransformFeedbacksHelper(GLsizei n, const GLuint* client_ids); // Workarounds void OnFboChanged() const; @@ -768,10 +764,6 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { return group_->framebuffer_manager(); } - ValuebufferManager* valuebuffer_manager() { - return group_->valuebuffer_manager(); - } - ProgramManager* program_manager() { return group_->program_manager(); } @@ -854,6 +846,24 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { sampler_manager()->RemoveSampler(client_id); } + // Creates a TransformFeedback for the given transformfeedback. + TransformFeedback* CreateTransformFeedback( + GLuint client_id, GLuint service_id) { + return transform_feedback_manager_->CreateTransformFeedback( + client_id, service_id); + } + + // Gets the TransformFeedback info for the given transformfeedback. + // Returns nullptr if none exists. + TransformFeedback* GetTransformFeedback(GLuint client_id) { + return transform_feedback_manager_->GetTransformFeedback(client_id); + } + + // Deletes the TransformFeedback info for the given transformfeedback. + void RemoveTransformFeedback(GLuint client_id) { + transform_feedback_manager_->RemoveTransformFeedback(client_id); + } + // Get the size (in pixels) of the currently bound frame buffer (either FBO // or regular back buffer). gfx::Size GetBoundReadFrameBufferSize(); @@ -983,22 +993,30 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { void DoCompressedCopyTextureCHROMIUM(GLuint source_id, GLuint dest_id); + // Helper for DoTexStorage2DEXT and DoTexStorage3D. + void TexStorageImpl(GLenum target, + GLsizei levels, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + ContextState::Dimension dimension, + const char* function_name); + // Wrapper for TexStorage2DEXT. - void DoTexStorage2DEXT( - GLenum target, - GLint levels, - GLenum internal_format, - GLsizei width, - GLsizei height); + void DoTexStorage2DEXT(GLenum target, + GLsizei levels, + GLenum internal_format, + GLsizei width, + GLsizei height); // Wrapper for TexStorage3D. - void DoTexStorage3D( - GLenum target, - GLint levels, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLsizei depth); + void DoTexStorage3D(GLenum target, + GLsizei levels, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth); void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key); void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target, @@ -1014,14 +1032,6 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { GLuint client_id); void DoApplyScreenSpaceAntialiasingCHROMIUM(); - bool DoIsValuebufferCHROMIUM(GLuint client_id); - void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer); - void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription); - void DoPopulateSubscribedValuesCHROMIUM(GLenum target); - void DoUniformValueBufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription); - void DoBindTexImage2DCHROMIUM( GLenum target, GLint image_id); @@ -1175,21 +1185,6 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { renderbuffer_manager()->RemoveRenderbuffer(client_id); } - // Creates a valuebuffer info for the given valuebuffer. - void CreateValuebuffer(GLuint client_id) { - return valuebuffer_manager()->CreateValuebuffer(client_id); - } - - // Gets the valuebuffer info for a given valuebuffer. - Valuebuffer* GetValuebuffer(GLuint client_id) { - return valuebuffer_manager()->GetValuebuffer(client_id); - } - - // Removes the valuebuffer info for the given valuebuffer. - void RemoveValuebuffer(GLuint client_id) { - valuebuffer_manager()->RemoveValuebuffer(client_id); - } - // Gets the vertex attrib manager for the given vertex array. VertexAttribManager* GetVertexAttribManager(GLuint client_id) { VertexAttribManager* info = @@ -1276,6 +1271,15 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { int height) override; // overridden from GLES2Decoder + bool ClearCompressedTextureLevel(Texture* texture, + unsigned target, + int level, + unsigned format, + int width, + int height) override; + bool IsCompressedTextureFormat(unsigned format) override; + + // overridden from GLES2Decoder bool ClearLevel3D(Texture* texture, unsigned target, int level, @@ -1300,31 +1304,18 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level); // Check if a framebuffer meets our requirements. + // Generates |gl_error| if the framebuffer is incomplete. bool CheckFramebufferValid( Framebuffer* framebuffer, GLenum target, bool clear_uncleared_images, + GLenum gl_error, const char* func_name); bool CheckBoundDrawFramebufferValid( bool clear_uncleared_images, const char* func_name); - bool CheckBoundReadFramebufferValid(const char* func_name); - - // Check if the current valuebuffer exists and is valid. If not generates - // the appropriate GL error. Returns true if the current valuebuffer is in - // a usable state. - bool CheckCurrentValuebuffer(const char* function_name); - - // Check if the current valuebuffer exists and is valiud and that the - // value buffer is actually subscribed to the given subscription - bool CheckCurrentValuebufferForSubscription(GLenum subscription, - const char* function_name); - - // Check if the location can be used for the given subscription target. If not - // generates the appropriate GL error. Returns true if the location is usable - bool CheckSubscriptionTarget(GLint location, - GLenum subscription, - const char* function_name); + // Generates |gl_error| if the bound read fbo is incomplete. + bool CheckBoundReadFramebufferValid(const char* func_name, GLenum gl_error); // Checks if the current program exists and is valid. If not generates the // appropriate GL error. Returns true if the current program is in a usable @@ -1386,6 +1377,12 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { void DoBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); + // Helper for DoBindBufferBase and DoBindBufferRange. + void BindIndexedBufferImpl(GLenum target, GLuint index, GLuint buffer, + GLintptr offset, GLsizeiptr size, + BindIndexedBufferFunctionType function_type, + const char* function_name); + // Wrapper for glBindFramebuffer since we need to track the current targets. void DoBindFramebuffer(GLenum target, GLuint framebuffer); @@ -1398,6 +1395,22 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { // Wrapper for glBindSampler since we need to track the current targets. void DoBindSampler(GLuint unit, GLuint sampler); + // Wrapper for glBindTransformFeedback since we need to emulate ES3 behaviors + // for BindBufferRange on Desktop GL lower than 4.2. + void DoBindTransformFeedback(GLenum target, GLuint transform_feedback); + + // Wrapper for glBeginTransformFeedback. + void DoBeginTransformFeedback(GLenum primitive_mode); + + // Wrapper for glEndTransformFeedback. + void DoEndTransformFeedback(); + + // Wrapper for glPauseTransformFeedback. + void DoPauseTransformFeedback(); + + // Wrapper for glResumeTransformFeedback. + void DoResumeTransformFeedback(); + // Wrapper for glBindVertexArrayOES void DoBindVertexArrayOES(GLuint array); void EmulateVertexArrayState(); @@ -1444,9 +1457,20 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { // Wrapper for glDiscardFramebufferEXT, since we need to track undefined // attachments. - void DoDiscardFramebufferEXT(GLenum target, - GLsizei numAttachments, - const GLenum* attachments); + void DoDiscardFramebufferEXT( + GLenum target, GLsizei count, const GLenum* attachments); + + void DoInvalidateFramebuffer( + GLenum target, GLsizei count, const GLenum* attachments); + void DoInvalidateSubFramebuffer( + GLenum target, GLsizei count, const GLenum* attachments, + GLint x, GLint y, GLsizei width, GLsizei height); + + // Helper for DoDiscardFramebufferEXT, DoInvalidate{Sub}Framebuffer. + void InvalidateFramebufferImpl( + GLenum target, GLsizei count, const GLenum* attachments, + GLint x, GLint y, GLsizei width, GLsizei height, + const char* function_name, FramebufferOperation op); // Wrapper for glEnable void DoEnable(GLenum cap); @@ -1509,6 +1533,17 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { // Wrapper for glGetIntegerv. void DoGetIntegerv(GLenum pname, GLint* params); + // Helper for DoGetIntegeri_v and DoGetInteger64i_v. + template <typename TYPE> + void GetIndexedIntegerImpl( + const char* function_name, GLenum target, GLuint index, TYPE* data); + + // Wrapper for glGetIntegeri_v. + void DoGetIntegeri_v(GLenum target, GLuint index, GLint* data); + + // Wrapper for glGetInteger64i_v. + void DoGetInteger64i_v(GLenum target, GLuint index, GLint64* data); + // Gets the max value in a range in a buffer. GLuint DoGetMaxValueInBufferCHROMIUM( GLuint buffer_id, GLsizei count, GLenum type, GLuint offset); @@ -1536,10 +1571,14 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { // Wrapper for glGetShaderiv void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params); + // Helper for DoGetTexParameter{f|i}v. + void GetTexParameterImpl( + GLenum target, GLenum pname, GLfloat* fparams, GLint* iparams, + const char* function_name); + // Wrappers for glGetTexParameter. void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params); void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params); - void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname); // Wrappers for glGetVertexAttrib. template <typename T> @@ -1558,6 +1597,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { bool DoIsShader(GLuint client_id); bool DoIsTexture(GLuint client_id); bool DoIsSampler(GLuint client_id); + bool DoIsTransformFeedback(GLuint client_id); bool DoIsVertexArrayOES(GLuint client_id); bool DoIsPathCHROMIUM(GLuint client_id); @@ -1854,7 +1894,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { return feature_info_->feature_flags(); } - const FeatureInfo::Workarounds& workarounds() const { + const GpuDriverBugWorkarounds& workarounds() const { return feature_info_->workarounds(); } @@ -1939,6 +1979,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { // http://crbug.com/99393. <rdar://problem/10949687> bool NeedsIOSurfaceReadbackWorkaround(); + bool InitializeCopyTextureCHROMIUM(const char* function_name); // Generate a member function prototype for each command in an automated and // typesafe way. #define GLES2_CMD_OP(name) \ @@ -1961,6 +2002,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { // All the state for this context. ContextState state_; + std::unique_ptr<TransformFeedbackManager> transform_feedback_manager_; + // Current width and height of the offscreen frame buffer. gfx::Size offscreen_size_; @@ -1989,11 +2032,11 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { // depth and stencil buffers are separate. With regular GL there is a single // packed depth stencil buffer in offscreen_target_depth_render_buffer_. // offscreen_target_stencil_render_buffer_ is unused. - scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_; - scoped_ptr<BackTexture> offscreen_target_color_texture_; - scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_; - scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_; - scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_; + std::unique_ptr<BackFramebuffer> offscreen_target_frame_buffer_; + std::unique_ptr<BackTexture> offscreen_target_color_texture_; + std::unique_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_; + std::unique_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_; + std::unique_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_; GLenum offscreen_target_color_format_; GLenum offscreen_target_depth_format_; GLenum offscreen_target_stencil_format_; @@ -2001,21 +2044,21 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { GLboolean offscreen_target_buffer_preserved_; // The copy that is saved when SwapBuffers is called. - scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_; - scoped_ptr<BackTexture> offscreen_saved_color_texture_; + std::unique_ptr<BackFramebuffer> offscreen_saved_frame_buffer_; + std::unique_ptr<BackTexture> offscreen_saved_color_texture_; scoped_refptr<TextureRef> offscreen_saved_color_texture_info_; // The copy that is used as the destination for multi-sample resolves. - scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_; - scoped_ptr<BackTexture> offscreen_resolved_color_texture_; + std::unique_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_; + std::unique_ptr<BackTexture> offscreen_resolved_color_texture_; GLenum offscreen_saved_color_format_; - scoped_ptr<QueryManager> query_manager_; + std::unique_ptr<QueryManager> query_manager_; - scoped_ptr<VertexArrayManager> vertex_array_manager_; + std::unique_ptr<VertexArrayManager> vertex_array_manager_; - scoped_ptr<ImageManager> image_manager_; + std::unique_ptr<ImageManager> image_manager_; FenceSyncReleaseCallback fence_sync_release_callback_; WaitFenceSyncCallback wait_fence_sync_callback_; @@ -2091,8 +2134,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { TextureToIOSurfaceMap texture_to_io_surface_map_; #endif - scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_; - scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_; + std::unique_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_; + std::unique_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_; // Cached values of the currently assigned viewport dimensions. GLsizei viewport_max_width_; @@ -2105,8 +2148,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { DecoderTextureState texture_state_; DecoderFramebufferState framebuffer_state_; - scoped_ptr<GPUTracer> gpu_tracer_; - scoped_ptr<GPUStateTracer> gpu_state_tracer_; + std::unique_ptr<GPUTracer> gpu_tracer_; + std::unique_ptr<GPUStateTracer> gpu_state_tracer_; const unsigned char* gpu_decoder_category_; int gpu_trace_level_; bool gpu_trace_commands_; @@ -2395,7 +2438,7 @@ bool BackTexture::AllocateStorage( return false; } - scoped_ptr<char[]> zero_data; + std::unique_ptr<char[]> zero_data; if (zero) { zero_data.reset(new char[image_size]); memset(zero_data.get(), 0, image_size); @@ -2666,21 +2709,18 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) GLES2DecoderImpl::~GLES2DecoderImpl() { } -bool GLES2DecoderImpl::Initialize(const scoped_refptr<gfx::GLSurface>& surface, - const scoped_refptr<gfx::GLContext>& context, - bool offscreen, - const gfx::Size& offscreen_size, - const DisallowedFeatures& disallowed_features, - const std::vector<int32_t>& attribs) { +bool GLES2DecoderImpl::Initialize( + const scoped_refptr<gfx::GLSurface>& surface, + const scoped_refptr<gfx::GLContext>& context, + bool offscreen, + const gfx::Size& offscreen_size, + const DisallowedFeatures& disallowed_features, + const ContextCreationAttribHelper& attrib_helper) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize"); DCHECK(context->IsCurrent(surface.get())); DCHECK(!context_.get()); DCHECK(!offscreen || !offscreen_size.IsEmpty()); - ContextCreationAttribHelper attrib_parser; - if (!attrib_parser.Parse(attribs)) - return false; - surfaceless_ = surface->IsSurfaceless() && !offscreen; set_initialized(); @@ -2711,24 +2751,29 @@ bool GLES2DecoderImpl::Initialize(const scoped_refptr<gfx::GLSurface>& surface, // Save the loseContextWhenOutOfMemory context creation attribute. lose_context_when_out_of_memory_ = - attrib_parser.lose_context_when_out_of_memory; + attrib_helper.lose_context_when_out_of_memory; // If the failIfMajorPerformanceCaveat context creation attribute was true // and we are using a software renderer, fail. - if (attrib_parser.fail_if_major_perf_caveat && + if (attrib_helper.fail_if_major_perf_caveat && feature_info_->feature_flags().is_swiftshader) { group_ = NULL; // Must not destroy ContextGroup if it is not initialized. Destroy(true); return false; } - if (!group_->Initialize(this, attrib_parser.context_type, + if (!group_->Initialize(this, attrib_helper.context_type, disallowed_features)) { group_ = NULL; // Must not destroy ContextGroup if it is not initialized. Destroy(true); return false; } CHECK_GL_ERROR(); + + bool needs_emulation = feature_info_->gl_version_info().IsLowerThanGL(4, 2); + transform_feedback_manager_.reset(new TransformFeedbackManager( + group_->max_transform_feedback_separate_attribs(), needs_emulation)); + if (feature_info_->context_type() == CONTEXT_TYPE_WEBGL2 || feature_info_->context_type() == CONTEXT_TYPE_OPENGLES3) { if (!feature_info_->IsES3Capable()) { @@ -2742,7 +2787,18 @@ bool GLES2DecoderImpl::Initialize(const scoped_refptr<gfx::GLSurface>& surface, frag_depth_explicitly_enabled_ = true; draw_buffers_explicitly_enabled_ = true; // TODO(zmo): Look into shader_texture_lod_explicitly_enabled_ situation. + + // Create a fake default transform feedback and bind to it. + GLuint default_transform_feedback = 0; + glGenTransformFeedbacks(1, &default_transform_feedback); + state_.default_transform_feedback = + transform_feedback_manager_->CreateTransformFeedback( + 0, default_transform_feedback); + glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, default_transform_feedback); + state_.bound_transform_feedback = state_.default_transform_feedback.get(); } + state_.indexed_uniform_buffer_bindings = new IndexedBufferBindingHost( + group_->max_uniform_buffer_bindings(), needs_emulation); state_.attrib_values.resize(group_->max_vertex_attribs()); vertex_array_manager_.reset(new VertexArrayManager()); @@ -2788,7 +2844,8 @@ bool GLES2DecoderImpl::Initialize(const scoped_refptr<gfx::GLSurface>& surface, glActiveTexture(GL_TEXTURE0 + tt); // We want the last bind to be 2D. TextureRef* ref; - if (features().oes_egl_image_external) { + if (features().oes_egl_image_external || + features().nv_egl_stream_consumer_external) { ref = texture_manager()->GetDefaultTextureInfo( GL_TEXTURE_EXTERNAL_OES); state_.texture_units[tt].bound_texture_external_oes = ref; @@ -2814,19 +2871,19 @@ bool GLES2DecoderImpl::Initialize(const scoped_refptr<gfx::GLSurface>& surface, GLint alpha_bits = 0; if (offscreen) { - if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 && + if (attrib_helper.samples > 0 && attrib_helper.sample_buffers > 0 && features().chromium_framebuffer_multisample) { // Per ext_framebuffer_multisample spec, need max bound on sample count. // max_sample_count must be initialized to a sane value. If // glGetIntegerv() throws a GL error, it leaves its argument unchanged. GLint max_sample_count = 1; glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count); - offscreen_target_samples_ = std::min(attrib_parser.samples, + offscreen_target_samples_ = std::min(attrib_helper.samples, max_sample_count); } else { offscreen_target_samples_ = 1; } - offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved; + offscreen_target_buffer_preserved_ = attrib_helper.buffer_preserved; if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) { const bool rgb8_supported = @@ -2835,12 +2892,12 @@ bool GLES2DecoderImpl::Initialize(const scoped_refptr<gfx::GLSurface>& surface, // little precision. Don't enable multisampling unless 8-bit render // buffer formats are available--instead fall back to 8-bit textures. if (rgb8_supported && offscreen_target_samples_ > 1) { - offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ? + offscreen_target_color_format_ = attrib_helper.alpha_size > 0 ? GL_RGBA8 : GL_RGB8; } else { offscreen_target_samples_ = 1; offscreen_target_color_format_ = - attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format + attrib_helper.alpha_size > 0 || workarounds().disable_gl_rgb_format ? GL_RGBA : GL_RGB; } @@ -2851,21 +2908,21 @@ bool GLES2DecoderImpl::Initialize(const scoped_refptr<gfx::GLSurface>& surface, feature_info_->feature_flags().packed_depth24_stencil8; VLOG(1) << "GL_OES_packed_depth_stencil " << (depth24_stencil8_supported ? "" : "not ") << "supported."; - if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) && + if ((attrib_helper.depth_size > 0 || attrib_helper.stencil_size > 0) && depth24_stencil8_supported) { offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8; offscreen_target_stencil_format_ = 0; } else { // It may be the case that this depth/stencil combination is not // supported, but this will be checked later by CheckFramebufferStatus. - offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ? + offscreen_target_depth_format_ = attrib_helper.depth_size > 0 ? GL_DEPTH_COMPONENT16 : 0; - offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ? + offscreen_target_stencil_format_ = attrib_helper.stencil_size > 0 ? GL_STENCIL_INDEX8 : 0; } } else { offscreen_target_color_format_ = - attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format + attrib_helper.alpha_size > 0 || workarounds().disable_gl_rgb_format ? GL_RGBA : GL_RGB; @@ -2877,20 +2934,20 @@ bool GLES2DecoderImpl::Initialize(const scoped_refptr<gfx::GLSurface>& surface, VLOG(1) << "GL_EXT_packed_depth_stencil " << (depth24_stencil8_supported ? "" : "not ") << "supported."; - if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) && + if ((attrib_helper.depth_size > 0 || attrib_helper.stencil_size > 0) && depth24_stencil8_supported) { offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8; offscreen_target_stencil_format_ = 0; } else { - offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ? + offscreen_target_depth_format_ = attrib_helper.depth_size > 0 ? GL_DEPTH_COMPONENT : 0; - offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ? + offscreen_target_stencil_format_ = attrib_helper.stencil_size > 0 ? GL_STENCIL_INDEX : 0; } } offscreen_saved_color_format_ = - attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format + attrib_helper.alpha_size > 0 || workarounds().disable_gl_rgb_format ? GL_RGBA : GL_RGB; @@ -2993,10 +3050,10 @@ bool GLES2DecoderImpl::Initialize(const scoped_refptr<gfx::GLSurface>& surface, // the user requested RGB then RGB. If the user did not specify a // preference than use whatever we were given. Same for DEPTH and STENCIL. back_buffer_color_format_ = - (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB; - back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0; + (attrib_helper.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB; + back_buffer_has_depth_ = attrib_helper.depth_size != 0 && depth_bits > 0; back_buffer_has_stencil_ = - attrib_parser.stencil_size != 0 && stencil_bits > 0; + attrib_helper.stencil_size != 0 && stencil_bits > 0; } state_.viewport_width = surface->GetSize().width(); @@ -3056,7 +3113,6 @@ bool GLES2DecoderImpl::Initialize(const scoped_refptr<gfx::GLSurface>& surface, DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); DoBindFramebuffer(GL_FRAMEBUFFER, 0); DoBindRenderbuffer(GL_RENDERBUFFER, 0); - DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0); bool call_gl_clear = !surfaceless_; #if defined(OS_ANDROID) @@ -3232,6 +3288,7 @@ Capabilities GLES2DecoderImpl::GetCapabilities() { #if defined(OS_MACOSX) // This is unconditionally true on mac, no need to test for it at runtime. caps.iosurface = true; + caps.chromium_image_rgb_emulation = true; #endif caps.post_sub_buffer = supports_post_sub_buffer_; @@ -3261,6 +3318,11 @@ Capabilities GLES2DecoderImpl::GetCapabilities() { feature_info_->feature_flags().occlusion_query_boolean; caps.timer_queries = query_manager_->GPUTimingAvailable(); + caps.disable_webgl_multisampling_color_mask_usage = + feature_info_->workarounds().disable_webgl_multisampling_color_mask_usage; + caps.disable_webgl_rgb_multisampling_usage = + feature_info_->workarounds().disable_webgl_rgb_multisampling_usage; + return caps; } @@ -3335,6 +3397,8 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { features().arb_texture_rectangle ? 1 : 0; resources.OES_EGL_image_external = features().oes_egl_image_external ? 1 : 0; + resources.NV_EGL_stream_consumer_external = + features().nv_egl_stream_consumer_external ? 1 : 0; resources.EXT_draw_buffers = features().ext_draw_buffers ? 1 : 0; resources.EXT_frag_depth = @@ -3352,6 +3416,8 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { features().arb_texture_rectangle ? 1 : 0; resources.OES_EGL_image_external = features().oes_egl_image_external ? 1 : 0; + resources.NV_EGL_stream_consumer_external = + features().nv_egl_stream_consumer_external ? 1 : 0; resources.EXT_blend_func_extended = features().ext_blend_func_extended ? 1 : 0; break; @@ -3419,7 +3485,7 @@ bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) { return false; } } - scoped_ptr<GLuint[]> service_ids(new GLuint[n]); + std::unique_ptr<GLuint[]> service_ids(new GLuint[n]); glGenBuffersARB(n, service_ids.get()); for (GLsizei ii = 0; ii < n; ++ii) { CreateBuffer(client_ids[ii], service_ids[ii]); @@ -3434,7 +3500,7 @@ bool GLES2DecoderImpl::GenFramebuffersHelper( return false; } } - scoped_ptr<GLuint[]> service_ids(new GLuint[n]); + std::unique_ptr<GLuint[]> service_ids(new GLuint[n]); glGenFramebuffersEXT(n, service_ids.get()); for (GLsizei ii = 0; ii < n; ++ii) { CreateFramebuffer(client_ids[ii], service_ids[ii]); @@ -3449,7 +3515,7 @@ bool GLES2DecoderImpl::GenRenderbuffersHelper( return false; } } - scoped_ptr<GLuint[]> service_ids(new GLuint[n]); + std::unique_ptr<GLuint[]> service_ids(new GLuint[n]); glGenRenderbuffersEXT(n, service_ids.get()); for (GLsizei ii = 0; ii < n; ++ii) { CreateRenderbuffer(client_ids[ii], service_ids[ii]); @@ -3457,43 +3523,45 @@ bool GLES2DecoderImpl::GenRenderbuffersHelper( return true; } -bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n, - const GLuint* client_ids) { +bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) { for (GLsizei ii = 0; ii < n; ++ii) { - if (GetValuebuffer(client_ids[ii])) { + if (GetTexture(client_ids[ii])) { return false; } } + std::unique_ptr<GLuint[]> service_ids(new GLuint[n]); + glGenTextures(n, service_ids.get()); for (GLsizei ii = 0; ii < n; ++ii) { - CreateValuebuffer(client_ids[ii]); + CreateTexture(client_ids[ii], service_ids[ii]); } return true; } -bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) { +bool GLES2DecoderImpl::GenSamplersHelper(GLsizei n, const GLuint* client_ids) { for (GLsizei ii = 0; ii < n; ++ii) { - if (GetTexture(client_ids[ii])) { + if (GetSampler(client_ids[ii])) { return false; } } - scoped_ptr<GLuint[]> service_ids(new GLuint[n]); - glGenTextures(n, service_ids.get()); + std::unique_ptr<GLuint[]> service_ids(new GLuint[n]); + glGenSamplers(n, service_ids.get()); for (GLsizei ii = 0; ii < n; ++ii) { - CreateTexture(client_ids[ii], service_ids[ii]); + CreateSampler(client_ids[ii], service_ids[ii]); } return true; } -bool GLES2DecoderImpl::GenSamplersHelper(GLsizei n, const GLuint* client_ids) { +bool GLES2DecoderImpl::GenTransformFeedbacksHelper( + GLsizei n, const GLuint* client_ids) { for (GLsizei ii = 0; ii < n; ++ii) { - if (GetSampler(client_ids[ii])) { + if (GetTransformFeedback(client_ids[ii])) { return false; } } - scoped_ptr<GLuint[]> service_ids(new GLuint[n]); - glGenSamplers(n, service_ids.get()); + std::unique_ptr<GLuint[]> service_ids(new GLuint[n]); + glGenTransformFeedbacks(n, service_ids.get()); for (GLsizei ii = 0; ii < n; ++ii) { - CreateSampler(client_ids[ii], service_ids[ii]); + CreateTransformFeedback(client_ids[ii], service_ids[ii]); } return true; } @@ -3541,6 +3609,7 @@ void GLES2DecoderImpl::DeleteBuffersHelper( if (buffer && !buffer->IsDeleted()) { buffer->RemoveMappedRange(); state_.RemoveBoundBuffer(buffer); + transform_feedback_manager_->RemoveBoundBuffer(buffer); RemoveBuffer(client_ids[ii]); } } @@ -3612,20 +3681,6 @@ void GLES2DecoderImpl::DeleteRenderbuffersHelper( } } -void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper( - GLsizei n, - const GLuint* client_ids) { - for (GLsizei ii = 0; ii < n; ++ii) { - Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]); - if (valuebuffer) { - if (state_.bound_valuebuffer.get() == valuebuffer) { - state_.bound_valuebuffer = NULL; - } - RemoveValuebuffer(client_ids[ii]); - } - } -} - void GLES2DecoderImpl::DeleteTexturesHelper( GLsizei n, const GLuint* client_ids) { bool supports_separate_framebuffer_binds = @@ -3680,9 +3735,27 @@ void GLES2DecoderImpl::DeleteSamplersHelper( } } -// } // anonymous namespace +void GLES2DecoderImpl::DeleteTransformFeedbacksHelper( + GLsizei n, const GLuint* client_ids) { + for (GLsizei ii = 0; ii < n; ++ii) { + TransformFeedback* transform_feedback = GetTransformFeedback( + client_ids[ii]); + if (transform_feedback) { + if (state_.bound_transform_feedback.get() == transform_feedback) { + // Bind to the default transform feedback. + DCHECK(state_.default_transform_feedback.get()); + state_.default_transform_feedback->DoBindTransformFeedback( + GL_TRANSFORM_FEEDBACK); + state_.bound_transform_feedback = + state_.default_transform_feedback.get(); + } + RemoveTransformFeedback(client_ids[ii]); + } + } +} bool GLES2DecoderImpl::MakeCurrent() { + DCHECK(surface_); if (!context_.get()) return false; @@ -3763,6 +3836,7 @@ bool GLES2DecoderImpl::CheckFramebufferValid( Framebuffer* framebuffer, GLenum target, bool clear_uncleared_images, + GLenum gl_error, const char* func_name) { if (!framebuffer) { if (surfaceless_) @@ -3802,8 +3876,7 @@ bool GLES2DecoderImpl::CheckFramebufferValid( GLenum completeness = framebuffer->IsPossiblyComplete(feature_info_.get()); if (completeness != GL_FRAMEBUFFER_COMPLETE) { - LOCAL_SET_GL_ERROR( - GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete"); + LOCAL_SET_GL_ERROR(gl_error, func_name, "framebuffer incomplete"); return false; } @@ -3816,8 +3889,7 @@ bool GLES2DecoderImpl::CheckFramebufferValid( if (framebuffer->GetStatus(texture_manager(), target) != GL_FRAMEBUFFER_COMPLETE) { LOCAL_SET_GL_ERROR( - GL_INVALID_FRAMEBUFFER_OPERATION, func_name, - "framebuffer incomplete (clear)"); + gl_error, func_name, "framebuffer incomplete (clear)"); return false; } ClearUnclearedAttachments(target, framebuffer); @@ -3828,8 +3900,7 @@ bool GLES2DecoderImpl::CheckFramebufferValid( if (framebuffer->GetStatus(texture_manager(), target) != GL_FRAMEBUFFER_COMPLETE) { LOCAL_SET_GL_ERROR( - GL_INVALID_FRAMEBUFFER_OPERATION, func_name, - "framebuffer incomplete (check)"); + gl_error, func_name, "framebuffer incomplete (check)"); return false; } framebuffer_manager()->MarkAsComplete(framebuffer); @@ -3843,17 +3914,20 @@ bool GLES2DecoderImpl::CheckBoundDrawFramebufferValid( GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER; Framebuffer* framebuffer = GetFramebufferInfoForTarget(target); bool valid = CheckFramebufferValid( - framebuffer, target, clear_uncleared_images, func_name); + framebuffer, target, clear_uncleared_images, + GL_INVALID_FRAMEBUFFER_OPERATION, func_name); if (valid && !features().chromium_framebuffer_multisample) OnUseFramebuffer(); return valid; } -bool GLES2DecoderImpl::CheckBoundReadFramebufferValid(const char* func_name) { +bool GLES2DecoderImpl::CheckBoundReadFramebufferValid( + const char* func_name, GLenum gl_error) { GLenum target = features().chromium_framebuffer_multisample ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER; Framebuffer* framebuffer = GetFramebufferInfoForTarget(target); - bool valid = CheckFramebufferValid(framebuffer, target, true, func_name); + bool valid = CheckFramebufferValid( + framebuffer, target, true, gl_error, func_name); return valid; } @@ -4081,24 +4155,26 @@ void GLES2DecoderImpl::Destroy(bool have_context) { if (!initialized()) return; - DCHECK(!have_context || context_->IsCurrent(NULL)); + DCHECK(!have_context || context_->IsCurrent(nullptr)); // Unbind everything. - state_.vertex_attrib_manager = NULL; - state_.default_vertex_attrib_manager = NULL; + state_.vertex_attrib_manager = nullptr; + state_.default_vertex_attrib_manager = nullptr; state_.texture_units.clear(); state_.sampler_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; - framebuffer_state_.bound_read_framebuffer = NULL; - framebuffer_state_.bound_draw_framebuffer = NULL; - state_.bound_renderbuffer = NULL; - state_.bound_valuebuffer = NULL; + state_.bound_array_buffer = nullptr; + state_.bound_copy_read_buffer = nullptr; + state_.bound_copy_write_buffer = nullptr; + state_.bound_pixel_pack_buffer = nullptr; + state_.bound_pixel_unpack_buffer = nullptr; + state_.bound_transform_feedback_buffer = nullptr; + state_.bound_uniform_buffer = nullptr; + framebuffer_state_.bound_read_framebuffer = nullptr; + framebuffer_state_.bound_draw_framebuffer = nullptr; + state_.bound_renderbuffer = nullptr; + state_.bound_transform_feedback = nullptr; + state_.default_transform_feedback = nullptr; + state_.indexed_uniform_buffer_bindings = nullptr; if (offscreen_saved_color_texture_info_.get()) { DCHECK(offscreen_target_color_texture_); @@ -4192,6 +4268,14 @@ void GLES2DecoderImpl::Destroy(bool have_context) { vertex_array_manager_.reset(); } + if (transform_feedback_manager_.get()) { + if (!have_context) { + transform_feedback_manager_->MarkContextLost(); + } + transform_feedback_manager_->Destroy(); + transform_feedback_manager_.reset(); + } + if (image_manager_.get()) { image_manager_->Destroy(have_context); image_manager_.reset(); @@ -4240,11 +4324,22 @@ void GLES2DecoderImpl::Destroy(bool have_context) { void GLES2DecoderImpl::SetSurface( const scoped_refptr<gfx::GLSurface>& surface) { DCHECK(context_->IsCurrent(NULL)); - DCHECK(surface_.get()); + DCHECK(surface); surface_ = surface; RestoreCurrentFramebufferBindings(); } +void GLES2DecoderImpl::ReleaseSurface() { + if (!context_.get()) + return; + if (WasContextLost()) { + DLOG(ERROR) << " GLES2DecoderImpl: Trying to release lost context."; + return; + } + context_->ReleaseCurrent(surface_.get()); + surface_ = nullptr; +} + void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) { if (!offscreen_saved_color_texture_.get()) { LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context"; @@ -4513,7 +4608,7 @@ error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands, if (DebugImpl && doing_gpu_trace) gpu_tracer_->End(kTraceDecoder); - if (DebugImpl && debug()) { + if (DebugImpl && debug() && !WasContextLost()) { GLenum error; while ((error = glGetError()) != GL_NO_ERROR) { LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] " @@ -4624,76 +4719,79 @@ void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) { glBindBuffer(target, service_id); } -void GLES2DecoderImpl::DoBindBufferBase(GLenum target, GLuint index, - GLuint client_id) { - Buffer* buffer = NULL; - GLuint service_id = 0; - if (client_id != 0) { - buffer = GetBuffer(client_id); - if (!buffer) { - if (!group_->bind_generates_resource()) { - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, - "glBindBufferBase", - "id not generated by glGenBuffers"); - return; - } - - // It's a new id so make a buffer for it. - glGenBuffersARB(1, &service_id); - CreateBuffer(client_id, service_id); - buffer = GetBuffer(client_id); - } - } - LogClientServiceForInfo(buffer, client_id, "glBindBufferBase"); - if (buffer) { - // TODO(kbr): track indexed bound buffers. - service_id = buffer->service_id(); - } +void GLES2DecoderImpl::BindIndexedBufferImpl( + GLenum target, GLuint index, GLuint client_id, + GLintptr offset, GLsizeiptr size, + BindIndexedBufferFunctionType function_type, const char* function_name) { switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER: { - GLint max_transform_feedback_separate_attribs = 0; - DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, - &max_transform_feedback_separate_attribs); - if (index >= - static_cast<GLuint>(max_transform_feedback_separate_attribs)) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, - "glBindBufferBase", "index out of range"); + if (index >= group_->max_transform_feedback_separate_attribs()) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, + "index out of range"); + return; + } + DCHECK(state_.bound_transform_feedback.get()); + if (state_.bound_transform_feedback->active()) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "bound transform feedback is active"); return; } break; } case GL_UNIFORM_BUFFER: { - GLint max_uniform_buffer_bindings = 0; - DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, - &max_uniform_buffer_bindings); - if (index >= static_cast<GLuint>(max_uniform_buffer_bindings)) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, - "glBindBufferBase", "index out of range"); + if (index >= group_->max_uniform_buffer_bindings()) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, + "index out of range"); return; } break; } default: - LOCAL_SET_GL_ERROR_INVALID_ENUM( - "glBindBufferBase", target, "invalid target"); - return; + NOTREACHED(); + break; } - state_.SetBoundBuffer(target, buffer); - glBindBufferBase(target, index, service_id); -} -void GLES2DecoderImpl::DoBindBufferRange(GLenum target, GLuint index, - GLuint client_id, - GLintptr offset, - GLsizeiptr size) { - Buffer* buffer = NULL; + if (function_type == kBindBufferRange) { + switch (target) { + case GL_TRANSFORM_FEEDBACK_BUFFER: + if ((size % 4 != 0) || (offset % 4 != 0)) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, + "size or offset are not multiples of 4"); + return; + } + break; + case GL_UNIFORM_BUFFER: { + if (offset % group_->uniform_buffer_offset_alignment() != 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, + "offset is not a multiple of UNIFORM_BUFFER_OFFSET_ALIGNMENT"); + return; + } + break; + } + default: + NOTREACHED(); + break; + } + + if (client_id != 0) { + if (size <= 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "size <= 0"); + return; + } + if (offset < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0"); + return; + } + } + } + + Buffer* buffer = nullptr; GLuint service_id = 0; if (client_id != 0) { buffer = GetBuffer(client_id); if (!buffer) { if (!group_->bind_generates_resource()) { - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, - "glBindBufferRange", + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "id not generated by glGenBuffers"); return; } @@ -4702,14 +4800,51 @@ void GLES2DecoderImpl::DoBindBufferRange(GLenum target, GLuint index, glGenBuffersARB(1, &service_id); CreateBuffer(client_id, service_id); buffer = GetBuffer(client_id); + DCHECK(buffer); } - } - LogClientServiceForInfo(buffer, client_id, "glBindBufferRange"); - if (buffer) { - // TODO(kbr): track indexed bound buffers. service_id = buffer->service_id(); } - glBindBufferRange(target, index, service_id, offset, size); + LogClientServiceForInfo(buffer, client_id, function_name); + + scoped_refptr<IndexedBufferBindingHost> bindings; + switch (target) { + case GL_TRANSFORM_FEEDBACK_BUFFER: + bindings = state_.bound_transform_feedback.get(); + break; + case GL_UNIFORM_BUFFER: + bindings = state_.indexed_uniform_buffer_bindings.get(); + break; + default: + NOTREACHED(); + break; + } + DCHECK(bindings); + switch (function_type) { + case kBindBufferBase: + bindings->DoBindBufferBase(target, index, buffer); + break; + case kBindBufferRange: + bindings->DoBindBufferRange(target, index, buffer, offset, size); + break; + default: + NOTREACHED(); + break; + } + state_.SetBoundBuffer(target, buffer); +} + +void GLES2DecoderImpl::DoBindBufferBase(GLenum target, GLuint index, + GLuint client_id) { + BindIndexedBufferImpl(target, index, client_id, 0, 0, + kBindBufferBase, "glBindBufferBase"); +} + +void GLES2DecoderImpl::DoBindBufferRange(GLenum target, GLuint index, + GLuint client_id, + GLintptr offset, + GLsizeiptr size) { + BindIndexedBufferImpl(target, index, client_id, offset, size, + kBindBufferRange, "glBindBufferRange"); } bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() { @@ -4860,14 +4995,6 @@ uint32_t GLES2DecoderImpl::GetAndClearBackbufferClearBitsForTest() { void GLES2DecoderImpl::OnFboChanged() const { if (workarounds().restore_scissor_on_fbo_change) state_.fbo_binding_for_scissor_workaround_dirty = true; - - if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) { - GLint bound_fbo_unsigned = -1; - glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned); - GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned); - if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo) - surface_->NotifyWasBound(); - } } // Called after the FBO is checked for completeness. @@ -4993,10 +5120,20 @@ void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) { return; } LogClientServiceForInfo(texture, client_id, "glBindTexture"); + glBindTexture(target, texture->service_id()); if (texture->target() == 0) { texture_manager()->SetTarget(texture_ref, target); + if (!feature_info_->gl_version_info().BehavesLikeGLES() && + feature_info_->gl_version_info().IsAtLeastGL(3, 2)) { + // In Desktop GL core profile and GL ES, depth textures are always + // sampled to the RED channel, whereas on Desktop GL compatibility + // proifle, they are sampled to RED, LUMINANCE, INTENSITY, or ALPHA + // channel, depending on the DEPTH_TEXTURE_MODE value. + // In theory we only need to apply this for depth textures, but it is + // simpler to apply to all textures. + glTexParameteri(target, GL_DEPTH_TEXTURE_MODE, GL_RED); + } } - glBindTexture(target, texture->service_id()); } else { glBindTexture(target, 0); } @@ -5029,6 +5166,80 @@ void GLES2DecoderImpl::DoBindSampler(GLuint unit, GLuint client_id) { state_.sampler_units[unit] = sampler; } +void GLES2DecoderImpl::DoBindTransformFeedback( + GLenum target, GLuint client_id) { + const char* function_name = "glBindTransformFeedback"; + + TransformFeedback* transform_feedback = nullptr; + if (client_id != 0) { + transform_feedback = GetTransformFeedback(client_id); + if (!transform_feedback) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "id not generated by glGenTransformFeedbacks"); + return; + } + } else { + transform_feedback = state_.default_transform_feedback.get(); + } + DCHECK(transform_feedback); + if (transform_feedback == state_.bound_transform_feedback.get()) + return; + if (state_.bound_transform_feedback->active() && + !state_.bound_transform_feedback->paused()) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "currently bound transform feedback is active"); + return; + } + LogClientServiceForInfo(transform_feedback, client_id, function_name); + transform_feedback->DoBindTransformFeedback(target); + state_.bound_transform_feedback = transform_feedback; +} + +void GLES2DecoderImpl::DoBeginTransformFeedback(GLenum primitive_mode) { + const char* function_name = "glBeginTransformFeedback"; + DCHECK(state_.bound_transform_feedback.get()); + if (state_.bound_transform_feedback->active()) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "transform feedback is already active"); + return; + } + state_.bound_transform_feedback->DoBeginTransformFeedback(primitive_mode); +} + +void GLES2DecoderImpl::DoEndTransformFeedback() { + const char* function_name = "glEndTransformFeedback"; + DCHECK(state_.bound_transform_feedback.get()); + if (!state_.bound_transform_feedback->active()) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "transform feedback is not active"); + return; + } + // TODO(zmo): Validate binding points. + state_.bound_transform_feedback->DoEndTransformFeedback(); +} + +void GLES2DecoderImpl::DoPauseTransformFeedback() { + DCHECK(state_.bound_transform_feedback.get()); + if (!state_.bound_transform_feedback->active() || + state_.bound_transform_feedback->paused()) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glPauseTransformFeedback", + "transform feedback is not active or already paused"); + return; + } + state_.bound_transform_feedback->DoPauseTransformFeedback(); +} + +void GLES2DecoderImpl::DoResumeTransformFeedback() { + DCHECK(state_.bound_transform_feedback.get()); + if (!state_.bound_transform_feedback->active() || + !state_.bound_transform_feedback->paused()) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glResumeTransformFeedback", + "transform feedback is not active or not paused"); + return; + } + state_.bound_transform_feedback->DoResumeTransformFeedback(); +} + void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) { if (state_.vertex_attrib_manager->Enable(index, false)) { if (index != 0 || feature_info_->gl_version_info().BehavesLikeGLES()) { @@ -5041,49 +5252,32 @@ void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) { } } -void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target, - GLsizei numAttachments, - const GLenum* attachments) { - if (workarounds().disable_discard_framebuffer) - return; - - Framebuffer* framebuffer = - GetFramebufferInfoForTarget(GL_FRAMEBUFFER); - - // Validates the attachments. If one of them fails - // the whole command fails. - for (GLsizei i = 0; i < numAttachments; ++i) { - if ((framebuffer && - !validators_->attachment.IsValid(attachments[i])) || - (!framebuffer && - !validators_->backbuffer_attachment.IsValid(attachments[i]))) { - LOCAL_SET_GL_ERROR_INVALID_ENUM( - "glDiscardFramebufferEXT", attachments[i], "attachments"); - return; - } - } +void GLES2DecoderImpl::InvalidateFramebufferImpl( + GLenum target, GLsizei count, const GLenum* attachments, + GLint x, GLint y, GLsizei width, GLsizei height, + const char* function_name, FramebufferOperation op) { + Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER); - // Marks each one of them as not cleared - for (GLsizei i = 0; i < numAttachments; ++i) { + // Validates the attachments. If one of them fails, the whole command fails. + GLenum thresh0 = GL_COLOR_ATTACHMENT0 + group_->max_color_attachments(); + GLenum thresh1 = GL_COLOR_ATTACHMENT15; + for (GLsizei i = 0; i < count; ++i) { if (framebuffer) { - framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(), - texture_manager(), - attachments[i], - false); + if (attachments[i] >= thresh0 && attachments[i] <= thresh1) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, function_name, "invalid attachment"); + return; + } + if (!validators_->attachment.IsValid(attachments[i])) { + LOCAL_SET_GL_ERROR_INVALID_ENUM( + function_name, attachments[i], "attachments"); + return; + } } else { - switch (attachments[i]) { - case GL_COLOR_EXT: - backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT; - break; - case GL_DEPTH_EXT: - backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT; - break; - case GL_STENCIL_EXT: - backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT; - break; - default: - NOTREACHED(); - break; + if (!validators_->backbuffer_attachment.IsValid(attachments[i])) { + LOCAL_SET_GL_ERROR_INVALID_ENUM( + function_name, attachments[i], "attachments"); + return; } } } @@ -5091,8 +5285,8 @@ void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target, // If the default framebuffer is bound but we are still rendering to an // FBO, translate attachment names that refer to default framebuffer // channels to corresponding framebuffer attachments. - scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]); - for (GLsizei i = 0; i < numAttachments; ++i) { + std::unique_ptr<GLenum[]> translated_attachments(new GLenum[count]); + for (GLsizei i = 0; i < count; ++i) { GLenum attachment = attachments[i]; if (!framebuffer && GetBackbufferServiceId()) { switch (attachment) { @@ -5113,15 +5307,93 @@ void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target, translated_attachments[i] = attachment; } - if (feature_info_->gl_version_info().is_es3) { - glInvalidateFramebuffer( - target, numAttachments, translated_attachments.get()); - } else { - glDiscardFramebufferEXT( - target, numAttachments, translated_attachments.get()); + bool dirty = false; + switch (op) { + case kFramebufferDiscard: + if (feature_info_->gl_version_info().is_es3) { + glInvalidateFramebuffer( + target, count, translated_attachments.get()); + } else { + glDiscardFramebufferEXT( + target, count, translated_attachments.get()); + } + dirty = true; + break; + case kFramebufferInvalidate: + if (feature_info_->gl_version_info().IsLowerThanGL(4, 3)) { + // no-op since the function isn't supported. + } else { + glInvalidateFramebuffer( + target, count, translated_attachments.get()); + dirty = true; + } + break; + case kFramebufferInvalidateSub: + // Make it an no-op because we don't have a mechanism to mark partial + // pixels uncleared yet. + // TODO(zmo): Revisit this. + break; + } + + if (!dirty) + return; + + // Marks each one of them as not cleared. + for (GLsizei i = 0; i < count; ++i) { + if (framebuffer) { + framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(), + texture_manager(), + attachments[i], + false); + } else { + switch (attachments[i]) { + case GL_COLOR_EXT: + backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT; + break; + case GL_DEPTH_EXT: + backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT; + break; + case GL_STENCIL_EXT: + backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT; + break; + default: + NOTREACHED(); + break; + } + } } } +void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target, + GLsizei count, + const GLenum* attachments) { + if (workarounds().disable_discard_framebuffer) + return; + + const GLsizei kWidthNotUsed = 1; + const GLsizei kHeightNotUsed = 1; + InvalidateFramebufferImpl( + target, count, attachments, 0, 0, kWidthNotUsed, kHeightNotUsed, + "glDiscardFramebufferEXT", kFramebufferDiscard); +} + +void GLES2DecoderImpl::DoInvalidateFramebuffer( + GLenum target, GLsizei count, const GLenum* attachments) { + const GLsizei kWidthNotUsed = 1; + const GLsizei kHeightNotUsed = 1; + InvalidateFramebufferImpl( + target, count, attachments, 0, 0, kWidthNotUsed, kHeightNotUsed, + "glInvalidateFramebuffer", kFramebufferInvalidate); +} + +void GLES2DecoderImpl::DoInvalidateSubFramebuffer( + GLenum target, GLsizei count, const GLenum* attachments, + GLint x, GLint y, GLsizei width, GLsizei height) { + InvalidateFramebufferImpl( + target, count, attachments, x, y, width, height, + "glInvalidateSubFramebuffer", kFramebufferInvalidateSub); +} + void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) { if (state_.vertex_attrib_manager->Enable(index, true)) { glEnableVertexAttribArray(index); @@ -5211,50 +5483,52 @@ void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) { bool GLES2DecoderImpl::GetHelper( GLenum pname, GLint* params, GLsizei* num_written) { DCHECK(num_written); - if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { - switch (pname) { - case GL_IMPLEMENTATION_COLOR_READ_FORMAT: - *num_written = 1; - // Return the GL implementation's preferred format and (see below type) - // if we have the GL extension that exposes this. This allows the GPU - // client to use the implementation's preferred format for glReadPixels - // for optimisation. - // - // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error - // case when requested on integer/floating point buffers but which is - // acceptable on GLES2 and with the GL_OES_read_format extension. - // - // Therefore if an error occurs we swallow the error and use the - // internal implementation. + switch (pname) { + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: + case GL_IMPLEMENTATION_COLOR_READ_TYPE: + // They are not supported on Desktop GL until 4.1, but could be exposed + // through GL_OES_read_format extension. However, a conflicting extension + // GL_ARB_ES2_compatibility specifies an error case when requested on + // integer/floating point buffers. + // To simpify the handling, we just query and check for GL errors. If an + // GL error occur, we fall back to our internal implementation. + *num_written = 1; + if (!CheckBoundReadFramebufferValid("glGetIntegerv", + GL_INVALID_OPERATION)) { if (params) { - if (context_->HasExtension("GL_OES_read_format")) { - ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper", - GetErrorState()); - glGetIntegerv(pname, params); - if (glGetError() == GL_NO_ERROR) - return true; - } - *params = GLES2Util::GetGLReadPixelsImplementationFormat( - GetBoundReadFrameBufferInternalFormat(), - GetBoundReadFrameBufferTextureType(), - feature_info_->feature_flags().ext_read_format_bgra); + *params = 0; } return true; - case GL_IMPLEMENTATION_COLOR_READ_TYPE: - *num_written = 1; - if (params) { - if (context_->HasExtension("GL_OES_read_format")) { - ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper", - GetErrorState()); - glGetIntegerv(pname, params); - if (glGetError() == GL_NO_ERROR) - return true; + } + if (params) { + ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper", + GetErrorState()); + glGetIntegerv(pname, params); + if (glGetError() != GL_NO_ERROR) { + if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT) { + *params = GLES2Util::GetGLReadPixelsImplementationFormat( + GetBoundReadFrameBufferInternalFormat(), + GetBoundReadFrameBufferTextureType(), + feature_info_->feature_flags().ext_read_format_bgra); + } else { + *params = GLES2Util::GetGLReadPixelsImplementationType( + GetBoundReadFrameBufferInternalFormat(), + GetBoundReadFrameBufferTextureType()); } - *params = GLES2Util::GetGLReadPixelsImplementationType( - GetBoundReadFrameBufferInternalFormat(), - GetBoundReadFrameBufferTextureType()); } - return true; + if (*params == GL_HALF_FLOAT && + (feature_info_->context_type() == CONTEXT_TYPE_WEBGL1 || + feature_info_->context_type() == CONTEXT_TYPE_OPENGLES2)) { + *params = GL_HALF_FLOAT_OES; + } + } + return true; + default: + break; + } + + if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { + switch (pname) { case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *num_written = 1; if (params) { @@ -5697,7 +5971,7 @@ void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) { DCHECK(params); GLsizei num_written = 0; if (GetNumValuesReturnedForGLGet(pname, &num_written)) { - scoped_ptr<GLint[]> values(new GLint[num_written]); + std::unique_ptr<GLint[]> values(new GLint[num_written]); if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) { GetHelper(pname, values.get(), &num_written); } @@ -5715,7 +5989,7 @@ void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) { GLsizei num_written = 0; if (!state_.GetStateAsGLfloat(pname, params, &num_written)) { if (GetHelper(pname, NULL, &num_written)) { - scoped_ptr<GLint[]> values(new GLint[num_written]); + std::unique_ptr<GLint[]> values(new GLint[num_written]); GetHelper(pname, values.get(), &num_written); for (GLsizei ii = 0; ii < num_written; ++ii) { params[ii] = static_cast<GLfloat>(values[ii]); @@ -5760,6 +6034,67 @@ void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) { } } +template <typename TYPE> +void GLES2DecoderImpl::GetIndexedIntegerImpl( + const char* function_name, GLenum target, GLuint index, TYPE* data) { + DCHECK(data); + scoped_refptr<IndexedBufferBindingHost> bindings; + switch (target) { + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + if (index >= group_->max_transform_feedback_separate_attribs()) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "invalid index"); + return; + } + bindings = state_.bound_transform_feedback.get(); + break; + case GL_UNIFORM_BUFFER_BINDING: + case GL_UNIFORM_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_START: + if (index >= group_->max_uniform_buffer_bindings()) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "invalid index"); + return; + } + bindings = state_.indexed_uniform_buffer_bindings.get(); + break; + default: + NOTREACHED(); + break; + } + DCHECK(bindings); + switch (target) { + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + case GL_UNIFORM_BUFFER_BINDING: + { + Buffer* buffer = bindings->GetBufferBinding(index); + *data = static_cast<TYPE>(buffer ? buffer->service_id() : 0); + } + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_SIZE: + *data = static_cast<TYPE>(bindings->GetBufferSize(index)); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + case GL_UNIFORM_BUFFER_START: + *data = static_cast<TYPE>(bindings->GetBufferStart(index)); + break; + default: + NOTREACHED(); + break; + } +} + +void GLES2DecoderImpl::DoGetIntegeri_v( + GLenum target, GLuint index, GLint* data) { + GetIndexedIntegerImpl<GLint>("glGetIntegeri_v", target, index, data); +} + +void GLES2DecoderImpl::DoGetInteger64i_v( + GLenum target, GLuint index, GLint64* data) { + GetIndexedIntegerImpl<GLint64>("glGetInteger64i_v", target, index, data); +} + void GLES2DecoderImpl::DoGetProgramiv( GLuint program_id, GLenum pname, GLint* params) { Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv"); @@ -6061,15 +6396,6 @@ void GLES2DecoderImpl::DoClearBufferiv( return; ApplyDirtyState(); - switch (buffer) { - case GL_COLOR: - case GL_STENCIL: - break; - default: - LOCAL_SET_GL_ERROR( - GL_INVALID_ENUM, "glClearBufferiv", "invalid buffer"); - return; - } if (buffer == GL_COLOR) { if (drawbuffer < 0 || drawbuffer >= static_cast<GLint>(group_->max_draw_buffers())) { @@ -6105,14 +6431,6 @@ void GLES2DecoderImpl::DoClearBufferuiv( return; ApplyDirtyState(); - switch (buffer) { - case GL_COLOR: - break; - default: - LOCAL_SET_GL_ERROR( - GL_INVALID_ENUM, "glClearBufferuiv", "invalid buffer"); - return; - } if (drawbuffer < 0 || drawbuffer >= static_cast<GLint>(group_->max_draw_buffers())) { LOCAL_SET_GL_ERROR( @@ -6136,15 +6454,6 @@ void GLES2DecoderImpl::DoClearBufferfv( return; ApplyDirtyState(); - switch (buffer) { - case GL_COLOR: - case GL_DEPTH: - break; - default: - LOCAL_SET_GL_ERROR( - GL_INVALID_ENUM, "glClearBufferfv", "invalid buffer"); - return; - } if (buffer == GL_COLOR) { if (drawbuffer < 0 || drawbuffer >= static_cast<GLint>(group_->max_draw_buffers())) { @@ -6180,14 +6489,6 @@ void GLES2DecoderImpl::DoClearBufferfi( return; ApplyDirtyState(); - switch (buffer) { - case GL_DEPTH_STENCIL: - break; - default: - LOCAL_SET_GL_ERROR( - GL_INVALID_ENUM, "glClearBufferfi", "invalid buffer"); - return; - } if (drawbuffer != 0) { LOCAL_SET_GL_ERROR( GL_INVALID_VALUE, "glClearBufferfi", "invalid drawBuffer"); @@ -6483,34 +6784,46 @@ void GLES2DecoderImpl::DoFramebufferTexture2DCommon( void GLES2DecoderImpl::DoFramebufferTextureLayer( GLenum target, GLenum attachment, GLuint client_texture_id, GLint level, GLint layer) { - // TODO(zmo): Add full validation. - GLuint service_id = 0; - TextureRef* texture_ref = NULL; + const char* function_name = "glFramebufferTextureLayer"; + + TextureRef* texture_ref = nullptr; Framebuffer* framebuffer = GetFramebufferInfoForTarget(target); if (!framebuffer) { LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glFramebufferTextureLayer", "no framebuffer bound."); + GL_INVALID_OPERATION, function_name, "no framebuffer bound."); return; } + GLuint service_id = 0; + GLenum texture_target = 0; if (client_texture_id) { texture_ref = GetTexture(client_texture_id); if (!texture_ref) { LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glFramebufferTextureLayer", "unknown texture_ref"); + GL_INVALID_VALUE, function_name, "unknown texture"); return; } service_id = texture_ref->service_id(); + + texture_target = texture_ref->texture()->target(); + switch (texture_target) { + case GL_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: + break; + default: + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "texture is neither TEXTURE_3D nor TEXTURE_2D_ARRAY"); + return; + } + if (!texture_manager()->ValidForTarget(texture_target, level, + 0, 0, layer)) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, function_name, "invalid level or layer"); + return; + } } - LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferTextureLayer"); glFramebufferTextureLayer(target, attachment, service_id, level, layer); - GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferTextureLayer"); - if (error == GL_NO_ERROR) { - framebuffer->AttachTextureLayer(attachment, texture_ref, - texture_ref ? texture_ref->texture()->target() : 0, - level, layer); - } + framebuffer->AttachTextureLayer( + attachment, texture_ref, texture_target, level, layer); if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) { framebuffer_state_.clear_state_dirty = true; } @@ -6630,7 +6943,8 @@ void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM( DCHECK(!ShouldDeferReads() && !ShouldDeferDraws()); if (!CheckBoundDrawFramebufferValid(true, "glBlitFramebufferCHROMIUM") || - !CheckBoundReadFramebufferValid("glBlitFramebufferCHROMIUM")) { + !CheckBoundReadFramebufferValid("glBlitFramebufferCHROMIUM", + GL_INVALID_FRAMEBUFFER_OPERATION)) { return; } @@ -7008,23 +7322,6 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) { } void GLES2DecoderImpl::DoReadBuffer(GLenum src) { - switch (src) { - case GL_NONE: - case GL_BACK: - break; - default: - { - GLenum upper_limit = static_cast<GLenum>( - group_->max_color_attachments() + GL_COLOR_ATTACHMENT0); - if (src < GL_COLOR_ATTACHMENT0 || src >= upper_limit) { - LOCAL_SET_GL_ERROR( - GL_INVALID_ENUM, "glReadBuffer", "invalid enum for src"); - return; - } - } - break; - } - Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER); if (framebuffer) { if (src == GL_BACK) { @@ -7151,55 +7448,6 @@ void GLES2DecoderImpl::DoTexParameteriv( "glTexParameteriv", GetErrorState(), texture, pname, *params); } -bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) { - if (!state_.bound_valuebuffer.get()) { - // There is no valuebuffer bound - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, - "no valuebuffer in use"); - return false; - } - return true; -} - -bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription( - GLenum subscription, - const char* function_name) { - if (!CheckCurrentValuebuffer(function_name)) { - return false; - } - if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) { - // The valuebuffer is not subscribed to the target - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, - "valuebuffer is not subscribed"); - return false; - } - return true; -} - -bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location, - GLenum subscription, - const char* function_name) { - if (!CheckCurrentProgramForUniform(location, function_name)) { - return false; - } - GLint real_location = -1; - GLint array_index = -1; - const Program::UniformInfo* info = - state_.current_program->GetUniformInfoByFakeLocation( - location, &real_location, &array_index); - if (!info) { - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location"); - return false; - } - if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) & - info->accepts_api_type) == 0) { - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, - "wrong type for subscription"); - return false; - } - return true; -} - bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) { if (!state_.current_program.get()) { // The program does not exist. @@ -7379,7 +7627,7 @@ void GLES2DecoderImpl::DoUniform1fv( return; } if (type == GL_BOOL) { - scoped_ptr<GLint[]> temp(new GLint[count]); + std::unique_ptr<GLint[]> temp(new GLint[count]); for (GLsizei ii = 0; ii < count; ++ii) { temp[ii] = static_cast<GLint>(value[ii] != 0.0f); } @@ -7403,7 +7651,7 @@ void GLES2DecoderImpl::DoUniform2fv( } if (type == GL_BOOL_VEC2) { GLsizei num_values = count * 2; - scoped_ptr<GLint[]> temp(new GLint[num_values]); + std::unique_ptr<GLint[]> temp(new GLint[num_values]); for (GLsizei ii = 0; ii < num_values; ++ii) { temp[ii] = static_cast<GLint>(value[ii] != 0.0f); } @@ -7427,7 +7675,7 @@ void GLES2DecoderImpl::DoUniform3fv( } if (type == GL_BOOL_VEC3) { GLsizei num_values = count * 3; - scoped_ptr<GLint[]> temp(new GLint[num_values]); + std::unique_ptr<GLint[]> temp(new GLint[num_values]); for (GLsizei ii = 0; ii < num_values; ++ii) { temp[ii] = static_cast<GLint>(value[ii] != 0.0f); } @@ -7451,7 +7699,7 @@ void GLES2DecoderImpl::DoUniform4fv( } if (type == GL_BOOL_VEC4) { GLsizei num_values = count * 4; - scoped_ptr<GLint[]> temp(new GLint[num_values]); + std::unique_ptr<GLint[]> temp(new GLint[num_values]); for (GLsizei ii = 0; ii < num_values; ++ii) { temp[ii] = static_cast<GLint>(value[ii] != 0.0f); } @@ -7751,27 +7999,35 @@ void GLES2DecoderImpl::DoUniformMatrix4x3fv( } void GLES2DecoderImpl::DoUseProgram(GLuint program_id) { + const char* function_name = "glUseProgram"; GLuint service_id = 0; - Program* program = NULL; + Program* program = nullptr; if (program_id) { - program = GetProgramInfoNotShader(program_id, "glUseProgram"); + program = GetProgramInfoNotShader(program_id, function_name); if (!program) { return; } if (!program->IsValid()) { // Program was not linked successfully. (ie, glLinkProgram) LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, "glUseProgram", "program not linked"); + GL_INVALID_OPERATION, function_name, "program not linked"); return; } service_id = program->service_id(); } + if (state_.bound_transform_feedback.get() && + state_.bound_transform_feedback->active() && + !state_.bound_transform_feedback->paused()) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "transformfeedback is active and not paused"); + return; + } if (state_.current_program.get()) { program_manager()->UnuseProgram(shader_manager(), state_.current_program.get()); } state_.current_program = program; - LogClientServiceMapping("glUseProgram", program_id, service_id); + LogClientServiceMapping(function_name, program_id, service_id); glUseProgram(service_id); if (state_.current_program.get()) { program_manager()->UseProgram(state_.current_program.get()); @@ -7798,9 +8054,9 @@ void GLES2DecoderImpl::DoCopyTexImage(Texture* texture, // as that allows the GLImage implemenatation to set it back to UNBOUND // and ensure that CopyTexImage() is called each time the texture is // used. - texture->SetLevelImage(textarget, 0, image, Texture::COPIED); + texture->SetLevelImageState(textarget, 0, Texture::COPIED); bool rv = image->CopyTexImage(textarget); - DCHECK(rv) << "Both BindTexImage() and CopyTexImage() failed"; + DCHECK(rv) << "CopyTexImage() failed"; } void GLES2DecoderImpl::DoCopyTexImageIfNeeded(Texture* texture, @@ -8180,7 +8436,7 @@ bool GLES2DecoderImpl::SimulateFixedAttribs( int num_elements = attrib->size() * num_vertices; const int src_size = num_elements * sizeof(int32_t); const int dst_size = num_elements * sizeof(float); - scoped_ptr<float[]> data(new float[num_elements]); + std::unique_ptr<float[]> data(new float[num_elements]); const int32_t* src = reinterpret_cast<const int32_t*>( attrib->buffer()->GetRange(attrib->offset(), src_size)); const int32_t* end = src + num_elements; @@ -8240,6 +8496,15 @@ error::Error GLES2DecoderImpl::DoDrawArrays( return error::kNoError; } + if (state_.bound_transform_feedback.get() && + state_.bound_transform_feedback->active() && + !state_.bound_transform_feedback->paused() && + mode != state_.bound_transform_feedback->primitive_mode()) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "mode is not identical with active transformfeedback's primitiveMode"); + return error::kNoError; + } + if (count == 0 || primcount == 0) { LOCAL_RENDER_WARNING("Render count or primcount is 0."); return error::kNoError; @@ -8353,6 +8618,14 @@ error::Error GLES2DecoderImpl::DoDrawElements(const char* function_name, return error::kNoError; } + if (state_.bound_transform_feedback.get() && + state_.bound_transform_feedback->active() && + !state_.bound_transform_feedback->paused()) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "transformfeedback is active and not paused"); + return error::kNoError; + } + if (count == 0 || primcount == 0) { return error::kNoError; } @@ -8408,7 +8681,6 @@ error::Error GLES2DecoderImpl::DoDrawElements(const char* function_name, } else { glDrawElementsInstancedANGLE(mode, count, type, indices, primcount); } - if (state_.enable_flags.primitive_restart_fixed_index && feature_info_->feature_flags(). emulate_primitive_restart_fixed_index) { @@ -8708,6 +8980,12 @@ bool GLES2DecoderImpl::DoIsSampler(GLuint client_id) { return sampler && !sampler->IsDeleted(); } +bool GLES2DecoderImpl::DoIsTransformFeedback(GLuint client_id) { + const TransformFeedback* transform_feedback = + GetTransformFeedback(client_id); + return transform_feedback && transform_feedback->has_been_bound(); +} + void GLES2DecoderImpl::DoAttachShader( GLuint program_client_id, GLint shader_client_id) { Program* program = GetProgramInfoNotShader( @@ -8820,37 +9098,52 @@ void GLES2DecoderImpl::DoGetSamplerParameteriv( glGetSamplerParameteriv(sampler->service_id(), pname, params); } -void GLES2DecoderImpl::DoGetTexParameterfv( - GLenum target, GLenum pname, GLfloat* params) { - InitTextureMaxAnisotropyIfNeeded(target, pname); - glGetTexParameterfv(target, pname, params); -} - -void GLES2DecoderImpl::DoGetTexParameteriv( - GLenum target, GLenum pname, GLint* params) { - InitTextureMaxAnisotropyIfNeeded(target, pname); - glGetTexParameteriv(target, pname, params); -} - -void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded( - GLenum target, GLenum pname) { - if (!workarounds().init_texture_max_anisotropy) - return; - if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT || - !validators_->texture_parameter.IsValid(pname)) { - return; - } - +void GLES2DecoderImpl::GetTexParameterImpl( + GLenum target, GLenum pname, GLfloat* fparams, GLint* iparams, + const char* function_name) { TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( &state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glGetTexParamter{fi}v", "unknown texture for target"); + GL_INVALID_OPERATION, function_name, "unknown texture for target"); return; } Texture* texture = texture_ref->texture(); - texture->InitTextureMaxAnisotropyIfNeeded(target); + switch (pname) { + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (workarounds().init_texture_max_anisotropy) { + texture->InitTextureMaxAnisotropyIfNeeded(target); + } + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (feature_info_->gl_version_info().IsLowerThanGL(4, 2)) { + GLint levels = texture->GetImmutableLevels(); + if (fparams) { + fparams[0] = static_cast<GLfloat>(levels); + } else { + iparams[0] = levels; + } + return; + } + break; + default: + break; + } + if (fparams) { + glGetTexParameterfv(target, pname, fparams); + } else { + glGetTexParameteriv(target, pname, iparams); + } +} + +void GLES2DecoderImpl::DoGetTexParameterfv( + GLenum target, GLenum pname, GLfloat* params) { + GetTexParameterImpl(target, pname, params, nullptr, "glGetTexParameterfv"); +} + +void GLES2DecoderImpl::DoGetTexParameteriv( + GLenum target, GLenum pname, GLint* params) { + GetTexParameterImpl(target, pname, nullptr, params, "glGetTexParameteriv"); } template <typename T> @@ -9454,7 +9747,8 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32_t immediate_data_size, return error::kNoError; } - if (!CheckBoundReadFramebufferValid("glReadPixels")) { + if (!CheckBoundReadFramebufferValid("glReadPixels", + GL_INVALID_FRAMEBUFFER_OPERATION)) { return error::kNoError; } GLenum src_internal_format = GetBoundReadFrameBufferInternalFormat(); @@ -9508,11 +9802,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32_t immediate_data_size, case GL_HALF_FLOAT_OES: case GL_FLOAT: case GL_UNSIGNED_INT_10F_11F_11F_REV: - if (!feature_info_->IsES3Enabled()) { - accepted_types.push_back(GL_UNSIGNED_BYTE); - } else { - accepted_types.push_back(GL_FLOAT); - } + accepted_types.push_back(GL_FLOAT); break; default: accepted_types.push_back(GL_UNSIGNED_BYTE); @@ -9550,6 +9840,10 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32_t immediate_data_size, "format and type incompatible with the current read framebuffer"); return error::kNoError; } + if (type == GL_HALF_FLOAT_OES && + !(feature_info_->gl_version_info().is_es2)) { + type = GL_HALF_FLOAT; + } if (width == 0 || height == 0) { return error::kNoError; } @@ -9568,7 +9862,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32_t immediate_data_size, LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels"); ScopedResolvedFrameBufferBinder binder(this, false, true); - scoped_ptr<ScopedFrameBufferReadPixelHelper> helper; + std::unique_ptr<ScopedFrameBufferReadPixelHelper> helper; if (NeedsIOSurfaceReadbackWorkaround()) helper.reset(new ScopedFrameBufferReadPixelHelper(&state_, this)); @@ -9847,9 +10141,17 @@ error::Error GLES2DecoderImpl::HandleScheduleCALayerCHROMIUM( const void* cmd_data) { const gles2::cmds::ScheduleCALayerCHROMIUM& c = *static_cast<const gles2::cmds::ScheduleCALayerCHROMIUM*>(cmd_data); + GLuint filter = c.filter; + if (filter != GL_NEAREST && filter != GL_LINEAR) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glScheduleCALayerCHROMIUM", + "invalid filter"); + return error::kNoError; + } + gl::GLImage* image = nullptr; - if (c.contents_texture_id) { - TextureRef* ref = texture_manager()->GetTexture(c.contents_texture_id); + GLuint contents_texture_id = c.contents_texture_id; + if (contents_texture_id) { + TextureRef* ref = texture_manager()->GetTexture(contents_texture_id); if (!ref) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glScheduleCALayerCHROMIUM", "unknown texture"); @@ -9877,10 +10179,10 @@ error::Error GLES2DecoderImpl::HandleScheduleCALayerCHROMIUM( mem[13], mem[17], mem[21], mem[25], mem[14], mem[18], mem[22], mem[26], mem[15], mem[19], mem[23], mem[27]); - if (!surface_->ScheduleCALayer(image, contents_rect, c.opacity, - c.background_color, c.edge_aa_mask, - bounds_rect, c.is_clipped ? true : false, - clip_rect, transform, c.sorting_context_id)) { + if (!surface_->ScheduleCALayer( + image, contents_rect, c.opacity, c.background_color, c.edge_aa_mask, + bounds_rect, c.is_clipped ? true : false, clip_rect, transform, + c.sorting_context_id, filter)) { LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glScheduleCALayerCHROMIUM", "failed to schedule CALayer"); } @@ -10367,7 +10669,7 @@ bool GLES2DecoderImpl::ClearLevel(Texture* texture, } // Assumes the size has already been checked. - scoped_ptr<char[]> zero(new char[size]); + std::unique_ptr<char[]> zero(new char[size]); memset(zero.get(), 0, size); glBindTexture(texture->target(), texture->service_id()); @@ -10385,6 +10687,52 @@ bool GLES2DecoderImpl::ClearLevel(Texture* texture, return true; } +bool GLES2DecoderImpl::ClearCompressedTextureLevel(Texture* texture, + unsigned target, + int level, + unsigned format, + int width, + int height) { + DCHECK(target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY); + // This code path can only be called if the texture was originally + // allocated via TexStorage2D. Note that TexStorage2D is exposed + // internally for ES 2.0 contexts, but compressed texture support is + // not part of that exposure. + DCHECK(feature_info_->IsES3Enabled()); + + GLsizei bytes_required = 0; + if (!GetCompressedTexSizeInBytes( + "ClearCompressedTextureLevel", width, height, 1, format, + &bytes_required)) { + return false; + } + + TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearCompressedTextureLevel", + "bytes_required", bytes_required); + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + std::unique_ptr<char[]> zero(new char[bytes_required]); + memset(zero.get(), 0, bytes_required); + glBindTexture(texture->target(), texture->service_id()); + glCompressedTexSubImage2D( + target, level, 0, 0, width, height, format, bytes_required, zero.get()); + TextureRef* bound_texture = + texture_manager()->GetTextureInfoForTarget(&state_, texture->target()); + glBindTexture(texture->target(), + bound_texture ? bound_texture->service_id() : 0); + Buffer* bound_buffer = buffer_manager()->GetBufferInfoForTarget( + &state_, GL_PIXEL_UNPACK_BUFFER); + if (bound_buffer) { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bound_buffer->service_id()); + } + return true; +} + +bool GLES2DecoderImpl::IsCompressedTextureFormat(unsigned format) { + return feature_info_->validators()->compressed_texture_format.IsValid( + format); +} + bool GLES2DecoderImpl::ClearLevel3D(Texture* texture, unsigned target, int level, @@ -10479,7 +10827,7 @@ bool GLES2DecoderImpl::ClearLevel3D(Texture* texture, // Include padding as some drivers incorrectly requires padding for the // last row. buffer_size += padding; - scoped_ptr<char[]> zero(new char[buffer_size]); + std::unique_ptr<char[]> zero(new char[buffer_size]); memset(zero.get(), 0, buffer_size); // TODO(zmo): Consider glMapBufferRange instead. glBufferData( @@ -10989,7 +11337,7 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D( framebuffer_state_.clear_state_dirty = true; } - scoped_ptr<int8_t[]> zero; + std::unique_ptr<int8_t[]> zero; if (!data) { zero.reset(new int8_t[image_size]); memset(zero.get(), 0, image_size); @@ -11184,7 +11532,7 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage3D( framebuffer_state_.clear_state_dirty = true; } - scoped_ptr<int8_t[]> zero; + std::unique_ptr<int8_t[]> zero; if (!data) { zero.reset(new int8_t[image_size]); memset(zero.get(), 0, image_size); @@ -11273,27 +11621,12 @@ void GLES2DecoderImpl::DoCompressedTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei image_size, const void* data) { - if (!validators_->texture_3_d_target.IsValid(target)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_ENUM, "glCompressedTexSubImage3D", "target"); - return; - } - if (!validators_->compressed_texture_format.IsValid(format)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM( - "glCompressedTexSubImage3D", format, "format"); - return; - } if (!texture_manager()->ValidForTarget(target, level, width, height, depth)) { LOCAL_SET_GL_ERROR( GL_INVALID_VALUE, "glCompressedTexSubImage3D", "dimensions out of range"); return; } - if (image_size < 0) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glCompressedTexSubImage3D", "imageSize < 0"); - return; - } TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( &state_, target); if (!texture_ref) { @@ -11304,8 +11637,10 @@ void GLES2DecoderImpl::DoCompressedTexSubImage3D( Texture* texture = texture_ref->texture(); GLenum type = 0, internal_format = 0; if (!texture->GetLevelType(target, level, &type, &internal_format)) { + std::string msg = base::StringPrintf( + "level %d does not exist", level); LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D", - "level does not exist"); + msg.c_str()); return; } if (internal_format != format) { @@ -11575,9 +11910,10 @@ void GLES2DecoderImpl::DoCompressedTexSubImage2D( GLenum type = 0; GLenum internal_format = 0; if (!texture->GetLevelType(target, level, &type, &internal_format)) { + std::string msg = base::StringPrintf( + "level %d does not exist", level); LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glCompressedTexSubImage2D", "level does not exist."); + GL_INVALID_OPERATION, "glCompressedTexSubImage2D", msg.c_str()); return; } if (internal_format != format) { @@ -11601,11 +11937,24 @@ void GLES2DecoderImpl::DoCompressedTexSubImage2D( return; } + if (!texture->IsLevelCleared(target, level)) { + // This can only happen if the compressed texture was allocated + // using TexStorage2D. + DCHECK(texture->IsImmutable()); + GLsizei level_width = 0, level_height = 0; + bool success = texture->GetLevelSize( + target, level, &level_width, &level_height, nullptr); + DCHECK(success); + // We can skip the clear if we're uploading the entire level. + if (xoffset == 0 && yoffset == 0 && + width == level_width && height == level_height) { + texture_manager()->SetLevelCleared(texture_ref, target, level, true); + } else { + texture_manager()->ClearTextureLevel(this, texture_ref, target, level); + } + DCHECK(texture->IsLevelCleared(target, level)); + } - // Note: There is no need to deal with texture cleared tracking here - // because the validation above means you can only get here if the level - // is already a matching compressed format and in that case - // CompressedTexImage2D already cleared the texture. glCompressedTexSubImage2D( target, level, xoffset, yoffset, width, height, format, image_size, data); @@ -11662,7 +12011,8 @@ void GLES2DecoderImpl::DoCopyTexImage2D( return; } - if (!CheckBoundReadFramebufferValid("glCopyTexImage2D")) { + if (!CheckBoundReadFramebufferValid("glCopyTexImage2D", + GL_INVALID_FRAMEBUFFER_OPERATION)) { return; } @@ -11750,7 +12100,7 @@ void GLES2DecoderImpl::DoCopyTexImage2D( copyWidth != width || copyHeight != height) { // some part was clipped so clear the rect. - scoped_ptr<char[]> zero(new char[pixels_size]); + std::unique_ptr<char[]> zero(new char[pixels_size]); memset(zero.get(), 0, pixels_size); glTexImage2D(target, level, texture_manager()->AdjustTexInternalFormat(internal_format), @@ -11861,7 +12211,8 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( return; } - if (!CheckBoundReadFramebufferValid("glCopyTexImage2D")) { + if (!CheckBoundReadFramebufferValid("glCopyTexImage2D", + GL_INVALID_FRAMEBUFFER_OPERATION)) { return; } @@ -12272,7 +12623,7 @@ error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32_t immediate_data_size, if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 || result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) { GLsizei num_values = result_size / sizeof(GLfloat); - scoped_ptr<GLint[]> temp(new GLint[num_values]); + std::unique_ptr<GLint[]> temp(new GLint[num_values]); glGetUniformiv(service_id, real_location, temp.get()); GLfloat* dst = result->GetData(); for (GLsizei ii = 0; ii < num_values; ++ii) { @@ -12633,7 +12984,7 @@ error::Error GLES2DecoderImpl::HandleShaderBinary(uint32_t immediate_data_size, if (shaders == NULL || binary == NULL) { return error::kOutOfBounds; } - scoped_ptr<GLuint[]> service_ids(new GLuint[n]); + std::unique_ptr<GLuint[]> service_ids(new GLuint[n]); for (GLsizei ii = 0; ii < n; ++ii) { Shader* shader = GetShader(shaders[ii]); if (!shader) { @@ -12858,7 +13209,7 @@ error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM( *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>( cmd_data); Bucket* bucket = CreateBucket(c.bucket_id); - scoped_refptr<FeatureInfo> info(new FeatureInfo()); + scoped_refptr<FeatureInfo> info(new FeatureInfo(workarounds())); DisallowedFeatures disallowed_features = feature_info_->disallowed_features(); disallowed_features.AllowExtensions(); info->Initialize(feature_info_->context_type(), disallowed_features); @@ -13108,6 +13459,10 @@ void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) { context_lost_reason_ = reason; current_decoder_error_ = error::kLostContext; context_was_lost_ = true; + + if (transform_feedback_manager_.get()) { + transform_feedback_manager_->MarkContextLost(); + } } bool GLES2DecoderImpl::CheckResetStatus() { @@ -13472,7 +13827,7 @@ bool GLES2DecoderImpl::GenVertexArraysOESHelper( CreateVertexAttribManager(client_ids[ii], 0, true); } } else { - scoped_ptr<GLuint[]> service_ids(new GLuint[n]); + std::unique_ptr<GLuint[]> service_ids(new GLuint[n]); glGenVertexArraysOES(n, service_ids.get()); for (GLsizei ii = 0; ii < n; ++ii) { @@ -13779,17 +14134,17 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( GLboolean unpack_premultiply_alpha, GLboolean unpack_unmultiply_alpha) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM"); - + static const char kFunctionName[] = "glCopyTextureCHROMIUM"; TextureRef* source_texture_ref = GetTexture(source_id); TextureRef* dest_texture_ref = GetTexture(dest_id); - if (!ValidateCopyTextureCHROMIUMTextures( - "glCopyTextureCHROMIUM", source_texture_ref, dest_texture_ref)) { + if (!ValidateCopyTextureCHROMIUMTextures(kFunctionName, source_texture_ref, + dest_texture_ref)) { return; } if (!ValidateCopyTextureCHROMIUMInternalFormats( - "glCopyTextureCHROMIUM", source_texture_ref, internal_format)) { + kFunctionName, source_texture_ref, internal_format)) { return; } @@ -13823,8 +14178,7 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( // Check that this type of texture is allowed. if (!texture_manager()->ValidForTarget(source_target, 0, source_width, source_height, 1)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions"); + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "Bad dimensions"); return; } } @@ -13835,7 +14189,7 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( &source_internal_format); if (dest_texture->IsImmutable()) { - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM", + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "texture is immutable"); return; } @@ -13843,21 +14197,12 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( // Clear the source texture if necessary. if (!texture_manager()->ClearTextureLevel(this, source_texture_ref, source_target, 0)) { - LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", - "dimensions too big"); + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, kFunctionName, "dimensions too big"); 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, features()); - RestoreCurrentFramebufferBindings(); - if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR) - return; - } + if (!InitializeCopyTextureCHROMIUM(kFunctionName)) + return; GLenum dest_type_previous = dest_type; GLenum dest_internal_format = internal_format; @@ -13877,14 +14222,14 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( dest_internal_format != internal_format || dest_type_previous != dest_type) { // Ensure that the glTexImage2D succeeds. - LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM"); + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(kFunctionName); glBindTexture(dest_target, dest_texture->service_id()); glTexImage2D(dest_target, 0, texture_manager()->AdjustTexInternalFormat(internal_format), source_width, source_height, 0, texture_manager()->AdjustTexFormat(internal_format), dest_type, NULL); - GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM"); + GLenum error = LOCAL_PEEK_GL_ERROR(kFunctionName); if (error != GL_NO_ERROR) { RestoreCurrentTextureBindings(&state_, dest_target); return; @@ -13950,11 +14295,12 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM( GLboolean unpack_unmultiply_alpha) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM"); + static const char kFunctionName[] = "glCopySubTextureCHROMIUM"; TextureRef* source_texture_ref = GetTexture(source_id); TextureRef* dest_texture_ref = GetTexture(dest_id); - if (!ValidateCopyTextureCHROMIUMTextures( - "glCopySubTextureCHROMIUM", source_texture_ref, dest_texture_ref)) { + if (!ValidateCopyTextureCHROMIUMTextures(kFunctionName, source_texture_ref, + dest_texture_ref)) { return; } @@ -13971,8 +14317,7 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM( source_width = size.width(); source_height = size.height(); if (source_width <= 0 || source_height <= 0) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM", - "invalid image size"); + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "invalid image size"); return; } @@ -13986,14 +14331,14 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM( int32_t max_y; if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y) || x < 0 || y < 0 || max_x > source_width || max_y > source_height) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM", + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "source texture bad dimensions"); return; } } else { if (!source_texture->GetLevelSize(source_target, 0, &source_width, &source_height, nullptr)) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM", + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "source texture has no level 0"); return; } @@ -14001,14 +14346,14 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM( // Check that this type of texture is allowed. if (!texture_manager()->ValidForTarget(source_target, 0, source_width, source_height, 1)) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM", + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "source texture bad dimensions"); return; } if (!source_texture->ValidForTexture(source_target, 0, x, y, 0, width, height, 1)) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM", + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "source texture bad dimensions."); return; } @@ -14024,41 +14369,32 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM( bool dest_level_defined = dest_texture->GetLevelType( dest_target, 0, &dest_type, &dest_internal_format); if (!dest_level_defined) { - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM", + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "destination texture is not defined"); return; } if (!dest_texture->ValidForTexture(dest_target, 0, xoffset, yoffset, 0, width, height, 1)) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM", + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "destination texture bad dimensions."); return; } - if (!ValidateCopyTextureCHROMIUMInternalFormats("glCopySubTextureCHROMIUM", - source_texture_ref, - dest_internal_format)) { + if (!ValidateCopyTextureCHROMIUMInternalFormats( + kFunctionName, source_texture_ref, dest_internal_format)) { return; } // Clear the source texture if necessary. if (!texture_manager()->ClearTextureLevel(this, source_texture_ref, source_target, 0)) { - LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, kFunctionName, "source texture dimensions too big"); 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("glCopySubTextureCHROMIUM"); - copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager()); - copy_texture_CHROMIUM_->Initialize(this, features()); - RestoreCurrentFramebufferBindings(); - if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR) - return; - } + if (!InitializeCopyTextureCHROMIUM(kFunctionName)) + return; int dest_width = 0; int dest_height = 0; @@ -14080,7 +14416,7 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM( // Otherwise clear part of texture level that is not already cleared. if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, dest_target, 0)) { - LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, kFunctionName, "destination texture dimensions too big"); return; } @@ -14133,16 +14469,29 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM( unpack_premultiply_alpha == GL_TRUE, unpack_unmultiply_alpha == GL_TRUE); } +bool GLES2DecoderImpl::InitializeCopyTextureCHROMIUM( + const char* function_name) { + // 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(function_name); + copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager()); + copy_texture_CHROMIUM_->Initialize(this, features()); + if (LOCAL_PEEK_GL_ERROR(function_name) != GL_NO_ERROR) + return false; + } + return true; +} + void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLuint source_id, GLuint dest_id) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM"); - + static const char kFunctionName[] = "glCompressedCopyTextureCHROMIUM"; TextureRef* source_texture_ref = GetTexture(source_id); TextureRef* dest_texture_ref = GetTexture(dest_id); if (!source_texture_ref || !dest_texture_ref) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopyTextureCHROMIUM", - "unknown texture ids"); + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "unknown texture ids"); return; } @@ -14157,16 +14506,13 @@ void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLuint source_id, 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"); + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "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", + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "source texture has no level 0"); return; } @@ -14174,9 +14520,7 @@ void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLuint source_id, // 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"); + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "Bad dimensions"); return; } } @@ -14187,34 +14531,23 @@ void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLuint source_id, source_texture->target(), 0, &source_type, &source_internal_format); if (dest_texture->IsImmutable()) { - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, - "glCompressedCopyTextureCHROMIUM", + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "texture is immutable"); return; } - if (!ValidateCompressedCopyTextureCHROMIUM( - "glCompressedCopyTextureCHROMIUM", - source_texture_ref, dest_texture_ref)) { + if (!ValidateCompressedCopyTextureCHROMIUM(kFunctionName, 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, features()); - RestoreCurrentFramebufferBindings(); - if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR) - return; - } + if (!InitializeCopyTextureCHROMIUM(kFunctionName)) + 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"); + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, kFunctionName, "dimensions too big"); return; } @@ -14242,16 +14575,16 @@ void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLuint source_id, GLsizei source_size = 0; bool did_get_size = GetCompressedTexSizeInBytes( - "glCompressedCopyTextureCHROMIUM", source_width, source_height, - 1, source_internal_format, &source_size); + kFunctionName, 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"); + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(kFunctionName); glCompressedTexImage2D(GL_TEXTURE_2D, 0, source_internal_format, source_width, source_height, 0, source_size, NULL); - GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM"); + GLenum error = LOCAL_PEEK_GL_ERROR(kFunctionName); if (error != GL_NO_ERROR) { RestoreCurrentTextureBindings(&state_, dest_texture->target()); return; @@ -14277,10 +14610,10 @@ void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLuint source_id, DoCopyTexImageIfNeeded(source_texture, source_texture->target()); // As a fallback, copy into a non-compressed GL_RGBA texture. - LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM"); + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(kFunctionName); glTexImage2D(dest_texture->target(), 0, GL_RGBA, source_width, source_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM"); + GLenum error = LOCAL_PEEK_GL_ERROR(kFunctionName); if (error != GL_NO_ERROR) { RestoreCurrentTextureBindings(&state_, dest_texture->target()); return; @@ -14298,143 +14631,36 @@ void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLuint source_id, false, false); } -void GLES2DecoderImpl::DoTexStorage2DEXT( - GLenum target, - GLint levels, - GLenum internal_format, - GLsizei width, - GLsizei height) { - TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT", - "width", width, "height", height); - if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) || - TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range"); +void GLES2DecoderImpl::TexStorageImpl(GLenum target, + GLsizei levels, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + ContextState::Dimension dimension, + const char* function_name) { + if (levels == 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "levels == 0"); return; } - TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( - &state_, target); - if (!texture_ref) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glTexStorage2DEXT", "unknown texture for target"); - return; - } - Texture* texture = texture_ref->texture(); - if (texture->IsAttachedToFramebuffer()) { - framebuffer_state_.clear_state_dirty = true; - } - if (texture->IsImmutable()) { + bool is_compressed_format = IsCompressedTextureFormat(internal_format); + if (is_compressed_format && target == GL_TEXTURE_3D) { LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glTexStorage2DEXT", "texture is immutable"); - return; - } - - GLenum format = TextureManager::ExtractFormatFromStorageFormat( - internal_format); - GLenum type = TextureManager::ExtractTypeFromStorageFormat(internal_format); - - { - GLsizei level_width = width; - GLsizei level_height = height; - uint32_t estimated_size = 0; - for (int ii = 0; ii < levels; ++ii) { - uint32_t level_size = 0; - if (!GLES2Util::ComputeImageDataSizes( - level_width, level_height, 1, format, type, state_.unpack_alignment, - &estimated_size, NULL, NULL) || - !SafeAddUint32(estimated_size, level_size, &estimated_size)) { - LOCAL_SET_GL_ERROR( - GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large"); - return; - } - level_width = std::max(1, level_width >> 1); - level_height = std::max(1, level_height >> 1); - } - if (!EnsureGPUMemoryAvailable(estimated_size)) { - LOCAL_SET_GL_ERROR( - GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory"); - return; - } - } - - LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT"); - glTexStorage2DEXT(target, levels, internal_format, width, height); - GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT"); - if (error == GL_NO_ERROR) { - GLsizei level_width = width; - GLsizei level_height = height; - - GLenum cur_format = feature_info_->IsES3Enabled() ? - internal_format : format; - for (int ii = 0; ii < levels; ++ii) { - if (target == GL_TEXTURE_CUBE_MAP) { - for (int jj = 0; jj < 6; ++jj) { - GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + jj; - texture_manager()->SetLevelInfo(texture_ref, face, ii, cur_format, - level_width, level_height, 1, 0, - format, type, gfx::Rect()); - } - } else { - texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_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); - } - texture->SetImmutable(true); - } -} - -void GLES2DecoderImpl::DoTexStorage3D( - GLenum target, - GLint levels, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLsizei depth) { - TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage3D", - "widthXheight", width * height, "depth", depth); - if (!validators_->texture_3_d_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexStorage3D", target, "target"); - return; - } - if (levels <= 0) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "levels <= 0"); - return; - } - if (!validators_->texture_internal_format_storage.IsValid(internal_format)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexStorage3D", internal_format, - "internal_format"); - return; - } - if (width <= 0) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "width <= 0"); - return; - } - if (height <= 0) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "height <= 0"); - return; - } - if (depth <= 0) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "depth <= 0"); + GL_INVALID_OPERATION, function_name, "target invalid for format"); return; } if (!texture_manager()->ValidForTarget(target, 0, width, height, depth) || TextureManager::ComputeMipMapCount( target, width, height, depth) < levels) { LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glTexStorage3D", "dimensions out of range"); + GL_INVALID_VALUE, function_name, "dimensions out of range"); return; } TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( &state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glTexStorage3D", "unknown texture for target"); + GL_INVALID_OPERATION, function_name, "unknown texture for target"); return; } Texture* texture = texture_ref->texture(); @@ -14443,7 +14669,7 @@ void GLES2DecoderImpl::DoTexStorage3D( } if (texture->IsImmutable()) { LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, "glTexStorage3D", "texture is immutable"); + GL_INVALID_OPERATION, function_name, "texture is immutable"); return; } @@ -14451,48 +14677,81 @@ void GLES2DecoderImpl::DoTexStorage3D( internal_format); GLenum type = TextureManager::ExtractTypeFromStorageFormat(internal_format); + std::vector<int32_t> level_size(levels); { GLsizei level_width = width; GLsizei level_height = height; GLsizei level_depth = depth; - uint32_t estimated_size = 0; + base::CheckedNumeric<uint32_t> estimated_size(0); + PixelStoreParams params; + params.alignment = 1; for (int ii = 0; ii < levels; ++ii) { - uint32_t level_size = 0; - if (!GLES2Util::ComputeImageDataSizes( - level_width, level_height, level_depth, format, type, - state_.unpack_alignment, - &estimated_size, NULL, NULL) || - !SafeAddUint32(estimated_size, level_size, &estimated_size)) { - LOCAL_SET_GL_ERROR( - GL_OUT_OF_MEMORY, "glTexStorage3D", "dimensions too large"); - return; + uint32_t size; + if (is_compressed_format) { + if (!GetCompressedTexSizeInBytes(function_name, + level_width, level_height, level_depth, + internal_format, &level_size[ii])) { + // GetCompressedTexSizeInBytes() already generates a GL error. + return; + } + size = static_cast<uint32_t>(level_size[ii]); + } else { + if (!GLES2Util::ComputeImageDataSizesES3(level_width, + level_height, + level_depth, + format, type, + params, + &size, + nullptr, nullptr, + nullptr, nullptr)) { + LOCAL_SET_GL_ERROR( + GL_OUT_OF_MEMORY, function_name, "dimensions too large"); + return; + } } + estimated_size += size; level_width = std::max(1, level_width >> 1); level_height = std::max(1, level_height >> 1); if (target == GL_TEXTURE_3D) level_depth = std::max(1, level_depth >> 1); } - if (!EnsureGPUMemoryAvailable(estimated_size)) { - LOCAL_SET_GL_ERROR( - GL_OUT_OF_MEMORY, "glTexStorage3D", "out of memory"); + if (!estimated_size.IsValid() || + !EnsureGPUMemoryAvailable(estimated_size.ValueOrDefault(0))) { + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "out of memory"); return; } } - LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage3D"); - glTexStorage3D(target, levels, internal_format, width, height, depth); - GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage3D"); - if (error == GL_NO_ERROR) { + // TODO(zmo): We might need to emulate TexStorage using TexImage or + // CompressedTexImage on Mac OSX where we expose ES3 APIs when the underlying + // driver is lower than 4.2 and ARB_texture_storage extension doesn't exist. + if (dimension == ContextState::k2D) { + glTexStorage2DEXT(target, levels, internal_format, width, height); + } else { + glTexStorage3D(target, levels, internal_format, width, height, depth); + } + + { GLsizei level_width = width; GLsizei level_height = height; GLsizei level_depth = depth; - - GLenum cur_format = feature_info_->IsES3Enabled() ? - internal_format : format; + GLenum adjusted_format = + feature_info_->IsES3Enabled() ? internal_format : format; for (int ii = 0; ii < levels; ++ii) { - texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_format, - level_width, level_height, level_depth, 0, - format, type, gfx::Rect()); + if (target == GL_TEXTURE_CUBE_MAP) { + for (int jj = 0; jj < 6; ++jj) { + GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + jj; + texture_manager()->SetLevelInfo(texture_ref, face, ii, + adjusted_format, + level_width, level_height, 1, + 0, format, type, gfx::Rect()); + } + } else { + texture_manager()->SetLevelInfo(texture_ref, target, ii, + adjusted_format, + level_width, level_height, level_depth, + 0, format, type, gfx::Rect()); + } level_width = std::max(1, level_width >> 1); level_height = std::max(1, level_height >> 1); if (target == GL_TEXTURE_3D) @@ -14502,6 +14761,29 @@ void GLES2DecoderImpl::DoTexStorage3D( } } +void GLES2DecoderImpl::DoTexStorage2DEXT(GLenum target, + GLsizei levels, + GLenum internal_format, + GLsizei width, + GLsizei height) { + TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2D", + "width", width, "height", height); + TexStorageImpl(target, levels, internal_format, width, height, 1, + ContextState::k2D, "glTexStorage2D"); +} + +void GLES2DecoderImpl::DoTexStorage3D(GLenum target, + GLsizei levels, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth) { + TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage3D", + "widthXheight", width * height, "depth", depth); + TexStorageImpl(target, levels, internal_format, width, height, depth, + ContextState::k3D, "glTexStorage3D"); +} + error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { @@ -14635,7 +14917,7 @@ error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate( cmd_data); GLenum target = static_cast<GLenum>(c.target); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -14702,73 +14984,6 @@ void GLES2DecoderImpl::DoApplyScreenSpaceAntialiasingCHROMIUM() { glApplyFramebufferAttachmentCMAAINTEL(); } -bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) { - const Valuebuffer* valuebuffer = GetValuebuffer(client_id); - return valuebuffer && valuebuffer->IsValid(); -} - -void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target, - GLuint client_id) { - Valuebuffer* valuebuffer = NULL; - if (client_id != 0) { - valuebuffer = GetValuebuffer(client_id); - if (!valuebuffer) { - if (!group_->bind_generates_resource()) { - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM", - "id not generated by glBindValuebufferCHROMIUM"); - return; - } - - // It's a new id so make a valuebuffer for it. - CreateValuebuffer(client_id); - valuebuffer = GetValuebuffer(client_id); - } - valuebuffer->MarkAsValid(); - } - state_.bound_valuebuffer = valuebuffer; -} - -void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target, - GLenum subscription) { - if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) { - return; - } - state_.bound_valuebuffer.get()->AddSubscription(subscription); -} - -void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) { - if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) { - return; - } - valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get()); -} - -void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription) { - if (!CheckCurrentValuebufferForSubscription( - subscription, "glPopulateSubscribedValuesCHROMIUM")) { - return; - } - if (!CheckSubscriptionTarget(location, subscription, - "glPopulateSubscribedValuesCHROMIUM")) { - return; - } - const ValueState* state = - state_.bound_valuebuffer.get()->GetState(subscription); - if (state) { - switch (subscription) { - case GL_MOUSE_POSITION_CHROMIUM: - DoUniform2iv(location, 1, state->int_value); - break; - default: - NOTREACHED() << "Unhandled uniform subscription target " - << subscription; - break; - } - } -} - void GLES2DecoderImpl::DoInsertEventMarkerEXT( GLsizei length, const GLchar* marker) { if (!marker) { @@ -15084,34 +15299,76 @@ error::Error GLES2DecoderImpl::HandleGetInternalformativ( 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); + std::vector<GLint> samples; + if (feature_info_->gl_version_info().IsLowerThanGL(4, 2)) { + if (!GLES2Util::IsIntegerFormat(format) && + !GLES2Util::IsFloatFormat(format)) { + // No multisampling for integer formats and float formats. + GLint max_samples = renderbuffer_manager()->max_samples(); + while (max_samples > 0) { + samples.push_back(max_samples); + max_samples = max_samples >> 1; } - break; - default: - NOTREACHED(); - break; + } + switch (pname) { + case GL_NUM_SAMPLE_COUNTS: + num_values = 1; + break; + case GL_SAMPLES: + num_values = static_cast<GLsizei>(samples.size()); + break; + default: + NOTREACHED(); + break; + } + } else { + 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) { + if (params == nullptr) { return error::kOutOfBounds; } // Check that the client initialized the result. if (result->size != 0) { return error::kInvalidArguments; } - glGetInternalformativ(target, format, pname, num_values, params); + if (feature_info_->gl_version_info().IsLowerThanGL(4, 2)) { + switch (pname) { + case GL_NUM_SAMPLE_COUNTS: + params[0] = static_cast<GLint>(samples.size()); + break; + case GL_SAMPLES: + for (size_t ii = 0; ii < samples.size(); ++ii) { + params[ii] = samples[ii]; + } + break; + default: + NOTREACHED(); + break; + } + } else { + glGetInternalformativ(target, format, pname, num_values, params); + } result->SetNumResults(num_values); return error::kNoError; } @@ -15354,7 +15611,7 @@ class PathCommandValidatorContext { bool GetPathNameData(const Cmd& cmd, GLuint num_paths, GLenum path_name_type, - scoped_ptr<GLuint[]>* out_buffer) { + std::unique_ptr<GLuint[]>* out_buffer) { DCHECK(validators_->path_name_type.IsValid(path_name_type)); GLuint path_base = static_cast<GLuint>(cmd.pathBase); uint32_t shm_id = static_cast<uint32_t>(cmd.paths_shm_id); @@ -15441,7 +15698,7 @@ class PathCommandValidatorContext { GLuint path_base, uint32_t shm_id, uint32_t shm_offset, - scoped_ptr<GLuint[]>* out_buffer) { + std::unique_ptr<GLuint[]>* out_buffer) { uint32_t paths_size = 0; if (!SafeMultiplyUint32(num_paths, sizeof(T), &paths_size)) { error_ = error::kOutOfBounds; @@ -15452,7 +15709,7 @@ class PathCommandValidatorContext { error_ = error::kOutOfBounds; return false; } - scoped_ptr<GLuint[]> result_paths(new GLuint[num_paths]); + std::unique_ptr<GLuint[]> result_paths(new GLuint[num_paths]); bool has_paths = false; for (GLuint i = 0; i < num_paths; ++i) { GLuint service_id = 0; @@ -15567,7 +15824,7 @@ error::Error GLES2DecoderImpl::HandlePathCommandsCHROMIUM( return error::kNoError; } - scoped_ptr<GLubyte[]> commands; + std::unique_ptr<GLubyte[]> commands; base::CheckedNumeric<GLsizei> num_coords_expected = 0; if (num_commands > 0) { @@ -15747,11 +16004,12 @@ error::Error GLES2DecoderImpl::HandlePathParameteriCHROMIUM( error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { + static const char kFunctionName[] = "glStencilFillPathCHROMIUM"; const gles2::cmds::StencilFillPathCHROMIUM& c = *static_cast<const gles2::cmds::StencilFillPathCHROMIUM*>(cmd_data); if (!features().chromium_path_rendering) return error::kUnknownCommand; - PathCommandValidatorContext v(this, "glStencilFillPathCHROMIUM"); + PathCommandValidatorContext v(this, kFunctionName); GLenum fill_mode = GL_COUNT_UP_CHROMIUM; GLuint mask = 0; if (!v.GetFillModeAndMask(c, &fill_mode, &mask)) @@ -15763,6 +16021,8 @@ error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM( // This holds for other rendering functions, too. return error::kNoError; } + if (!CheckBoundDrawFramebufferValid(true, kFunctionName)) + return error::kNoError; ApplyDirtyState(); glStencilFillPathNV(service_id, fill_mode, mask); return error::kNoError; @@ -15771,6 +16031,7 @@ error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM( error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { + static const char kFunctionName[] = "glStencilStrokePathCHROMIUM"; const gles2::cmds::StencilStrokePathCHROMIUM& c = *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM*>(cmd_data); if (!features().chromium_path_rendering) @@ -15782,6 +16043,8 @@ error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM( } GLint reference = static_cast<GLint>(c.reference); GLuint mask = static_cast<GLuint>(c.mask); + if (!CheckBoundDrawFramebufferValid(true, kFunctionName)) + return error::kNoError; ApplyDirtyState(); glStencilStrokePathNV(service_id, reference, mask); return error::kNoError; @@ -15790,12 +16053,13 @@ error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM( error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { + static const char kFunctionName[] = "glCoverFillPathCHROMIUM"; const gles2::cmds::CoverFillPathCHROMIUM& c = *static_cast<const gles2::cmds::CoverFillPathCHROMIUM*>(cmd_data); if (!features().chromium_path_rendering) return error::kUnknownCommand; - PathCommandValidatorContext v(this, "glCoverFillPathCHROMIUM"); + PathCommandValidatorContext v(this, kFunctionName); GLenum cover_mode = GL_BOUNDING_BOX_CHROMIUM; if (!v.GetCoverMode(c, &cover_mode)) return v.error(); @@ -15803,7 +16067,8 @@ error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM( GLuint service_id = 0; if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) return error::kNoError; - + if (!CheckBoundDrawFramebufferValid(true, kFunctionName)) + return error::kNoError; ApplyDirtyState(); glCoverFillPathNV(service_id, cover_mode); return error::kNoError; @@ -15812,12 +16077,13 @@ error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM( error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { + static const char kFunctionName[] = "glCoverStrokePathCHROMIUM"; const gles2::cmds::CoverStrokePathCHROMIUM& c = *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM*>(cmd_data); if (!features().chromium_path_rendering) return error::kUnknownCommand; - PathCommandValidatorContext v(this, "glCoverStrokePathCHROMIUM"); + PathCommandValidatorContext v(this, kFunctionName); GLenum cover_mode = GL_BOUNDING_BOX_CHROMIUM; if (!v.GetCoverMode(c, &cover_mode)) return v.error(); @@ -15826,6 +16092,8 @@ error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM( if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) return error::kNoError; + if (!CheckBoundDrawFramebufferValid(true, kFunctionName)) + return error::kNoError; ApplyDirtyState(); glCoverStrokePathNV(service_id, cover_mode); return error::kNoError; @@ -15834,13 +16102,14 @@ error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM( error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { + static const char kFunctionName[] = "glStencilThenCoverFillPathCHROMIUM"; const gles2::cmds::StencilThenCoverFillPathCHROMIUM& c = *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM*>( cmd_data); if (!features().chromium_path_rendering) return error::kUnknownCommand; - PathCommandValidatorContext v(this, "glStencilThenCoverFillPathCHROMIUM"); + PathCommandValidatorContext v(this, kFunctionName); GLenum fill_mode = GL_COUNT_UP_CHROMIUM; GLuint mask = 0; GLenum cover_mode = GL_BOUNDING_BOX_CHROMIUM; @@ -15852,6 +16121,8 @@ error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM( if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) return error::kNoError; + if (!CheckBoundDrawFramebufferValid(true, kFunctionName)) + return error::kNoError; ApplyDirtyState(); glStencilThenCoverFillPathNV(service_id, fill_mode, mask, cover_mode); return error::kNoError; @@ -15860,13 +16131,14 @@ error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM( error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { + static const char kFunctionName[] = "glStencilThenCoverStrokePathCHROMIUM"; const gles2::cmds::StencilThenCoverStrokePathCHROMIUM& c = *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM*>( cmd_data); if (!features().chromium_path_rendering) return error::kUnknownCommand; - PathCommandValidatorContext v(this, "glStencilThenCoverStrokePathCHROMIUM"); + PathCommandValidatorContext v(this, kFunctionName); GLenum cover_mode = GL_BOUNDING_BOX_CHROMIUM; if (!v.GetCoverMode(c, &cover_mode)) return v.error(); @@ -15877,6 +16149,9 @@ error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM( GLint reference = static_cast<GLint>(c.reference); GLuint mask = static_cast<GLuint>(c.mask); + + if (!CheckBoundDrawFramebufferValid(true, kFunctionName)) + return error::kNoError; ApplyDirtyState(); glStencilThenCoverStrokePathNV(service_id, reference, mask, cover_mode); return error::kNoError; @@ -15885,13 +16160,14 @@ error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM( error::Error GLES2DecoderImpl::HandleStencilFillPathInstancedCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { + static const char kFunctionName[] = "glStencilFillPathInstancedCHROMIUM"; const gles2::cmds::StencilFillPathInstancedCHROMIUM& c = *static_cast<const gles2::cmds::StencilFillPathInstancedCHROMIUM*>( cmd_data); if (!features().chromium_path_rendering) return error::kUnknownCommand; - PathCommandValidatorContext v(this, "glStencilFillPathInstancedCHROMIUM"); + PathCommandValidatorContext v(this, kFunctionName); GLuint num_paths = 0; GLenum path_name_type = GL_NONE; GLenum fill_mode = GL_COUNT_UP_CHROMIUM; @@ -15905,7 +16181,7 @@ error::Error GLES2DecoderImpl::HandleStencilFillPathInstancedCHROMIUM( if (num_paths == 0) return error::kNoError; - scoped_ptr<GLuint[]> paths; + std::unique_ptr<GLuint[]> paths; if (!v.GetPathNameData(c, num_paths, path_name_type, &paths)) return v.error(); @@ -15913,6 +16189,8 @@ error::Error GLES2DecoderImpl::HandleStencilFillPathInstancedCHROMIUM( if (!v.GetTransforms(c, num_paths, transform_type, &transforms)) return v.error(); + if (!CheckBoundDrawFramebufferValid(true, kFunctionName)) + return error::kNoError; ApplyDirtyState(); glStencilFillPathInstancedNV(num_paths, GL_UNSIGNED_INT, paths.get(), 0, fill_mode, mask, transform_type, transforms); @@ -15922,13 +16200,14 @@ error::Error GLES2DecoderImpl::HandleStencilFillPathInstancedCHROMIUM( error::Error GLES2DecoderImpl::HandleStencilStrokePathInstancedCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { + static const char kFunctionName[] = "glStencilStrokePathInstancedCHROMIUM"; const gles2::cmds::StencilStrokePathInstancedCHROMIUM& c = *static_cast<const gles2::cmds::StencilStrokePathInstancedCHROMIUM*>( cmd_data); if (!features().chromium_path_rendering) return error::kUnknownCommand; - PathCommandValidatorContext v(this, "glStencilStrokePathInstancedCHROMIUM"); + PathCommandValidatorContext v(this, kFunctionName); GLuint num_paths = 0; GLenum path_name_type = GL_NONE; GLenum transform_type = GL_NONE; @@ -15939,7 +16218,7 @@ error::Error GLES2DecoderImpl::HandleStencilStrokePathInstancedCHROMIUM( if (num_paths == 0) return error::kNoError; - scoped_ptr<GLuint[]> paths; + std::unique_ptr<GLuint[]> paths; if (!v.GetPathNameData(c, num_paths, path_name_type, &paths)) return v.error(); @@ -15949,6 +16228,8 @@ error::Error GLES2DecoderImpl::HandleStencilStrokePathInstancedCHROMIUM( GLint reference = static_cast<GLint>(c.reference); GLuint mask = static_cast<GLuint>(c.mask); + if (!CheckBoundDrawFramebufferValid(true, kFunctionName)) + return error::kNoError; ApplyDirtyState(); glStencilStrokePathInstancedNV(num_paths, GL_UNSIGNED_INT, paths.get(), 0, reference, mask, transform_type, transforms); @@ -15958,13 +16239,14 @@ error::Error GLES2DecoderImpl::HandleStencilStrokePathInstancedCHROMIUM( error::Error GLES2DecoderImpl::HandleCoverFillPathInstancedCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { + static const char kFunctionName[] = "glCoverFillPathInstancedCHROMIUM"; const gles2::cmds::CoverFillPathInstancedCHROMIUM& c = *static_cast<const gles2::cmds::CoverFillPathInstancedCHROMIUM*>( cmd_data); if (!features().chromium_path_rendering) return error::kUnknownCommand; - PathCommandValidatorContext v(this, "glCoverFillPathInstancedCHROMIUM"); + PathCommandValidatorContext v(this, kFunctionName); GLuint num_paths = 0; GLenum path_name_type = GL_NONE; GLenum cover_mode = GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM; @@ -15977,7 +16259,7 @@ error::Error GLES2DecoderImpl::HandleCoverFillPathInstancedCHROMIUM( if (num_paths == 0) return error::kNoError; - scoped_ptr<GLuint[]> paths; + std::unique_ptr<GLuint[]> paths; if (!v.GetPathNameData(c, num_paths, path_name_type, &paths)) return v.error(); @@ -15985,6 +16267,8 @@ error::Error GLES2DecoderImpl::HandleCoverFillPathInstancedCHROMIUM( if (!v.GetTransforms(c, num_paths, transform_type, &transforms)) return v.error(); + if (!CheckBoundDrawFramebufferValid(true, kFunctionName)) + return error::kNoError; ApplyDirtyState(); glCoverFillPathInstancedNV(num_paths, GL_UNSIGNED_INT, paths.get(), 0, cover_mode, transform_type, transforms); @@ -15994,13 +16278,14 @@ error::Error GLES2DecoderImpl::HandleCoverFillPathInstancedCHROMIUM( error::Error GLES2DecoderImpl::HandleCoverStrokePathInstancedCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { + static const char kFunctionName[] = "glCoverStrokePathInstancedCHROMIUM"; const gles2::cmds::CoverStrokePathInstancedCHROMIUM& c = *static_cast<const gles2::cmds::CoverStrokePathInstancedCHROMIUM*>( cmd_data); if (!features().chromium_path_rendering) return error::kUnknownCommand; - PathCommandValidatorContext v(this, "glCoverStrokePathInstancedCHROMIUM"); + PathCommandValidatorContext v(this, kFunctionName); GLuint num_paths = 0; GLenum path_name_type = GL_NONE; GLenum cover_mode = GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM; @@ -16013,7 +16298,7 @@ error::Error GLES2DecoderImpl::HandleCoverStrokePathInstancedCHROMIUM( if (num_paths == 0) return error::kNoError; - scoped_ptr<GLuint[]> paths; + std::unique_ptr<GLuint[]> paths; if (!v.GetPathNameData(c, num_paths, path_name_type, &paths)) return v.error(); @@ -16021,6 +16306,8 @@ error::Error GLES2DecoderImpl::HandleCoverStrokePathInstancedCHROMIUM( if (!v.GetTransforms(c, num_paths, transform_type, &transforms)) return v.error(); + if (!CheckBoundDrawFramebufferValid(true, kFunctionName)) + return error::kNoError; ApplyDirtyState(); glCoverStrokePathInstancedNV(num_paths, GL_UNSIGNED_INT, paths.get(), 0, cover_mode, transform_type, transforms); @@ -16030,14 +16317,16 @@ error::Error GLES2DecoderImpl::HandleCoverStrokePathInstancedCHROMIUM( error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathInstancedCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { + static const char kFunctionName[] = + "glStencilThenCoverFillPathInstancedCHROMIUM"; const gles2::cmds::StencilThenCoverFillPathInstancedCHROMIUM& c = *static_cast< const gles2::cmds::StencilThenCoverFillPathInstancedCHROMIUM*>( cmd_data); if (!features().chromium_path_rendering) return error::kUnknownCommand; - PathCommandValidatorContext v(this, - "glStencilThenCoverFillPathInstancedCHROMIUM"); + PathCommandValidatorContext v(this, kFunctionName); + GLuint num_paths = 0; GLenum path_name_type = GL_NONE; GLenum fill_mode = GL_COUNT_UP_CHROMIUM; @@ -16053,7 +16342,7 @@ error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathInstancedCHROMIUM( if (num_paths == 0) return error::kNoError; - scoped_ptr<GLuint[]> paths; + std::unique_ptr<GLuint[]> paths; if (!v.GetPathNameData(c, num_paths, path_name_type, &paths)) return v.error(); @@ -16061,6 +16350,8 @@ error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathInstancedCHROMIUM( if (!v.GetTransforms(c, num_paths, transform_type, &transforms)) return v.error(); + if (!CheckBoundDrawFramebufferValid(true, kFunctionName)) + return error::kNoError; ApplyDirtyState(); glStencilThenCoverFillPathInstancedNV(num_paths, GL_UNSIGNED_INT, paths.get(), 0, fill_mode, mask, cover_mode, @@ -16072,14 +16363,15 @@ error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathInstancedCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { + static const char kFunctionName[] = + "glStencilThenCoverStrokeInstancedCHROMIUM"; const gles2::cmds::StencilThenCoverStrokePathInstancedCHROMIUM& c = *static_cast< const gles2::cmds::StencilThenCoverStrokePathInstancedCHROMIUM*>( cmd_data); if (!features().chromium_path_rendering) return error::kUnknownCommand; - PathCommandValidatorContext v(this, - "glStencilThenCoverStrokeInstancedCHROMIUM"); + PathCommandValidatorContext v(this, kFunctionName); GLuint num_paths = 0; GLenum path_name_type = GL_NONE; GLenum cover_mode = GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM; @@ -16092,7 +16384,7 @@ GLES2DecoderImpl::HandleStencilThenCoverStrokePathInstancedCHROMIUM( if (num_paths == 0) return error::kNoError; - scoped_ptr<GLuint[]> paths; + std::unique_ptr<GLuint[]> paths; if (!v.GetPathNameData(c, num_paths, path_name_type, &paths)) return v.error(); @@ -16102,6 +16394,9 @@ GLES2DecoderImpl::HandleStencilThenCoverStrokePathInstancedCHROMIUM( GLint reference = static_cast<GLint>(c.reference); GLuint mask = static_cast<GLuint>(c.mask); + + if (!CheckBoundDrawFramebufferValid(true, kFunctionName)) + return error::kNoError; ApplyDirtyState(); glStencilThenCoverStrokePathInstancedNV( num_paths, GL_UNSIGNED_INT, paths.get(), 0, reference, mask, cover_mode, diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h index 297b9cfae81..b038c24f921 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -43,8 +43,9 @@ class ImageManager; class Logger; class QueryManager; class Texture; +class TransformFeedbackManager; class VertexArrayManager; -class ValuebufferManager; +struct ContextCreationAttribHelper; struct ContextState; struct DisallowedFeatures { @@ -151,13 +152,16 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, bool offscreen, const gfx::Size& offscreen_size, const DisallowedFeatures& disallowed_features, - const std::vector<int32_t>& attribs) = 0; + const ContextCreationAttribHelper& attrib_helper) = 0; // Destroys the graphics context. virtual void Destroy(bool have_context) = 0; // Set the surface associated with the default FBO. virtual void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) = 0; + // Releases the surface associated with the GL context. + // The decoder should not be used until a new surface is set. + virtual void ReleaseSurface() = 0; virtual void ProduceFrontBuffer(const Mailbox& mailbox) = 0; @@ -205,15 +209,15 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, // Gets the QueryManager for this context. virtual QueryManager* GetQueryManager() = 0; + // Gets the TransformFeedbackManager for this context. + virtual TransformFeedbackManager* GetTransformFeedbackManager() = 0; + // Gets the VertexArrayManager for this context. virtual VertexArrayManager* GetVertexArrayManager() = 0; // Gets the ImageManager for this context. virtual ImageManager* GetImageManager() = 0; - // Gets the ValuebufferManager for this context. - virtual ValuebufferManager* GetValuebufferManager() = 0; - // Returns false if there are no pending queries. virtual bool HasPendingQueries() const = 0; @@ -246,6 +250,19 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, int width, int height) = 0; + // Clears a level sub area of a compressed 2D texture. + // Returns false if a GL error should be generated. + virtual bool ClearCompressedTextureLevel(Texture* texture, + unsigned target, + int level, + unsigned format, + int width, + int height) = 0; + + // Indicates whether a given internal format is one for a compressed + // texture. + virtual bool IsCompressedTextureFormat(unsigned format) = 0; + // Clears a level of a 3D texture. // Returns false if a GL error should be generated. virtual bool ClearLevel3D(Texture* texture, 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 b56ae2cd647..ac09b95e26e 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -59,6 +59,10 @@ error::Error GLES2DecoderImpl::HandleBindBufferBase( GLenum target = static_cast<GLenum>(c.target); GLuint index = static_cast<GLuint>(c.index); GLuint buffer = c.buffer; + if (!validators_->indexed_buffer_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glBindBufferBase", target, "target"); + return error::kNoError; + } DoBindBufferBase(target, index, buffer); return error::kNoError; } @@ -76,6 +80,14 @@ error::Error GLES2DecoderImpl::HandleBindBufferRange( GLuint buffer = c.buffer; GLintptr offset = static_cast<GLintptr>(c.offset); GLsizeiptr size = static_cast<GLsizeiptr>(c.size); + if (!validators_->indexed_buffer_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glBindBufferRange", target, "target"); + return error::kNoError; + } + if (size < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glBindBufferRange", "size < 0"); + return error::kNoError; + } DoBindBufferRange(target, index, buffer, offset, size); return error::kNoError; } @@ -150,13 +162,12 @@ error::Error GLES2DecoderImpl::HandleBindTransformFeedback( (void)c; GLenum target = static_cast<GLenum>(c.target); GLuint transformfeedback = c.transformfeedback; - if (!group_->GetTransformFeedbackServiceId(transformfeedback, - &transformfeedback)) { - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindTransformFeedback", - "invalid transformfeedback id"); + if (!validators_->transform_feedback_bind_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glBindTransformFeedback", target, + "target"); return error::kNoError; } - glBindTransformFeedback(target, transformfeedback); + DoBindTransformFeedback(target, transformfeedback); return error::kNoError; } @@ -366,6 +377,10 @@ error::Error GLES2DecoderImpl::HandleClearBufferfi(uint32_t immediate_data_size, GLint drawbuffers = static_cast<GLint>(c.drawbuffers); GLfloat depth = static_cast<GLfloat>(c.depth); GLint stencil = static_cast<GLint>(c.stencil); + if (!validators_->bufferfi.IsValid(buffer)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glClearBufferfi", buffer, "buffer"); + return error::kNoError; + } DoClearBufferfi(buffer, drawbuffers, depth, stencil); return error::kNoError; } @@ -381,7 +396,7 @@ error::Error GLES2DecoderImpl::HandleClearBufferfvImmediate( GLenum buffer = static_cast<GLenum>(c.buffer); GLint drawbuffers = static_cast<GLint>(c.drawbuffers); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 4, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLfloat), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -389,6 +404,10 @@ error::Error GLES2DecoderImpl::HandleClearBufferfvImmediate( } const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (!validators_->bufferfv.IsValid(buffer)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glClearBufferfv", buffer, "buffer"); + return error::kNoError; + } if (value == NULL) { return error::kOutOfBounds; } @@ -407,7 +426,7 @@ error::Error GLES2DecoderImpl::HandleClearBufferivImmediate( GLenum buffer = static_cast<GLenum>(c.buffer); GLint drawbuffers = static_cast<GLint>(c.drawbuffers); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLint), 4, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLint), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -415,6 +434,10 @@ error::Error GLES2DecoderImpl::HandleClearBufferivImmediate( } const GLint* value = GetImmediateDataAs<const GLint*>(c, data_size, immediate_data_size); + if (!validators_->bufferiv.IsValid(buffer)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glClearBufferiv", buffer, "buffer"); + return error::kNoError; + } if (value == NULL) { return error::kOutOfBounds; } @@ -433,7 +456,7 @@ error::Error GLES2DecoderImpl::HandleClearBufferuivImmediate( GLenum buffer = static_cast<GLenum>(c.buffer); GLint drawbuffers = static_cast<GLint>(c.drawbuffers); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLuint), 4, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLuint), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -441,6 +464,10 @@ error::Error GLES2DecoderImpl::HandleClearBufferuivImmediate( } const GLuint* value = GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); + if (!validators_->bufferuiv.IsValid(buffer)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glClearBufferuiv", buffer, "buffer"); + return error::kNoError; + } if (value == NULL) { return error::kOutOfBounds; } @@ -595,6 +622,36 @@ error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3D( uint32_t data_size = imageSize; const void* data = GetSharedMemoryAs<const void*>( c.data_shm_id, c.data_shm_offset, data_size); + if (!validators_->texture_3_d_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glCompressedTexSubImage3D", target, + "target"); + return error::kNoError; + } + if (width < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D", + "width < 0"); + return error::kNoError; + } + if (height < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D", + "height < 0"); + return error::kNoError; + } + if (depth < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D", + "depth < 0"); + return error::kNoError; + } + if (!validators_->compressed_texture_format.IsValid(format)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glCompressedTexSubImage3D", format, + "format"); + return error::kNoError; + } + if (imageSize < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D", + "imageSize < 0"); + return error::kNoError; + } if (data == NULL) { return error::kOutOfBounds; } @@ -616,6 +673,20 @@ error::Error GLES2DecoderImpl::HandleCopyBufferSubData( GLintptr readoffset = static_cast<GLintptr>(c.readoffset); GLintptr writeoffset = static_cast<GLintptr>(c.writeoffset); GLsizeiptr size = static_cast<GLsizeiptr>(c.size); + if (!validators_->buffer_target.IsValid(readtarget)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glCopyBufferSubData", readtarget, + "readtarget"); + return error::kNoError; + } + if (!validators_->buffer_target.IsValid(writetarget)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glCopyBufferSubData", writetarget, + "writetarget"); + return error::kNoError; + } + if (size < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyBufferSubData", "size < 0"); + return error::kNoError; + } glCopyBufferSubData(readtarget, writetarget, readoffset, writeoffset, size); return error::kNoError; } @@ -714,6 +785,18 @@ error::Error GLES2DecoderImpl::HandleCopyTexSubImage3D( GLint y = static_cast<GLint>(c.y); GLsizei width = static_cast<GLsizei>(c.width); GLsizei height = static_cast<GLsizei>(c.height); + if (!validators_->texture_3_d_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glCopyTexSubImage3D", target, "target"); + return error::kNoError; + } + if (width < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyTexSubImage3D", "width < 0"); + return error::kNoError; + } + if (height < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyTexSubImage3D", "height < 0"); + return error::kNoError; + } glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); return error::kNoError; @@ -912,13 +995,7 @@ error::Error GLES2DecoderImpl::HandleDeleteTransformFeedbacksImmediate( if (ids == NULL) { return error::kOutOfBounds; } - for (GLsizei ii = 0; ii < n; ++ii) { - GLuint service_id = 0; - if (group_->GetTransformFeedbackServiceId(ids[ii], &service_id)) { - glDeleteTransformFeedbacks(1, &service_id); - group_->RemoveTransformFeedbackId(ids[ii]); - } - } + DeleteTransformFeedbacksHelper(n, ids); return error::kNoError; } @@ -1139,6 +1216,16 @@ error::Error GLES2DecoderImpl::HandleFramebufferTextureLayer( GLuint texture = c.texture; GLint level = static_cast<GLint>(c.level); GLint layer = static_cast<GLint>(c.layer); + if (!validators_->frame_buffer_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glFramebufferTextureLayer", target, + "target"); + return error::kNoError; + } + if (!validators_->attachment.IsValid(attachment)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glFramebufferTextureLayer", attachment, + "attachment"); + return error::kNoError; + } DoFramebufferTextureLayer(target, attachment, texture, level, layer); return error::kNoError; } @@ -1305,15 +1392,8 @@ error::Error GLES2DecoderImpl::HandleGenTransformFeedbacksImmediate( if (ids == NULL) { return error::kOutOfBounds; } - for (GLsizei ii = 0; ii < n; ++ii) { - if (group_->GetTransformFeedbackServiceId(ids[ii], NULL)) { - return error::kInvalidArguments; - } - } - scoped_ptr<GLuint[]> service_ids(new GLuint[n]); - glGenTransformFeedbacks(n, service_ids.get()); - for (GLsizei ii = 0; ii < n; ++ii) { - group_->AddTransformFeedbackId(ids[ii], service_ids[ii]); + if (!GenTransformFeedbacksHelper(n, ids)) { + return error::kInvalidArguments; } return error::kNoError; } @@ -1366,6 +1446,15 @@ error::Error GLES2DecoderImpl::HandleGetBufferParameteri64v( Result* result = GetSharedMemoryAs<Result*>( c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values)); GLint64* params = result ? result->GetData() : NULL; + if (!validators_->buffer_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetBufferParameteri64v", target, + "target"); + return error::kNoError; + } + if (!validators_->buffer_parameter_64.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetBufferParameteri64v", pname, "pname"); + return error::kNoError; + } if (params == NULL) { return error::kOutOfBounds; } @@ -1518,6 +1607,10 @@ error::Error GLES2DecoderImpl::HandleGetInteger64v(uint32_t immediate_data_size, Result* result = GetSharedMemoryAs<Result*>( c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values)); GLint64* params = result ? result->GetData() : NULL; + if (!validators_->g_l_state.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInteger64v", pname, "pname"); + return error::kNoError; + } if (params == NULL) { return error::kOutOfBounds; } @@ -1549,22 +1642,21 @@ error::Error GLES2DecoderImpl::HandleGetIntegeri_v(uint32_t immediate_data_size, Result* result = GetSharedMemoryAs<Result*>(c.data_shm_id, c.data_shm_offset, Result::ComputeSize(num_values)); GLint* data = result ? result->GetData() : NULL; + if (!validators_->indexed_g_l_state.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetIntegeri_v", pname, "pname"); + return error::kNoError; + } if (data == NULL) { return error::kOutOfBounds; } - LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetIntegeri_v"); // Check that the client initialized the result. if (result->size != 0) { return error::kInvalidArguments; } - glGetIntegeri_v(pname, index, data); - GLenum error = LOCAL_PEEK_GL_ERROR("GetIntegeri_v"); - if (error == GL_NO_ERROR) { - result->SetNumResults(num_values); - } + DoGetIntegeri_v(pname, index, data); + result->SetNumResults(num_values); return error::kNoError; } - error::Error GLES2DecoderImpl::HandleGetInteger64i_v( uint32_t immediate_data_size, const void* cmd_data) { @@ -1581,22 +1673,21 @@ error::Error GLES2DecoderImpl::HandleGetInteger64i_v( Result* result = GetSharedMemoryAs<Result*>(c.data_shm_id, c.data_shm_offset, Result::ComputeSize(num_values)); GLint64* data = result ? result->GetData() : NULL; + if (!validators_->indexed_g_l_state.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInteger64i_v", pname, "pname"); + return error::kNoError; + } if (data == NULL) { return error::kOutOfBounds; } - LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetInteger64i_v"); // Check that the client initialized the result. if (result->size != 0) { return error::kInvalidArguments; } - glGetInteger64i_v(pname, index, data); - GLenum error = LOCAL_PEEK_GL_ERROR("GetInteger64i_v"); - if (error == GL_NO_ERROR) { - result->SetNumResults(num_values); - } + DoGetInteger64i_v(pname, index, data); + result->SetNumResults(num_values); return error::kNoError; } - error::Error GLES2DecoderImpl::HandleGetIntegerv(uint32_t immediate_data_size, const void* cmd_data) { const gles2::cmds::GetIntegerv& c = @@ -1718,6 +1809,10 @@ error::Error GLES2DecoderImpl::HandleGetSamplerParameterfv( Result* result = GetSharedMemoryAs<Result*>( c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values)); GLfloat* params = result ? result->GetData() : NULL; + if (!validators_->sampler_parameter.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetSamplerParameterfv", pname, "pname"); + return error::kNoError; + } if (params == NULL) { return error::kOutOfBounds; } @@ -1750,6 +1845,10 @@ error::Error GLES2DecoderImpl::HandleGetSamplerParameteriv( Result* result = GetSharedMemoryAs<Result*>( c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values)); GLint* params = result ? result->GetData() : NULL; + if (!validators_->sampler_parameter.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetSamplerParameteriv", pname, "pname"); + return error::kNoError; + } if (params == NULL) { return error::kOutOfBounds; } @@ -1814,6 +1913,10 @@ error::Error GLES2DecoderImpl::HandleGetSynciv(uint32_t immediate_data_size, Result* result = GetSharedMemoryAs<Result*>( c.values_shm_id, c.values_shm_offset, Result::ComputeSize(num_values)); GLint* values = result ? result->GetData() : NULL; + if (!validators_->sync_parameter.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetSynciv", pname, "pname"); + return error::kNoError; + } if (values == NULL) { return error::kOutOfBounds; } @@ -1995,6 +2098,10 @@ error::Error GLES2DecoderImpl::HandleGetVertexAttribIiv( Result* result = GetSharedMemoryAs<Result*>( c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values)); GLint* params = result ? result->GetData() : NULL; + if (!validators_->vertex_attribute.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetVertexAttribIiv", pname, "pname"); + return error::kNoError; + } if (params == NULL) { return error::kOutOfBounds; } @@ -2027,6 +2134,10 @@ error::Error GLES2DecoderImpl::HandleGetVertexAttribIuiv( Result* result = GetSharedMemoryAs<Result*>( c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values)); GLuint* params = result ? result->GetData() : NULL; + if (!validators_->vertex_attribute.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetVertexAttribIuiv", pname, "pname"); + return error::kNoError; + } if (params == NULL) { return error::kOutOfBounds; } @@ -2087,8 +2198,9 @@ error::Error GLES2DecoderImpl::HandleInvalidateFramebufferImmediate( (void)c; GLenum target = static_cast<GLenum>(c.target); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -2096,10 +2208,20 @@ error::Error GLES2DecoderImpl::HandleInvalidateFramebufferImmediate( } const GLenum* attachments = GetImmediateDataAs<const GLenum*>(c, data_size, immediate_data_size); + if (!validators_->frame_buffer_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glInvalidateFramebuffer", target, + "target"); + return error::kNoError; + } + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glInvalidateFramebuffer", + "count < 0"); + return error::kNoError; + } if (attachments == NULL) { return error::kOutOfBounds; } - glInvalidateFramebuffer(target, count, attachments); + DoInvalidateFramebuffer(target, count, attachments); return error::kNoError; } @@ -2114,8 +2236,9 @@ error::Error GLES2DecoderImpl::HandleInvalidateSubFramebufferImmediate( (void)c; GLenum target = static_cast<GLenum>(c.target); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -2127,10 +2250,30 @@ error::Error GLES2DecoderImpl::HandleInvalidateSubFramebufferImmediate( GLint y = static_cast<GLint>(c.y); GLsizei width = static_cast<GLsizei>(c.width); GLsizei height = static_cast<GLsizei>(c.height); + if (!validators_->frame_buffer_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glInvalidateSubFramebuffer", target, + "target"); + return error::kNoError; + } + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glInvalidateSubFramebuffer", + "count < 0"); + return error::kNoError; + } if (attachments == NULL) { return error::kOutOfBounds; } - glInvalidateSubFramebuffer(target, count, attachments, x, y, width, height); + if (width < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glInvalidateSubFramebuffer", + "width < 0"); + return error::kNoError; + } + if (height < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glInvalidateSubFramebuffer", + "height < 0"); + return error::kNoError; + } + DoInvalidateSubFramebuffer(target, count, attachments, x, y, width, height); return error::kNoError; } @@ -2303,9 +2446,7 @@ error::Error GLES2DecoderImpl::HandleIsTransformFeedback( if (!result_dst) { return error::kOutOfBounds; } - GLuint service_transformfeedback = 0; - *result_dst = group_->GetTransformFeedbackServiceId( - transformfeedback, &service_transformfeedback); + *result_dst = DoIsTransformFeedback(transformfeedback); return error::kNoError; } @@ -2344,7 +2485,7 @@ error::Error GLES2DecoderImpl::HandlePauseTransformFeedback( const gles2::cmds::PauseTransformFeedback& c = *static_cast<const gles2::cmds::PauseTransformFeedback*>(cmd_data); (void)c; - glPauseTransformFeedback(); + DoPauseTransformFeedback(); return error::kNoError; } @@ -2372,6 +2513,10 @@ error::Error GLES2DecoderImpl::HandleReadBuffer(uint32_t immediate_data_size, *static_cast<const gles2::cmds::ReadBuffer*>(cmd_data); (void)c; GLenum src = static_cast<GLenum>(c.src); + if (!validators_->read_buffer.IsValid(src)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadBuffer", src, "src"); + return error::kNoError; + } DoReadBuffer(src); return error::kNoError; } @@ -2425,7 +2570,7 @@ error::Error GLES2DecoderImpl::HandleResumeTransformFeedback( const gles2::cmds::ResumeTransformFeedback& c = *static_cast<const gles2::cmds::ResumeTransformFeedback*>(cmd_data); (void)c; - glResumeTransformFeedback(); + DoResumeTransformFeedback(); return error::kNoError; } @@ -2452,6 +2597,10 @@ error::Error GLES2DecoderImpl::HandleSamplerParameterf( GLuint sampler = c.sampler; GLenum pname = static_cast<GLenum>(c.pname); GLfloat param = static_cast<GLfloat>(c.param); + if (!validators_->sampler_parameter.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glSamplerParameterf", pname, "pname"); + return error::kNoError; + } DoSamplerParameterf(sampler, pname, param); return error::kNoError; } @@ -2467,7 +2616,7 @@ error::Error GLES2DecoderImpl::HandleSamplerParameterfvImmediate( GLuint sampler = c.sampler; GLenum pname = static_cast<GLenum>(c.pname); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 1, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLfloat), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -2475,6 +2624,10 @@ error::Error GLES2DecoderImpl::HandleSamplerParameterfvImmediate( } const GLfloat* params = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (!validators_->sampler_parameter.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glSamplerParameterfv", pname, "pname"); + return error::kNoError; + } if (params == NULL) { return error::kOutOfBounds; } @@ -2493,6 +2646,10 @@ error::Error GLES2DecoderImpl::HandleSamplerParameteri( GLuint sampler = c.sampler; GLenum pname = static_cast<GLenum>(c.pname); GLint param = static_cast<GLint>(c.param); + if (!validators_->sampler_parameter.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glSamplerParameteri", pname, "pname"); + return error::kNoError; + } DoSamplerParameteri(sampler, pname, param); return error::kNoError; } @@ -2508,7 +2665,7 @@ error::Error GLES2DecoderImpl::HandleSamplerParameterivImmediate( GLuint sampler = c.sampler; GLenum pname = static_cast<GLenum>(c.pname); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLint), 1, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLint), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -2516,6 +2673,10 @@ error::Error GLES2DecoderImpl::HandleSamplerParameterivImmediate( } const GLint* params = GetImmediateDataAs<const GLint*>(c, data_size, immediate_data_size); + if (!validators_->sampler_parameter.IsValid(pname)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glSamplerParameteriv", pname, "pname"); + return error::kNoError; + } if (params == NULL) { return error::kOutOfBounds; } @@ -2814,7 +2975,7 @@ error::Error GLES2DecoderImpl::HandleTexParameterfvImmediate( GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 1, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLfloat), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -2866,7 +3027,7 @@ error::Error GLES2DecoderImpl::HandleTexParameterivImmediate( GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLint), 1, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLint), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -2902,6 +3063,31 @@ error::Error GLES2DecoderImpl::HandleTexStorage3D(uint32_t immediate_data_size, GLsizei width = static_cast<GLsizei>(c.width); GLsizei height = static_cast<GLsizei>(c.height); GLsizei depth = static_cast<GLsizei>(c.depth); + if (!validators_->texture_3_d_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexStorage3D", target, "target"); + return error::kNoError; + } + if (levels < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "levels < 0"); + return error::kNoError; + } + if (!validators_->texture_internal_format_storage.IsValid(internalFormat)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexStorage3D", internalFormat, + "internalFormat"); + return error::kNoError; + } + if (width < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "width < 0"); + return error::kNoError; + } + if (height < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "height < 0"); + return error::kNoError; + } + if (depth < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "depth < 0"); + return error::kNoError; + } DoTexStorage3D(target, levels, internalFormat, width, height, depth); return error::kNoError; } @@ -2933,6 +3119,11 @@ error::Error GLES2DecoderImpl::HandleTransformFeedbackVaryingsBucket( len.size() > 0 ? const_cast<const GLint*>(&len[0]) : NULL; (void)length; GLenum buffermode = static_cast<GLenum>(c.buffermode); + if (!validators_->buffer_mode.IsValid(buffermode)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glTransformFeedbackVaryings", buffermode, + "buffermode"); + return error::kNoError; + } DoTransformFeedbackVaryings(program, count, varyings, buffermode); return error::kNoError; } @@ -2959,8 +3150,9 @@ error::Error GLES2DecoderImpl::HandleUniform1fvImmediate( (void)c; GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 1, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -2968,6 +3160,10 @@ error::Error GLES2DecoderImpl::HandleUniform1fvImmediate( } const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniform1fv", "count < 0"); + return error::kNoError; + } if (v == NULL) { return error::kOutOfBounds; } @@ -2994,8 +3190,9 @@ error::Error GLES2DecoderImpl::HandleUniform1ivImmediate( (void)c; GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLint), 1, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLint), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3003,6 +3200,10 @@ error::Error GLES2DecoderImpl::HandleUniform1ivImmediate( } const GLint* v = GetImmediateDataAs<const GLint*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniform1iv", "count < 0"); + return error::kNoError; + } if (v == NULL) { return error::kOutOfBounds; } @@ -3036,8 +3237,9 @@ error::Error GLES2DecoderImpl::HandleUniform1uivImmediate( (void)c; GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLuint), 1, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLuint), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3045,6 +3247,10 @@ error::Error GLES2DecoderImpl::HandleUniform1uivImmediate( } const GLuint* v = GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniform1uiv", "count < 0"); + return error::kNoError; + } if (v == NULL) { return error::kOutOfBounds; } @@ -3075,8 +3281,9 @@ error::Error GLES2DecoderImpl::HandleUniform2fvImmediate( (void)c; GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 2, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 2, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3084,6 +3291,10 @@ error::Error GLES2DecoderImpl::HandleUniform2fvImmediate( } const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniform2fv", "count < 0"); + return error::kNoError; + } if (v == NULL) { return error::kOutOfBounds; } @@ -3114,8 +3325,9 @@ error::Error GLES2DecoderImpl::HandleUniform2ivImmediate( (void)c; GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLint), 2, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLint), 2, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3123,6 +3335,10 @@ error::Error GLES2DecoderImpl::HandleUniform2ivImmediate( } const GLint* v = GetImmediateDataAs<const GLint*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniform2iv", "count < 0"); + return error::kNoError; + } if (v == NULL) { return error::kOutOfBounds; } @@ -3157,8 +3373,9 @@ error::Error GLES2DecoderImpl::HandleUniform2uivImmediate( (void)c; GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLuint), 2, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLuint), 2, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3166,6 +3383,10 @@ error::Error GLES2DecoderImpl::HandleUniform2uivImmediate( } const GLuint* v = GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniform2uiv", "count < 0"); + return error::kNoError; + } if (v == NULL) { return error::kOutOfBounds; } @@ -3197,8 +3418,9 @@ error::Error GLES2DecoderImpl::HandleUniform3fvImmediate( (void)c; GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 3, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 3, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3206,6 +3428,10 @@ error::Error GLES2DecoderImpl::HandleUniform3fvImmediate( } const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniform3fv", "count < 0"); + return error::kNoError; + } if (v == NULL) { return error::kOutOfBounds; } @@ -3237,8 +3463,9 @@ error::Error GLES2DecoderImpl::HandleUniform3ivImmediate( (void)c; GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLint), 3, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLint), 3, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3246,6 +3473,10 @@ error::Error GLES2DecoderImpl::HandleUniform3ivImmediate( } const GLint* v = GetImmediateDataAs<const GLint*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniform3iv", "count < 0"); + return error::kNoError; + } if (v == NULL) { return error::kOutOfBounds; } @@ -3281,8 +3512,9 @@ error::Error GLES2DecoderImpl::HandleUniform3uivImmediate( (void)c; GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLuint), 3, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLuint), 3, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3290,6 +3522,10 @@ error::Error GLES2DecoderImpl::HandleUniform3uivImmediate( } const GLuint* v = GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniform3uiv", "count < 0"); + return error::kNoError; + } if (v == NULL) { return error::kOutOfBounds; } @@ -3322,8 +3558,9 @@ error::Error GLES2DecoderImpl::HandleUniform4fvImmediate( (void)c; GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 4, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3331,6 +3568,10 @@ error::Error GLES2DecoderImpl::HandleUniform4fvImmediate( } const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniform4fv", "count < 0"); + return error::kNoError; + } if (v == NULL) { return error::kOutOfBounds; } @@ -3363,8 +3604,9 @@ error::Error GLES2DecoderImpl::HandleUniform4ivImmediate( (void)c; GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLint), 4, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLint), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3372,6 +3614,10 @@ error::Error GLES2DecoderImpl::HandleUniform4ivImmediate( } const GLint* v = GetImmediateDataAs<const GLint*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniform4iv", "count < 0"); + return error::kNoError; + } if (v == NULL) { return error::kOutOfBounds; } @@ -3408,8 +3654,9 @@ error::Error GLES2DecoderImpl::HandleUniform4uivImmediate( (void)c; GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLuint), 4, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLuint), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3417,6 +3664,10 @@ error::Error GLES2DecoderImpl::HandleUniform4uivImmediate( } const GLuint* v = GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniform4uiv", "count < 0"); + return error::kNoError; + } if (v == NULL) { return error::kOutOfBounds; } @@ -3433,8 +3684,9 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix2fvImmediate( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 4, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3442,6 +3694,10 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix2fvImmediate( } const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniformMatrix2fv", "count < 0"); + return error::kNoError; + } if (value == NULL) { return error::kOutOfBounds; } @@ -3460,8 +3716,9 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix2x3fvImmediate( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 6, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 6, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3469,6 +3726,10 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix2x3fvImmediate( } const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniformMatrix2x3fv", "count < 0"); + return error::kNoError; + } if (value == NULL) { return error::kOutOfBounds; } @@ -3487,8 +3748,9 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix2x4fvImmediate( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 8, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 8, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3496,6 +3758,10 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix2x4fvImmediate( } const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniformMatrix2x4fv", "count < 0"); + return error::kNoError; + } if (value == NULL) { return error::kOutOfBounds; } @@ -3512,8 +3778,9 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix3fvImmediate( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 9, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 9, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3521,6 +3788,10 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix3fvImmediate( } const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniformMatrix3fv", "count < 0"); + return error::kNoError; + } if (value == NULL) { return error::kOutOfBounds; } @@ -3539,8 +3810,9 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix3x2fvImmediate( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 6, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 6, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3548,6 +3820,10 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix3x2fvImmediate( } const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniformMatrix3x2fv", "count < 0"); + return error::kNoError; + } if (value == NULL) { return error::kOutOfBounds; } @@ -3566,8 +3842,9 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix3x4fvImmediate( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 12, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 12, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3575,6 +3852,10 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix3x4fvImmediate( } const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniformMatrix3x4fv", "count < 0"); + return error::kNoError; + } if (value == NULL) { return error::kOutOfBounds; } @@ -3591,8 +3872,9 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix4fvImmediate( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 16, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 16, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3600,6 +3882,10 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix4fvImmediate( } const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniformMatrix4fv", "count < 0"); + return error::kNoError; + } if (value == NULL) { return error::kOutOfBounds; } @@ -3618,8 +3904,9 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix4x2fvImmediate( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 8, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 8, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3627,6 +3914,10 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix4x2fvImmediate( } const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniformMatrix4x2fv", "count < 0"); + return error::kNoError; + } if (value == NULL) { return error::kOutOfBounds; } @@ -3645,8 +3936,9 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix4x3fvImmediate( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 12, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLfloat), 12, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3654,6 +3946,10 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix4x3fvImmediate( } const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (count < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUniformMatrix4x3fv", "count < 0"); + return error::kNoError; + } if (value == NULL) { return error::kOutOfBounds; } @@ -3702,7 +3998,7 @@ error::Error GLES2DecoderImpl::HandleVertexAttrib1fvImmediate( (void)c; GLuint indx = static_cast<GLuint>(c.indx); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 1, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLfloat), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3738,7 +4034,7 @@ error::Error GLES2DecoderImpl::HandleVertexAttrib2fvImmediate( (void)c; GLuint indx = static_cast<GLuint>(c.indx); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 2, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLfloat), 2, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3775,7 +4071,7 @@ error::Error GLES2DecoderImpl::HandleVertexAttrib3fvImmediate( (void)c; GLuint indx = static_cast<GLuint>(c.indx); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 3, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLfloat), 3, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3813,7 +4109,7 @@ error::Error GLES2DecoderImpl::HandleVertexAttrib4fvImmediate( (void)c; GLuint indx = static_cast<GLuint>(c.indx); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 4, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLfloat), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3855,7 +4151,7 @@ error::Error GLES2DecoderImpl::HandleVertexAttribI4ivImmediate( (void)c; GLuint indx = static_cast<GLuint>(c.indx); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLint), 4, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLint), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -3897,7 +4193,7 @@ error::Error GLES2DecoderImpl::HandleVertexAttribI4uivImmediate( (void)c; GLuint indx = static_cast<GLuint>(c.indx); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLuint), 4, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLuint), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -4193,7 +4489,12 @@ error::Error GLES2DecoderImpl::HandleBeginTransformFeedback( *static_cast<const gles2::cmds::BeginTransformFeedback*>(cmd_data); (void)c; GLenum primitivemode = static_cast<GLenum>(c.primitivemode); - glBeginTransformFeedback(primitivemode); + if (!validators_->transform_feedback_primitive_mode.IsValid(primitivemode)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glBeginTransformFeedback", primitivemode, + "primitivemode"); + return error::kNoError; + } + DoBeginTransformFeedback(primitivemode); return error::kNoError; } @@ -4205,7 +4506,7 @@ error::Error GLES2DecoderImpl::HandleEndTransformFeedback( const gles2::cmds::EndTransformFeedback& c = *static_cast<const gles2::cmds::EndTransformFeedback*>(cmd_data); (void)c; - glEndTransformFeedback(); + DoEndTransformFeedback(); return error::kNoError; } @@ -4486,7 +4787,7 @@ error::Error GLES2DecoderImpl::HandleProduceTextureCHROMIUMImmediate( (void)c; GLenum target = static_cast<GLenum>(c.target); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -4516,7 +4817,7 @@ error::Error GLES2DecoderImpl::HandleProduceTextureDirectCHROMIUMImmediate( GLuint texture = c.texture; GLenum target = static_cast<GLenum>(c.target); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -4545,7 +4846,7 @@ error::Error GLES2DecoderImpl::HandleConsumeTextureCHROMIUMImmediate( (void)c; GLenum target = static_cast<GLenum>(c.target); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -4565,146 +4866,6 @@ error::Error GLES2DecoderImpl::HandleConsumeTextureCHROMIUMImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleGenValuebuffersCHROMIUMImmediate( - uint32_t immediate_data_size, - const void* cmd_data) { - const gles2::cmds::GenValuebuffersCHROMIUMImmediate& c = - *static_cast<const gles2::cmds::GenValuebuffersCHROMIUMImmediate*>( - cmd_data); - (void)c; - GLsizei n = static_cast<GLsizei>(c.n); - uint32_t data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - GLuint* buffers = - GetImmediateDataAs<GLuint*>(c, data_size, immediate_data_size); - if (buffers == NULL) { - return error::kOutOfBounds; - } - if (!GenValuebuffersCHROMIUMHelper(n, buffers)) { - return error::kInvalidArguments; - } - return error::kNoError; -} - -error::Error GLES2DecoderImpl::HandleDeleteValuebuffersCHROMIUMImmediate( - uint32_t immediate_data_size, - const void* cmd_data) { - const gles2::cmds::DeleteValuebuffersCHROMIUMImmediate& c = - *static_cast<const gles2::cmds::DeleteValuebuffersCHROMIUMImmediate*>( - cmd_data); - (void)c; - GLsizei n = static_cast<GLsizei>(c.n); - uint32_t data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - const GLuint* valuebuffers = - GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); - if (valuebuffers == NULL) { - return error::kOutOfBounds; - } - DeleteValuebuffersCHROMIUMHelper(n, valuebuffers); - return error::kNoError; -} - -error::Error GLES2DecoderImpl::HandleIsValuebufferCHROMIUM( - uint32_t immediate_data_size, - const void* cmd_data) { - const gles2::cmds::IsValuebufferCHROMIUM& c = - *static_cast<const gles2::cmds::IsValuebufferCHROMIUM*>(cmd_data); - (void)c; - GLuint valuebuffer = c.valuebuffer; - typedef cmds::IsValuebufferCHROMIUM::Result Result; - Result* result_dst = GetSharedMemoryAs<Result*>( - c.result_shm_id, c.result_shm_offset, sizeof(*result_dst)); - if (!result_dst) { - return error::kOutOfBounds; - } - *result_dst = DoIsValuebufferCHROMIUM(valuebuffer); - return error::kNoError; -} - -error::Error GLES2DecoderImpl::HandleBindValuebufferCHROMIUM( - uint32_t immediate_data_size, - const void* cmd_data) { - const gles2::cmds::BindValuebufferCHROMIUM& c = - *static_cast<const gles2::cmds::BindValuebufferCHROMIUM*>(cmd_data); - (void)c; - GLenum target = static_cast<GLenum>(c.target); - GLuint valuebuffer = c.valuebuffer; - if (!validators_->value_buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glBindValuebufferCHROMIUM", target, - "target"); - return error::kNoError; - } - DoBindValueBufferCHROMIUM(target, valuebuffer); - return error::kNoError; -} - -error::Error GLES2DecoderImpl::HandleSubscribeValueCHROMIUM( - uint32_t immediate_data_size, - const void* cmd_data) { - const gles2::cmds::SubscribeValueCHROMIUM& c = - *static_cast<const gles2::cmds::SubscribeValueCHROMIUM*>(cmd_data); - (void)c; - GLenum target = static_cast<GLenum>(c.target); - GLenum subscription = static_cast<GLenum>(c.subscription); - if (!validators_->value_buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glSubscribeValueCHROMIUM", target, - "target"); - return error::kNoError; - } - if (!validators_->subscription_target.IsValid(subscription)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glSubscribeValueCHROMIUM", subscription, - "subscription"); - return error::kNoError; - } - DoSubscribeValueCHROMIUM(target, subscription); - return error::kNoError; -} - -error::Error GLES2DecoderImpl::HandlePopulateSubscribedValuesCHROMIUM( - uint32_t immediate_data_size, - const void* cmd_data) { - const gles2::cmds::PopulateSubscribedValuesCHROMIUM& c = - *static_cast<const gles2::cmds::PopulateSubscribedValuesCHROMIUM*>( - cmd_data); - (void)c; - GLenum target = static_cast<GLenum>(c.target); - if (!validators_->value_buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glPopulateSubscribedValuesCHROMIUM", - target, "target"); - return error::kNoError; - } - DoPopulateSubscribedValuesCHROMIUM(target); - return error::kNoError; -} - -error::Error GLES2DecoderImpl::HandleUniformValuebufferCHROMIUM( - uint32_t immediate_data_size, - const void* cmd_data) { - const gles2::cmds::UniformValuebufferCHROMIUM& c = - *static_cast<const gles2::cmds::UniformValuebufferCHROMIUM*>(cmd_data); - (void)c; - GLint location = static_cast<GLint>(c.location); - GLenum target = static_cast<GLenum>(c.target); - GLenum subscription = static_cast<GLenum>(c.subscription); - if (!validators_->value_buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glUniformValuebufferCHROMIUM", target, - "target"); - return error::kNoError; - } - if (!validators_->subscription_target.IsValid(subscription)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glUniformValuebufferCHROMIUM", - subscription, "subscription"); - return error::kNoError; - } - DoUniformValueBufferCHROMIUM(location, target, subscription); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleBindTexImage2DCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { @@ -4762,8 +4923,9 @@ error::Error GLES2DecoderImpl::HandleDiscardFramebufferEXTImmediate( GLenum target = static_cast<GLenum>(c.target); GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -4811,8 +4973,9 @@ error::Error GLES2DecoderImpl::HandleDrawBuffersEXTImmediate( *static_cast<const gles2::cmds::DrawBuffersEXTImmediate*>(cmd_data); (void)c; GLsizei count = static_cast<GLsizei>(c.count); - uint32_t data_size; - if (!ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { + uint32_t data_size = 0; + if (count >= 0 && + !GLES2Util::ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -4873,7 +5036,7 @@ error::Error GLES2DecoderImpl::HandleMatrixLoadfCHROMIUMImmediate( GLenum matrixMode = static_cast<GLenum>(c.matrixMode); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 16, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLfloat), 16, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { @@ -5025,7 +5188,7 @@ GLES2DecoderImpl::HandleUniformMatrix4fvStreamTextureMatrixCHROMIUMImmediate( GLint location = static_cast<GLint>(c.location); GLboolean transpose = static_cast<GLboolean>(c.transpose); uint32_t data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 16, &data_size)) { + if (!GLES2Util::ComputeDataSize(1, sizeof(GLfloat), 16, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc index ff93ba138b8..766a338a273 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc @@ -4,6 +4,8 @@ #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" + namespace gpu { namespace gles2 { 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 396f531a3a2..1e289d813c0 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -13,6 +13,7 @@ #include "base/callback.h" #include "base/macros.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "testing/gmock/include/gmock/gmock.h" @@ -49,9 +50,10 @@ class MockGLES2Decoder : public GLES2Decoder { bool offscreen, const gfx::Size& size, const DisallowedFeatures& disallowed_features, - const std::vector<int32_t>& attribs)); + const ContextCreationAttribHelper& attrib_helper)); MOCK_METHOD1(Destroy, void(bool have_context)); MOCK_METHOD1(SetSurface, void(const scoped_refptr<gfx::GLSurface>& surface)); + MOCK_METHOD0(ReleaseSurface, void()); MOCK_METHOD1(ProduceFrontBuffer, void(const Mailbox& mailbox)); MOCK_METHOD1(ResizeOffscreenFrameBuffer, bool(const gfx::Size& size)); MOCK_METHOD0(MakeCurrent, bool()); @@ -83,9 +85,10 @@ class MockGLES2Decoder : public GLES2Decoder { MOCK_CONST_METHOD0(ClearAllAttributes, void()); MOCK_CONST_METHOD0(RestoreAllAttributes, void()); MOCK_METHOD0(GetQueryManager, gpu::gles2::QueryManager*()); + MOCK_METHOD0( + GetTransformFeedbackManager, gpu::gles2::TransformFeedbackManager*()); MOCK_METHOD0(GetVertexArrayManager, gpu::gles2::VertexArrayManager*()); MOCK_METHOD0(GetImageManager, gpu::gles2::ImageManager*()); - MOCK_METHOD0(GetValuebufferManager, gpu::gles2::ValuebufferManager*()); MOCK_METHOD1( SetResizeCallback, void(const base::Callback<void(gfx::Size, float)>&)); MOCK_METHOD1(SetIgnoreCachedStateForTest, void(bool ignore)); @@ -113,6 +116,15 @@ class MockGLES2Decoder : public GLES2Decoder { int y_offset, int width, int height)); + MOCK_METHOD6(ClearCompressedTextureLevel, + bool(Texture* texture, + unsigned target, + int level, + unsigned format, + int width, + int height)); + MOCK_METHOD1(IsCompressedTextureFormat, + bool(unsigned format)); MOCK_METHOD8(ClearLevel3D, bool(Texture* texture, unsigned target, 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 5c1e0486816..f57f875cb06 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -1339,6 +1339,7 @@ TEST_P(GLES2DecoderManualInitTest, MemoryTrackerBufferData) { TEST_P(GLES2DecoderManualInitTest, ImmutableCopyTexImage2D) { const GLenum kTarget = GL_TEXTURE_2D; const GLint kLevel = 0; + const GLint kLevels = 2; const GLenum kInternalFormat = GL_RGBA; const GLenum kSizedInternalFormat = GL_RGBA8; const GLsizei kWidth = 4; @@ -1349,8 +1350,9 @@ TEST_P(GLES2DecoderManualInitTest, ImmutableCopyTexImage2D) { init.has_alpha = true; init.request_alpha = true; init.bind_generates_resource = true; + init.gl_version = "OpenGL ES 2.0"; // To avoid TexStorage emulation. InitDecoder(init); - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoBindTexture(kTarget, client_texture_id_, kServiceTextureId); // CopyTexImage2D will call arbitrary amount of GetErrors. EXPECT_CALL(*gl_, GetError()) @@ -1364,7 +1366,7 @@ TEST_P(GLES2DecoderManualInitTest, ImmutableCopyTexImage2D) { EXPECT_CALL(*gl_, TexStorage2DEXT( - kTarget, kLevel, kSizedInternalFormat, kWidth, kHeight)) + kTarget, kLevels, kSizedInternalFormat, kWidth, kHeight)) .Times(1); CopyTexImage2D copy_cmd; copy_cmd.Init(kTarget, kLevel, kInternalFormat, 0, 0, kWidth, kHeight); @@ -1372,7 +1374,7 @@ TEST_P(GLES2DecoderManualInitTest, ImmutableCopyTexImage2D) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); TexStorage2DEXT storage_cmd; - storage_cmd.Init(kTarget, kLevel, kSizedInternalFormat, kWidth, kHeight); + storage_cmd.Init(kTarget, kLevels, kSizedInternalFormat, kWidth, kHeight); EXPECT_EQ(error::kNoError, ExecuteCmd(storage_cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); @@ -1422,6 +1424,67 @@ TEST_P(GLES2DecoderTest, LoseContextCHROMIUMInvalidArgs1_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } +TEST_P(GLES3DecoderTest, TransformFeedbackStates) { + cmds::BeginTransformFeedback begin_cmd; + begin_cmd.Init(GL_POINTS); + cmds::EndTransformFeedback end_cmd; + end_cmd.Init(); + cmds::PauseTransformFeedback pause_cmd; + pause_cmd.Init(); + cmds::ResumeTransformFeedback resume_cmd; + resume_cmd.Init(); + + // Before Begin: Pause, Resume, and End is invalid. + EXPECT_EQ(error::kNoError, ExecuteCmd(end_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + EXPECT_EQ(error::kNoError, ExecuteCmd(pause_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + EXPECT_EQ(error::kNoError, ExecuteCmd(resume_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Begin + EXPECT_CALL(*gl_, BeginTransformFeedback(GL_POINTS)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Begin again is invalid. + EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Before Pause: Resume is invalid. + EXPECT_EQ(error::kNoError, ExecuteCmd(resume_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Pause + EXPECT_CALL(*gl_, PauseTransformFeedback()) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(pause_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Pause again is invalid. + EXPECT_EQ(error::kNoError, ExecuteCmd(pause_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Resume + EXPECT_CALL(*gl_, ResumeTransformFeedback()) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(resume_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // End + EXPECT_CALL(*gl_, EndTransformFeedback()) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(end_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + class GLES2DecoderDoCommandsTest : public GLES2DecoderTest { public: GLES2DecoderDoCommandsTest() { @@ -1441,6 +1504,90 @@ class GLES2DecoderDoCommandsTest : public GLES2DecoderTest { int entries_per_cmd_; }; +TEST_P(GLES3DecoderTest, BindTransformFeedbackValidArgs) { + EXPECT_CALL(*gl_, BindTransformFeedback(GL_TRANSFORM_FEEDBACK, + kServiceTransformFeedbackId)); + SpecializedSetup<cmds::BindTransformFeedback, 0>(true); + cmds::BindTransformFeedback cmd; + cmd.Init(GL_TRANSFORM_FEEDBACK, client_transformfeedback_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES3DecoderTest, GenDeleteTransformFeedbacksImmediateValidArgs) { + EXPECT_CALL(*gl_, GenTransformFeedbacks(1, _)) + .WillOnce(SetArgPointee<1>(kNewServiceId)); + cmds::GenTransformFeedbacksImmediate* gen_cmd = + GetImmediateAs<cmds::GenTransformFeedbacksImmediate>(); + GLuint temp = kNewClientId; + SpecializedSetup<cmds::GenTransformFeedbacksImmediate, 0>(true); + gen_cmd->Init(1, &temp); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(*gen_cmd, sizeof(temp))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(GetTransformFeedback(kNewClientId) != nullptr); + + EXPECT_CALL(*gl_, + DeleteTransformFeedbacks(1, Pointee(kNewServiceId))) + .Times(1); + cmds::DeleteTransformFeedbacksImmediate& delete_cmd = + *GetImmediateAs<cmds::DeleteTransformFeedbacksImmediate>(); + SpecializedSetup<cmds::DeleteTransformFeedbacksImmediate, 0>(true); + delete_cmd.Init(1, &temp); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(delete_cmd, sizeof(&temp))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(GetTransformFeedback(kNewClientId) == nullptr); +} + +TEST_P(GLES3DecoderTest, DeleteTransformFeedbacksImmediateInvalidArgs) { + cmds::DeleteTransformFeedbacksImmediate& cmd = + *GetImmediateAs<cmds::DeleteTransformFeedbacksImmediate>(); + SpecializedSetup<cmds::DeleteTransformFeedbacksImmediate, 0>(false); + GLuint temp = kInvalidClientId; + cmd.Init(1, &temp); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES3DecoderTest, GenTransformFeedbacksImmediateInvalidArgs) { + EXPECT_CALL(*gl_, GenTransformFeedbacks(_, _)).Times(0); + cmds::GenTransformFeedbacksImmediate* cmd = + GetImmediateAs<cmds::GenTransformFeedbacksImmediate>(); + SpecializedSetup<cmds::GenTransformFeedbacksImmediate, 0>(false); + cmd->Init(1, &client_transformfeedback_id_); + EXPECT_EQ(error::kInvalidArguments, + ExecuteImmediateCmd(*cmd, sizeof(&client_transformfeedback_id_))); +} + +TEST_P(GLES3DecoderTest, GetIntegeri_vValidArgs) { + EXPECT_CALL(*gl_, GetIntegeri_v(_, _, _)).Times(0); + typedef cmds::GetIntegeri_v::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + cmds::GetIntegeri_v cmd; + cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 2, shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( + GL_TRANSFORM_FEEDBACK_BUFFER_BINDING), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES3DecoderTest, GetInteger64i_vValidArgs) { + EXPECT_CALL(*gl_, GetInteger64i_v(_, _, _)).Times(0); + typedef cmds::GetInteger64i_v::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + cmds::GetInteger64i_v cmd; + cmd.Init(GL_UNIFORM_BUFFER_SIZE, 2, shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( + GL_UNIFORM_BUFFER_SIZE), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + // Test that processing with 0 entries does nothing. TEST_P(GLES2DecoderDoCommandsTest, DoCommandsOneOfZero) { int num_processed = -1; 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 06d220af970..a9bfe425155 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 @@ -51,35 +51,6 @@ TEST_P(GLES2DecoderTest1, BindBufferInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_P(GLES2DecoderTest1, BindBufferRangeValidArgs) { - EXPECT_CALL(*gl_, BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 2, - kServiceBufferId, 4, 4)); - SpecializedSetup<cmds::BindBufferRange, 0>(true); - cmds::BindBufferRange cmd; - cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, client_buffer_id_, 4, 4); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); -} - -TEST_P(GLES2DecoderTest1, BindBufferRangeValidArgsNewId) { - EXPECT_CALL(*gl_, BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 2, - kNewServiceId, 4, 4)); - EXPECT_CALL(*gl_, GenBuffersARB(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); - SpecializedSetup<cmds::BindBufferRange, 0>(true); - cmds::BindBufferRange cmd; - cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewClientId, 4, 4); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE(GetBuffer(kNewClientId) != NULL); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); -} - TEST_P(GLES2DecoderTest1, BindFramebufferValidArgs) { EXPECT_CALL(*gl_, BindFramebufferEXT(GL_FRAMEBUFFER, kServiceFramebufferId)); SpecializedSetup<cmds::BindFramebuffer, 0>(true); @@ -153,58 +124,6 @@ TEST_P(GLES2DecoderTest1, BindSamplerValidArgs) { EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); } -TEST_P(GLES2DecoderTest1, BindTextureValidArgs) { - EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)); - SpecializedSetup<cmds::BindTexture, 0>(true); - cmds::BindTexture cmd; - cmd.Init(GL_TEXTURE_2D, client_texture_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, BindTextureValidArgsNewId) { - EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kNewServiceId)); - EXPECT_CALL(*gl_, GenTextures(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); - SpecializedSetup<cmds::BindTexture, 0>(true); - cmds::BindTexture cmd; - cmd.Init(GL_TEXTURE_2D, kNewClientId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE(GetTexture(kNewClientId) != NULL); -} - -TEST_P(GLES2DecoderTest1, BindTextureInvalidArgs0_0) { - EXPECT_CALL(*gl_, BindTexture(_, _)).Times(0); - SpecializedSetup<cmds::BindTexture, 0>(false); - cmds::BindTexture cmd; - cmd.Init(GL_TEXTURE_1D, client_texture_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, BindTextureInvalidArgs0_1) { - EXPECT_CALL(*gl_, BindTexture(_, _)).Times(0); - SpecializedSetup<cmds::BindTexture, 0>(false); - cmds::BindTexture cmd; - cmd.Init(GL_TEXTURE_3D, client_texture_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, BindTransformFeedbackValidArgs) { - EXPECT_CALL(*gl_, BindTransformFeedback(GL_TRANSFORM_FEEDBACK, - kServiceTransformFeedbackId)); - SpecializedSetup<cmds::BindTransformFeedback, 0>(true); - cmds::BindTransformFeedback cmd; - cmd.Init(GL_TRANSFORM_FEEDBACK, client_transformfeedback_id_); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); -} - TEST_P(GLES2DecoderTest1, BlendColorValidArgs) { EXPECT_CALL(*gl_, BlendColor(1, 2, 3, 4)); SpecializedSetup<cmds::BlendColor, 0>(true); @@ -590,37 +509,6 @@ TEST_P(GLES2DecoderTest1, DeleteTexturesImmediateInvalidArgs) { EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); } -TEST_P(GLES2DecoderTest1, DeleteTransformFeedbacksImmediateValidArgs) { - EXPECT_CALL(*gl_, - DeleteTransformFeedbacks(1, Pointee(kServiceTransformFeedbackId))) - .Times(1); - cmds::DeleteTransformFeedbacksImmediate& cmd = - *GetImmediateAs<cmds::DeleteTransformFeedbacksImmediate>(); - SpecializedSetup<cmds::DeleteTransformFeedbacksImmediate, 0>(true); - cmd.Init(1, &client_transformfeedback_id_); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(client_transformfeedback_id_))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_FALSE( - GetTransformFeedbackServiceId(client_transformfeedback_id_, NULL)); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, - ExecuteImmediateCmd(cmd, sizeof(client_transformfeedback_id_))); -} - -TEST_P(GLES2DecoderTest1, DeleteTransformFeedbacksImmediateInvalidArgs) { - cmds::DeleteTransformFeedbacksImmediate& cmd = - *GetImmediateAs<cmds::DeleteTransformFeedbacksImmediate>(); - SpecializedSetup<cmds::DeleteTransformFeedbacksImmediate, 0>(false); - GLuint temp = kInvalidClientId; - cmd.Init(1, &temp); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp))); -} - TEST_P(GLES2DecoderTest1, DepthFuncValidArgs) { EXPECT_CALL(*gl_, DepthFunc(GL_NEVER)); SpecializedSetup<cmds::DepthFunc, 0>(true); @@ -795,20 +683,6 @@ TEST_P(GLES2DecoderTest1, FramebufferRenderbufferInvalidArgs2_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_P(GLES2DecoderTest1, FramebufferTextureLayerValidArgs) { - EXPECT_CALL(*gl_, - FramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - kServiceTextureId, 4, 5)); - SpecializedSetup<cmds::FramebufferTextureLayer, 0>(true); - cmds::FramebufferTextureLayer cmd; - cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, client_texture_id_, 4, 5); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); -} - TEST_P(GLES2DecoderTest1, FrontFaceValidArgs) { EXPECT_CALL(*gl_, FrontFace(GL_CW)); SpecializedSetup<cmds::FrontFace, 0>(true); @@ -961,36 +835,6 @@ TEST_P(GLES2DecoderTest1, GenTexturesImmediateInvalidArgs) { ExecuteImmediateCmd(*cmd, sizeof(&client_texture_id_))); } -TEST_P(GLES2DecoderTest1, GenTransformFeedbacksImmediateValidArgs) { - EXPECT_CALL(*gl_, GenTransformFeedbacks(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); - cmds::GenTransformFeedbacksImmediate* cmd = - GetImmediateAs<cmds::GenTransformFeedbacksImmediate>(); - GLuint temp = kNewClientId; - SpecializedSetup<cmds::GenTransformFeedbacksImmediate, 0>(true); - decoder_->set_unsafe_es3_apis_enabled(true); - cmd->Init(1, &temp); - EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(*cmd, sizeof(temp))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - GLuint service_id; - EXPECT_TRUE(GetTransformFeedbackServiceId(kNewClientId, &service_id)); - EXPECT_EQ(kNewServiceId, service_id); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(*cmd, sizeof(temp))); -} - -TEST_P(GLES2DecoderTest1, GenTransformFeedbacksImmediateInvalidArgs) { - EXPECT_CALL(*gl_, GenTransformFeedbacks(_, _)).Times(0); - cmds::GenTransformFeedbacksImmediate* cmd = - GetImmediateAs<cmds::GenTransformFeedbacksImmediate>(); - SpecializedSetup<cmds::GenTransformFeedbacksImmediate, 0>(false); - cmd->Init(1, &client_transformfeedback_id_); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kInvalidArguments, - ExecuteImmediateCmd(*cmd, sizeof(&client_transformfeedback_id_))); - decoder_->set_unsafe_es3_apis_enabled(false); -} - TEST_P(GLES2DecoderTest1, GetBooleanvValidArgs) { EXPECT_CALL(*gl_, GetError()).WillRepeatedly(Return(GL_NO_ERROR)); SpecializedSetup<cmds::GetBooleanv, 0>(true); @@ -1285,48 +1129,6 @@ TEST_P(GLES2DecoderTest1, GetInteger64vValidArgs) { EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); } -TEST_P(GLES2DecoderTest1, GetIntegeri_vValidArgs) { - EXPECT_CALL(*gl_, GetError()).WillRepeatedly(Return(GL_NO_ERROR)); - SpecializedSetup<cmds::GetIntegeri_v, 0>(true); - typedef cmds::GetIntegeri_v::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 2, - result->GetData())); - result->size = 0; - cmds::GetIntegeri_v cmd; - cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 2, 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_TRANSFORM_FEEDBACK_BUFFER_BINDING), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); -} - -TEST_P(GLES2DecoderTest1, GetInteger64i_vValidArgs) { - EXPECT_CALL(*gl_, GetError()).WillRepeatedly(Return(GL_NO_ERROR)); - SpecializedSetup<cmds::GetInteger64i_v, 0>(true); - typedef cmds::GetInteger64i_v::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetInteger64i_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 2, - result->GetData())); - result->size = 0; - cmds::GetInteger64i_v cmd; - cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 2, 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_TRANSFORM_FEEDBACK_BUFFER_BINDING), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); -} - TEST_P(GLES2DecoderTest1, GetIntegervValidArgs) { EXPECT_CALL(*gl_, GetError()).WillRepeatedly(Return(GL_NO_ERROR)); SpecializedSetup<cmds::GetIntegerv, 0>(true); diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h index 417b4ea037a..facc8ab9214 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h @@ -727,18 +727,6 @@ TEST_P(GLES2DecoderTest2, LinkProgramValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_P(GLES2DecoderTest2, PauseTransformFeedbackValidArgs) { - EXPECT_CALL(*gl_, PauseTransformFeedback()); - SpecializedSetup<cmds::PauseTransformFeedback, 0>(true); - cmds::PauseTransformFeedback cmd; - cmd.Init(); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); -} - TEST_P(GLES2DecoderTest2, PolygonOffsetValidArgs) { EXPECT_CALL(*gl_, PolygonOffset(1, 2)); SpecializedSetup<cmds::PolygonOffset, 0>(true); @@ -795,18 +783,6 @@ TEST_P(GLES2DecoderTest2, RenderbufferStorageInvalidArgs3_0) { EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } -TEST_P(GLES2DecoderTest2, ResumeTransformFeedbackValidArgs) { - EXPECT_CALL(*gl_, ResumeTransformFeedback()); - SpecializedSetup<cmds::ResumeTransformFeedback, 0>(true); - cmds::ResumeTransformFeedback cmd; - cmd.Init(); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); -} - TEST_P(GLES2DecoderTest2, SampleCoverageValidArgs) { EXPECT_CALL(*gl_, SampleCoverage(1, true)); SpecializedSetup<cmds::SampleCoverage, 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 9045f5c9c3f..54a821a413b 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 @@ -306,30 +306,6 @@ TEST_P(GLES2DecoderTest3, ViewportInvalidArgs3_0) { EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } -TEST_P(GLES2DecoderTest3, BeginTransformFeedbackValidArgs) { - EXPECT_CALL(*gl_, BeginTransformFeedback(GL_POINTS)); - SpecializedSetup<cmds::BeginTransformFeedback, 0>(true); - cmds::BeginTransformFeedback cmd; - cmd.Init(GL_POINTS); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); -} - -TEST_P(GLES2DecoderTest3, EndTransformFeedbackValidArgs) { - EXPECT_CALL(*gl_, EndTransformFeedback()); - SpecializedSetup<cmds::EndTransformFeedback, 0>(true); - cmds::EndTransformFeedback cmd; - cmd.Init(); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); -} - TEST_P(GLES2DecoderTest3, PopGroupMarkerEXTValidArgs) { SpecializedSetup<cmds::PopGroupMarkerEXT, 0>(true); cmds::PopGroupMarkerEXT cmd; @@ -346,25 +322,6 @@ TEST_P(GLES2DecoderTest3, SwapBuffersValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_P(GLES2DecoderTest3, IsValuebufferCHROMIUMValidArgs) { - SpecializedSetup<cmds::IsValuebufferCHROMIUM, 0>(true); - cmds::IsValuebufferCHROMIUM cmd; - cmd.Init(client_valuebuffer_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_P(GLES2DecoderTest3, IsValuebufferCHROMIUMInvalidArgsBadSharedMemoryId) { - SpecializedSetup<cmds::IsValuebufferCHROMIUM, 0>(false); - cmds::IsValuebufferCHROMIUM cmd; - cmd.Init(client_valuebuffer_id_, kInvalidSharedMemoryId, - shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - cmd.Init(client_valuebuffer_id_, shared_memory_id_, - kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - TEST_P(GLES2DecoderTest3, SwapIntervalValidArgs) { SpecializedSetup<cmds::SwapInterval, 0>(true); cmds::SwapInterval cmd; 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 cbe3112b391..1401d2d8f27 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 @@ -8,6 +8,7 @@ #include <stdint.h> #include <algorithm> +#include <memory> #include <string> #include <vector> @@ -15,7 +16,6 @@ #include "base/strings/string_split.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" -#include "gpu/command_buffer/common/value_state.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/logger.h" @@ -31,6 +31,7 @@ using ::gfx::MockGLInterface; using ::testing::_; using ::testing::AnyNumber; +using ::testing::AtMost; using ::testing::DoAll; using ::testing::InSequence; using ::testing::Invoke; @@ -111,7 +112,6 @@ GLES2DecoderTestBase::GLES2DecoderTestBase() client_fragment_shader_id_(122), client_query_id_(123), client_vertexarray_id_(124), - client_valuebuffer_id_(125), client_transformfeedback_id_(126), client_sync_id_(127), service_renderbuffer_id_(0), @@ -188,15 +188,17 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( SetupMockGLBehaviors(); - scoped_refptr<FeatureInfo> feature_info; - if (command_line) - feature_info = new FeatureInfo(*command_line); - group_ = scoped_refptr<ContextGroup>( - new ContextGroup(gpu_preferences_, NULL, memory_tracker_, - new ShaderTranslatorCache(gpu_preferences_), - new FramebufferCompletenessCache, feature_info.get(), - new SubscriptionRefSet, new ValueStateMap, - normalized_init.bind_generates_resource)); + scoped_refptr<FeatureInfo> feature_info = new FeatureInfo; + if (command_line) { + GpuDriverBugWorkarounds gpu_driver_bug_workaround(command_line); + feature_info = new FeatureInfo(*command_line, gpu_driver_bug_workaround); + } + + group_ = scoped_refptr<ContextGroup>(new ContextGroup( + gpu_preferences_, NULL, memory_tracker_, + new ShaderTranslatorCache(gpu_preferences_), + new FramebufferCompletenessCache, feature_info, + normalized_init.bind_generates_resource)); bool use_default_textures = normalized_init.bind_generates_resource; InSequence sequence; @@ -242,6 +244,14 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_DRAW_BUFFERS, _)) .WillOnce(SetArgumentPointee<1>(kMaxDrawBuffers)) .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, GenTransformFeedbacks(1, _)) + .WillOnce(SetArgumentPointee<1>(kServiceDefaultTransformFeedbackId)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindTransformFeedback(GL_TRANSFORM_FEEDBACK, + kServiceDefaultTransformFeedbackId)) + .Times(1) + .RetiresOnSaturation(); } if (group_->feature_info()->feature_flags().native_vertex_array_object) { @@ -290,7 +300,10 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0 + tt)) .Times(1) .RetiresOnSaturation(); - if (group_->feature_info()->feature_flags().oes_egl_image_external) { + if (group_->feature_info()->feature_flags().oes_egl_image_external || + group_->feature_info() + ->feature_flags() + .nv_egl_stream_consumer_external) { EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_EXTERNAL_OES, use_default_textures @@ -418,21 +431,13 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( shared_memory_id_ = kSharedMemoryId; shared_memory_base_ = buffer->memory(); - static const int32_t kLoseContextWhenOutOfMemory = 0x10002; - static const int32_t kWebGLVersion = 0x10003; - - int32_t attributes[] = { - EGL_ALPHA_SIZE, - normalized_init.request_alpha ? 8 : 0, - EGL_DEPTH_SIZE, - normalized_init.request_depth ? 24 : 0, - EGL_STENCIL_SIZE, - normalized_init.request_stencil ? 8 : 0, - kLoseContextWhenOutOfMemory, - normalized_init.lose_context_when_out_of_memory ? 1 : 0, - kWebGLVersion, - init.context_type}; - std::vector<int32_t> attribs(attributes, attributes + arraysize(attributes)); + gles2::ContextCreationAttribHelper attribs; + attribs.alpha_size = normalized_init.request_alpha ? 8 : 0; + attribs.depth_size = normalized_init.request_depth ? 24 : 0; + attribs.stencil_size = normalized_init.request_stencil ? 8 : 0; + attribs.lose_context_when_out_of_memory = + normalized_init.lose_context_when_out_of_memory; + attribs.context_type = init.context_type; decoder_.reset(GLES2Decoder::Create(group_.get())); decoder_->SetIgnoreCachedStateForTest(ignore_cached_state_for_test_); @@ -521,6 +526,19 @@ void GLES2DecoderTestBase::ResetDecoder() { .Times(1) .RetiresOnSaturation(); } + if (group_->feature_info()->IsES3Capable()) { + // fake default transform feedback. + EXPECT_CALL(*gl_, DeleteTransformFeedbacks(1, _)) + .Times(1) + .RetiresOnSaturation(); + } + if (group_->feature_info()->gl_version_info().IsAtLeastGL(4, 0) || + group_->feature_info()->gl_version_info().IsAtLeastGLES(3, 0)) { + // |client_transformfeedback_id_| + EXPECT_CALL(*gl_, DeleteTransformFeedbacks(1, _)) + .Times(1) + .RetiresOnSaturation(); + } } decoder_->EndDecoding(); @@ -645,7 +663,7 @@ void GLES2DecoderTestBase::SetBucketAsCStrings(uint32_t bucket_id, char str_end) { uint32_t header_size = sizeof(GLint) * (count + 1); uint32_t total_size = header_size; - scoped_ptr<GLint[]> header(new GLint[count + 1]); + std::unique_ptr<GLint[]> header(new GLint[count + 1]); header[0] = static_cast<GLint>(count_in_header); for (GLsizei ii = 0; ii < count; ++ii) { header[ii + 1] = str && str[ii] ? strlen(str[ii]) : 0; @@ -1131,6 +1149,11 @@ void GLES2DecoderTestBase::DoBindTexture( EXPECT_CALL(*gl_, BindTexture(target, service_id)) .Times(1) .RetiresOnSaturation(); + if (!group_->feature_info()->gl_version_info().BehavesLikeGLES() && + group_->feature_info()->gl_version_info().IsAtLeastGL(3, 2)) { + EXPECT_CALL(*gl_, TexParameteri(target, GL_DEPTH_TEXTURE_MODE, GL_RED)) + .Times(AtMost(1)); + } cmds::BindTexture cmd; cmd.Init(target, client_id); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); @@ -1479,6 +1502,7 @@ const GLuint GLES2DecoderTestBase::kServiceElementBufferId; const GLuint GLES2DecoderTestBase::kServiceQueryId; const GLuint GLES2DecoderTestBase::kServiceVertexArrayId; const GLuint GLES2DecoderTestBase::kServiceTransformFeedbackId; +const GLuint GLES2DecoderTestBase::kServiceDefaultTransformFeedbackId; const GLuint GLES2DecoderTestBase::kServiceSyncId; const int32_t GLES2DecoderTestBase::kSharedMemoryId; @@ -1987,8 +2011,7 @@ void GLES2DecoderTestBase::SetupInitStateManualExpectations(bool es3_capable) { GLES2DecoderWithShaderTestBase::MockCommandBufferEngine:: MockCommandBufferEngine() { - - scoped_ptr<base::SharedMemory> shm(new base::SharedMemory()); + std::unique_ptr<base::SharedMemory> shm(new base::SharedMemory()); shm->CreateAndMapAnonymous(kSharedBufferSize); valid_buffer_ = MakeBufferFromSharedMemory(std::move(shm), kSharedBufferSize); 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 68bfdcd29b9..c519ba58cb4 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 @@ -8,6 +8,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/message_loop/message_loop.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" @@ -26,7 +28,7 @@ #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/test_helper.h" #include "gpu/command_buffer/service/texture_manager.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" +#include "gpu/command_buffer/service/transform_feedback_manager.h" #include "gpu/command_buffer/service/vertex_array_manager.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_mock.h" @@ -132,10 +134,6 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { return group_->program_manager()->GetProgram(client_id); } - Valuebuffer* GetValuebuffer(GLuint client_id) { - return group_->valuebuffer_manager()->GetValuebuffer(client_id); - } - QueryManager::Query* GetQueryInfo(GLuint client_id) { return decoder_->GetQueryManager()->GetQuery(client_id); } @@ -144,9 +142,9 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { return group_->sampler_manager()->GetSampler(client_id); } - bool GetTransformFeedbackServiceId( - GLuint client_id, GLuint* service_id) const { - return group_->GetTransformFeedbackServiceId(client_id, service_id); + TransformFeedback* GetTransformFeedback(GLuint client_id) { + return decoder_->GetTransformFeedbackManager()->GetTransformFeedback( + client_id); } bool GetSyncServiceId(GLuint client_id, GLsync* service_id) const { @@ -163,18 +161,14 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { return group_->program_manager(); } - ValuebufferManager* valuebuffer_manager() { - return group_->valuebuffer_manager(); - } - - ValueStateMap* pending_valuebuffer_state() { - return group_->pending_valuebuffer_state(); - } - FeatureInfo* feature_info() { return group_->feature_info(); } + FramebufferCompletenessCache* framebuffer_completeness_cache() const { + return group_->framebuffer_completeness_cache(); + } + ImageManager* GetImageManager() { return decoder_->GetImageManager(); } void DoCreateProgram(GLuint client_id, GLuint service_id); @@ -517,7 +511,8 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { static const GLuint kServiceQueryId = 309; static const GLuint kServiceVertexArrayId = 310; static const GLuint kServiceTransformFeedbackId = 311; - static const GLuint kServiceSyncId = 312; + static const GLuint kServiceDefaultTransformFeedbackId = 312; + static const GLuint kServiceSyncId = 313; static const int32_t kSharedMemoryId = 401; static const size_t kSharedBufferSize = 2048; @@ -627,11 +622,11 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { static const char* kOutputVariable1NameESSL3; // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; + std::unique_ptr<::testing::StrictMock<::gfx::MockGLInterface>> gl_; scoped_refptr<gfx::GLSurfaceStub> surface_; scoped_refptr<GLContextMock> context_; - scoped_ptr<MockGLES2Decoder> mock_decoder_; - scoped_ptr<GLES2Decoder> decoder_; + std::unique_ptr<MockGLES2Decoder> mock_decoder_; + std::unique_ptr<GLES2Decoder> decoder_; MemoryTracker* memory_tracker_; GLuint client_buffer_id_; @@ -646,7 +641,6 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { GLuint client_fragment_shader_id_; GLuint client_query_id_; GLuint client_vertexarray_id_; - GLuint client_valuebuffer_id_; GLuint client_transformfeedback_id_; GLuint client_sync_id_; @@ -754,7 +748,7 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { void SetupInitStateManualExpectations(bool es3_capable); - scoped_ptr< ::testing::StrictMock<MockCommandBufferEngine> > engine_; + std::unique_ptr<::testing::StrictMock<MockCommandBufferEngine>> engine_; GpuPreferences gpu_preferences_; scoped_refptr<ContextGroup> group_; MockGLStates gl_states_; diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc index b6c01624e29..38f118eef84 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc @@ -21,39 +21,51 @@ namespace { } // namespace anonymous -TEST_P(GLES2DecoderTest, BindBufferBaseValidArgs) { +TEST_P(GLES3DecoderTest, BindBufferBaseValidArgs) { EXPECT_CALL( *gl_, BindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kServiceBufferId)); - EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, _)) - .WillOnce(SetArgPointee<1>(4)) - .RetiresOnSaturation(); SpecializedSetup<cmds::BindBufferBase, 0>(true); cmds::BindBufferBase cmd; cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, client_buffer_id_); - decoder_->set_unsafe_es3_apis_enabled(true); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); } -TEST_P(GLES2DecoderTest, BindBufferBaseValidArgsNewId) { +TEST_P(GLES3DecoderTest, BindBufferBaseValidArgsNewId) { EXPECT_CALL(*gl_, BindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewServiceId)); - EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, _)) - .WillOnce(SetArgPointee<1>(4)) - .RetiresOnSaturation(); EXPECT_CALL(*gl_, GenBuffersARB(1, _)) .WillOnce(SetArgPointee<1>(kNewServiceId)); SpecializedSetup<cmds::BindBufferBase, 0>(true); cmds::BindBufferBase cmd; cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewClientId); - decoder_->set_unsafe_es3_apis_enabled(true); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); EXPECT_TRUE(GetBuffer(kNewClientId) != NULL); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); +} + + +TEST_P(GLES3DecoderTest, BindBufferRangeValidArgs) { + EXPECT_CALL(*gl_, BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 2, + kServiceBufferId, 4, 4)); + SpecializedSetup<cmds::BindBufferRange, 0>(true); + cmds::BindBufferRange cmd; + cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, client_buffer_id_, 4, 4); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES3DecoderTest, BindBufferRangeValidArgsNewId) { + EXPECT_CALL(*gl_, BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 2, + kNewServiceId, 4, 4)); + EXPECT_CALL(*gl_, GenBuffersARB(1, _)) + .WillOnce(SetArgPointee<1>(kNewServiceId)); + SpecializedSetup<cmds::BindBufferRange, 0>(true); + cmds::BindBufferRange cmd; + cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewClientId, 4, 4); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(GetBuffer(kNewClientId) != NULL); } TEST_P(GLES2DecoderTest, MapBufferRangeUnmapBufferReadSucceeds) { 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 f021289f560..47306f984df 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 @@ -8,6 +8,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/command_line.h" #include "base/strings/string_number_conversions.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" @@ -572,8 +574,8 @@ void GLES2DecoderTest::CheckReadPixelsOutOfRange(GLint in_read_x, EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); GLint unpadded_row_size = emu.ComputeImageDataSize(in_read_width, 1); - scoped_ptr<int8_t[]> zero(new int8_t[unpadded_row_size]); - scoped_ptr<int8_t[]> pack(new int8_t[kPackAlignment]); + std::unique_ptr<int8_t[]> zero(new int8_t[unpadded_row_size]); + std::unique_ptr<int8_t[]> pack(new int8_t[kPackAlignment]); memset(zero.get(), kInitialMemoryValue, unpadded_row_size); memset(pack.get(), kInitialMemoryValue, kPackAlignment); for (GLint yy = 0; yy < in_read_height; ++yy) { @@ -3196,47 +3198,37 @@ TEST_P(GLES2DecoderManualInitTest, EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer)); } -TEST_P(GLES2DecoderManualInitTest, ReadFormatExtension) { - InitState init; - init.extensions = "GL_OES_read_format"; - init.bind_generates_resource = true; - InitDecoder(init); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()).Times(6).RetiresOnSaturation(); - - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - GetIntegerv cmd; - const GLuint kFBOClientTextureId = 4100; - const GLuint kFBOServiceTextureId = 4101; - - // Register a texture id. - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgPointee<1>(kFBOServiceTextureId)) - .RetiresOnSaturation(); - GenHelper<GenTexturesImmediate>(kFBOClientTextureId); - - // Setup "render to" texture. - DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); +TEST_P(GLES2DecoderTest, ImplementationReadColorFormatAndType) { + ClearSharedMemory(); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset); DoBindFramebuffer( GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); DoFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kFBOClientTextureId, - kFBOServiceTextureId, + client_texture_id_, + kServiceTextureId, 0, GL_NO_ERROR); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + GetIntegerv cmd; + result->size = 0; + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(_)) + .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(1).RetiresOnSaturation(); cmd.Init(GL_IMPLEMENTATION_COLOR_READ_FORMAT, shared_memory_id_, @@ -3246,6 +3238,15 @@ TEST_P(GLES2DecoderManualInitTest, ReadFormatExtension) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); result->size = 0; + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(_)) + .Times(0); EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(1).RetiresOnSaturation(); cmd.Init(GL_IMPLEMENTATION_COLOR_READ_TYPE, shared_memory_id_, @@ -3255,60 +3256,38 @@ TEST_P(GLES2DecoderManualInitTest, ReadFormatExtension) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_P(GLES2DecoderManualInitTest, NoReadFormatExtension) { - InitState init; - init.bind_generates_resource = true; - InitDecoder(init); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - GetIntegerv cmd; - const GLuint kFBOClientTextureId = 4100; - const GLuint kFBOServiceTextureId = 4101; - - // Register a texture id. - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgPointee<1>(kFBOServiceTextureId)) - .RetiresOnSaturation(); - GenHelper<GenTexturesImmediate>(kFBOClientTextureId); +TEST_P(GLES3DecoderTest, FramebufferTextureLayerNoBoundFramebuffer) { + DoBindTexture(GL_TEXTURE_3D, client_texture_id_, kServiceTextureId); + EXPECT_CALL(*gl_, FramebufferTextureLayer(_, _, _, _, _)).Times(0); + cmds::FramebufferTextureLayer cmd; + cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, client_texture_id_, 4, 5); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} - // Setup "render to" texture. - DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); +TEST_P(GLES3DecoderTest, FramebufferTextureLayerInvalidTextureTarget) { DoBindFramebuffer( GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); - DoFramebufferTexture2D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - kFBOClientTextureId, - kFBOServiceTextureId, - 0, - GL_NO_ERROR); - - result->size = 0; - EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(0).RetiresOnSaturation(); - cmd.Init(GL_IMPLEMENTATION_COLOR_READ_FORMAT, - shared_memory_id_, - shared_memory_offset_); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + EXPECT_CALL(*gl_, FramebufferTextureLayer(_, _, _, _, _)).Times(0); + cmds::FramebufferTextureLayer cmd; + cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, client_texture_id_, 4, 5); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(1, result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} - result->size = 0; - EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(0).RetiresOnSaturation(); - cmd.Init(GL_IMPLEMENTATION_COLOR_READ_TYPE, - shared_memory_id_, - shared_memory_offset_); +TEST_P(GLES3DecoderTest, FramebufferTextureLayerValidArgs) { + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoBindTexture(GL_TEXTURE_3D, client_texture_id_, kServiceTextureId); + EXPECT_CALL(*gl_, FramebufferTextureLayer(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + kServiceTextureId, 4, 5)) + .Times(1) + .RetiresOnSaturation(); + cmds::FramebufferTextureLayer cmd; + cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, client_texture_id_, 4, 5); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(1, result->GetNumResults()); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } 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 c9d8ba16aac..8e1420ba4fd 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 @@ -49,6 +49,16 @@ using ::testing::SetArgPointee; using ::testing::StrEq; using ::testing::StrictMock; +namespace { +class EmulatingRGBImageStub : public gl::GLImageStub { + protected: + ~EmulatingRGBImageStub() override {} + bool EmulatingRGB() const override { + return true; + } +}; +} // namespace + namespace gpu { namespace gles2 { @@ -3477,10 +3487,6 @@ TEST_P(GLES3DecoderTest, TexStorage3DValidArgs) { EXPECT_CALL(*gl_, TexStorage3D(GL_TEXTURE_3D, 2, GL_RGB565, 4, 5, 6)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); cmds::TexStorage3D cmd; cmd.Init(GL_TEXTURE_3D, 2, GL_RGB565, 4, 5, 6); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); @@ -3680,6 +3686,131 @@ TEST_P(GLES3DecoderTest, ClearLevel3DMultipleCallsPerLayer) { texture, kTarget, kLevel, kFormat, kType, kWidth, kHeight, kDepth)); } +// Test that copyTexImage2D uses the emulated internal format, rather than the +// real internal format. +TEST_P(GLES2DecoderWithShaderTest, CHROMIUMImageEmulatingRGB) { + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + GLenum target = GL_TEXTURE_2D; + GLint level = 0; + GLsizei width = 1; + GLsizei height = 1; + + // Generate the source framebuffer. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, + kServiceFramebufferId); + + GLenum destination_texture_formats[] = {GL_RGBA, GL_RGB}; + for (int use_rgb_emulation = 0; use_rgb_emulation < 2; ++ use_rgb_emulation) { + for (size_t destination_texture_index = 0; destination_texture_index < 2; + ++destination_texture_index) { + // Generate and bind the source image. Making a new image for each set of + // parameters is easier than trying to reuse images. Obviously there's no + // performance penalty. + int image_id = use_rgb_emulation * 2 + destination_texture_index; + scoped_refptr<gl::GLImage> image; + if (use_rgb_emulation) + image = new EmulatingRGBImageStub; + else + image = new gl::GLImageStub; + GetImageManager()->AddImage(image.get(), image_id); + EXPECT_FALSE(GetImageManager()->LookupImage(image_id) == NULL); + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + + DoBindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id); + DoFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, + kFBOClientTextureId, kFBOServiceTextureId, level, + GL_NO_ERROR); + + GLenum destination_texture_format = + destination_texture_formats[destination_texture_index]; + bool should_succeed = + !use_rgb_emulation || (destination_texture_format == GL_RGB); + if (should_succeed) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + CopyTexImage2D(GL_TEXTURE_2D, 0, destination_texture_format, + 0, 0, 1, 1, 0)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + } + + if (destination_texture_index == 0 || !framebuffer_completeness_cache()) { + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) + .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) + .RetiresOnSaturation(); + } + + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + CopyTexImage2D cmd; + cmd.Init(target, level, destination_texture_format, 0, 0, width, height); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + GLenum expectation = should_succeed ? GL_NO_ERROR : GL_INVALID_OPERATION; + EXPECT_EQ(expectation, static_cast<GLenum>(GetGLError())); + } + } +} + +TEST_P(GLES2DecoderTest, BindTextureValidArgs) { + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)) + .Times(1) + .RetiresOnSaturation(); + if (!feature_info()->gl_version_info().BehavesLikeGLES() && + feature_info()->gl_version_info().IsAtLeastGL(3, 2)) { + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, + GL_DEPTH_TEXTURE_MODE, + GL_RED)) + .Times(1) + .RetiresOnSaturation(); + } + cmds::BindTexture cmd; + cmd.Init(GL_TEXTURE_2D, client_texture_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest, BindTextureValidArgsNewId) { + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kNewServiceId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgumentPointee<1>(kNewServiceId)); + if (!feature_info()->gl_version_info().BehavesLikeGLES() && + feature_info()->gl_version_info().IsAtLeastGL(3, 2)) { + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, + GL_DEPTH_TEXTURE_MODE, + GL_RED)) + .Times(1) + .RetiresOnSaturation(); + } + cmds::BindTexture cmd; + cmd.Init(GL_TEXTURE_2D, kNewClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(GetTexture(kNewClientId) != NULL); +} + +TEST_P(GLES2DecoderTest, BindTextureInvalidArgs) { + EXPECT_CALL(*gl_, BindTexture(_, _)).Times(0); + cmds::BindTexture cmd; + cmd.Init(GL_TEXTURE_1D, client_texture_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + + cmd.Init(GL_TEXTURE_3D, client_texture_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + // TODO(gman): Complete this test. // TEST_P(GLES2DecoderTest, CompressedTexImage2DGLError) { // } diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_valuebuffer.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_valuebuffer.cc deleted file mode 100644 index 8f1b0e03951..00000000000 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_valuebuffer.cc +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gpu/command_buffer/service/gles2_cmd_decoder.h" - -#include <stdint.h> - -#include "base/command_line.h" -#include "gpu/command_buffer/common/gles2_cmd_format.h" -#include "gpu/command_buffer/common/gles2_cmd_utils.h" -#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" -#include "gpu/command_buffer/service/test_helper.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/gl/gl_implementation.h" -#include "ui/gl/gl_mock.h" -#include "ui/gl/gl_surface_stub.h" - -using ::gfx::MockGLInterface; -using ::testing::_; - -namespace gpu { -namespace gles2 { - -using namespace cmds; - -TEST_P(GLES2DecoderWithShaderTest, ValuebufferBasic) { - const uint32_t kBufferId = 123; - ValueState valuestate; - valuestate.int_value[0] = 111; - valuestate.int_value[1] = 222; - valuebuffer_manager()->CreateValuebuffer(kBufferId); - pending_valuebuffer_state()->UpdateState( - GL_MOUSE_POSITION_CHROMIUM, valuestate); - BindValuebufferCHROMIUM cmd1; - cmd1.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, kBufferId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); - SubscribeValueCHROMIUM cmd2; - cmd2.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, GL_MOUSE_POSITION_CHROMIUM); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - PopulateSubscribedValuesCHROMIUM cmd3; - cmd3.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd3)); - EXPECT_CALL(*gl_, Uniform2iv(kUniform2RealLocation, 1, _)).Times(1); - UniformValuebufferCHROMIUM cmd4; - cmd4.Init(kUniform2FakeLocation, GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, - GL_MOUSE_POSITION_CHROMIUM); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd4)); -} - -TEST_P(GLES2DecoderWithShaderTest, SubscribeValuebufferNotBound) { - const uint32_t kBufferId = 123; - ValueState valuestate; - valuestate.int_value[0] = 111; - valuestate.int_value[1] = 222; - valuebuffer_manager()->CreateValuebuffer(kBufferId); - pending_valuebuffer_state()->UpdateState( - GL_MOUSE_POSITION_CHROMIUM, valuestate); - SubscribeValueCHROMIUM cmd1; - cmd1.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, GL_MOUSE_POSITION_CHROMIUM); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_P(GLES2DecoderWithShaderTest, PopulateValuebufferNoSubscription) { - const uint32_t kBufferId = 123; - ValueState valuestate; - valuestate.int_value[0] = 111; - valuestate.int_value[1] = 222; - valuebuffer_manager()->CreateValuebuffer(kBufferId); - pending_valuebuffer_state()->UpdateState( - GL_MOUSE_POSITION_CHROMIUM, valuestate); - BindValuebufferCHROMIUM cmd1; - cmd1.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, kBufferId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); - PopulateSubscribedValuesCHROMIUM cmd2; - cmd2.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ(GL_NONE, GetGLError()); -} - -TEST_P(GLES2DecoderWithShaderTest, UniformValuebufferNoState) { - const uint32_t kBufferId = 123; - ValueState valuestate; - valuestate.int_value[0] = 111; - valuestate.int_value[1] = 222; - valuebuffer_manager()->CreateValuebuffer(kBufferId); - pending_valuebuffer_state()->UpdateState( - GL_MOUSE_POSITION_CHROMIUM, valuestate); - BindValuebufferCHROMIUM cmd1; - cmd1.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, kBufferId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); - SubscribeValueCHROMIUM cmd2; - cmd2.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, GL_MOUSE_POSITION_CHROMIUM); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_CALL(*gl_, Uniform2iv(kUniform2RealLocation, 1, _)).Times(0); - UniformValuebufferCHROMIUM cmd3; - cmd3.Init(kUniform2FakeLocation, GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, - GL_MOUSE_POSITION_CHROMIUM); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd3)); - EXPECT_EQ(GL_NONE, GetGLError()); -} - -TEST_P(GLES2DecoderWithShaderTest, UniformValuebufferInvalidLocation) { - const uint32_t kBufferId = 123; - ValueState valuestate; - valuestate.int_value[0] = 111; - valuestate.int_value[1] = 222; - valuebuffer_manager()->CreateValuebuffer(kBufferId); - pending_valuebuffer_state()->UpdateState( - GL_MOUSE_POSITION_CHROMIUM, valuestate); - BindValuebufferCHROMIUM cmd1; - cmd1.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, kBufferId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); - SubscribeValueCHROMIUM cmd2; - cmd2.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, GL_MOUSE_POSITION_CHROMIUM); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - PopulateSubscribedValuesCHROMIUM cmd3; - cmd3.Init(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd3)); - EXPECT_CALL(*gl_, Uniform2iv(kUniform2RealLocation, 1, _)).Times(0); - UniformValuebufferCHROMIUM cmd4; - cmd4.Init(kUniform1FakeLocation, GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, - GL_MOUSE_POSITION_CHROMIUM); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd4)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -} // namespace gles2 -} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_validation_autogen.h index 99161c643f4..229963fd394 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_validation_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_validation_autogen.h @@ -253,12 +253,7 @@ class QueryTargetValidator { }; QueryTargetValidator query_target; -class ReadBufferValidator { - public: - bool IsValid(const GLenum value) const; -}; -ReadBufferValidator read_buffer; - +ValueValidator<GLenum> read_buffer; ValueValidator<GLenum> read_pixel_format; ValueValidator<GLenum> read_pixel_type; ValueValidator<GLenum> render_buffer_format; @@ -308,7 +303,6 @@ class StringTypeValidator { }; StringTypeValidator string_type; -ValueValidator<GLenum> subscription_target; ValueValidator<GLbitfield> sync_flush_flags; class SyncParameterValidator { public: @@ -389,7 +383,6 @@ class UniformParameterValidator { }; UniformParameterValidator uniform_parameter; -ValueValidator<GLenum> value_buffer_target; class VertexAttribITypeValidator { public: bool IsValid(const GLenum value) const; 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 8cbb4bff3c8..3a3b84b4618 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 @@ -745,29 +745,25 @@ bool Validators::QueryTargetValidator::IsValid(const GLenum value) const { return false; }; -bool Validators::ReadBufferValidator::IsValid(const GLenum value) const { - switch (value) { - case GL_NONE: - case GL_BACK: - case GL_COLOR_ATTACHMENT0: - case GL_COLOR_ATTACHMENT1: - case GL_COLOR_ATTACHMENT2: - case GL_COLOR_ATTACHMENT3: - case GL_COLOR_ATTACHMENT4: - case GL_COLOR_ATTACHMENT5: - case GL_COLOR_ATTACHMENT6: - case GL_COLOR_ATTACHMENT7: - case GL_COLOR_ATTACHMENT8: - case GL_COLOR_ATTACHMENT9: - case GL_COLOR_ATTACHMENT10: - case GL_COLOR_ATTACHMENT11: - case GL_COLOR_ATTACHMENT12: - case GL_COLOR_ATTACHMENT13: - case GL_COLOR_ATTACHMENT14: - case GL_COLOR_ATTACHMENT15: - return true; - } - return false; +static const GLenum valid_read_buffer_table[] = { + GL_NONE, + GL_BACK, + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3, + GL_COLOR_ATTACHMENT4, + GL_COLOR_ATTACHMENT5, + GL_COLOR_ATTACHMENT6, + GL_COLOR_ATTACHMENT7, + GL_COLOR_ATTACHMENT8, + GL_COLOR_ATTACHMENT9, + GL_COLOR_ATTACHMENT10, + GL_COLOR_ATTACHMENT11, + GL_COLOR_ATTACHMENT12, + GL_COLOR_ATTACHMENT13, + GL_COLOR_ATTACHMENT14, + GL_COLOR_ATTACHMENT15, }; static const GLenum valid_read_pixel_format_table[] = { @@ -947,10 +943,6 @@ bool Validators::StringTypeValidator::IsValid(const GLenum value) const { return false; }; -static const GLenum valid_subscription_target_table[] = { - GL_MOUSE_POSITION_CHROMIUM, -}; - static const GLbitfield valid_sync_flush_flags_table[] = { GL_SYNC_FLUSH_COMMANDS_BIT, 0, }; @@ -1331,10 +1323,6 @@ bool Validators::UniformParameterValidator::IsValid(const GLenum value) const { return false; }; -static const GLenum valid_value_buffer_target_table[] = { - GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, -}; - bool Validators::VertexAttribITypeValidator::IsValid(const GLenum value) const { switch (value) { case GL_BYTE: @@ -1401,6 +1389,7 @@ Validators::Validators() index_type(valid_index_type_table, arraysize(valid_index_type_table)), pixel_store(valid_pixel_store_table, arraysize(valid_pixel_store_table)), pixel_type(valid_pixel_type_table, arraysize(valid_pixel_type_table)), + read_buffer(valid_read_buffer_table, arraysize(valid_read_buffer_table)), read_pixel_format(valid_read_pixel_format_table, arraysize(valid_read_pixel_format_table)), read_pixel_type(valid_read_pixel_type_table, @@ -1414,8 +1403,6 @@ Validators::Validators() shader_binary_format(), src_blend_factor(valid_src_blend_factor_table, arraysize(valid_src_blend_factor_table)), - subscription_target(valid_subscription_target_table, - arraysize(valid_subscription_target_table)), sync_flush_flags(valid_sync_flush_flags_table, arraysize(valid_sync_flush_flags_table)), texture_bind_target(valid_texture_bind_target_table, @@ -1449,8 +1436,6 @@ Validators::Validators() transform_feedback_bind_target( valid_transform_feedback_bind_target_table, arraysize(valid_transform_feedback_bind_target_table)), - value_buffer_target(valid_value_buffer_target_table, - arraysize(valid_value_buffer_target_table)), vertex_attrib_type(valid_vertex_attrib_type_table, arraysize(valid_vertex_attrib_type_table)), vertex_attribute(valid_vertex_attribute_table, diff --git a/chromium/gpu/command_buffer/service/gpu_preferences.h b/chromium/gpu/command_buffer/service/gpu_preferences.h index d2429de9ac9..6fe15b0eace 100644 --- a/chromium/gpu/command_buffer/service/gpu_preferences.h +++ b/chromium/gpu/command_buffer/service/gpu_preferences.h @@ -50,6 +50,9 @@ struct GPU_EXPORT GpuPreferences { #if defined(OS_WIN) // Enables experimental hardware acceleration for VP8/VP9 video decoding. bool enable_accelerated_vpx_decode = false; + + // Enables support for avoiding copying DXGI NV12 textures. + bool enable_zero_copy_dxgi_video = false; #endif // =================================== @@ -97,9 +100,6 @@ struct GPU_EXPORT GpuPreferences { // Allows async texture uploads (off main thread) via GL context sharing. bool enable_share_group_async_texture_upload = false; - // Enable WebGL subscribe uniform extension. - bool enable_subscribe_uniform_extension = false; - // Simulates shared textures when share groups are not available. // Not available everywhere. bool enable_threaded_texture_mailboxes = false; diff --git a/chromium/gpu/command_buffer/service/gpu_service_test.cc b/chromium/gpu/command_buffer/service/gpu_service_test.cc index 5be0b9bf8cf..4db0019230a 100644 --- a/chromium/gpu/command_buffer/service/gpu_service_test.cc +++ b/chromium/gpu/command_buffer/service/gpu_service_test.cc @@ -9,6 +9,7 @@ #include "ui/gl/gl_context_stub_with_extensions.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface_stub.h" #include "ui/gl/test/gl_surface_test_support.h" namespace gpu { @@ -33,6 +34,8 @@ void GpuServiceTest::SetUpWithGLVersion(const char* gl_version, context_ = new gfx::GLContextStubWithExtensions; context_->AddExtensionsString(gl_extensions); context_->SetGLVersionString(gl_version); + surface_ = new gfx::GLSurfaceStub; + context_->MakeCurrent(surface_.get()); gfx::GLSurfaceTestSupport::InitializeDynamicMockBindings(context_.get()); ran_setup_ = true; } @@ -43,6 +46,8 @@ void GpuServiceTest::SetUp() { void GpuServiceTest::TearDown() { DCHECK(ran_setup_); + context_ = nullptr; + surface_ = nullptr; ::gfx::MockGLInterface::SetGLInterface(NULL); gl_.reset(); gfx::ClearGLBindings(); @@ -54,5 +59,10 @@ void GpuServiceTest::TearDown() { gfx::GLContext* GpuServiceTest::GetGLContext() { return context_.get(); } + +gfx::GLSurface* GpuServiceTest::GetGLSurface() { + return surface_.get(); +} + } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gpu_service_test.h b/chromium/gpu/command_buffer/service/gpu_service_test.h index e547ff12fda..5caa9de29c3 100644 --- a/chromium/gpu/command_buffer/service/gpu_service_test.h +++ b/chromium/gpu/command_buffer/service/gpu_service_test.h @@ -5,8 +5,9 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_SERVICE_TEST_H_ #define GPU_COMMAND_BUFFER_SERVICE_GPU_SERVICE_TEST_H_ +#include <memory> + #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -14,6 +15,8 @@ namespace gfx { class GLContextStubWithExtensions; +class GLSurface; +class GLSurfaceStub; } namespace gpu { @@ -30,13 +33,15 @@ class GpuServiceTest : public testing::Test { void SetUp() override; void TearDown() override; gfx::GLContext* GetGLContext(); + gfx::GLSurface* GetGLSurface(); - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; + std::unique_ptr<::testing::StrictMock<::gfx::MockGLInterface>> gl_; private: bool ran_setup_; bool ran_teardown_; scoped_refptr<gfx::GLContextStubWithExtensions> context_; + scoped_refptr<gfx::GLSurfaceStub> surface_; base::MessageLoop message_loop_; }; diff --git a/chromium/gpu/command_buffer/service/gpu_state_tracer.cc b/chromium/gpu/command_buffer/service/gpu_state_tracer.cc index add3bf3acef..f26d3dfcc21 100644 --- a/chromium/gpu/command_buffer/service/gpu_state_tracer.cc +++ b/chromium/gpu/command_buffer/service/gpu_state_tracer.cc @@ -6,6 +6,7 @@ #include "base/base64.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/trace_event/trace_event.h" #include "context_state.h" #include "ui/gfx/codec/png_codec.h" @@ -19,7 +20,7 @@ const int kBytesPerPixel = 4; class Snapshot : public base::trace_event::ConvertableToTraceFormat { public: - static scoped_ptr<Snapshot> Create(const ContextState* state); + static std::unique_ptr<Snapshot> Create(const ContextState* state); ~Snapshot() override {} @@ -44,8 +45,8 @@ class Snapshot : public base::trace_event::ConvertableToTraceFormat { Snapshot::Snapshot(const ContextState* state) : state_(state) {} -scoped_ptr<Snapshot> Snapshot::Create(const ContextState* state) { - return make_scoped_ptr(new Snapshot(state)); +std::unique_ptr<Snapshot> Snapshot::Create(const ContextState* state) { + return base::WrapUnique(new Snapshot(state)); } bool Snapshot::SaveScreenshot(const gfx::Size& size) { @@ -99,8 +100,9 @@ void Snapshot::AppendAsTraceFormat(std::string* out) const { *out += "}"; } -scoped_ptr<GPUStateTracer> GPUStateTracer::Create(const ContextState* state) { - return scoped_ptr<GPUStateTracer>(new GPUStateTracer(state)); +std::unique_ptr<GPUStateTracer> GPUStateTracer::Create( + const ContextState* state) { + return std::unique_ptr<GPUStateTracer>(new GPUStateTracer(state)); } GPUStateTracer::GPUStateTracer(const ContextState* state) : state_(state) { @@ -117,7 +119,7 @@ void GPUStateTracer::TakeSnapshotWithCurrentFramebuffer(const gfx::Size& size) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.debug"), "GPUStateTracer::TakeSnapshotWithCurrentFramebuffer"); - scoped_ptr<Snapshot> snapshot(Snapshot::Create(state_)); + std::unique_ptr<Snapshot> snapshot(Snapshot::Create(state_)); // Only save a screenshot for now. if (!snapshot->SaveScreenshot(size)) diff --git a/chromium/gpu/command_buffer/service/gpu_state_tracer.h b/chromium/gpu/command_buffer/service/gpu_state_tracer.h index 1cb7fe92534..09a873bd517 100644 --- a/chromium/gpu/command_buffer/service/gpu_state_tracer.h +++ b/chromium/gpu/command_buffer/service/gpu_state_tracer.h @@ -5,8 +5,9 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_STATE_TRACER_H_ #define GPU_COMMAND_BUFFER_SERVICE_GPU_STATE_TRACER_H_ +#include <memory> + #include "base/macros.h" -#include "base/memory/scoped_ptr.h" namespace gfx { class Size; @@ -20,7 +21,7 @@ struct ContextState; // Saves GPU state such as framebuffer contents while tracing. class GPUStateTracer { public: - static scoped_ptr<GPUStateTracer> Create(const ContextState* state); + static std::unique_ptr<GPUStateTracer> Create(const ContextState* state); ~GPUStateTracer(); // Take a state snapshot with a screenshot of the currently bound framebuffer. diff --git a/chromium/gpu/command_buffer/service/gpu_switches.cc b/chromium/gpu/command_buffer/service/gpu_switches.cc index 389afcb902c..829fa8c71a2 100644 --- a/chromium/gpu/command_buffer/service/gpu_switches.cc +++ b/chromium/gpu/command_buffer/service/gpu_switches.cc @@ -54,10 +54,6 @@ const char kDisableGpuShaderDiskCache[] = "disable-gpu-shader-disk-cache"; const char kEnableShareGroupAsyncTextureUpload[] = "enable-share-group-async-texture-upload"; -// Enable WebGL subscribe uniform extension. -const char kEnableSubscribeUniformExtension[] = - "enable-subscribe-uniform-extension"; - // Simulates shared textures when share groups are not available. Not available // everywhere. const char kEnableThreadedTextureMailboxes[] = diff --git a/chromium/gpu/command_buffer/service/gpu_switches.h b/chromium/gpu/command_buffer/service/gpu_switches.h index 5b50e0bad13..60185d8704c 100644 --- a/chromium/gpu/command_buffer/service/gpu_switches.h +++ b/chromium/gpu/command_buffer/service/gpu_switches.h @@ -26,7 +26,6 @@ GPU_EXPORT extern const char kForceGpuMemAvailableMb[]; GPU_EXPORT extern const char kGpuProgramCacheSizeKb[]; GPU_EXPORT extern const char kDisableGpuShaderDiskCache[]; GPU_EXPORT extern const char kEnableShareGroupAsyncTextureUpload[]; -GPU_EXPORT extern const char kEnableSubscribeUniformExtension[]; GPU_EXPORT extern const char kEnableThreadedTextureMailboxes[]; GPU_EXPORT extern const char kGLShaderIntermOutput[]; GPU_EXPORT extern const char kEmulateShaderPrecision[]; diff --git a/chromium/gpu/command_buffer/service/gpu_tracer.cc b/chromium/gpu/command_buffer/service/gpu_tracer.cc index 049f10eccfe..db9fb700814 100644 --- a/chromium/gpu/command_buffer/service/gpu_tracer.cc +++ b/chromium/gpu/command_buffer/service/gpu_tracer.cc @@ -14,7 +14,7 @@ #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/threading/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" diff --git a/chromium/gpu/command_buffer/service/gpu_tracer.h b/chromium/gpu/command_buffer/service/gpu_tracer.h index 41fd2913479..438c9cbba48 100644 --- a/chromium/gpu/command_buffer/service/gpu_tracer.h +++ b/chromium/gpu/command_buffer/service/gpu_tracer.h @@ -9,12 +9,12 @@ #include <stdint.h> #include <deque> +#include <memory> #include <stack> #include <string> #include <vector> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" @@ -193,7 +193,7 @@ class GPU_EXPORT GPUTrace const std::string category_; const std::string name_; scoped_refptr<Outputter> outputter_; - scoped_ptr<gfx::GPUTimer> gpu_timer_; + std::unique_ptr<gfx::GPUTimer> gpu_timer_; const bool service_enabled_ = false; const bool device_enabled_ = false; diff --git a/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc b/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc index 760818d166c..161507420aa 100644 --- a/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc +++ b/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc @@ -747,8 +747,8 @@ class GPUTracerTest : public GpuServiceTest { decoder_ = nullptr; GpuServiceTest::TearDown(); } - scoped_ptr<MockGLES2Decoder> decoder_; - scoped_ptr<GPUTracerTester> tracer_tester_; + std::unique_ptr<MockGLES2Decoder> decoder_; + std::unique_ptr<GPUTracerTester> tracer_tester_; }; TEST_F(GPUTracerTest, IsTracingTest) { 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 27824398429..85729e5f187 100644 --- a/chromium/gpu/command_buffer/service/in_process_command_buffer.cc +++ b/chromium/gpu/command_buffer/service/in_process_command_buffer.cc @@ -21,11 +21,11 @@ #include "base/numerics/safe_conversions.h" #include "base/sequence_checker.h" #include "base/single_thread_task_runner.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" +#include "gpu/command_buffer/client/gpu_control_client.h" #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" #include "gpu/command_buffer/common/sync_token.h" -#include "gpu/command_buffer/common/value_state.h" #include "gpu/command_buffer/service/command_buffer_service.h" #include "gpu/command_buffer/service/command_executor.h" #include "gpu/command_buffer/service/context_group.h" @@ -39,17 +39,12 @@ #include "gpu/command_buffer/service/query_manager.h" #include "gpu/command_buffer/service/sync_point_manager.h" #include "gpu/command_buffer/service/transfer_buffer_manager.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" #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) -#include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h" -#include "ui/gl/android/surface_texture.h" -#endif +#include "ui/gl/init/gl_factory.h" #if defined(OS_WIN) #include <windows.h> @@ -89,7 +84,7 @@ struct GpuInProcessThreadHolder { GpuInProcessThreadHolder() : sync_point_manager(new SyncPointManager(false)), gpu_thread(new GpuInProcessThread(sync_point_manager.get())) {} - scoped_ptr<SyncPointManager> sync_point_manager; + std::unique_ptr<SyncPointManager> sync_point_manager; scoped_refptr<InProcessCommandBuffer::Service> gpu_thread; }; @@ -151,10 +146,12 @@ scoped_refptr<InProcessCommandBuffer::Service> GetInitialService( } // anonyous namespace -InProcessCommandBuffer::Service::Service() {} +InProcessCommandBuffer::Service::Service() + : gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()) {} InProcessCommandBuffer::Service::Service(const GpuPreferences& gpu_preferences) - : gpu_preferences_(gpu_preferences) {} + : gpu_preferences_(gpu_preferences), + gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()) {} InProcessCommandBuffer::Service::~Service() {} @@ -163,6 +160,11 @@ InProcessCommandBuffer::Service::gpu_preferences() { return gpu_preferences_; } +const gpu::GpuDriverBugWorkarounds& +InProcessCommandBuffer::Service::gpu_driver_bug_workarounds() { + return gpu_driver_bug_workarounds_; +} + scoped_refptr<gfx::GLShareGroup> InProcessCommandBuffer::Service::share_group() { if (!share_group_.get()) @@ -178,22 +180,6 @@ InProcessCommandBuffer::Service::mailbox_manager() { return mailbox_manager_; } -scoped_refptr<gles2::SubscriptionRefSet> -InProcessCommandBuffer::Service::subscription_ref_set() { - if (!subscription_ref_set_.get()) { - subscription_ref_set_ = new gles2::SubscriptionRefSet(); - } - return subscription_ref_set_; -} - -scoped_refptr<ValueStateMap> -InProcessCommandBuffer::Service::pending_valuebuffer_state() { - if (!pending_valuebuffer_state_.get()) { - pending_valuebuffer_state_ = new ValueStateMap(); - } - return pending_valuebuffer_state_; -} - gpu::gles2::ProgramCache* InProcessCommandBuffer::Service::program_cache() { if (!program_cache_.get() && (gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary || @@ -212,6 +198,10 @@ InProcessCommandBuffer::InProcessCommandBuffer( CommandBufferId::FromUnsafeValue(g_next_command_buffer_id.GetNext())), delayed_work_pending_(false), image_factory_(nullptr), + gpu_control_client_(nullptr), +#if DCHECK_IS_ON() + context_lost_(false), +#endif last_put_offset_(-1), gpu_memory_buffer_manager_(nullptr), next_fence_sync_release_(1), @@ -219,6 +209,7 @@ InProcessCommandBuffer::InProcessCommandBuffer( flush_event_(false, false), service_(GetInitialService(service)), fence_sync_wait_event_(false, false), + client_thread_weak_ptr_factory_(this), gpu_thread_weak_ptr_factory_(this) { DCHECK(service_.get()); next_image_id_.GetNext(); @@ -245,7 +236,7 @@ bool InProcessCommandBuffer::MakeCurrent() { return true; } -void InProcessCommandBuffer::PumpCommands() { +void InProcessCommandBuffer::PumpCommandsOnGpuThread() { CheckSequencedThread(); command_buffer_lock_.AssertAcquired(); @@ -255,32 +246,26 @@ void InProcessCommandBuffer::PumpCommands() { executor_->PutChanged(); } -bool InProcessCommandBuffer::GetBufferChanged(int32_t transfer_buffer_id) { - CheckSequencedThread(); - command_buffer_lock_.AssertAcquired(); - command_buffer_->SetGetBuffer(transfer_buffer_id); - return true; -} - bool InProcessCommandBuffer::Initialize( scoped_refptr<gfx::GLSurface> surface, bool is_offscreen, gfx::AcceleratedWidget window, const gfx::Size& size, - const std::vector<int32_t>& attribs, + const gles2::ContextCreationAttribHelper& attribs, gfx::GpuPreference gpu_preference, - const base::Closure& context_lost_callback, InProcessCommandBuffer* share_group, GpuMemoryBufferManager* gpu_memory_buffer_manager, ImageFactory* image_factory) { DCHECK(!share_group || service_.get() == share_group->service_.get()); - context_lost_callback_ = WrapCallback(context_lost_callback); - if (surface.get()) { + if (surface) { // GPU thread must be the same as client thread due to GLSurface not being // thread safe. sequence_checker_.reset(new base::SequenceChecker); surface_ = surface; + } else { + origin_task_runner_ = base::ThreadTaskRunnerHandle::Get(); + client_thread_weak_ptr_ = client_thread_weak_ptr_factory_.GetWeakPtr(); } gpu::Capabilities capabilities; @@ -325,38 +310,28 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( transfer_buffer_manager_ = manager; manager->Initialize(); - scoped_ptr<CommandBufferService> command_buffer( + std::unique_ptr<CommandBufferService> command_buffer( new CommandBufferService(transfer_buffer_manager_.get())); command_buffer->SetPutOffsetChangeCallback(base::Bind( - &InProcessCommandBuffer::PumpCommands, gpu_thread_weak_ptr_)); + &InProcessCommandBuffer::PumpCommandsOnGpuThread, gpu_thread_weak_ptr_)); command_buffer->SetParseErrorCallback(base::Bind( - &InProcessCommandBuffer::OnContextLost, gpu_thread_weak_ptr_)); - - if (!command_buffer->Initialize()) { - LOG(ERROR) << "Could not initialize command buffer."; - DestroyOnGpuThread(); - return false; - } + &InProcessCommandBuffer::OnContextLostOnGpuThread, gpu_thread_weak_ptr_)); gl_share_group_ = params.context_group ? params.context_group->gl_share_group_ : service_->share_group(); -#if defined(OS_ANDROID) - stream_texture_manager_.reset(new StreamTextureManagerInProcess); -#endif - bool bind_generates_resource = false; + scoped_refptr<gles2::FeatureInfo> feature_info = + new gles2::FeatureInfo(service_->gpu_driver_bug_workarounds()); decoder_.reset(gles2::GLES2Decoder::Create( params.context_group ? params.context_group->decoder_->GetContextGroup() - : new gles2::ContextGroup(service_->gpu_preferences(), - service_->mailbox_manager(), NULL, - service_->shader_translator_cache(), - service_->framebuffer_completeness_cache(), - NULL, service_->subscription_ref_set(), - service_->pending_valuebuffer_state(), - bind_generates_resource))); + : new gles2::ContextGroup( + service_->gpu_preferences(), service_->mailbox_manager(), NULL, + service_->shader_translator_cache(), + service_->framebuffer_completeness_cache(), feature_info, + bind_generates_resource))); executor_.reset(new CommandExecutor(command_buffer.get(), decoder_.get(), decoder_.get())); @@ -368,9 +343,9 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( if (!surface_.get()) { if (params.is_offscreen) - surface_ = gfx::GLSurface::CreateOffscreenGLSurface(params.size); + surface_ = gl::init::CreateOffscreenGLSurface(params.size); else - surface_ = gfx::GLSurface::CreateViewGLSurface(params.window); + surface_ = gl::init::CreateViewGLSurface(params.window); } if (!surface_.get()) { @@ -390,7 +365,7 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( .use_virtualized_gl_contexts) { context_ = gl_share_group_->GetSharedContext(); if (!context_.get()) { - context_ = gfx::GLContext::CreateGLContext( + context_ = gl::init::CreateGLContext( gl_share_group_.get(), surface_.get(), params.gpu_preference); gl_share_group_->SetSharedContext(context_.get()); } @@ -403,8 +378,8 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( context_ = NULL; } } else { - context_ = gfx::GLContext::CreateGLContext( - gl_share_group_.get(), surface_.get(), params.gpu_preference); + context_ = gl::init::CreateGLContext(gl_share_group_.get(), surface_.get(), + params.gpu_preference); } if (!context_.get()) { @@ -455,7 +430,8 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( void InProcessCommandBuffer::Destroy() { CheckSequencedThread(); - + client_thread_weak_ptr_factory_.InvalidateWeakPtrs(); + gpu_control_client_ = nullptr; base::WaitableEvent completion(true, false); bool result = false; base::Callback<bool(void)> destroy_task = base::Bind( @@ -475,17 +451,14 @@ bool InProcessCommandBuffer::DestroyOnGpuThread() { decoder_->Destroy(have_context); decoder_.reset(); } - context_ = NULL; - surface_ = NULL; - sync_point_client_ = NULL; + context_ = nullptr; + surface_ = nullptr; + sync_point_client_ = nullptr; if (sync_point_order_data_) { sync_point_order_data_->Destroy(); sync_point_order_data_ = nullptr; } - gl_share_group_ = NULL; -#if defined(OS_ANDROID) - stream_texture_manager_.reset(); -#endif + gl_share_group_ = nullptr; return true; } @@ -495,12 +468,25 @@ void InProcessCommandBuffer::CheckSequencedThread() { sequence_checker_->CalledOnValidSequencedThread()); } +void InProcessCommandBuffer::OnContextLostOnGpuThread() { + if (!origin_task_runner_) + return OnContextLost(); // Just kidding, we're on the client thread. + origin_task_runner_->PostTask( + FROM_HERE, base::Bind(&InProcessCommandBuffer::OnContextLost, + client_thread_weak_ptr_)); +} + void InProcessCommandBuffer::OnContextLost() { CheckSequencedThread(); - if (!context_lost_callback_.is_null()) { - context_lost_callback_.Run(); - context_lost_callback_.Reset(); - } + +#if DCHECK_IS_ON() + // This method shouldn't be called more than once. + DCHECK(!context_lost_); + context_lost_ = true; +#endif + + if (gpu_control_client_) + gpu_control_client_->OnGpuControlLostContext(); } CommandBuffer::State InProcessCommandBuffer::GetStateFast() { @@ -554,7 +540,7 @@ void InProcessCommandBuffer::FlushOnGpuThread(int32_t put_offset, } } -void InProcessCommandBuffer::PerformDelayedWork() { +void InProcessCommandBuffer::PerformDelayedWorkOnGpuThread() { CheckSequencedThread(); delayed_work_pending_ = false; base::AutoLock lock(command_buffer_lock_); @@ -572,8 +558,9 @@ void InProcessCommandBuffer::ScheduleDelayedWorkOnGpuThread() { if (delayed_work_pending_) return; delayed_work_pending_ = true; - service_->ScheduleDelayedWork(base::Bind( - &InProcessCommandBuffer::PerformDelayedWork, gpu_thread_weak_ptr_)); + service_->ScheduleDelayedWork( + base::Bind(&InProcessCommandBuffer::PerformDelayedWorkOnGpuThread, + gpu_thread_weak_ptr_)); } void InProcessCommandBuffer::Flush(int32_t put_offset) { @@ -670,6 +657,10 @@ void InProcessCommandBuffer::DestroyTransferBufferOnGpuThread(int32_t id) { command_buffer_->DestroyTransferBuffer(id); } +void InProcessCommandBuffer::SetGpuControlClient(GpuControlClient* client) { + gpu_control_client_ = client; +} + gpu::Capabilities InProcessCommandBuffer::GetCapabilities() { return capabilities_; } @@ -823,11 +814,11 @@ int32_t InProcessCommandBuffer::CreateGpuMemoryBufferImage( CheckSequencedThread(); DCHECK(gpu_memory_buffer_manager_); - scoped_ptr<gfx::GpuMemoryBuffer> buffer( + std::unique_ptr<gfx::GpuMemoryBuffer> buffer( gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( gfx::Size(width, height), gpu::DefaultBufferFormatForImageFormat(internalformat), - gfx::BufferUsage::SCANOUT, 0 /* surface_id */)); + gfx::BufferUsage::SCANOUT, gpu::kNullSurfaceHandle)); if (!buffer) return -1; @@ -922,12 +913,6 @@ void InProcessCommandBuffer::SetLock(base::Lock*) { NOTREACHED(); } -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; -} - void InProcessCommandBuffer::EnsureWorkVisible() { // This is only relevant for out-of-process command buffers. } @@ -974,26 +959,11 @@ bool InProcessCommandBuffer::CanWaitUnverifiedSyncToken( return sync_token->namespace_id() == GetNamespaceID(); } -uint32_t InProcessCommandBuffer::CreateStreamTextureOnGpuThread( - uint32_t client_texture_id) { -#if defined(OS_ANDROID) - return stream_texture_manager_->CreateStreamTexture( - client_texture_id, decoder_->GetContextGroup()->texture_manager()); -#else - return 0; -#endif -} - gpu::error::Error InProcessCommandBuffer::GetLastError() { CheckSequencedThread(); return last_state_.error; } -bool InProcessCommandBuffer::Initialize() { - NOTREACHED(); - return false; -} - namespace { void PostCallback( @@ -1008,7 +978,7 @@ void PostCallback( } } -void RunOnTargetThread(scoped_ptr<base::Closure> callback) { +void RunOnTargetThread(std::unique_ptr<base::Closure> callback) { DCHECK(callback.get()); callback->Run(); } @@ -1019,7 +989,7 @@ base::Closure InProcessCommandBuffer::WrapCallback( const base::Closure& callback) { // Make sure the callback gets deleted on the target thread by passing // ownership. - scoped_ptr<base::Closure> scoped_callback(new base::Closure(callback)); + std::unique_ptr<base::Closure> scoped_callback(new base::Closure(callback)); base::Closure callback_on_client_thread = base::Bind(&RunOnTargetThread, base::Passed(&scoped_callback)); base::Closure wrapped_callback = @@ -1030,26 +1000,6 @@ base::Closure InProcessCommandBuffer::WrapCallback( return wrapped_callback; } -#if defined(OS_ANDROID) -scoped_refptr<gfx::SurfaceTexture> InProcessCommandBuffer::GetSurfaceTexture( - uint32_t stream_id) { - DCHECK(stream_texture_manager_); - return stream_texture_manager_->GetSurfaceTexture(stream_id); -} - -uint32_t InProcessCommandBuffer::CreateStreamTexture(uint32_t texture_id) { - base::WaitableEvent completion(true, false); - uint32_t stream_id = 0; - base::Callback<uint32_t(void)> task = - base::Bind(&InProcessCommandBuffer::CreateStreamTextureOnGpuThread, - base::Unretained(this), texture_id); - QueueTask( - base::Bind(&RunTaskWithResult<uint32_t>, task, &stream_id, &completion)); - completion.Wait(); - return stream_id; -} -#endif - GpuInProcessThread::GpuInProcessThread(SyncPointManager* sync_point_manager) : base::Thread("GpuThread"), sync_point_manager_(sync_point_manager) { Start(); 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 731c4868f54..f7c6da00388 100644 --- a/chromium/gpu/command_buffer/service/in_process_command_buffer.h +++ b/chromium/gpu/command_buffer/service/in_process_command_buffer.h @@ -9,6 +9,7 @@ #include <stdint.h> #include <map> +#include <memory> #include <vector> #include "base/atomic_sequence_num.h" @@ -17,14 +18,15 @@ #include "base/containers/scoped_ptr_hash_map.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" #include "gpu/command_buffer/client/gpu_control.h" #include "gpu/command_buffer/common/command_buffer.h" #include "gpu/command_buffer/service/gpu_preferences.h" +#include "gpu/config/gpu_driver_bug_workarounds.h" #include "gpu/gpu_export.h" #include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/native_widget_types.h" @@ -42,28 +44,18 @@ class GLSurface; class Size; } -#if defined(OS_ANDROID) -namespace gfx { -class SurfaceTexture; -} -namespace gpu { -class StreamTextureManagerInProcess; -} -#endif - namespace gpu { class SyncPointClient; class SyncPointOrderData; class SyncPointManager; -class ValueStateMap; namespace gles2 { +struct ContextCreationAttribHelper; class FramebufferCompletenessCache; class GLES2Decoder; class MailboxManager; class ProgramCache; class ShaderTranslatorCache; -class SubscriptionRefSet; } class CommandBufferServiceBase; @@ -90,16 +82,13 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, bool is_offscreen, gfx::AcceleratedWidget window, const gfx::Size& size, - const std::vector<int32_t>& attribs, + const gles2::ContextCreationAttribHelper& attribs, gfx::GpuPreference gpu_preference, - const base::Closure& context_lost_callback, InProcessCommandBuffer* share_group, GpuMemoryBufferManager* gpu_memory_buffer_manager, ImageFactory* image_factory); - void Destroy(); // CommandBuffer implementation: - bool Initialize() override; State GetLastState() override; int32_t GetLastToken() override; void Flush(int32_t put_offset) override; @@ -113,6 +102,8 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, gpu::error::Error GetLastError() override; // GpuControl implementation: + // NOTE: The GpuControlClient will be called on the client thread. + void SetGpuControlClient(GpuControlClient*) override; gpu::Capabilities GetCapabilities() override; int32_t CreateImage(ClientBuffer buffer, size_t width, @@ -125,7 +116,6 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, unsigned usage) override; void SignalQuery(uint32_t query_id, const base::Closure& callback) override; void SetLock(base::Lock*) override; - bool IsGpuChannelLost() override; void EnsureWorkVisible() override; CommandBufferNamespace GetNamespaceID() const override; CommandBufferId GetCommandBufferID() const override; @@ -142,7 +132,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, class Service { public: Service(); - explicit Service(const gpu::GpuPreferences& gpu_preferences); + Service(const gpu::GpuPreferences& gpu_preferences); virtual ~Service(); virtual void AddRef() const = 0; @@ -162,45 +152,39 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, framebuffer_completeness_cache() = 0; virtual SyncPointManager* sync_point_manager() = 0; const GpuPreferences& gpu_preferences(); + const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds(); scoped_refptr<gfx::GLShareGroup> share_group(); scoped_refptr<gles2::MailboxManager> mailbox_manager(); - scoped_refptr<gles2::SubscriptionRefSet> subscription_ref_set(); - scoped_refptr<gpu::ValueStateMap> pending_valuebuffer_state(); gpu::gles2::ProgramCache* program_cache(); private: const GpuPreferences gpu_preferences_; + const GpuDriverBugWorkarounds gpu_driver_bug_workarounds_; scoped_refptr<gfx::GLShareGroup> share_group_; scoped_refptr<gles2::MailboxManager> mailbox_manager_; - scoped_refptr<gles2::SubscriptionRefSet> subscription_ref_set_; - scoped_refptr<gpu::ValueStateMap> pending_valuebuffer_state_; - scoped_ptr<gpu::gles2::ProgramCache> program_cache_; + std::unique_ptr<gpu::gles2::ProgramCache> program_cache_; }; -#if defined(OS_ANDROID) - scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(uint32_t stream_id); - uint32_t CreateStreamTexture(uint32_t texture_id); -#endif - private: struct InitializeOnGpuThreadParams { bool is_offscreen; gfx::AcceleratedWidget window; const gfx::Size& size; - const std::vector<int32_t>& attribs; + const gles2::ContextCreationAttribHelper& attribs; gfx::GpuPreference gpu_preference; gpu::Capabilities* capabilities; // Ouptut. InProcessCommandBuffer* context_group; ImageFactory* image_factory; - InitializeOnGpuThreadParams(bool is_offscreen, - gfx::AcceleratedWidget window, - const gfx::Size& size, - const std::vector<int32_t>& attribs, - gfx::GpuPreference gpu_preference, - gpu::Capabilities* capabilities, - InProcessCommandBuffer* share_group, - ImageFactory* image_factory) + InitializeOnGpuThreadParams( + bool is_offscreen, + gfx::AcceleratedWidget window, + const gfx::Size& size, + const gles2::ContextCreationAttribHelper& attribs, + gfx::GpuPreference gpu_preference, + gpu::Capabilities* capabilities, + InProcessCommandBuffer* share_group, + ImageFactory* image_factory) : is_offscreen(is_offscreen), window(window), size(size), @@ -212,10 +196,10 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, }; bool InitializeOnGpuThread(const InitializeOnGpuThreadParams& params); + void Destroy(); bool DestroyOnGpuThread(); void FlushOnGpuThread(int32_t put_offset, uint32_t order_num); void ScheduleDelayedWorkOnGpuThread(); - uint32_t CreateStreamTextureOnGpuThread(uint32_t client_texture_id); bool MakeCurrent(); base::Closure WrapCallback(const base::Closure& callback); State GetStateFast(); @@ -239,29 +223,35 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, void DestroyImageOnGpuThread(int32_t id); void SetGetBufferOnGpuThread(int32_t shm_id, base::WaitableEvent* completion); - // Callbacks: + // Callbacks on the gpu thread. + void OnContextLostOnGpuThread(); + void PumpCommandsOnGpuThread(); + void PerformDelayedWorkOnGpuThread(); + // Callback implementations on the client thread. void OnContextLost(); - bool GetBufferChanged(int32_t transfer_buffer_id); - void PumpCommands(); - void PerformDelayedWork(); const CommandBufferId command_buffer_id_; // Members accessed on the gpu thread (possibly with the exception of // creation): - bool context_lost_; + scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_; - scoped_ptr<CommandExecutor> executor_; - scoped_ptr<gles2::GLES2Decoder> decoder_; + std::unique_ptr<CommandExecutor> executor_; + std::unique_ptr<gles2::GLES2Decoder> decoder_; scoped_refptr<gfx::GLContext> context_; scoped_refptr<gfx::GLSurface> surface_; scoped_refptr<SyncPointOrderData> sync_point_order_data_; - scoped_ptr<SyncPointClient> sync_point_client_; + std::unique_ptr<SyncPointClient> sync_point_client_; base::Closure context_lost_callback_; - bool delayed_work_pending_; // Used to throttle PerformDelayedWork. + // Used to throttle PerformDelayedWorkOnGpuThread. + bool delayed_work_pending_; ImageFactory* image_factory_; // Members accessed on the client thread: + GpuControlClient* gpu_control_client_; +#if DCHECK_IS_ON() + bool context_lost_; +#endif State last_state_; int32_t last_put_offset_; gpu::Capabilities capabilities_; @@ -271,7 +261,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, uint64_t flushed_fence_sync_release_; // Accessed on both threads: - scoped_ptr<CommandBufferServiceBase> command_buffer_; + std::unique_ptr<CommandBufferServiceBase> command_buffer_; base::Lock command_buffer_lock_; base::WaitableEvent flush_event_; scoped_refptr<Service> service_; @@ -280,15 +270,13 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, scoped_refptr<gfx::GLShareGroup> gl_share_group_; base::WaitableEvent fence_sync_wait_event_; -#if defined(OS_ANDROID) - scoped_ptr<StreamTextureManagerInProcess> stream_texture_manager_; -#endif - // Only used with explicit scheduling and the gpu thread is the same as // the client thread. - scoped_ptr<base::SequenceChecker> sequence_checker_; + std::unique_ptr<base::SequenceChecker> sequence_checker_; + base::WeakPtr<InProcessCommandBuffer> client_thread_weak_ptr_; base::WeakPtr<InProcessCommandBuffer> gpu_thread_weak_ptr_; + base::WeakPtrFactory<InProcessCommandBuffer> client_thread_weak_ptr_factory_; base::WeakPtrFactory<InProcessCommandBuffer> gpu_thread_weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(InProcessCommandBuffer); diff --git a/chromium/gpu/command_buffer/service/indexed_buffer_binding_host.cc b/chromium/gpu/command_buffer/service/indexed_buffer_binding_host.cc new file mode 100644 index 00000000000..fb5c11ba94c --- /dev/null +++ b/chromium/gpu/command_buffer/service/indexed_buffer_binding_host.cc @@ -0,0 +1,248 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/indexed_buffer_binding_host.h" + +#include "gpu/command_buffer/service/buffer_manager.h" + +namespace gpu { +namespace gles2 { + +IndexedBufferBindingHost::IndexedBufferBinding::IndexedBufferBinding() + : type(kBindBufferNone), + offset(0), + size(0), + effective_full_buffer_size(0) { +} + +IndexedBufferBindingHost::IndexedBufferBinding::IndexedBufferBinding( + const IndexedBufferBindingHost::IndexedBufferBinding& other) + : type(other.type), + buffer(other.buffer.get()), + offset(other.offset), + size(other.size), + effective_full_buffer_size(other.effective_full_buffer_size) { +} + +IndexedBufferBindingHost::IndexedBufferBinding::~IndexedBufferBinding() { +} + +bool IndexedBufferBindingHost::IndexedBufferBinding::operator==( + const IndexedBufferBindingHost::IndexedBufferBinding& other) const { + if (type == kBindBufferNone && other.type == kBindBufferNone) { + // This should be the most common case so an early out. + return true; + } + return (type == other.type && + buffer.get() == other.buffer.get() && + offset == other.offset && + size == other.size && + effective_full_buffer_size == other.effective_full_buffer_size); +} + +void IndexedBufferBindingHost::IndexedBufferBinding::SetBindBufferBase( + Buffer* _buffer) { + if (!_buffer) { + Reset(); + return; + } + type = kBindBufferBase; + buffer = _buffer; + offset = 0; + size = 0; + effective_full_buffer_size = 0; +} + +void IndexedBufferBindingHost::IndexedBufferBinding::SetBindBufferRange( + Buffer* _buffer, GLintptr _offset, GLsizeiptr _size) { + if (!_buffer) { + Reset(); + return; + } + type = kBindBufferRange; + buffer = _buffer; + offset = _offset; + size = _size; + effective_full_buffer_size = _buffer ? _buffer->size() : 0; +} + +void IndexedBufferBindingHost::IndexedBufferBinding::Reset() { + type = kBindBufferNone; + buffer = nullptr; + offset = 0; + size = 0; + effective_full_buffer_size = 0; +} + + +IndexedBufferBindingHost::IndexedBufferBindingHost( + uint32_t max_bindings, bool needs_emulation) + : needs_emulation_(needs_emulation), + max_non_null_binding_index_plus_one_(0u) { + buffer_bindings_.resize(max_bindings); +} + +IndexedBufferBindingHost::~IndexedBufferBindingHost() { +} + +void IndexedBufferBindingHost::DoBindBufferBase( + GLenum target, GLuint index, Buffer* buffer) { + DCHECK_LT(index, buffer_bindings_.size()); + GLuint service_id = buffer ? buffer->service_id() : 0; + glBindBufferBase(target, index, service_id); + + buffer_bindings_[index].SetBindBufferBase(buffer); + UpdateMaxNonNullBindingIndex(index); +} + +void IndexedBufferBindingHost::DoBindBufferRange( + GLenum target, GLuint index, Buffer* buffer, GLintptr offset, + GLsizeiptr size) { + DCHECK_LT(index, buffer_bindings_.size()); + GLuint service_id = buffer ? buffer->service_id() : 0; + if (buffer && needs_emulation_) { + DoAdjustedBindBufferRange( + target, index, service_id, offset, size, buffer->size()); + } else { + glBindBufferRange(target, index, service_id, offset, size); + } + + buffer_bindings_[index].SetBindBufferRange(buffer, offset, size); + UpdateMaxNonNullBindingIndex(index); +} + +// static +void IndexedBufferBindingHost::DoAdjustedBindBufferRange( + GLenum target, GLuint index, GLuint service_id, GLintptr offset, + GLsizeiptr size, GLsizeiptr full_buffer_size) { + GLsizeiptr adjusted_size = size; + if (offset >= full_buffer_size) { + // Situation 1: We can't really call glBindBufferRange with reasonable + // offset/size without triggering a GL error because size == 0 isn't + // valid. + // TODO(zmo): it's ambiguous in the GL 4.1 spec whether BindBufferBase + // generates a GL error in such case. In reality, no error is generated on + // MacOSX with AMD/4.1. + glBindBufferBase(target, index, service_id); + return; + } else if (offset + size > full_buffer_size) { + adjusted_size = full_buffer_size - offset; + // size needs to be a multiple of 4. + adjusted_size = adjusted_size & ~3; + if (adjusted_size == 0) { + // Situation 2: The original size is valid, but the adjusted size + // is 0 and isn't valid. Handle it the same way as situation 1. + glBindBufferBase(target, index, service_id); + return; + } + } + glBindBufferRange(target, index, service_id, offset, adjusted_size); +} + +void IndexedBufferBindingHost::OnBindHost(GLenum target) { + if (needs_emulation_) { + // If some bound buffers change size since last time the transformfeedback + // is bound, we might need to reset the ranges. + for (size_t ii = 0; ii < buffer_bindings_.size(); ++ii) { + Buffer* buffer = buffer_bindings_[ii].buffer.get(); + if (buffer && buffer_bindings_[ii].type == kBindBufferRange && + buffer_bindings_[ii].effective_full_buffer_size != buffer->size()) { + DoAdjustedBindBufferRange( + target, ii, buffer->service_id(), buffer_bindings_[ii].offset, + buffer_bindings_[ii].size, buffer->size()); + buffer_bindings_[ii].effective_full_buffer_size = buffer->size(); + } + } + } +} + +void IndexedBufferBindingHost::OnBufferData(GLenum target, Buffer* buffer) { + DCHECK(buffer); + if (needs_emulation_) { + // If some bound buffers change size since last time the transformfeedback + // is bound, we might need to reset the ranges. + for (size_t ii = 0; ii < buffer_bindings_.size(); ++ii) { + if (buffer_bindings_[ii].buffer.get() != buffer) + continue; + if (buffer_bindings_[ii].type == kBindBufferRange && + buffer_bindings_[ii].effective_full_buffer_size != buffer->size()) { + DoAdjustedBindBufferRange( + target, ii, buffer->service_id(), buffer_bindings_[ii].offset, + buffer_bindings_[ii].size, buffer->size()); + buffer_bindings_[ii].effective_full_buffer_size = buffer->size(); + } + } + } +} + +void IndexedBufferBindingHost::RemoveBoundBuffer(Buffer* buffer) { + for (size_t ii = 0; ii < buffer_bindings_.size(); ++ii) { + if (buffer_bindings_[ii].buffer.get() == buffer) { + buffer_bindings_[ii].Reset(); + UpdateMaxNonNullBindingIndex(ii); + } + } +} + +Buffer* IndexedBufferBindingHost::GetBufferBinding(GLuint index) const { + DCHECK_LT(index, buffer_bindings_.size()); + return buffer_bindings_[index].buffer.get(); +} + +GLsizeiptr IndexedBufferBindingHost::GetBufferSize(GLuint index) const { + DCHECK_LT(index, buffer_bindings_.size()); + return buffer_bindings_[index].size; +} + +GLintptr IndexedBufferBindingHost::GetBufferStart(GLuint index) const { + DCHECK_LT(index, buffer_bindings_.size()); + return buffer_bindings_[index].offset; +} + +void IndexedBufferBindingHost::RestoreBindings( + IndexedBufferBindingHost* prev) { + size_t limit = max_non_null_binding_index_plus_one_; + if (prev && prev->max_non_null_binding_index_plus_one_ > limit) { + limit = prev->max_non_null_binding_index_plus_one_; + } + for (size_t ii = 0; ii < limit; ++ii) { + if (prev && buffer_bindings_[ii] == prev->buffer_bindings_[ii]) { + continue; + } + switch (buffer_bindings_[ii].type) { + case kBindBufferBase: + case kBindBufferNone: + DoBindBufferBase( + GL_UNIFORM_BUFFER, ii, buffer_bindings_[ii].buffer.get()); + break; + case kBindBufferRange: + DoBindBufferRange( + GL_UNIFORM_BUFFER, ii, buffer_bindings_[ii].buffer.get(), + buffer_bindings_[ii].offset, buffer_bindings_[ii].size); + break; + } + } +} + +void IndexedBufferBindingHost::UpdateMaxNonNullBindingIndex( + size_t changed_index) { + size_t plus_one = changed_index + 1; + DCHECK_LT(changed_index, buffer_bindings_.size()); + if (buffer_bindings_[changed_index].buffer.get()) { + max_non_null_binding_index_plus_one_ = + std::max(max_non_null_binding_index_plus_one_, plus_one); + } else { + if (plus_one == max_non_null_binding_index_plus_one_) { + for (size_t ii = changed_index; ii > 0; --ii) { + if (buffer_bindings_[ii - 1].buffer.get()) { + max_non_null_binding_index_plus_one_ = ii; + break; + } + } + } + } +} + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/indexed_buffer_binding_host.h b/chromium/gpu/command_buffer/service/indexed_buffer_binding_host.h new file mode 100644 index 00000000000..54e88569e1b --- /dev/null +++ b/chromium/gpu/command_buffer/service/indexed_buffer_binding_host.h @@ -0,0 +1,105 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_INDEXED_BUFFER_BINDING_HOST_H_ +#define GPU_COMMAND_BUFFER_SERVICE_INDEXED_BUFFER_BINDING_HOST_H_ + +#include <vector> + +#include "base/memory/ref_counted.h" +#include "gpu/command_buffer/service/gl_utils.h" +#include "gpu/gpu_export.h" + +namespace gpu { +namespace gles2 { + +class Buffer; + +// This is a base class for indexed buffer bindings tracking. +// TransformFeedback and Program should inherit from this base class, +// for tracking indexed TRANSFORM_FEEDBACK_BUFFER / UNIFORM_BUFFER bindings. +class GPU_EXPORT IndexedBufferBindingHost : + public base::RefCounted<IndexedBufferBindingHost> { + public: + // |needs_emulation| is set to true on Desktop GL 4.1 or lower. + IndexedBufferBindingHost(uint32_t max_bindings, bool needs_emulation); + + // The following two functions do state update and call the underlying GL + // function. All validations have been done already and the GL function is + // guaranteed to succeed. + void DoBindBufferBase(GLenum target, GLuint index, Buffer* buffer); + void DoBindBufferRange( + GLenum target, GLuint index, Buffer* buffer, GLintptr offset, + GLsizeiptr size); + + // This is called on the active host when glBufferData is called and buffer + // size might change. + void OnBufferData(GLenum target, Buffer* buffer); + + // This is called when the host become active. + void OnBindHost(GLenum target); + + void RemoveBoundBuffer(Buffer* buffer); + + Buffer* GetBufferBinding(GLuint index) const; + GLsizeiptr GetBufferSize(GLuint index) const; + GLintptr GetBufferStart(GLuint index) const; + + // This is used only for UNIFORM_BUFFER bindings in context switching. + void RestoreBindings(IndexedBufferBindingHost* prev); + + protected: + friend class base::RefCounted<IndexedBufferBindingHost>; + + virtual ~IndexedBufferBindingHost(); + + private: + enum IndexedBufferBindingType { + kBindBufferBase, + kBindBufferRange, + kBindBufferNone + }; + + struct IndexedBufferBinding { + IndexedBufferBindingType type; + scoped_refptr<Buffer> buffer; + + // The following fields are only used if |type| is kBindBufferRange. + GLintptr offset; + GLsizeiptr size; + // The full buffer size at the last successful glBindBufferRange call. + GLsizeiptr effective_full_buffer_size; + + IndexedBufferBinding(); + IndexedBufferBinding(const IndexedBufferBinding& other); + ~IndexedBufferBinding(); + + bool operator==(const IndexedBufferBinding& other) const; + + void SetBindBufferBase(Buffer* _buffer); + void SetBindBufferRange( + Buffer* _buffer, GLintptr _offset, GLsizeiptr _size); + void Reset(); + }; + + // This is called on Desktop GL lower than 4.2, where the range + // (offset + size) can't go beyond the buffer's size. + static void DoAdjustedBindBufferRange( + GLenum target, GLuint index, GLuint service_id, GLintptr offset, + GLsizeiptr size, GLsizeiptr full_buffer_size); + + void UpdateMaxNonNullBindingIndex(size_t changed_index); + + std::vector<IndexedBufferBinding> buffer_bindings_; + + bool needs_emulation_; + + // This is used for optimization purpose in context switching. + size_t max_non_null_binding_index_plus_one_; +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_INDEXED_BUFFER_BINDING_HOST_H_ diff --git a/chromium/gpu/command_buffer/service/indexed_buffer_binding_host_unittest.cc b/chromium/gpu/command_buffer/service/indexed_buffer_binding_host_unittest.cc new file mode 100644 index 00000000000..bab99180a55 --- /dev/null +++ b/chromium/gpu/command_buffer/service/indexed_buffer_binding_host_unittest.cc @@ -0,0 +1,168 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/buffer_manager.h" +#include "gpu/command_buffer/service/gpu_service_test.h" +#include "gpu/command_buffer/service/indexed_buffer_binding_host.h" +#include "ui/gl/gl_mock.h" + +namespace gpu { +namespace gles2 { + +namespace { +const uint32_t kMaxBindings = 16; +const GLuint kBufferClientId = 87; +const GLuint kBufferServiceId = 987; +} // namespace anonymous + +class IndexedBufferBindingHostTest : public GpuServiceTest { + public: + IndexedBufferBindingHostTest() + : host_(new IndexedBufferBindingHost(kMaxBindings, true)), + buffer_manager_(new BufferManager(nullptr, nullptr)) { + buffer_manager_->CreateBuffer(kBufferClientId, kBufferServiceId); + buffer_ = buffer_manager_->GetBuffer(kBufferClientId); + DCHECK(buffer_.get()); + } + + ~IndexedBufferBindingHostTest() override {} + + protected: + void SetUp() override { + GpuServiceTest::SetUpWithGLVersion("4.1", ""); + } + + void TearDown() override { + host_->RemoveBoundBuffer(buffer_.get()); + buffer_ = nullptr; + buffer_manager_->MarkContextLost(); + buffer_manager_->Destroy(); + buffer_manager_.reset(); + GpuServiceTest::TearDown(); + } + + void SetBufferSize(GLenum target, GLsizeiptr size) { + buffer_manager_->SetInfo( + buffer_.get(), target, size, GL_STATIC_DRAW, false); + } + + scoped_refptr<IndexedBufferBindingHost> host_; + std::unique_ptr<BufferManager> buffer_manager_; + scoped_refptr<Buffer> buffer_; +}; + +TEST_F(IndexedBufferBindingHostTest, DoBindBufferRangeUninitializedBuffer) { + const GLenum kTarget = GL_TRANSFORM_FEEDBACK_BUFFER; + const GLuint kIndex = 2; + const GLintptr kOffset = 4; + const GLsizeiptr kSize = 8; + + EXPECT_CALL(*gl_, BindBufferBase(kTarget, kIndex, kBufferServiceId)) + .Times(1) + .RetiresOnSaturation(); + + host_->DoBindBufferRange(kTarget, kIndex, buffer_.get(), kOffset, kSize); + + for (uint32_t index = 0; index < kMaxBindings; ++index) { + if (index != kIndex) { + EXPECT_EQ(nullptr, host_->GetBufferBinding(index)); + } else { + EXPECT_EQ(buffer_.get(), host_->GetBufferBinding(index)); + EXPECT_EQ(kSize, host_->GetBufferSize(index)); + EXPECT_EQ(kOffset, host_->GetBufferStart(index)); + } + } +} + +TEST_F(IndexedBufferBindingHostTest, DoBindBufferRangeBufferWithoutEnoughSize) { + const GLenum kTarget = GL_TRANSFORM_FEEDBACK_BUFFER; + const GLuint kIndex = 2; + const GLintptr kOffset = 4; + const GLsizeiptr kSize = 8; + const GLsizeiptr kBufferSize = kOffset + kSize - 2; + + SetBufferSize(kTarget, kBufferSize); + + GLsizeiptr clamped_size = ((kBufferSize - kOffset) >> 2) << 2; + + EXPECT_CALL(*gl_, BindBufferRange(kTarget, kIndex, kBufferServiceId, kOffset, + clamped_size)) + .Times(1) + .RetiresOnSaturation(); + + host_->DoBindBufferRange(kTarget, kIndex, buffer_.get(), kOffset, kSize); + + for (uint32_t index = 0; index < kMaxBindings; ++index) { + if (index != kIndex) { + EXPECT_EQ(nullptr, host_->GetBufferBinding(index)); + } else { + EXPECT_EQ(buffer_.get(), host_->GetBufferBinding(index)); + EXPECT_EQ(kSize, host_->GetBufferSize(index)); + EXPECT_EQ(kOffset, host_->GetBufferStart(index)); + } + } + + // Now adjust buffer size to be big enough. + EXPECT_CALL(*gl_, BindBufferRange(kTarget, kIndex, kBufferServiceId, kOffset, + kSize)) + .Times(1) + .RetiresOnSaturation(); + + SetBufferSize(kTarget, kOffset + kSize); + host_->OnBufferData(kTarget, buffer_.get()); +} + +TEST_F(IndexedBufferBindingHostTest, RestoreBindings) { + const GLenum kTarget = GL_UNIFORM_BUFFER; + const GLuint kIndex = 2; + const GLuint kOtherIndex = 10; + const GLintptr kOffset = 4; + const GLsizeiptr kSize = 8; + const GLsizeiptr kBufferSize = kOffset + kSize - 2; + + GLsizeiptr clamped_size = ((kBufferSize - kOffset) >> 2) << 2; + + SetBufferSize(kTarget, kBufferSize); + // Set up host + EXPECT_CALL(*gl_, BindBufferBase(kTarget, kIndex, kBufferServiceId)) + .Times(1) + .RetiresOnSaturation(); + host_->DoBindBufferBase(kTarget, kIndex, buffer_.get()); + // Set up the second host + scoped_refptr<IndexedBufferBindingHost> other = + new IndexedBufferBindingHost(kMaxBindings, true); + EXPECT_CALL(*gl_, BindBufferRange(kTarget, kOtherIndex, kBufferServiceId, + kOffset, clamped_size)) + .Times(1) + .RetiresOnSaturation(); + other->DoBindBufferRange(kTarget, kOtherIndex, buffer_.get(), kOffset, kSize); + + { + // Switching from |other| to |host_|. + EXPECT_CALL(*gl_, BindBufferBase(kTarget, kIndex, kBufferServiceId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindBufferBase(kTarget, kOtherIndex, 0)) + .Times(1) + .RetiresOnSaturation(); + host_->RestoreBindings(other.get()); + } + + { + // Switching from |host_| to |other|. + EXPECT_CALL(*gl_, BindBufferBase(kTarget, kIndex, 0)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindBufferRange(kTarget, kOtherIndex, kBufferServiceId, + kOffset, clamped_size)) + .Times(1) + .RetiresOnSaturation(); + other->RestoreBindings(host_.get()); + } +} + +} // namespace gles2 +} // namespace gpu + + diff --git a/chromium/gpu/command_buffer/service/mailbox_manager_sync.cc b/chromium/gpu/command_buffer/service/mailbox_manager_sync.cc index 8cf799232fa..72c033823c0 100644 --- a/chromium/gpu/command_buffer/service/mailbox_manager_sync.cc +++ b/chromium/gpu/command_buffer/service/mailbox_manager_sync.cc @@ -292,8 +292,7 @@ void MailboxManagerSync::UpdateDefinitionLocked( if (definition.Matches(texture)) return; - DCHECK(!image || image_buffer.get()); - if (image && !image_buffer->IsClient(image)) { + if (image && (!image_buffer || !image_buffer->IsClient(image))) { LOG(ERROR) << "MailboxSync: Incompatible attachment"; return; } diff --git a/chromium/gpu/command_buffer/service/memory_program_cache.cc b/chromium/gpu/command_buffer/service/memory_program_cache.cc index ced200d57e0..4cd3fd2edc0 100644 --- a/chromium/gpu/command_buffer/service/memory_program_cache.cc +++ b/chromium/gpu/command_buffer/service/memory_program_cache.cc @@ -214,7 +214,7 @@ ProgramCache::ProgramLoadResult MemoryProgramCache::LoadLinkedProgram( shader_b->set_output_variable_list(value->output_variable_list_1()); if (!shader_callback.is_null() && !disable_gpu_shader_disk_cache_) { - scoped_ptr<GpuProgramProto> proto( + std::unique_ptr<GpuProgramProto> proto( GpuProgramProto::default_instance().New()); proto->set_sha(sha, kHashLength); proto->set_format(value->format()); @@ -242,7 +242,7 @@ void MemoryProgramCache::SaveLinkedProgram( if (length == 0 || static_cast<unsigned int>(length) > max_size_bytes_) { return; } - scoped_ptr<char[]> binary(new char[length]); + std::unique_ptr<char[]> binary(new char[length]); glGetProgramBinary(program, length, NULL, @@ -283,7 +283,7 @@ void MemoryProgramCache::SaveLinkedProgram( } if (!shader_callback.is_null() && !disable_gpu_shader_disk_cache_) { - scoped_ptr<GpuProgramProto> proto( + std::unique_ptr<GpuProgramProto> proto( GpuProgramProto::default_instance().New()); proto->set_sha(sha, kHashLength); proto->set_format(format); @@ -308,7 +308,8 @@ void MemoryProgramCache::SaveLinkedProgram( } void MemoryProgramCache::LoadProgram(const std::string& program) { - scoped_ptr<GpuProgramProto> proto(GpuProgramProto::default_instance().New()); + std::unique_ptr<GpuProgramProto> proto( + GpuProgramProto::default_instance().New()); if (proto->ParseFromString(program)) { AttributeMap vertex_attribs; UniformMap vertex_uniforms; @@ -353,7 +354,7 @@ void MemoryProgramCache::LoadProgram(const std::string& program) { &fragment_output_variables); } - scoped_ptr<char[]> binary(new char[proto->program().length()]); + std::unique_ptr<char[]> binary(new char[proto->program().length()]); memcpy(binary.get(), proto->program().c_str(), proto->program().length()); store_.Put( diff --git a/chromium/gpu/command_buffer/service/memory_program_cache.h b/chromium/gpu/command_buffer/service/memory_program_cache.h index 14d3ac06fd3..6710c1c5766 100644 --- a/chromium/gpu/command_buffer/service/memory_program_cache.h +++ b/chromium/gpu/command_buffer/service/memory_program_cache.h @@ -8,13 +8,13 @@ #include <stddef.h> #include <map> +#include <memory> #include <string> #include "base/containers/hash_tables.h" #include "base/containers/mru_cache.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/program_cache.h" @@ -130,7 +130,7 @@ class GPU_EXPORT MemoryProgramCache : public ProgramCache { const GLsizei length_; const GLenum format_; - const scoped_ptr<const char[]> data_; + const std::unique_ptr<const char[]> data_; const std::string program_hash_; const std::string shader_0_hash_; const AttributeMap attrib_map_0_; diff --git a/chromium/gpu/command_buffer/service/memory_program_cache_unittest.cc b/chromium/gpu/command_buffer/service/memory_program_cache_unittest.cc index 7662942724c..a4a78c62990 100644 --- a/chromium/gpu/command_buffer/service/memory_program_cache_unittest.cc +++ b/chromium/gpu/command_buffer/service/memory_program_cache_unittest.cc @@ -7,6 +7,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/bind.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/service/gl_utils.h" @@ -182,7 +184,7 @@ class MemoryProgramCacheTest : public GpuServiceTest { .WillOnce(SetArgPointee<2>(GL_FALSE)); } - scoped_ptr<MemoryProgramCache> cache_; + std::unique_ptr<MemoryProgramCache> cache_; ShaderManager shader_manager_; Shader* vertex_shader_; Shader* fragment_shader_; @@ -560,8 +562,8 @@ TEST_F(MemoryProgramCacheTest, MemoryProgramCacheEviction) { fragment_shader_->set_source("al sdfkjdk"); TestHelper::SetShaderStates(gl_.get(), fragment_shader_, true); - scoped_ptr<char[]> bigTestBinary = - scoped_ptr<char[]>(new char[kEvictingBinaryLength]); + std::unique_ptr<char[]> bigTestBinary = + std::unique_ptr<char[]>(new char[kEvictingBinaryLength]); for (size_t i = 0; i < kEvictingBinaryLength; ++i) { bigTestBinary[i] = i % 250; } diff --git a/chromium/gpu/command_buffer/service/path_manager_unittest.cc b/chromium/gpu/command_buffer/service/path_manager_unittest.cc index 8a20db5b856..236a74d7b8a 100644 --- a/chromium/gpu/command_buffer/service/path_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/path_manager_unittest.cc @@ -4,7 +4,8 @@ #include "gpu/command_buffer/service/path_manager.h" -#include "base/memory/scoped_ptr.h" +#include <memory> + #include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/mocks.h" #include "testing/gtest/include/gtest/gtest.h" @@ -29,7 +30,7 @@ class PathManagerTest : public GpuServiceTest { GpuServiceTest::TearDown(); } - scoped_ptr<PathManager> manager_; + std::unique_ptr<PathManager> manager_; }; TEST_F(PathManagerTest, Basic) { diff --git a/chromium/gpu/command_buffer/service/program_cache.cc b/chromium/gpu/command_buffer/service/program_cache.cc index 56c84b86a91..b542f18e183 100644 --- a/chromium/gpu/command_buffer/service/program_cache.cc +++ b/chromium/gpu/command_buffer/service/program_cache.cc @@ -6,8 +6,9 @@ #include <stddef.h> +#include <memory> #include <string> -#include "base/memory/scoped_ptr.h" + #include "gpu/command_buffer/service/shader_manager.h" #include "third_party/angle/src/common/version.h" @@ -123,7 +124,7 @@ void ProgramCache::ComputeProgramHash( const size_t total_size = shader0_size + shader1_size + angle_commit_size + map_size + var_size + sizeof(transform_feedback_buffer_mode); - scoped_ptr<unsigned char[]> buffer(new unsigned char[total_size]); + std::unique_ptr<unsigned char[]> buffer(new unsigned char[total_size]); memcpy(buffer.get(), hashed_shader_0, shader0_size); memcpy(&buffer[shader0_size], hashed_shader_1, shader1_size); size_t current_pos = shader0_size + shader1_size; diff --git a/chromium/gpu/command_buffer/service/program_cache_unittest.cc b/chromium/gpu/command_buffer/service/program_cache_unittest.cc index f4949ce28b8..6cb32bc9c2a 100644 --- a/chromium/gpu/command_buffer/service/program_cache_unittest.cc +++ b/chromium/gpu/command_buffer/service/program_cache_unittest.cc @@ -4,7 +4,8 @@ #include "gpu/command_buffer/service/program_cache.h" -#include "base/memory/scoped_ptr.h" +#include <memory> + #include "gpu/command_buffer/service/mocks.h" #include "testing/gtest/include/gtest/gtest.h" @@ -91,7 +92,7 @@ class ProgramCacheTest : public testing::Test { cache_(new NoBackendProgramCache()) { } protected: - scoped_ptr<NoBackendProgramCache> cache_; + std::unique_ptr<NoBackendProgramCache> cache_; std::vector<std::string> varyings_; }; diff --git a/chromium/gpu/command_buffer/service/program_manager.cc b/chromium/gpu/command_buffer/service/program_manager.cc index 91d49918edc..397529441f0 100644 --- a/chromium/gpu/command_buffer/service/program_manager.cc +++ b/chromium/gpu/command_buffer/service/program_manager.cc @@ -8,6 +8,7 @@ #include <stdint.h> #include <algorithm> +#include <memory> #include <set> #include <utility> #include <vector> @@ -15,7 +16,6 @@ #include "base/command_line.h" #include "base/containers/hash_tables.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" #include "base/numerics/safe_math.h" #include "base/strings/string_number_conversions.h" @@ -320,7 +320,7 @@ void Program::UpdateLogInfo() { set_log_info(NULL); return; } - scoped_ptr<char[]> temp(new char[max_len]); + std::unique_ptr<char[]> temp(new char[max_len]); GLint len = 0; glGetProgramInfoLog(service_id_, max_len, &len, temp.get()); DCHECK(max_len == 0 || len < max_len); @@ -464,7 +464,7 @@ void Program::Update() { glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs); glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len); // TODO(gman): Should we check for error? - scoped_ptr<char[]> name_buffer(new char[max_len]); + std::unique_ptr<char[]> name_buffer(new char[max_len]); for (GLint ii = 0; ii < num_attribs; ++ii) { GLsizei length = 0; GLsizei size = 0; @@ -492,7 +492,9 @@ void Program::Update() { } for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { const VertexAttrib& info = attrib_infos_[ii]; - attrib_location_to_index_map_[info.location] = ii; + if (info.location >= 0 && info.location <= max_location) { + attrib_location_to_index_map_[info.location] = ii; + } } #if !defined(NDEBUG) @@ -552,7 +554,7 @@ void Program::UpdateUniforms() { glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &name_buffer_length); DCHECK(name_buffer_length > 0); - scoped_ptr<char[]> name_buffer(new char[name_buffer_length]); + std::unique_ptr<char[]> name_buffer(new char[name_buffer_length]); size_t unused_client_location_cursor = 0; @@ -726,7 +728,7 @@ void Program::UpdateFragmentInputs() { &max_len); DCHECK(max_len > 0); - scoped_ptr<char[]> name_buffer(new char[max_len]); + std::unique_ptr<char[]> name_buffer(new char[max_len]); Shader* fragment_shader = attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get(); @@ -1787,7 +1789,7 @@ bool Program::CheckVaryingsPacking( if (combined_map.size() == 0) return true; - scoped_ptr<ShVariableInfo[]> variables( + std::unique_ptr<ShVariableInfo[]> variables( new ShVariableInfo[combined_map.size()]); size_t index = 0; for (const auto& key_value : combined_map) { diff --git a/chromium/gpu/command_buffer/service/program_manager.h b/chromium/gpu/command_buffer/service/program_manager.h index 1d0c9919957..05072deb3bd 100644 --- a/chromium/gpu/command_buffer/service/program_manager.h +++ b/chromium/gpu/command_buffer/service/program_manager.h @@ -9,8 +9,10 @@ #include <stdint.h> #include <map> +#include <memory> #include <string> #include <vector> + #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -506,7 +508,7 @@ class GPU_EXPORT Program : public base::RefCounted<Program> { bool uniforms_cleared_; // Log info - scoped_ptr<std::string> log_info_; + std::unique_ptr<std::string> log_info_; // attribute-location binding map from glBindAttribLocation() calls. LocationMap bind_attrib_location_map_; diff --git a/chromium/gpu/command_buffer/service/program_manager_unittest.cc b/chromium/gpu/command_buffer/service/program_manager_unittest.cc index 088342bce3a..5fcb3dcbb4d 100644 --- a/chromium/gpu/command_buffer/service/program_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/program_manager_unittest.cc @@ -8,9 +8,9 @@ #include <stdint.h> #include <algorithm> +#include <memory> #include "base/command_line.h" -#include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" @@ -86,7 +86,7 @@ class ProgramManagerTestBase : public GpuServiceTest { GpuServiceTest::TearDown(); } - scoped_ptr<ProgramManager> manager_; + std::unique_ptr<ProgramManager> manager_; GpuPreferences gpu_preferences_; scoped_refptr<FeatureInfo> feature_info_; }; @@ -2118,7 +2118,7 @@ class ProgramManagerWithCacheTest : public ProgramManagerTestBase { .Times(1); } - scoped_ptr<MockProgramCache> cache_; + std::unique_ptr<MockProgramCache> cache_; Shader* vertex_shader_; Shader* fragment_shader_; diff --git a/chromium/gpu/command_buffer/service/query_manager.cc b/chromium/gpu/command_buffer/service/query_manager.cc index c2cd4ec976b..5d86dcfcad6 100644 --- a/chromium/gpu/command_buffer/service/query_manager.cc +++ b/chromium/gpu/command_buffer/service/query_manager.cc @@ -479,7 +479,7 @@ class CommandsCompletedQuery : public QueryManager::Query { ~CommandsCompletedQuery() override; private: - scoped_ptr<gfx::GLFence> fence_; + std::unique_ptr<gfx::GLFence> fence_; base::TimeTicks begin_time_; }; @@ -559,7 +559,7 @@ class TimeElapsedQuery : public QueryManager::Query { ~TimeElapsedQuery() override; private: - scoped_ptr<gfx::GPUTimer> gpu_timer_; + std::unique_ptr<gfx::GPUTimer> gpu_timer_; }; TimeElapsedQuery::TimeElapsedQuery(QueryManager* manager, @@ -636,7 +636,7 @@ class TimeStampQuery : public QueryManager::Query { ~TimeStampQuery() override; private: - scoped_ptr<gfx::GPUTimer> gpu_timer_; + std::unique_ptr<gfx::GPUTimer> gpu_timer_; }; TimeStampQuery::TimeStampQuery(QueryManager* manager, @@ -809,7 +809,7 @@ QueryManager::Query* QueryManager::CreateQuery(GLenum target, return query.get(); } -scoped_ptr<gfx::GPUTimer> QueryManager::CreateGPUTimer(bool elapsed_time) { +std::unique_ptr<gfx::GPUTimer> QueryManager::CreateGPUTimer(bool elapsed_time) { return gpu_timing_client_->CreateGPUTimer(elapsed_time); } diff --git a/chromium/gpu/command_buffer/service/query_manager.h b/chromium/gpu/command_buffer/service/query_manager.h index f9f6816a23d..f09339b0f96 100644 --- a/chromium/gpu/command_buffer/service/query_manager.h +++ b/chromium/gpu/command_buffer/service/query_manager.h @@ -8,13 +8,14 @@ #include <stdint.h> #include <deque> +#include <memory> #include <vector> + #include "base/atomicops.h" #include "base/containers/hash_tables.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/gpu_export.h" @@ -261,7 +262,7 @@ class GPU_EXPORT QueryManager { return decoder_; } - scoped_ptr<gfx::GPUTimer> CreateGPUTimer(bool elapsed_time); + std::unique_ptr<gfx::GPUTimer> CreateGPUTimer(bool elapsed_time); bool GPUTimingAvailable(); void GenQueries(GLsizei n, const GLuint* queries); diff --git a/chromium/gpu/command_buffer/service/query_manager_unittest.cc b/chromium/gpu/command_buffer/service/query_manager_unittest.cc index 8f61ff22bd6..351f9b09d5b 100644 --- a/chromium/gpu/command_buffer/service/query_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/query_manager_unittest.cc @@ -5,6 +5,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/error_state_mock.h" @@ -97,19 +99,21 @@ class QueryManagerTest : public GpuServiceTest { EXPECT_TRUE(manager_->EndQuery(query, submit_count)); } - scoped_ptr<MockGLES2Decoder> decoder_; - scoped_ptr<QueryManager> manager_; + std::unique_ptr<MockGLES2Decoder> decoder_; + std::unique_ptr<QueryManager> manager_; private: class MockCommandBufferEngine : public CommandBufferEngine { public: MockCommandBufferEngine() { - scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); + std::unique_ptr<base::SharedMemory> shared_memory( + new base::SharedMemory()); shared_memory->CreateAndMapAnonymous(kSharedBufferSize); valid_buffer_ = MakeBufferFromSharedMemory(std::move(shared_memory), kSharedBufferSize); - scoped_ptr<base::SharedMemory> shared_memory2(new base::SharedMemory()); + std::unique_ptr<base::SharedMemory> shared_memory2( + new base::SharedMemory()); shared_memory2->CreateAndMapAnonymous(kSharedBufferSize); valid_buffer2_ = MakeBufferFromSharedMemory(std::move(shared_memory2), kSharedBufferSize); @@ -157,7 +161,7 @@ class QueryManagerTest : public GpuServiceTest { scoped_refptr<gpu::Buffer> invalid_buffer_; }; - scoped_ptr<MockCommandBufferEngine> engine_; + std::unique_ptr<MockCommandBufferEngine> engine_; }; class QueryManagerManualSetupTest : public QueryManagerTest { @@ -510,7 +514,7 @@ TEST_F(QueryManagerTest, ARBOcclusionQuery2) { "GL_ARB_occlusion_query2"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); feature_info->InitializeForTesting(); - scoped_ptr<QueryManager> manager( + std::unique_ptr<QueryManager> manager( new QueryManager(decoder_.get(), feature_info.get())); EXPECT_CALL(*gl_, GenQueries(1, _)) @@ -544,7 +548,7 @@ TEST_F(QueryManagerTest, ARBOcclusionQuery) { "GL_ARB_occlusion_query"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); feature_info->InitializeForTesting(); - scoped_ptr<QueryManager> manager( + std::unique_ptr<QueryManager> manager( new QueryManager(decoder_.get(), feature_info.get())); EXPECT_CALL(*gl_, GenQueries(1, _)) @@ -577,7 +581,7 @@ TEST_F(QueryManagerTest, ARBOcclusionPauseResume) { "GL_ARB_occlusion_query"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); feature_info->InitializeForTesting(); - scoped_ptr<QueryManager> manager( + std::unique_ptr<QueryManager> manager( new QueryManager(decoder_.get(), feature_info.get())); EXPECT_CALL(*gl_, GenQueries(1, _)) @@ -920,7 +924,7 @@ TEST_F(QueryManagerTest, GetErrorQuery) { TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), ""); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); feature_info->InitializeForTesting(); - scoped_ptr<QueryManager> manager( + std::unique_ptr<QueryManager> manager( new QueryManager(decoder_.get(), feature_info.get())); QueryManager::Query* query = manager->CreateQuery( diff --git a/chromium/gpu/command_buffer/service/renderbuffer_manager.cc b/chromium/gpu/command_buffer/service/renderbuffer_manager.cc index f368209a8e9..51349c01345 100644 --- a/chromium/gpu/command_buffer/service/renderbuffer_manager.cc +++ b/chromium/gpu/command_buffer/service/renderbuffer_manager.cc @@ -9,7 +9,7 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/trace_event.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" diff --git a/chromium/gpu/command_buffer/service/renderbuffer_manager.h b/chromium/gpu/command_buffer/service/renderbuffer_manager.h index d44b5769fd5..f808e967f96 100644 --- a/chromium/gpu/command_buffer/service/renderbuffer_manager.h +++ b/chromium/gpu/command_buffer/service/renderbuffer_manager.h @@ -8,11 +8,12 @@ #include <stddef.h> #include <stdint.h> +#include <memory> #include <string> + #include "base/containers/hash_tables.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/gpu_export.h" @@ -187,7 +188,7 @@ class GPU_EXPORT RenderbufferManager void StartTracking(Renderbuffer* renderbuffer); void StopTracking(Renderbuffer* renderbuffer); - scoped_ptr<MemoryTypeTracker> memory_type_tracker_; + std::unique_ptr<MemoryTypeTracker> memory_type_tracker_; MemoryTracker* memory_tracker_; GLint max_renderbuffer_size_; diff --git a/chromium/gpu/command_buffer/service/renderbuffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/renderbuffer_manager_unittest.cc index 815d8eec87b..a0271836d76 100644 --- a/chromium/gpu/command_buffer/service/renderbuffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/renderbuffer_manager_unittest.cc @@ -49,7 +49,7 @@ class RenderbufferManagerTestBase : public GpuServiceTest { } scoped_refptr<FeatureInfo> feature_info_; - scoped_ptr<RenderbufferManager> manager_; + std::unique_ptr<RenderbufferManager> manager_; }; class RenderbufferManagerTest : public RenderbufferManagerTestBase { diff --git a/chromium/gpu/command_buffer/service/sampler_manager.h b/chromium/gpu/command_buffer/service/sampler_manager.h index 6dc470ac8d9..8d8534328a5 100644 --- a/chromium/gpu/command_buffer/service/sampler_manager.h +++ b/chromium/gpu/command_buffer/service/sampler_manager.h @@ -6,11 +6,11 @@ #define GPU_COMMAND_BUFFER_SERVICE_SAMPLER_MANAGER_H_ #include <vector> + #include "base/containers/hash_tables.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/gpu_export.h" diff --git a/chromium/gpu/command_buffer/service/shader_manager.h b/chromium/gpu/command_buffer/service/shader_manager.h index 31a86e8d6b1..69e0cd6f983 100644 --- a/chromium/gpu/command_buffer/service/shader_manager.h +++ b/chromium/gpu/command_buffer/service/shader_manager.h @@ -6,11 +6,11 @@ #define GPU_COMMAND_BUFFER_SERVICE_SHADER_MANAGER_H_ #include <string> + #include "base/containers/hash_tables.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/shader_translator.h" #include "gpu/gpu_export.h" diff --git a/chromium/gpu/command_buffer/service/shader_manager_unittest.cc b/chromium/gpu/command_buffer/service/shader_manager_unittest.cc index 93471ec1014..1aef0569022 100644 --- a/chromium/gpu/command_buffer/service/shader_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/shader_manager_unittest.cc @@ -4,7 +4,6 @@ #include "gpu/command_buffer/service/shader_manager.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/mocks.h" #include "gpu/command_buffer/service/test_helper.h" diff --git a/chromium/gpu/command_buffer/service/shader_translator.h b/chromium/gpu/command_buffer/service/shader_translator.h index 04b1206a41b..ac8d6f8d31d 100644 --- a/chromium/gpu/command_buffer/service/shader_translator.h +++ b/chromium/gpu/command_buffer/service/shader_translator.h @@ -10,7 +10,6 @@ #include "base/containers/hash_tables.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/observer_list.h" #include "gpu/gpu_export.h" #include "third_party/angle/include/GLSLANG/ShaderLang.h" 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 deleted file mode 100644 index 35a7a841afa..00000000000 --- a/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h" - -#include <stdint.h> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/macros.h" -#include "gpu/command_buffer/service/texture_manager.h" -#include "ui/gfx/geometry/size.h" -#include "ui/gl/android/surface_texture.h" -#include "ui/gl/gl_bindings.h" -#include "ui/gl/gl_image.h" - -namespace gpu { - -namespace { - -// Simply wraps a SurfaceTexture reference as a GLImage. -class GLImageImpl : public gl::GLImage { - public: - GLImageImpl(uint32_t texture_id, - gles2::TextureManager* texture_manager, - const scoped_refptr<gfx::SurfaceTexture>& surface_texture, - const base::Closure& release_callback); - - // implement gl::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; - bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, - int z_order, - gfx::OverlayTransform transform, - const gfx::Rect& bounds_rect, - const gfx::RectF& crop_rect) override; - void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, - uint64_t process_tracing_id, - const std::string& dump_name) override; - - private: - ~GLImageImpl() override; - - uint32_t texture_id_; - gles2::TextureManager* texture_manager_; - scoped_refptr<gfx::SurfaceTexture> surface_texture_; - base::Closure release_callback_; - - DISALLOW_COPY_AND_ASSIGN(GLImageImpl); -}; - -GLImageImpl::GLImageImpl( - uint32_t texture_id, - gles2::TextureManager* texture_manager, - const scoped_refptr<gfx::SurfaceTexture>& surface_texture, - const base::Closure& release_callback) - : texture_id_(texture_id), - texture_manager_(texture_manager), - surface_texture_(surface_texture), - release_callback_(release_callback) {} - -GLImageImpl::~GLImageImpl() { - release_callback_.Run(); -} - -void GLImageImpl::Destroy(bool have_context) { - NOTREACHED(); -} - -gfx::Size GLImageImpl::GetSize() { - return gfx::Size(); -} - -unsigned GLImageImpl::GetInternalFormat() { - return GL_RGBA; -} - -bool GLImageImpl::BindTexImage(unsigned target) { - NOTREACHED(); - return false; -} - -void GLImageImpl::ReleaseTexImage(unsigned target) { - NOTREACHED(); -} - -bool GLImageImpl::CopyTexImage(unsigned target) { - if (target != GL_TEXTURE_EXTERNAL_OES) - return false; - - GLint texture_id; - glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_id); - DCHECK(texture_id); - - // The following code only works if we're being asked to copy into - // |texture_id_|. Copying into a different texture is not supported. - if (static_cast<unsigned>(texture_id) != texture_id_) - return false; - - surface_texture_->UpdateTexImage(); - - gles2::Texture* texture = - texture_manager_->GetTextureForServiceId(texture_id_); - if (texture) { - // By setting image state to UNBOUND instead of COPIED we ensure that - // CopyTexImage() is called each time the surface texture is used for - // drawing. - texture->SetLevelImage(GL_TEXTURE_EXTERNAL_OES, 0, this, - gles2::Texture::UNBOUND); - } - return true; -} - -bool GLImageImpl::CopyTexSubImage(unsigned target, - const gfx::Point& offset, - const gfx::Rect& rect) { - return false; -} - -bool GLImageImpl::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, - int z_order, - gfx::OverlayTransform transform, - const gfx::Rect& bounds_rect, - const gfx::RectF& crop_rect) { - NOTREACHED(); - return false; -} - -void GLImageImpl::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, - uint64_t process_tracing_id, - const std::string& dump_name) { - // TODO(ericrk): Implement GLImage OnMemoryDump. crbug.com/514914 -} - -} // anonymous namespace - -StreamTextureManagerInProcess::StreamTextureManagerInProcess() - : next_id_(1), weak_factory_(this) {} - -StreamTextureManagerInProcess::~StreamTextureManagerInProcess() { - if (!textures_.empty()) { - LOG(WARNING) << "Undestroyed surface textures while tearing down " - "StreamTextureManager."; - } -} - -GLuint StreamTextureManagerInProcess::CreateStreamTexture( - uint32_t client_texture_id, - gles2::TextureManager* texture_manager) { - CalledOnValidThread(); - - gles2::TextureRef* texture = texture_manager->GetTexture(client_texture_id); - - if (!texture || (texture->texture()->target() && - texture->texture()->target() != GL_TEXTURE_EXTERNAL_OES)) { - return 0; - } - - scoped_refptr<gfx::SurfaceTexture> surface_texture( - gfx::SurfaceTexture::Create(texture->service_id())); - - uint32_t stream_id = next_id_++; - base::Closure release_callback = - base::Bind(&StreamTextureManagerInProcess::OnReleaseStreamTexture, - weak_factory_.GetWeakPtr(), stream_id); - scoped_refptr<gl::GLImage> gl_image( - new GLImageImpl(texture->service_id(), texture_manager, surface_texture, - release_callback)); - - 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, gfx::Rect(size)); - texture_manager->SetLevelImage(texture, GL_TEXTURE_EXTERNAL_OES, 0, - gl_image.get(), gles2::Texture::UNBOUND); - - { - base::AutoLock lock(map_lock_); - textures_[stream_id] = surface_texture; - } - - if (next_id_ == 0) - next_id_++; - - return stream_id; -} - -void StreamTextureManagerInProcess::OnReleaseStreamTexture(uint32_t stream_id) { - CalledOnValidThread(); - base::AutoLock lock(map_lock_); - textures_.erase(stream_id); -} - -// This can get called from any thread. -scoped_refptr<gfx::SurfaceTexture> -StreamTextureManagerInProcess::GetSurfaceTexture(uint32_t stream_id) { - base::AutoLock lock(map_lock_); - TextureMap::const_iterator it = textures_.find(stream_id); - if (it != textures_.end()) - return it->second; - - return NULL; -} - -} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.h b/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.h deleted file mode 100644 index 1f503bf192e..00000000000 --- a/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_STREAM_TEXTURE_MANAGER_IN_PROCESS_ANDROID_H_ -#define GPU_STREAM_TEXTURE_MANAGER_IN_PROCESS_ANDROID_H_ - -#include <stdint.h> - -#include <map> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/synchronization/lock.h" -#include "base/threading/non_thread_safe.h" - -namespace gfx { -class SurfaceTexture; -} - -namespace gpu { - -namespace gles2 { -class TextureManager; -} - -class StreamTextureManagerInProcess : public base::NonThreadSafe { - public: - StreamTextureManagerInProcess(); - ~StreamTextureManagerInProcess(); - - uint32_t CreateStreamTexture(uint32_t client_texture_id, - gles2::TextureManager* texture_manager); - - // This method can be called from any thread. - scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(uint32_t stream_id); - - private: - void OnReleaseStreamTexture(uint32_t stream_id); - - typedef std::map<uint32_t, scoped_refptr<gfx::SurfaceTexture>> TextureMap; - TextureMap textures_; - base::Lock map_lock_; - uint32_t next_id_; - - base::WeakPtrFactory<StreamTextureManagerInProcess> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(StreamTextureManagerInProcess); -}; - -} // gpu - -#endif // GPU_STREAM_TEXTURE_MANAGER_IN_PROCESS_ANDROID_H_ diff --git a/chromium/gpu/command_buffer/service/sync_point_manager.cc b/chromium/gpu/command_buffer/service/sync_point_manager.cc index 2adf5df6d5a..022895ad494 100644 --- a/chromium/gpu/command_buffer/service/sync_point_manager.cc +++ b/chromium/gpu/command_buffer/service/sync_point_manager.cc @@ -14,6 +14,7 @@ #include "base/containers/hash_tables.h" #include "base/location.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/rand_util.h" #include "base/sequence_checker.h" #include "base/single_thread_task_runner.h" @@ -87,7 +88,8 @@ void SyncPointOrderData::BeginProcessingOrderNumber(uint32_t order_num) { } for (OrderFence& order_fence : ensure_releases) { - order_fence.client_state->EnsureReleased(order_fence.fence_release); + order_fence.client_state->EnsureWaitReleased(order_fence.fence_release, + order_fence.release_callback); } } @@ -125,15 +127,20 @@ void SyncPointOrderData::FinishProcessingOrderNumber(uint32_t order_num) { } for (OrderFence& order_fence : ensure_releases) { - order_fence.client_state->EnsureReleased(order_fence.fence_release); + order_fence.client_state->EnsureWaitReleased(order_fence.fence_release, + order_fence.release_callback); } } SyncPointOrderData::OrderFence::OrderFence( uint32_t order, uint64_t release, + const base::Closure& callback, scoped_refptr<SyncPointClientState> state) - : order_num(order), fence_release(release), client_state(state) {} + : order_num(order), + fence_release(release), + release_callback(callback), + client_state(state) {} SyncPointOrderData::OrderFence::OrderFence(const OrderFence& other) = default; @@ -151,7 +158,8 @@ SyncPointOrderData::~SyncPointOrderData() {} bool SyncPointOrderData::ValidateReleaseOrderNumber( scoped_refptr<SyncPointClientState> client_state, uint32_t wait_order_num, - uint64_t fence_release) { + uint64_t fence_release, + const base::Closure& release_callback) { base::AutoLock auto_lock(lock_); if (destroyed_) return false; @@ -169,8 +177,8 @@ bool SyncPointOrderData::ValidateReleaseOrderNumber( // gets released eventually. const uint32_t expected_order_num = std::min(unprocessed_order_num_, wait_order_num); - order_fence_queue_.push( - OrderFence(expected_order_num, fence_release, client_state)); + order_fence_queue_.push(OrderFence(expected_order_num, fence_release, + release_callback, client_state)); return true; } @@ -202,7 +210,7 @@ bool SyncPointClientState::WaitForRelease(CommandBufferNamespace namespace_id, base::AutoLock auto_lock(fence_sync_lock_); if (release > fence_sync_release_) { if (!order_data_->ValidateReleaseOrderNumber(this, wait_order_num, - release)) { + release, callback)) { return false; } else { // Add the callback which will be called upon release. @@ -224,7 +232,14 @@ void SyncPointClientState::ReleaseFenceSync(uint64_t release) { std::vector<base::Closure> callback_list; { base::AutoLock auto_lock(fence_sync_lock_); - ReleaseFenceSyncLocked(release, &callback_list); + DCHECK_GT(release, fence_sync_release_); + + fence_sync_release_ = release; + while (!release_callback_queue_.empty() && + release_callback_queue_.top().release_count <= release) { + callback_list.push_back(release_callback_queue_.top().callback_closure); + release_callback_queue_.pop(); + } } for (const base::Closure& closure : callback_list) { @@ -232,33 +247,41 @@ void SyncPointClientState::ReleaseFenceSync(uint64_t release) { } } -void SyncPointClientState::EnsureReleased(uint64_t release) { +void SyncPointClientState::EnsureWaitReleased(uint64_t release, + const base::Closure& callback) { // Call callbacks without the lock to avoid possible deadlocks. - std::vector<base::Closure> callback_list; + bool call_callback = false; { base::AutoLock auto_lock(fence_sync_lock_); if (release <= fence_sync_release_) return; - ReleaseFenceSyncLocked(release, &callback_list); - } + std::vector<ReleaseCallback> popped_callbacks; + popped_callbacks.reserve(release_callback_queue_.size()); - for (const base::Closure& closure : callback_list) { - closure.Run(); + while (!release_callback_queue_.empty() && + release_callback_queue_.top().release_count <= release) { + const ReleaseCallback& top_item = release_callback_queue_.top(); + if (top_item.release_count == release && + top_item.callback_closure.Equals(callback)) { + // Call the callback, and discard this item from the callback queue. + call_callback = true; + } else { + // Store the item to be placed back into the callback queue later. + popped_callbacks.push_back(top_item); + } + release_callback_queue_.pop(); + } + + // Add back in popped items. + for (const ReleaseCallback& popped_callback : popped_callbacks) { + release_callback_queue_.push(popped_callback); + } } -} -void SyncPointClientState::ReleaseFenceSyncLocked( - uint64_t release, - std::vector<base::Closure>* callback_list) { - fence_sync_lock_.AssertAcquired(); - DCHECK_GT(release, fence_sync_release_); - - fence_sync_release_ = release; - while (!release_callback_queue_.empty() && - release_callback_queue_.top().release_count <= release) { - callback_list->push_back(release_callback_queue_.top().callback_closure); - release_callback_queue_.pop(); + if (call_callback) { + // This effectively releases the wait without releasing the fence. + callback.Run(); } } @@ -370,7 +393,7 @@ SyncPointManager::~SyncPointManager() { } } -scoped_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClient( +std::unique_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClient( scoped_refptr<SyncPointOrderData> order_data, CommandBufferNamespace namespace_id, CommandBufferId client_id) { @@ -384,11 +407,12 @@ scoped_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClient( namespace_id, client_id))); DCHECK(result.second); - return make_scoped_ptr(result.first->second); + return base::WrapUnique(result.first->second); } -scoped_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClientWaiter() { - return make_scoped_ptr(new SyncPointClient); +std::unique_ptr<SyncPointClient> +SyncPointManager::CreateSyncPointClientWaiter() { + return base::WrapUnique(new SyncPointClient); } scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState( diff --git a/chromium/gpu/command_buffer/service/sync_point_manager.h b/chromium/gpu/command_buffer/service/sync_point_manager.h index 49769fb14fa..7a3695c9886 100644 --- a/chromium/gpu/command_buffer/service/sync_point_manager.h +++ b/chromium/gpu/command_buffer/service/sync_point_manager.h @@ -8,6 +8,7 @@ #include <stdint.h> #include <functional> +#include <memory> #include <queue> #include <unordered_map> #include <vector> @@ -17,7 +18,6 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" @@ -73,10 +73,12 @@ class GPU_EXPORT SyncPointOrderData struct OrderFence { uint32_t order_num; uint64_t fence_release; + base::Closure release_callback; scoped_refptr<SyncPointClientState> client_state; OrderFence(uint32_t order, uint64_t release, + const base::Closure& release_callback, scoped_refptr<SyncPointClientState> state); OrderFence(const OrderFence& other); ~OrderFence(); @@ -97,7 +99,8 @@ class GPU_EXPORT SyncPointOrderData bool ValidateReleaseOrderNumber( scoped_refptr<SyncPointClientState> client_state, uint32_t wait_order_num, - uint64_t fence_release); + uint64_t fence_release, + const base::Closure& release_callback); // Non thread-safe functions need to be called from a single thread. base::ThreadChecker processing_thread_checker_; @@ -182,10 +185,12 @@ class GPU_EXPORT SyncPointClientState uint64_t release, const base::Closure& callback); + // Releases a fence sync and all fence syncs below. void ReleaseFenceSync(uint64_t release); - void EnsureReleased(uint64_t release); - void ReleaseFenceSyncLocked(uint64_t release, - std::vector<base::Closure>* callback_list); + + // Does not release the fence sync, but releases callbacks waiting on that + // fence sync. + void EnsureWaitReleased(uint64_t release, const base::Closure& callback); typedef base::Callback<void(CommandBufferNamespace, CommandBufferId)> OnWaitCallback; @@ -291,14 +296,14 @@ class GPU_EXPORT SyncPointManager { ~SyncPointManager(); // Creates/Destroy a sync point client which message processors should hold. - scoped_ptr<SyncPointClient> CreateSyncPointClient( + std::unique_ptr<SyncPointClient> CreateSyncPointClient( scoped_refptr<SyncPointOrderData> order_data, CommandBufferNamespace namespace_id, CommandBufferId client_id); // Creates a sync point client which cannot process order numbers but can only // Wait out of order. - scoped_ptr<SyncPointClient> CreateSyncPointClientWaiter(); + std::unique_ptr<SyncPointClient> CreateSyncPointClientWaiter(); // Finds the state of an already created sync point client. scoped_refptr<SyncPointClientState> GetSyncPointClientState( diff --git a/chromium/gpu/command_buffer/service/sync_point_manager_unittest.cc b/chromium/gpu/command_buffer/service/sync_point_manager_unittest.cc index e6cdeeaa7db..a9f6c56b878 100644 --- a/chromium/gpu/command_buffer/service/sync_point_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/sync_point_manager_unittest.cc @@ -4,6 +4,7 @@ #include <stdint.h> +#include <memory> #include <queue> #include "base/bind.h" @@ -37,12 +38,12 @@ class SyncPointManagerTest : public testing::Test { *client_id_ptr = client_id; } - scoped_ptr<SyncPointManager> sync_point_manager_; + std::unique_ptr<SyncPointManager> sync_point_manager_; }; struct SyncPointStream { scoped_refptr<SyncPointOrderData> order_data; - scoped_ptr<SyncPointClient> client; + std::unique_ptr<SyncPointClient> client; std::queue<uint32_t> order_numbers; SyncPointStream(SyncPointManager* sync_point_manager, @@ -120,7 +121,7 @@ TEST_F(SyncPointManagerTest, SyncPointClientRegistration) { scoped_refptr<SyncPointOrderData> order_data = SyncPointOrderData::Create(); - scoped_ptr<SyncPointClient> client = + std::unique_ptr<SyncPointClient> client = sync_point_manager_->CreateSyncPointClient(order_data, kNamespaceId, kBufferId); @@ -136,7 +137,7 @@ TEST_F(SyncPointManagerTest, BasicFenceSyncRelease) { const CommandBufferId kBufferId = CommandBufferId::FromUnsafeValue(0x123); scoped_refptr<SyncPointOrderData> order_data = SyncPointOrderData::Create(); - scoped_ptr<SyncPointClient> client = + std::unique_ptr<SyncPointClient> client = sync_point_manager_->CreateSyncPointClient(order_data, kNamespaceId, kBufferId); scoped_refptr<SyncPointClientState> client_state = client->client_state(); @@ -161,10 +162,10 @@ TEST_F(SyncPointManagerTest, MultipleClientsPerOrderData) { const CommandBufferId kBufferId2 = CommandBufferId::FromUnsafeValue(0x234); scoped_refptr<SyncPointOrderData> order_data = SyncPointOrderData::Create(); - scoped_ptr<SyncPointClient> client1 = + std::unique_ptr<SyncPointClient> client1 = sync_point_manager_->CreateSyncPointClient(order_data, kNamespaceId, kBufferId1); - scoped_ptr<SyncPointClient> client2 = + std::unique_ptr<SyncPointClient> client2 = sync_point_manager_->CreateSyncPointClient(order_data, kNamespaceId, kBufferId2); @@ -380,13 +381,21 @@ TEST_F(SyncPointManagerTest, NonExistentRelease2) { EXPECT_EQ(10, test_num); // Even though release stream order [1] did not have a release, it - // should still release the fence when finish processing since the wait - // stream had expected on to exist there. + // should have changed test_num although the fence sync is still not released. release_stream.BeginProcessing(); ASSERT_EQ(1u, release_stream.order_data->current_order_num()); release_stream.EndProcessing(); - EXPECT_TRUE(release_stream.client->client_state()->IsFenceSyncReleased(1)); + EXPECT_FALSE(release_stream.client->client_state()->IsFenceSyncReleased(1)); EXPECT_EQ(123, test_num); + + // Ensure that the wait callback does not get triggered again when it is + // actually released. + test_num = 1; + release_stream.AllocateOrderNum(sync_point_manager_.get()); + release_stream.BeginProcessing(); + release_stream.client->ReleaseFenceSync(1); + release_stream.EndProcessing(); + EXPECT_EQ(1, test_num); } TEST_F(SyncPointManagerTest, NonExistentOrderNumRelease) { @@ -432,11 +441,18 @@ TEST_F(SyncPointManagerTest, NonExistentOrderNumRelease) { EXPECT_FALSE(release_stream.client->client_state()->IsFenceSyncReleased(1)); EXPECT_EQ(10, test_num); - // Beginning order [4] should immediately trigger the release. + // Beginning order [4] should immediately trigger the wait although the fence + // sync is still not released yet. release_stream.BeginProcessing(); ASSERT_EQ(4u, release_stream.order_data->current_order_num()); - EXPECT_TRUE(release_stream.client->client_state()->IsFenceSyncReleased(1)); + EXPECT_FALSE(release_stream.client->client_state()->IsFenceSyncReleased(1)); EXPECT_EQ(123, test_num); + + // Ensure that the wait callback does not get triggered again when it is + // actually released. + test_num = 1; + release_stream.client->ReleaseFenceSync(1); + EXPECT_EQ(1, test_num); } TEST_F(SyncPointManagerTest, OnWaitCallbackTest) { diff --git a/chromium/gpu/command_buffer/service/test_helper.cc b/chromium/gpu/command_buffer/service/test_helper.cc index 632d2af302b..7f265328a54 100644 --- a/chromium/gpu/command_buffer/service/test_helper.cc +++ b/chromium/gpu/command_buffer/service/test_helper.cc @@ -79,6 +79,7 @@ const GLint TestHelper::kMaxTextureSize; const GLint TestHelper::kMaxCubeMapTextureSize; const GLint TestHelper::kMaxRectangleTextureSize; const GLint TestHelper::kMax3DTextureSize; +const GLint TestHelper::kMaxArrayTextureLayers; const GLint TestHelper::kNumVertexAttribs; const GLint TestHelper::kNumTextureUnits; const GLint TestHelper::kMaxTextureImageUnits; @@ -93,6 +94,9 @@ const GLint TestHelper::kMaxVertexOutputComponents; const GLint TestHelper::kMaxFragmentInputComponents; const GLint TestHelper::kMaxProgramTexelOffset; const GLint TestHelper::kMinProgramTexelOffset; +const GLint TestHelper::kMaxTransformFeedbackSeparateAttribs; +const GLint TestHelper::kMaxUniformBufferBindings; +const GLint TestHelper::kUniformBufferOffsetAlignment; #endif std::vector<std::string> TestHelper::split_extensions_; @@ -358,6 +362,18 @@ void TestHelper::SetupContextGroupInitExpectations( .RetiresOnSaturation(); } + if (gl_info.IsES3Capable()) { + EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, _)) + .WillOnce(SetArgumentPointee<1>(kMaxTransformFeedbackSeparateAttribs)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, GetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, _)) + .WillOnce(SetArgumentPointee<1>(kMaxUniformBufferBindings)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, GetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, _)) + .WillOnce(SetArgumentPointee<1>(kUniformBufferOffsetAlignment)) + .RetiresOnSaturation(); + } + EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _)) .WillOnce(SetArgumentPointee<1>(kNumVertexAttribs)) .RetiresOnSaturation(); @@ -375,6 +391,11 @@ void TestHelper::SetupContextGroupInitExpectations( .WillOnce(SetArgumentPointee<1>(kMax3DTextureSize)) .RetiresOnSaturation(); } + if (gl_info.IsES3Capable()) { + EXPECT_CALL(*gl, GetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, _)) + .WillOnce(SetArgumentPointee<1>(kMaxArrayTextureLayers)) + .RetiresOnSaturation(); + } if (strstr(extensions, "GL_ARB_texture_rectangle")) { EXPECT_CALL(*gl, GetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE, _)) .WillOnce(SetArgumentPointee<1>(kMaxRectangleTextureSize)) diff --git a/chromium/gpu/command_buffer/service/test_helper.h b/chromium/gpu/command_buffer/service/test_helper.h index d0e23991f80..de06dffca81 100644 --- a/chromium/gpu/command_buffer/service/test_helper.h +++ b/chromium/gpu/command_buffer/service/test_helper.h @@ -46,6 +46,7 @@ class TestHelper { static const GLint kMaxTextureSize = 2048; static const GLint kMaxCubeMapTextureSize = 2048; static const GLint kMax3DTextureSize = 1024; + static const GLint kMaxArrayTextureLayers = 256; static const GLint kMaxRectangleTextureSize = 64; static const GLint kNumVertexAttribs = 16; static const GLint kNumTextureUnits = 8; @@ -63,6 +64,10 @@ class TestHelper { static const GLint kMaxProgramTexelOffset = 7; static const GLint kMinProgramTexelOffset = -8; + static const GLint kMaxTransformFeedbackSeparateAttribs = 4; + static const GLint kMaxUniformBufferBindings = 24; + static const GLint kUniformBufferOffsetAlignment = 1; + struct AttribInfo { const char* name; GLint size; diff --git a/chromium/gpu/command_buffer/service/texture_definition.cc b/chromium/gpu/command_buffer/service/texture_definition.cc index f8346c0339d..44bf4ed93be 100644 --- a/chromium/gpu/command_buffer/service/texture_definition.cc +++ b/chromium/gpu/command_buffer/service/texture_definition.cc @@ -10,7 +10,6 @@ #include "base/lazy_instance.h" #include "base/memory/linked_ptr.h" -#include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "base/threading/thread_local.h" // gl_stream_texture_image.h is included to work around crbug.com/595189, a diff --git a/chromium/gpu/command_buffer/service/texture_manager.cc b/chromium/gpu/command_buffer/service/texture_manager.cc index 8297c6d0455..d77b22e20e7 100644 --- a/chromium/gpu/command_buffer/service/texture_manager.cc +++ b/chromium/gpu/command_buffer/service/texture_manager.cc @@ -15,7 +15,7 @@ #include "base/lazy_instance.h" #include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/context_state.h" @@ -65,6 +65,7 @@ struct TextureSignature { bool can_render_; bool can_render_to_; bool npot_; + bool emulating_rgb_; // Since we will be hashing this signature structure, the padding must be // zero initialized. Although the C++11 specifications specify that this is @@ -86,7 +87,8 @@ struct TextureSignature { bool has_image, bool can_render, bool can_render_to, - bool npot) { + bool npot, + bool emulating_rgb) { memset(this, 0, sizeof(TextureSignature)); target_ = target; level_ = level; @@ -113,6 +115,7 @@ struct TextureSignature { can_render_ = can_render; can_render_to_ = can_render_to; npot_ = npot; + emulating_rgb_ = emulating_rgb; } }; @@ -376,7 +379,8 @@ Texture::Texture(GLuint service_id) estimated_size_(0), can_render_condition_(CAN_RENDER_ALWAYS), texture_max_anisotropy_initialized_(false), - compatibility_swizzle_(nullptr) {} + compatibility_swizzle_(nullptr), + emulating_rgb_(false) {} Texture::~Texture() { if (mailbox_manager_) @@ -587,7 +591,8 @@ void Texture::AddToSignature( info.image.get() != NULL, CanRender(feature_info), CanRenderTo(feature_info, level), - npot_); + npot_, + emulating_rgb_); signature->append(TextureTag, sizeof(TextureTag)); signature->append(reinterpret_cast<const char*>(&signature_data), @@ -866,6 +871,19 @@ void Texture::UpdateHasImages() { (*it)->manager()->UpdateNumImages(delta); } +void Texture::UpdateEmulatingRGB() { + for (const FaceInfo& face_info : face_infos_) { + for (const LevelInfo& level_info : face_info.level_infos) { + if (level_info.image && level_info.image->EmulatingRGB()) { + emulating_rgb_ = true; + return; + } + } + } + emulating_rgb_ = false; +} + + void Texture::IncAllFramebufferStateChangeCount() { for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) (*it)->manager()->IncFramebufferStateChangeCount(); @@ -986,6 +1004,27 @@ void Texture::SetLevelInfo(GLenum target, } } +void Texture::SetStreamTextureServiceId(GLuint service_id) { + GLuint new_service_id = service_id ? service_id : owned_service_id_; + + // Take no action if this isn't an OES_EXTERNAL texture. + if (target_ && target_ != GL_TEXTURE_EXTERNAL_OES) + return; + + if (service_id_ != new_service_id) { + service_id_ = new_service_id; + IncrementManagerServiceIdGeneration(); + if (gfx::GLContext* context = gfx::GLContext::GetCurrent()) { + // It would be preferable to pass in the decoder, and ask it to do this + // instead. However, there are several cases, such as TextureDefinition, + // that show up without a clear context owner. So, instead, we use the + // current state's state restorer. + if (gfx::GLStateRestorer* restorer = context->GetGLStateRestorer()) + restorer->RestoreAllExternalTextureBindingsIfNeeded(); + } + } +} + void Texture::MarkLevelAsInternalWorkaround(GLenum target, GLint level) { DCHECK_GE(level, 0); size_t face_index = GLES2Util::GLTargetToFaceIndex(target); @@ -1319,6 +1358,21 @@ bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { return true; } +GLint Texture::GetImmutableLevels() const { + if (!immutable_) + return 0; + GLint levels = 0; + if (immutable_) { + DCHECK(face_infos_.size() > 0); + for (size_t ii = 0; ii < face_infos_[0].level_infos.size(); ++ii) { + const Texture::LevelInfo& info = face_infos_[0].level_infos[ii]; + if (info.target != 0) + levels++; + } + } + return levels; +} + gfx::Rect Texture::GetLevelClearedRect(GLenum target, GLint level) const { size_t face_index = GLES2Util::GLTargetToFaceIndex(target); if (face_index >= face_infos_.size() || @@ -1391,30 +1445,45 @@ bool Texture::ClearLevel( if (!cleared) return false; } else { - // Clear all remaining sub regions. - const int x[] = { + if (decoder->IsCompressedTextureFormat(info.internal_format)) { + // An uncleared level of a compressed texture can only occur when + // allocating the texture with TexStorage2D. In this case the level + // is cleared just before a call to CompressedTexSubImage2D, to avoid + // having to clear a sub-rectangle of a compressed texture, which + // would be problematic. + DCHECK(IsImmutable()); + DCHECK(info.cleared_rect == gfx::Rect()); + bool cleared = decoder->ClearCompressedTextureLevel( + this, info.target, info.level, info.internal_format, + info.width, info.height); + if (!cleared) + return false; + } else { + // Clear all remaining sub regions. + const int x[] = { 0, info.cleared_rect.x(), info.cleared_rect.right(), info.width}; - const int y[] = { + 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; + 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; + } } } } @@ -1429,14 +1498,13 @@ void Texture::SetLevelImageInternal(GLenum target, gl::GLImage* image, GLStreamTextureImage* stream_texture_image, ImageState state) { + DCHECK(!stream_texture_image || stream_texture_image == image); 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>(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]; + Texture::LevelInfo& info = face_infos_[face_index].level_infos[level]; DCHECK_EQ(info.target, target); DCHECK_EQ(info.level, level); info.image = image; @@ -1445,22 +1513,38 @@ void Texture::SetLevelImageInternal(GLenum target, UpdateCanRenderCondition(); UpdateHasImages(); + UpdateEmulatingRGB(); } void Texture::SetLevelImage(GLenum target, GLint level, gl::GLImage* image, ImageState state) { + SetStreamTextureServiceId(0); SetLevelImageInternal(target, level, image, nullptr, state); } void Texture::SetLevelStreamTextureImage(GLenum target, GLint level, GLStreamTextureImage* image, - ImageState state) { + ImageState state, + GLuint service_id) { + SetStreamTextureServiceId(service_id); SetLevelImageInternal(target, level, image, image, state); } +void Texture::SetLevelImageState(GLenum target, GLint level, ImageState state) { + 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]; + DCHECK_EQ(info.target, target); + DCHECK_EQ(info.level, level); + info.image_state = state; +} + const Texture::LevelInfo* Texture::GetLevelInfo(GLint target, GLint level) const { if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES && @@ -1558,7 +1642,8 @@ bool Texture::CanRenderTo(const FeatureInfo* feature_info, GLint level) const { IsValid(internal_format) && internal_format != GL_ALPHA && internal_format != GL_LUMINANCE && - internal_format != GL_LUMINANCE_ALPHA) || + internal_format != GL_LUMINANCE_ALPHA && + internal_format != GL_SRGB_EXT) || feature_info->validators()-> texture_sized_color_renderable_internal_format.IsValid( internal_format)); @@ -1569,30 +1654,6 @@ bool Texture::CanRenderTo(const FeatureInfo* feature_info, GLint level) const { return (color_renderable || depth_renderable || stencil_renderable); } -void Texture::SetUnownedServiceId(GLuint service_id) { - GLuint new_service_id = service_id; - - // Take no action if this isn't an OES_EXTERNAL texture. - if (target_ && target_ != GL_TEXTURE_EXTERNAL_OES) - return; - - if (!service_id) - new_service_id = owned_service_id_; - - if (service_id_ != new_service_id) { - service_id_ = new_service_id; - IncrementManagerServiceIdGeneration(); - if (gfx::GLContext* context = gfx::GLContext::GetCurrent()) { - // It would be preferable to pass in the decoder, and ask it to do this - // instead. However, there are several cases, such as TextureDefinition, - // that show up without a clear context owner. So, instead, we use the - // current state's state restorer. - if (gfx::GLStateRestorer* restorer = context->GetGLStateRestorer()) - restorer->RestoreAllExternalTextureBindingsIfNeeded(); - } - } -} - GLenum Texture::GetCompatibilitySwizzleForChannel(GLenum channel) { return GetSwizzleForChannel(channel, compatibility_swizzle_); } @@ -1621,6 +1682,10 @@ void Texture::ApplyFormatWorkarounds(FeatureInfo* feature_info) { } } +bool Texture::EmulatingRGB() { + return emulating_rgb_; +} + TextureRef::TextureRef(TextureManager* manager, GLuint client_id, Texture* texture) @@ -1652,6 +1717,7 @@ TextureManager::TextureManager(MemoryTracker* memory_tracker, GLint max_cube_map_texture_size, GLint max_rectangle_texture_size, GLint max_3d_texture_size, + GLint max_array_texture_layers, bool use_default_textures) : memory_type_tracker_(new MemoryTypeTracker(memory_tracker)), memory_tracker_(memory_tracker), @@ -1661,14 +1727,15 @@ TextureManager::TextureManager(MemoryTracker* memory_tracker, max_cube_map_texture_size_(max_cube_map_texture_size), max_rectangle_texture_size_(max_rectangle_texture_size), max_3d_texture_size_(max_3d_texture_size), + max_array_texture_layers_(max_array_texture_layers), max_levels_(ComputeMipMapCount(GL_TEXTURE_2D, max_texture_size, max_texture_size, - max_texture_size)), + 0)), max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP, max_cube_map_texture_size, max_cube_map_texture_size, - max_cube_map_texture_size)), + 0)), max_3d_levels_(ComputeMipMapCount(GL_TEXTURE_3D, max_3d_texture_size, max_3d_texture_size, @@ -1702,7 +1769,8 @@ bool TextureManager::Initialize() { GL_TEXTURE_2D_ARRAY, &black_texture_ids_[kTexture2DArray]); } - if (feature_info_->feature_flags().oes_egl_image_external) { + if (feature_info_->feature_flags().oes_egl_image_external || + feature_info_->feature_flags().nv_egl_stream_consumer_external) { default_textures_[kExternalOES] = CreateDefaultAndBlackTextures( GL_TEXTURE_EXTERNAL_OES, &black_texture_ids_[kExternalOES]); } @@ -1787,15 +1855,17 @@ scoped_refptr<TextureRef> bool TextureManager::ValidForTarget( GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) { + if (level < 0 || level >= MaxLevelsForTarget(target)) + return false; GLsizei max_size = MaxSizeForTarget(target) >> level; - return level >= 0 && - width >= 0 && + GLsizei max_depth = + (target == GL_TEXTURE_2D_ARRAY ? max_array_texture_layers() : max_size); + return width >= 0 && height >= 0 && depth >= 0 && - level < MaxLevelsForTarget(target) && width <= max_size && height <= max_size && - depth <= max_size && + depth <= max_depth && (level == 0 || feature_info_->feature_flags().npot_ok || (!GLES2Util::IsNPOT(width) && !GLES2Util::IsNPOT(height) && @@ -2041,9 +2111,19 @@ void TextureManager::SetLevelStreamTextureImage(TextureRef* ref, GLenum target, GLint level, GLStreamTextureImage* image, - Texture::ImageState state) { + Texture::ImageState state, + GLuint service_id) { + DCHECK(ref); + ref->texture()->SetLevelStreamTextureImage(target, level, image, state, + service_id); +} + +void TextureManager::SetLevelImageState(TextureRef* ref, + GLenum target, + GLint level, + Texture::ImageState state) { DCHECK(ref); - ref->texture()->SetLevelStreamTextureImage(target, level, image, state); + ref->texture()->SetLevelImageState(target, level, state); } size_t TextureManager::GetSignatureSize() const { @@ -2096,15 +2176,18 @@ bool TextureManager::ValidateTextureParameters( // So the validation is not necessary for TexSubImage. if (tex_image_call && !validators->texture_internal_format.IsValid(internal_format)) { - ERRORSTATE_SET_GL_ERROR( - error_state, GL_INVALID_VALUE, function_name, - "invalid internal_format"); + std::string msg = base::StringPrintf("invalid internal_format 0x%x", + internal_format); + ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, + msg.c_str()); return false; } if (!g_format_type_validator.Get().IsValid(internal_format, format, type)) { - ERRORSTATE_SET_GL_ERROR( - error_state, GL_INVALID_OPERATION, function_name, - "invalid internalformat/format/type combination"); + std::string msg = base::StringPrintf( + "invalid internalformat/format/type combination 0x%x/0x%x/0x%x", + internal_format, format, type); + ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, + msg.c_str()); return false; } if (!feature_info_->IsES3Enabled()) { @@ -2321,7 +2404,7 @@ void TextureManager::ValidateAndDoTexImage( return; } DoTexImageArguments new_args = args; - scoped_ptr<char[]> zero(new char[args.pixels_size]); + std::unique_ptr<char[]> zero(new char[args.pixels_size]); memset(zero.get(), 0, args.pixels_size); for (GLenum face : undefined_faces) { new_args.target = face; @@ -2332,20 +2415,42 @@ void TextureManager::ValidateAndDoTexImage( } } + if (texture_state->unpack_overlapping_rows_separately_unpack_buffer && + buffer) { + ContextState::Dimension dimension = + (args.command_type == DoTexImageArguments::kTexImage3D) + ? ContextState::k3D + : ContextState::k2D; + const PixelStoreParams unpack_params(state->GetUnpackParams(dimension)); + if (unpack_params.row_length != 0 && + unpack_params.row_length < args.width) { + // The rows overlap in unpack memory. Upload the texture row by row to + // work around driver bug. + + ReserveTexImageToBeFilled(texture_state, state, framebuffer_state, + function_name, texture_ref, args); + + DoTexSubImageArguments sub_args = { + args.target, args.level, 0, 0, 0, args.width, args.height, args.depth, + args.format, args.type, args.pixels, args.pixels_size, args.padding, + args.command_type == DoTexImageArguments::kTexImage3D + ? DoTexSubImageArguments::kTexSubImage3D + : DoTexSubImageArguments::kTexSubImage2D}; + DoTexSubImageRowByRowWorkaround(texture_state, state, sub_args, + unpack_params); + + SetLevelCleared(texture_ref, args.target, args.level, true); + return; + } + } + if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) { uint32_t buffer_size = static_cast<uint32_t>(buffer->size()); if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) { // In ValidateTexImage(), we already made sure buffer size is no less // than offset + pixels_size. - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, nullptr); - DoTexImageArguments new_args = args; - new_args.pixels = nullptr; - // pixels_size might be incorrect, but it's not used in this case. - DoTexImage(texture_state, state, framebuffer_state, function_name, - texture_ref, new_args); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->service_id()); - state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, buffer); + ReserveTexImageToBeFilled(texture_state, state, framebuffer_state, + function_name, texture_ref, args); DoTexSubImageArguments sub_args = { args.target, args.level, 0, 0, 0, args.width, args.height, args.depth, @@ -2363,6 +2468,25 @@ void TextureManager::ValidateAndDoTexImage( function_name, texture_ref, args); } +void TextureManager::ReserveTexImageToBeFilled( + DecoderTextureState* texture_state, + ContextState* state, + DecoderFramebufferState* framebuffer_state, + const char* function_name, + TextureRef* texture_ref, + const DoTexImageArguments& args) { + Buffer* buffer = state->bound_pixel_unpack_buffer.get(); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, nullptr); + DoTexImageArguments new_args = args; + new_args.pixels = nullptr; + // pixels_size might be incorrect, but it's not used in this case. + DoTexImage(texture_state, state, framebuffer_state, function_name, + texture_ref, new_args); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->service_id()); + state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, buffer); +} + bool TextureManager::ValidateTexSubImage(ContextState* state, const char* function_name, const DoTexSubImageArguments& args, @@ -2390,8 +2514,10 @@ bool TextureManager::ValidateTexSubImage(ContextState* state, GLenum internal_format = 0; if (!texture->GetLevelType(args.target, args.level, ¤t_type, &internal_format)) { + std::string msg = base::StringPrintf( + "level %d does not exist", args.level); ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, - "level does not exist."); + msg.c_str()); return false; } if (!ValidateTextureParameters(error_state, function_name, false, args.format, @@ -2508,6 +2634,24 @@ void TextureManager::ValidateAndDoTexSubImage( } Buffer* buffer = state->bound_pixel_unpack_buffer.get(); + + if (texture_state->unpack_overlapping_rows_separately_unpack_buffer && + buffer) { + ContextState::Dimension dimension = + (args.command_type == DoTexSubImageArguments::kTexSubImage3D) + ? ContextState::k3D + : ContextState::k2D; + const PixelStoreParams unpack_params(state->GetUnpackParams(dimension)); + if (unpack_params.row_length != 0 && + unpack_params.row_length < args.width) { + // The rows overlap in unpack memory. Upload the texture row by row to + // work around driver bug. + DoTexSubImageRowByRowWorkaround(texture_state, state, args, + unpack_params); + return; + } + } + if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) { uint32_t buffer_size = static_cast<uint32_t>(buffer->size()); if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) { @@ -2655,6 +2799,58 @@ void TextureManager::DoTexSubImageWithAlignmentWorkaround( DCHECK_EQ(ToGLuint(args.pixels) + args.pixels_size, offset); } +void TextureManager::DoTexSubImageRowByRowWorkaround( + DecoderTextureState* texture_state, + ContextState* state, + const DoTexSubImageArguments& args, + const PixelStoreParams& unpack_params) { + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + DCHECK_EQ(0, state->unpack_skip_pixels); + DCHECK_EQ(0, state->unpack_skip_rows); + DCHECK_EQ(0, state->unpack_skip_images); + + GLenum format = AdjustTexFormat(args.format); + + GLsizei row_bytes = unpack_params.row_length * + GLES2Util::ComputeImageGroupSize(format, args.type); + GLsizei alignment_diff = row_bytes % unpack_params.alignment; + if (alignment_diff != 0) { + row_bytes += unpack_params.alignment - alignment_diff; + } + DCHECK_EQ(0, row_bytes % unpack_params.alignment); + if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) { + GLsizei image_height = args.height; + if (unpack_params.image_height != 0) { + image_height = unpack_params.image_height; + } + GLsizei image_bytes = row_bytes * image_height; + for (GLsizei image = 0; image < args.depth; ++image) { + GLsizei image_byte_offset = image * image_bytes; + for (GLsizei row = 0; row < args.height; ++row) { + GLsizei byte_offset = image_byte_offset + row * row_bytes; + const GLubyte* row_pixels = + reinterpret_cast<const GLubyte*>(args.pixels) + byte_offset; + glTexSubImage3D(args.target, args.level, args.xoffset, + row + args.yoffset, image + args.zoffset, args.width, 1, + 1, format, args.type, row_pixels); + } + } + } else { + for (GLsizei row = 0; row < args.height; ++row) { + GLsizei byte_offset = row * row_bytes; + const GLubyte* row_pixels = + reinterpret_cast<const GLubyte*>(args.pixels) + byte_offset; + glTexSubImage2D(args.target, args.level, args.xoffset, row + args.yoffset, + args.width, 1, format, args.type, row_pixels); + } + } + + // Restore unpack state + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_params.alignment); + glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_params.row_length); +} + GLenum TextureManager::AdjustTexInternalFormat(GLenum format) const { if (feature_info_->gl_version_info().is_desktop_core_profile) { const Texture::CompatibilitySwizzle* swizzle = diff --git a/chromium/gpu/command_buffer/service/texture_manager.h b/chromium/gpu/command_buffer/service/texture_manager.h index 2485146677a..6eca1fb8cf9 100644 --- a/chromium/gpu/command_buffer/service/texture_manager.h +++ b/chromium/gpu/command_buffer/service/texture_manager.h @@ -10,9 +10,11 @@ #include <algorithm> #include <list> +#include <memory> #include <set> #include <string> #include <vector> + #include "base/containers/hash_tables.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -151,12 +153,6 @@ class GPU_EXPORT Texture { owned_service_id_ = service_id; } - // Causes us to report |service_id| as our service id, but does not delete - // it when we are destroyed. Will rebind any OES_EXTERNAL texture units to - // our new service id in all contexts. If |service_id| is zero, then we - // revert to our original service id. - void SetUnownedServiceId(GLuint service_id); - // Returns the target this texure was first bound to or 0 if it has not // been bound. Once a texture is bound to a specific target it can never be // bound to a different target. @@ -179,19 +175,29 @@ class GPU_EXPORT Texture { bool GetLevelType( GLint target, GLint level, GLenum* type, GLenum* internal_format) const; - // Set the image for a particular level. + // Set the image for a particular level. If a GLStreamTextureImage was + // previously set with SetLevelStreamTextureImage(), this will reset + // |service_id_| back to |owned_service_id_|, removing the service id override + // set by the GLStreamTextureImage. void SetLevelImage(GLenum target, GLint level, gl::GLImage* image, ImageState state); - // Set the GLStreamTextureImage for a particular level. This is identical - // to SetLevelImage, but it also permits GetLevelStreamTextureImage to return - // the image. + // Set the GLStreamTextureImage for a particular level. This is like + // SetLevelImage, but it also makes it optional to override |service_id_| with + // a texture bound to the stream texture, and permits + // GetLevelStreamTextureImage to return the image. See + // SetStreamTextureServiceId() for the details of how |service_id| is used. void SetLevelStreamTextureImage(GLenum target, GLint level, GLStreamTextureImage* image, - ImageState state); + ImageState state, + GLuint service_id); + + // Set the ImageState for the image bound to the given level. + void SetLevelImageState(GLenum target, GLint level, ImageState state); + // Get the image associated with a particular level. Returns NULL if level // does not exist. @@ -246,6 +252,9 @@ class GPU_EXPORT Texture { return immutable_; } + // Return 0 if it's not immutable. + GLint GetImmutableLevels() const; + // 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; @@ -269,6 +278,8 @@ class GPU_EXPORT Texture { void ApplyFormatWorkarounds(FeatureInfo* feature_info); + bool EmulatingRGB(); + private: friend class MailboxManagerImpl; friend class MailboxManagerSync; @@ -335,8 +346,7 @@ class GPU_EXPORT Texture { GLStreamTextureImage* stream_texture_image, ImageState state); - // Helper for GetLevel*Image. Returns the LevelInfo for |target| and |level| - // if it's set, else NULL. + // Returns the LevelInfo for |target| and |level| if it's set, else NULL. const LevelInfo* GetLevelInfo(GLint target, GLint level) const; // Set the info for a particular level. @@ -351,6 +361,12 @@ class GPU_EXPORT Texture { GLenum type, const gfx::Rect& cleared_rect); + // Causes us to report |service_id| as our service id, but does not delete + // it when we are destroyed. Will rebind any OES_EXTERNAL texture units to + // our new service id in all contexts. If |service_id| is zero, then we + // revert to |owned_service_id_|. + void SetStreamTextureServiceId(GLuint service_id); + void MarkLevelAsInternalWorkaround(GLenum target, GLint level); // In GLES2 "texture complete" means it has all required mips for filtering @@ -488,6 +504,10 @@ class GPU_EXPORT Texture { // texture. void UpdateHasImages(); + // Updates the flag that indicates whether this texture requires RGB + // emulation. + void UpdateEmulatingRGB(); + // Increment the framebuffer state change count in all the managers // referencing this texture. void IncAllFramebufferStateChangeCount(); @@ -501,8 +521,7 @@ class GPU_EXPORT Texture { void IncrementManagerServiceIdGeneration(); // Return the service id of the texture that we will delete when we are - // destroyed. Normally, this is the same as service_id(), unless it is - // overridden by SetUnownedServiceId. + // destroyed. GLuint owned_service_id() const { return owned_service_id_; } GLenum GetCompatibilitySwizzleForChannel(GLenum channel); @@ -521,16 +540,14 @@ class GPU_EXPORT Texture { // one of refs_. TextureRef* memory_tracking_ref_; - // The id of the texure + // The id of the texture. GLuint service_id_; - // The id of the texture that we are responsible for deleting. Normally, - // this is the same as service_id_, unless a call to SetUnownedServiceId - // overrides it. In that case, we'll use the overridden service id (stored - // in |service_id_|) for all purposes except deleting the texture name. - // Whoever calls SetUnownedServiceId is assumed to handle deleting that id, - // and only after we are either deleted or told to stop using it via - // another call to SetUnownedServiceId. + // The id of the texture that we are responsible for deleting. Normally, this + // is the same as |service_id_|, unless a GLStreamTextureImage with its own + // service id is bound. In that case the GLStreamTextureImage service id is + // stored in |service_id_| and overrides the owned service id for all purposes + // except deleting the texture name. GLuint owned_service_id_; // Whether all renderable mips of this texture have been cleared. @@ -592,6 +609,8 @@ class GPU_EXPORT Texture { const CompatibilitySwizzle* compatibility_swizzle_; + bool emulating_rgb_; + DISALLOW_COPY_AND_ASSIGN(Texture); }; @@ -638,7 +657,7 @@ class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> { struct DecoderTextureState { // total_texture_upload_time automatically initialized to 0 in default // constructor. - explicit DecoderTextureState(const FeatureInfo::Workarounds& workarounds) + explicit DecoderTextureState(const GpuDriverBugWorkarounds& workarounds) : tex_image_failed(false), texture_upload_count(0), texsubimage_faster_than_teximage( @@ -647,7 +666,9 @@ struct DecoderTextureState { workarounds.force_cube_map_positive_x_allocation), force_cube_complete(workarounds.force_cube_complete), unpack_alignment_workaround_with_unpack_buffer( - workarounds.unpack_alignment_workaround_with_unpack_buffer) {} + workarounds.unpack_alignment_workaround_with_unpack_buffer), + unpack_overlapping_rows_separately_unpack_buffer( + workarounds.unpack_overlapping_rows_separately_unpack_buffer) {} // 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 @@ -663,6 +684,7 @@ struct DecoderTextureState { bool force_cube_map_positive_x_allocation; bool force_cube_complete; bool unpack_alignment_workaround_with_unpack_buffer; + bool unpack_overlapping_rows_separately_unpack_buffer; }; // This class keeps track of the textures and their sizes so we can do NPOT and @@ -703,6 +725,7 @@ class GPU_EXPORT TextureManager : public base::trace_event::MemoryDumpProvider { GLsizei max_cube_map_texture_size, GLsizei max_rectangle_texture_size, GLsizei max_3d_texture_size, + GLsizei max_array_texture_layers, bool use_default_textures); ~TextureManager() override; @@ -748,6 +771,10 @@ class GPU_EXPORT TextureManager : public base::trace_event::MemoryDumpProvider { } } + GLsizei max_array_texture_layers() const { + return max_array_texture_layers_; + } + // Returns the maxium number of levels a texture of the given size can have. static GLsizei ComputeMipMapCount(GLenum target, GLsizei width, @@ -915,7 +942,13 @@ class GPU_EXPORT TextureManager : public base::trace_event::MemoryDumpProvider { GLenum target, GLint level, GLStreamTextureImage* image, - Texture::ImageState state); + Texture::ImageState state, + GLuint service_id); + + void SetLevelImageState(TextureRef* ref, + GLenum target, + GLint level, + Texture::ImageState state); size_t GetSignatureSize() const; @@ -1063,11 +1096,26 @@ class GPU_EXPORT TextureManager : public base::trace_event::MemoryDumpProvider { TextureRef* texture_ref, const DoTexImageArguments& args); + // Reserve memory for the texture and set its attributes so it can be filled + // with TexSubImage. The image contents are undefined after this function, + // so make sure it's subsequently filled in its entirety. + void ReserveTexImageToBeFilled(DecoderTextureState* texture_state, + ContextState* state, + DecoderFramebufferState* framebuffer_state, + const char* function_name, + TextureRef* texture_ref, + const DoTexImageArguments& args); + void DoTexSubImageWithAlignmentWorkaround( DecoderTextureState* texture_state, ContextState* state, const DoTexSubImageArguments& args); + void DoTexSubImageRowByRowWorkaround(DecoderTextureState* texture_state, + ContextState* state, + const DoTexSubImageArguments& args, + const PixelStoreParams& unpack_params); + void StartTracking(TextureRef* texture); void StopTracking(TextureRef* texture); @@ -1083,7 +1131,7 @@ class GPU_EXPORT TextureManager : public base::trace_event::MemoryDumpProvider { TextureRef* ref); MemoryTypeTracker* GetMemTracker(); - scoped_ptr<MemoryTypeTracker> memory_type_tracker_; + std::unique_ptr<MemoryTypeTracker> memory_type_tracker_; MemoryTracker* memory_tracker_; scoped_refptr<FeatureInfo> feature_info_; @@ -1098,6 +1146,7 @@ class GPU_EXPORT TextureManager : public base::trace_event::MemoryDumpProvider { GLsizei max_cube_map_texture_size_; GLsizei max_rectangle_texture_size_; GLsizei max_3d_texture_size_; + GLsizei max_array_texture_layers_; GLint max_levels_; GLint max_cube_map_levels_; GLint max_3d_levels_; diff --git a/chromium/gpu/command_buffer/service/texture_manager_unittest.cc b/chromium/gpu/command_buffer/service/texture_manager_unittest.cc index 322e2dc3ae0..a615fbdfc48 100644 --- a/chromium/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/texture_manager_unittest.cc @@ -7,11 +7,11 @@ #include <stddef.h> #include <stdint.h> +#include <memory> #include <utility> #include "base/command_line.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/error_state_mock.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/framebuffer_manager.h" @@ -59,11 +59,12 @@ class TextureManagerTest : public GpuServiceTest { static const GLint kMaxCubeMapTextureSize = 8; static const GLint kMaxRectangleTextureSize = 32; static const GLint kMaxExternalTextureSize = 32; - static const GLint kMax3DTextureSize = 256; + static const GLint kMax3DTextureSize = 512; + static const GLint kMaxArrayTextureLayers = 256; static const GLint kMax2dLevels = 6; static const GLint kMaxCubeMapLevels = 4; static const GLint kMaxExternalLevels = 1; - static const GLint kMax3dLevels = 9; + static const GLint kMax3dLevels = 10; static const bool kUseDefaultTextures = false; TextureManagerTest() { @@ -71,7 +72,8 @@ class TextureManagerTest : public GpuServiceTest { // enabled without FeatureInfo::EnableES3Validators(). base::CommandLine command_line(0, nullptr); command_line.AppendSwitch(switches::kEnableUnsafeES3APIs); - feature_info_ = new FeatureInfo(command_line); + GpuDriverBugWorkarounds gpu_driver_bug_workaround(&command_line); + feature_info_ = new FeatureInfo(command_line, gpu_driver_bug_workaround); } ~TextureManagerTest() override {} @@ -85,6 +87,7 @@ class TextureManagerTest : public GpuServiceTest { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures)); TestHelper::SetupTextureManagerInitExpectations( gl_.get(), false, false, "", kUseDefaultTextures); @@ -123,8 +126,8 @@ class TextureManagerTest : public GpuServiceTest { } scoped_refptr<FeatureInfo> feature_info_; - scoped_ptr<TextureManager> manager_; - scoped_ptr<MockErrorState> error_state_; + std::unique_ptr<TextureManager> manager_; + std::unique_ptr<MockErrorState> error_state_; }; // GCC requires these declarations, but MSVC requires they not be present @@ -134,6 +137,7 @@ const GLint TextureManagerTest::kMaxCubeMapTextureSize; const GLint TextureManagerTest::kMaxRectangleTextureSize; const GLint TextureManagerTest::kMaxExternalTextureSize; const GLint TextureManagerTest::kMax3DTextureSize; +const GLint TextureManagerTest::kMaxArrayTextureLayers; const GLint TextureManagerTest::kMax2dLevels; const GLint TextureManagerTest::kMaxCubeMapLevels; const GLint TextureManagerTest::kMaxExternalLevels; @@ -166,6 +170,7 @@ class GLStreamTextureImageStub : public GLStreamTextureImage { void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, uint64_t process_tracing_id, const std::string& dump_name) override {} + bool EmulatingRGB() const override { return false; } void GetTextureMatrix(float matrix[16]) override {} protected: @@ -244,6 +249,7 @@ TEST_F(TextureManagerTest, UseDefaultTexturesTrue) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, use_default_textures); manager.Initialize(); @@ -265,6 +271,7 @@ TEST_F(TextureManagerTest, UseDefaultTexturesFalse) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, use_default_textures); manager.Initialize(); @@ -287,6 +294,7 @@ TEST_F(TextureManagerTest, UseDefaultTexturesTrueES3) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, use_default_textures); manager.Initialize(); @@ -307,6 +315,7 @@ TEST_F(TextureManagerTest, UseDefaultTexturesFalseES3) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, use_default_textures); manager.Initialize(); @@ -325,6 +334,7 @@ TEST_F(TextureManagerTest, TextureUsageExt) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures); manager.Initialize(); const GLuint kClient1Id = 1; @@ -353,6 +363,7 @@ TEST_F(TextureManagerTest, Destroy) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures); manager.Initialize(); // Check we can create texture. @@ -413,6 +424,7 @@ TEST_F(TextureManagerTest, MaxValues) { manager_->MaxSizeForTarget(GL_TEXTURE_EXTERNAL_OES)); EXPECT_EQ(kMaxTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_2D_ARRAY)); EXPECT_EQ(kMax3DTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_3D)); + EXPECT_EQ(kMaxArrayTextureLayers, manager_->max_array_texture_layers()); } TEST_F(TextureManagerTest, ValidForTarget) { @@ -440,6 +452,19 @@ TEST_F(TextureManagerTest, ValidForTarget) { // Check NPOT height on level 1 EXPECT_FALSE(manager_->ValidForTarget(GL_TEXTURE_2D, 1, 2, 5, 1)); + // check array textures. + EXPECT_TRUE(manager_->ValidForTarget( + GL_TEXTURE_2D_ARRAY, 0, kMaxTextureSize, kMaxTextureSize, + kMaxArrayTextureLayers)); + EXPECT_FALSE(manager_->ValidForTarget( + GL_TEXTURE_2D_ARRAY, 1, kMaxTextureSize, kMaxTextureSize, + kMaxArrayTextureLayers)); + EXPECT_TRUE(manager_->ValidForTarget( + GL_TEXTURE_2D_ARRAY, 1, kMaxTextureSize / 2, kMaxTextureSize / 2, + kMaxArrayTextureLayers)); + EXPECT_TRUE(manager_->ValidForTarget( + GL_TEXTURE_2D_ARRAY, kMax2dLevels - 1, 0, 0, kMaxArrayTextureLayers)); + // check cube EXPECT_TRUE(manager_->ValidForTarget( GL_TEXTURE_CUBE_MAP, 0, @@ -497,6 +522,7 @@ TEST_F(TextureManagerTest, ValidForTargetNPOT) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures); // Check NPOT width on level 0 EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 0, 5, 2, 1)); @@ -509,48 +535,6 @@ TEST_F(TextureManagerTest, ValidForTargetNPOT) { manager.Destroy(false); } -TEST_F(TextureManagerTest, OverrideServiceID) { - // Create a texture. - const GLuint kClientId = 1; - const GLuint kServiceId = 11; - manager_->CreateTexture(kClientId, kServiceId); - scoped_refptr<TextureRef> texture_ref(manager_->GetTexture(kClientId)); - manager_->SetTarget(texture_ref.get(), GL_TEXTURE_EXTERNAL_OES); - - Texture* texture = texture_ref->texture(); - GLuint owned_service_id = TextureTestHelper::owned_service_id(texture); - GLuint service_id = texture->service_id(); - // Initially, the texture should use the same service id that it owns. - EXPECT_EQ(owned_service_id, service_id); - - // Override the service_id. - GLuint unowned_service_id = service_id + 1; - texture->SetUnownedServiceId(unowned_service_id); - - // Make sure that service_id() changed but owned_service_id() didn't. - EXPECT_EQ(unowned_service_id, texture->service_id()); - EXPECT_EQ(owned_service_id, TextureTestHelper::owned_service_id(texture)); - - // Undo the override. - texture->SetUnownedServiceId(0); - - // The service IDs should be back as they were. - EXPECT_EQ(service_id, texture->service_id()); - EXPECT_EQ(owned_service_id, TextureTestHelper::owned_service_id(texture)); - - // Override again, so that we can check delete behavior. - texture->SetUnownedServiceId(unowned_service_id); - EXPECT_EQ(unowned_service_id, texture->service_id()); - EXPECT_EQ(owned_service_id, TextureTestHelper::owned_service_id(texture)); - - // Remove the texture. It should delete the texture id that it owns, even - // though it is overridden. - EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(owned_service_id))) - .Times(1) - .RetiresOnSaturation(); - manager_->RemoveTexture(kClientId); -} - TEST_F(TextureManagerTest, AlphaLuminanceCompatibilityProfile) { const GLuint kClientId = 1; const GLuint kServiceId = 11; @@ -564,6 +548,7 @@ TEST_F(TextureManagerTest, AlphaLuminanceCompatibilityProfile) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures); manager.Initialize(); @@ -608,6 +593,7 @@ TEST_F(TextureManagerTest, AlphaLuminanceCoreProfileEmulation) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures); manager.Initialize(); @@ -700,7 +686,8 @@ class TextureTestBase : public GpuServiceTest { static const GLint kMaxTextureSize = 32; static const GLint kMaxCubeMapTextureSize = 8; static const GLint kMaxRectangleTextureSize = 32; - static const GLint kMax3DTextureSize = 256; + static const GLint kMax3DTextureSize = 512; + static const GLint kMaxArrayTextureLayers = 256; static const GLint kMax2dLevels = 6; static const GLint kMaxCubeMapLevels = 4; static const GLuint kClient1Id = 1; @@ -727,6 +714,7 @@ class TextureTestBase : public GpuServiceTest { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures)); decoder_.reset(new ::testing::StrictMock<gles2::MockGLES2Decoder>()); error_state_.reset(new ::testing::StrictMock<gles2::MockErrorState>()); @@ -760,10 +748,10 @@ class TextureTestBase : public GpuServiceTest { texture_ref, pname, value, error); } - scoped_ptr<MockGLES2Decoder> decoder_; - scoped_ptr<MockErrorState> error_state_; + std::unique_ptr<MockGLES2Decoder> decoder_; + std::unique_ptr<MockErrorState> error_state_; scoped_refptr<FeatureInfo> feature_info_; - scoped_ptr<TextureManager> manager_; + std::unique_ptr<TextureManager> manager_; scoped_refptr<TextureRef> texture_ref_; }; @@ -1032,6 +1020,7 @@ TEST_F(TextureTest, NPOT2DNPOTOK) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); @@ -1333,6 +1322,7 @@ TEST_F(TextureTest, FloatNotLinear) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); @@ -1365,6 +1355,7 @@ TEST_F(TextureTest, FloatLinear) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); @@ -1389,6 +1380,7 @@ TEST_F(TextureTest, HalfFloatNotLinear) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); @@ -1421,6 +1413,7 @@ TEST_F(TextureTest, HalfFloatLinear) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); @@ -1445,6 +1438,7 @@ TEST_F(TextureTest, EGLImageExternal) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); @@ -1467,6 +1461,7 @@ TEST_F(TextureTest, DepthTexture) { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, + kMaxArrayTextureLayers, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); @@ -1611,6 +1606,10 @@ TEST_F(TextureTest, SafeUnsafe) { TEST_F(TextureTest, ClearTexture) { EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _)) .WillRepeatedly(Return(true)); + // The code path taken when IsCompressedTextureFormat returns true + // is covered best by the WebGL 2.0 conformance tests. + EXPECT_CALL(*decoder_, IsCompressedTextureFormat(_)) + .WillRepeatedly(Return(false)); 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, gfx::Rect()); @@ -1710,13 +1709,15 @@ TEST_F(TextureTest, GetLevelStreamTextureImage) { scoped_refptr<GLStreamTextureImage> image(new GLStreamTextureImageStub); manager_->SetLevelStreamTextureImage(texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES, 0, image.get(), - Texture::BOUND); + Texture::BOUND, 0); EXPECT_FALSE(texture->GetLevelImage(GL_TEXTURE_EXTERNAL_OES, 0) == NULL); EXPECT_FALSE( texture->GetLevelStreamTextureImage(GL_TEXTURE_EXTERNAL_OES, 0) == NULL); + // Replace it as a normal image. + scoped_refptr<gl::GLImage> image2(new gl::GLImageStub); manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES, 0, - image.get(), Texture::BOUND); + image2.get(), Texture::BOUND); EXPECT_FALSE(texture->GetLevelImage(GL_TEXTURE_EXTERNAL_OES, 0) == NULL); EXPECT_TRUE(texture->GetLevelStreamTextureImage(GL_TEXTURE_EXTERNAL_OES, 0) == NULL); @@ -1724,7 +1725,7 @@ TEST_F(TextureTest, GetLevelStreamTextureImage) { // Image should be reset when SetLevelInfo is called. manager_->SetLevelStreamTextureImage(texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES, 0, image.get(), - Texture::UNBOUND); + Texture::UNBOUND, 0); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); @@ -1733,6 +1734,70 @@ TEST_F(TextureTest, GetLevelStreamTextureImage) { NULL); } +TEST_F(TextureTest, SetLevelImageState) { + manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); + Texture* texture = texture_ref_->texture(); + // Set image, initially BOUND. + scoped_refptr<gl::GLImage> image(new gl::GLImageStub); + manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_2D, 0, image.get(), + Texture::BOUND); + Texture::ImageState state; + texture->GetLevelImage(GL_TEXTURE_2D, 0, &state); + EXPECT_EQ(state, Texture::BOUND); + // Change the state. + texture->SetLevelImageState(GL_TEXTURE_2D, 0, Texture::COPIED); + texture->GetLevelImage(GL_TEXTURE_2D, 0, &state); + EXPECT_EQ(state, Texture::COPIED); +} + +TEST_F(TextureTest, SetStreamTextureImageServiceID) { + manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES, 0, + GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + gfx::Rect(2, 2)); + Texture* texture = texture_ref_->texture(); + + GLuint owned_service_id = TextureTestHelper::owned_service_id(texture); + GLuint service_id = texture->service_id(); + // Initially, the texture should use the same service id that it owns. + EXPECT_EQ(owned_service_id, service_id); + + // Override the service_id. + GLuint stream_texture_service_id = service_id + 1; + scoped_refptr<GLStreamTextureImage> image(new GLStreamTextureImageStub); + manager_->SetLevelStreamTextureImage( + texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES, 0, image.get(), + Texture::BOUND, stream_texture_service_id); + + // Make sure that service_id() changed but owned_service_id() didn't. + EXPECT_EQ(stream_texture_service_id, texture->service_id()); + EXPECT_EQ(owned_service_id, TextureTestHelper::owned_service_id(texture)); + + // Undo the override. + manager_->SetLevelStreamTextureImage(texture_ref_.get(), + GL_TEXTURE_EXTERNAL_OES, 0, image.get(), + Texture::BOUND, 0); + + // The service IDs should be back as they were. + EXPECT_EQ(service_id, texture->service_id()); + EXPECT_EQ(owned_service_id, TextureTestHelper::owned_service_id(texture)); + + // Override again, so that we can check delete behavior. + manager_->SetLevelStreamTextureImage( + texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES, 0, image.get(), + Texture::BOUND, stream_texture_service_id); + + // Remove the Texture. It should delete the texture id that it owns, even + // though it is overridden. + EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(owned_service_id))) + .Times(1) + .RetiresOnSaturation(); + manager_->RemoveTexture(kClient1Id); + texture_ref_ = nullptr; +} + namespace { bool InSet(std::set<std::string>* string_set, const std::string& str) { @@ -2037,6 +2102,10 @@ TEST_F(ProduceConsumeTextureTest, ProduceConsumeClearRectangle) { GetLevelInfo(restored_texture.get(), GL_TEXTURE_RECTANGLE_ARB, 0)); EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _)) .WillRepeatedly(Return(true)); + // The code path taken when IsCompressedTextureFormat returns true + // is covered best by the WebGL 2.0 conformance tests. + EXPECT_CALL(*decoder_, IsCompressedTextureFormat(_)) + .WillRepeatedly(Return(false)); EXPECT_TRUE(manager_->ClearTextureLevel( decoder_.get(), restored_texture.get(), GL_TEXTURE_RECTANGLE_ARB, 0)); } @@ -2165,6 +2234,7 @@ class SharedTextureTest : public GpuServiceTest { TextureManagerTest::kMaxCubeMapTextureSize, TextureManagerTest::kMaxRectangleTextureSize, TextureManagerTest::kMax3DTextureSize, + TextureManagerTest::kMaxArrayTextureLayers, kUseDefaultTextures)); memory_tracker2_ = new CountingMemoryTracker; texture_manager2_.reset( @@ -2174,6 +2244,7 @@ class SharedTextureTest : public GpuServiceTest { TextureManagerTest::kMaxCubeMapTextureSize, TextureManagerTest::kMaxRectangleTextureSize, TextureManagerTest::kMax3DTextureSize, + TextureManagerTest::kMaxArrayTextureLayers, kUseDefaultTextures)); TestHelper::SetupTextureManagerInitExpectations( gl_.get(), false, false, "", kUseDefaultTextures); @@ -2194,9 +2265,9 @@ class SharedTextureTest : public GpuServiceTest { protected: scoped_refptr<FeatureInfo> feature_info_; scoped_refptr<CountingMemoryTracker> memory_tracker1_; - scoped_ptr<TextureManager> texture_manager1_; + std::unique_ptr<TextureManager> texture_manager1_; scoped_refptr<CountingMemoryTracker> memory_tracker2_; - scoped_ptr<TextureManager> texture_manager2_; + std::unique_ptr<TextureManager> texture_manager2_; }; TEST_F(SharedTextureTest, DeleteTextures) { diff --git a/chromium/gpu/command_buffer/service/transfer_buffer_manager.cc b/chromium/gpu/command_buffer/service/transfer_buffer_manager.cc index f9db75e062d..22752bacc2e 100644 --- a/chromium/gpu/command_buffer/service/transfer_buffer_manager.cc +++ b/chromium/gpu/command_buffer/service/transfer_buffer_manager.cc @@ -7,12 +7,12 @@ #include <stdint.h> #include <limits> +#include <memory> #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/process/process_handle.h" #include "base/strings/stringprintf.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_allocator_dump.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/process_memory_dump.h" @@ -58,7 +58,7 @@ bool TransferBufferManager::Initialize() { bool TransferBufferManager::RegisterTransferBuffer( int32_t id, - scoped_ptr<BufferBacking> buffer_backing) { + std::unique_ptr<BufferBacking> buffer_backing) { if (id <= 0) { DVLOG(0) << "Cannot register transfer buffer with non-positive ID."; return false; diff --git a/chromium/gpu/command_buffer/service/transfer_buffer_manager.h b/chromium/gpu/command_buffer/service/transfer_buffer_manager.h index 884316054f1..31489785881 100644 --- a/chromium/gpu/command_buffer/service/transfer_buffer_manager.h +++ b/chromium/gpu/command_buffer/service/transfer_buffer_manager.h @@ -8,6 +8,7 @@ #include <stddef.h> #include <stdint.h> +#include <memory> #include <set> #include <vector> @@ -26,8 +27,9 @@ class MemoryTracker; class GPU_EXPORT TransferBufferManagerInterface : public base::RefCounted<TransferBufferManagerInterface> { public: - virtual bool RegisterTransferBuffer(int32_t id, - scoped_ptr<BufferBacking> buffer) = 0; + virtual bool RegisterTransferBuffer( + int32_t id, + std::unique_ptr<BufferBacking> buffer) = 0; virtual void DestroyTransferBuffer(int32_t id) = 0; virtual scoped_refptr<Buffer> GetTransferBuffer(int32_t id) = 0; @@ -50,7 +52,7 @@ class GPU_EXPORT TransferBufferManager bool Initialize(); bool RegisterTransferBuffer( int32_t id, - scoped_ptr<BufferBacking> buffer_backing) override; + std::unique_ptr<BufferBacking> buffer_backing) override; void DestroyTransferBuffer(int32_t id) override; scoped_refptr<Buffer> GetTransferBuffer(int32_t id) override; 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 56edaedbf3a..1e12ae68a64 100644 --- a/chromium/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc @@ -6,7 +6,8 @@ #include <stddef.h> -#include "base/memory/scoped_ptr.h" +#include <memory> + #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -40,10 +41,10 @@ TEST_F(TransferBufferManagerTest, OutOfRangeHandleMapsToNull) { } TEST_F(TransferBufferManagerTest, CanRegisterTransferBuffer) { - scoped_ptr<base::SharedMemory> shm(new base::SharedMemory()); + std::unique_ptr<base::SharedMemory> shm(new base::SharedMemory()); shm->CreateAndMapAnonymous(kBufferSize); base::SharedMemory* shm_raw_pointer = shm.get(); - scoped_ptr<SharedMemoryBufferBacking> backing( + std::unique_ptr<SharedMemoryBufferBacking> backing( new SharedMemoryBufferBacking(std::move(shm), kBufferSize)); SharedMemoryBufferBacking* backing_raw_ptr = backing.get(); @@ -63,14 +64,14 @@ class FakeBufferBacking : public BufferBacking { return reinterpret_cast<void*>(0xBADF00D0); } size_t GetSize() const override { return 42; } - static scoped_ptr<BufferBacking> Make() { - return scoped_ptr<BufferBacking>(new FakeBufferBacking); + static std::unique_ptr<BufferBacking> Make() { + return std::unique_ptr<BufferBacking>(new FakeBufferBacking); } }; TEST_F(TransferBufferManagerTest, CanDestroyTransferBuffer) { EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer( - 1, scoped_ptr<BufferBacking>(new FakeBufferBacking))); + 1, std::unique_ptr<BufferBacking>(new FakeBufferBacking))); transfer_buffer_manager_->DestroyTransferBuffer(1); scoped_refptr<Buffer> registered = transfer_buffer_manager_->GetTransferBuffer(1); @@ -106,7 +107,7 @@ TEST_F(TransferBufferManagerTest, CannotRegisterNullTransferBuffer) { } TEST_F(TransferBufferManagerTest, CannotRegisterNegativeTransferBufferId) { - scoped_ptr<base::SharedMemory> shm(new base::SharedMemory()); + std::unique_ptr<base::SharedMemory> shm(new base::SharedMemory()); shm->CreateAndMapAnonymous(kBufferSize); EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer( -1, FakeBufferBacking::Make())); diff --git a/chromium/gpu/command_buffer/service/transform_feedback_manager.cc b/chromium/gpu/command_buffer/service/transform_feedback_manager.cc new file mode 100644 index 00000000000..e474c0bc07b --- /dev/null +++ b/chromium/gpu/command_buffer/service/transform_feedback_manager.cc @@ -0,0 +1,125 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/transform_feedback_manager.h" + +#include "gpu/command_buffer/service/buffer_manager.h" +#include "ui/gl/gl_version_info.h" + +namespace gpu { +namespace gles2 { + +TransformFeedback::TransformFeedback(TransformFeedbackManager* manager, + GLuint service_id) + : IndexedBufferBindingHost( + manager->max_transform_feedback_separate_attribs(), + manager->needs_emulation()), + manager_(manager), + service_id_(service_id), + has_been_bound_(false), + active_(false), + paused_(false), + primitive_mode_(GL_NONE) { + DCHECK_LT(0u, service_id); +} + +TransformFeedback::~TransformFeedback() { + if (!manager_->lost_context()) { + glDeleteTransformFeedbacks(1, &service_id_); + } +} + +void TransformFeedback::DoBindTransformFeedback(GLenum target) { + DCHECK_LT(0u, service_id_); + glBindTransformFeedback(target, service_id_); + has_been_bound_ = true; + OnBindHost(target); + if (active_ && !paused_) { + // This could only happen during virtual context switching. + // Otherwise the validation should generate a GL error without calling + // into this function. + glResumeTransformFeedback(); + } +} + +void TransformFeedback::DoBeginTransformFeedback(GLenum primitive_mode) { + DCHECK(!active_); + DCHECK(primitive_mode == GL_POINTS || + primitive_mode == GL_LINES || + primitive_mode == GL_TRIANGLES); + glBeginTransformFeedback(primitive_mode); + active_ = true; + primitive_mode_ = primitive_mode; +} + +void TransformFeedback::DoEndTransformFeedback() { + DCHECK(active_); + glEndTransformFeedback(); + active_ = false; + paused_ = false; +} + +void TransformFeedback::DoPauseTransformFeedback() { + DCHECK(active_ && !paused_); + glPauseTransformFeedback(); + paused_ = true; +} + +void TransformFeedback::DoResumeTransformFeedback() { + DCHECK(active_ && paused_); + glResumeTransformFeedback(); + paused_ = false; +} + + +TransformFeedbackManager::TransformFeedbackManager( + GLuint max_transform_feedback_separate_attribs, bool needs_emulation) + : max_transform_feedback_separate_attribs_( + max_transform_feedback_separate_attribs), + needs_emulation_(needs_emulation), + lost_context_(false) { +} + +TransformFeedbackManager::~TransformFeedbackManager() { + DCHECK(transform_feedbacks_.empty()); +} + +void TransformFeedbackManager::Destroy() { + transform_feedbacks_.clear(); +} + +TransformFeedback* TransformFeedbackManager::CreateTransformFeedback( + GLuint client_id, GLuint service_id) { + scoped_refptr<TransformFeedback> transform_feedback( + new TransformFeedback(this, service_id)); + auto result = transform_feedbacks_.insert( + std::make_pair(client_id, transform_feedback)); + DCHECK(result.second); + return result.first->second.get(); +} + +TransformFeedback* TransformFeedbackManager::GetTransformFeedback( + GLuint client_id) { + if (client_id == 0) { + return nullptr; + } + auto it = transform_feedbacks_.find(client_id); + return it != transform_feedbacks_.end() ? it->second.get() : nullptr; +} + +void TransformFeedbackManager::RemoveTransformFeedback(GLuint client_id) { + if (client_id) { + transform_feedbacks_.erase(client_id); + } +} + +void TransformFeedbackManager::RemoveBoundBuffer(Buffer* buffer) { + for (auto iter = transform_feedbacks_.begin(); + iter != transform_feedbacks_.end(); ++iter) { + iter->second->RemoveBoundBuffer(buffer); + } +} + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/transform_feedback_manager.h b/chromium/gpu/command_buffer/service/transform_feedback_manager.h new file mode 100644 index 00000000000..8162d2ffcb9 --- /dev/null +++ b/chromium/gpu/command_buffer/service/transform_feedback_manager.h @@ -0,0 +1,131 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_TRANSFORM_FEEDBACK_MANAGER_H_ +#define GPU_COMMAND_BUFFER_SERVICE_TRANSFORM_FEEDBACK_MANAGER_H_ + +#include <vector> + +#include "base/containers/hash_tables.h" +#include "base/memory/ref_counted.h" +#include "gpu/command_buffer/service/gl_utils.h" +#include "gpu/command_buffer/service/indexed_buffer_binding_host.h" +#include "gpu/gpu_export.h" + +namespace gfx { +struct GLVersionInfo; +}; + +namespace gpu { +namespace gles2 { + +class Buffer; +class TransformFeedbackManager; + +// Info about TransformFeedbacks currently in the system. +class GPU_EXPORT TransformFeedback : public IndexedBufferBindingHost { + public: + TransformFeedback(TransformFeedbackManager* manager, GLuint service_id); + + // All the following functions do state update and call the underlying GL + // function. All validations have been done already and the GL function is + // guaranteed to succeed. + void DoBindTransformFeedback(GLenum target); + void DoBeginTransformFeedback(GLenum primitive_mode); + void DoEndTransformFeedback(); + void DoPauseTransformFeedback(); + void DoResumeTransformFeedback(); + + GLuint service_id() const { + return service_id_; + } + + bool has_been_bound() const { + return has_been_bound_; + } + + bool active() const { + return active_; + } + + bool paused() const { + return paused_; + } + + GLenum primitive_mode() const { + return primitive_mode_; + } + + private: + ~TransformFeedback() override; + + // The manager that owns this Buffer. + TransformFeedbackManager* manager_; + + GLuint service_id_; + + bool has_been_bound_; + + bool active_; + bool paused_; + + GLenum primitive_mode_; +}; + +// This class keeps tracks of the transform feedbacks and their states. +class GPU_EXPORT TransformFeedbackManager { + public: + // |needs_emulation| is true on Desktop GL 4.1 or lower. + TransformFeedbackManager(GLuint max_transform_feedback_separate_attribs, + bool needs_emulation); + ~TransformFeedbackManager(); + + void MarkContextLost() { + lost_context_ = true; + } + + // Must call before destruction. + void Destroy(); + + // Creates a TransformFeedback from the given client/service IDs and + // insert it into the list. + TransformFeedback* CreateTransformFeedback( + GLuint client_id, GLuint service_id); + + TransformFeedback* GetTransformFeedback(GLuint client_id); + + // Removes a TransformFeedback info for the given client ID. + void RemoveTransformFeedback(GLuint client_id); + + void RemoveBoundBuffer(Buffer* buffer); + + GLuint max_transform_feedback_separate_attribs() const { + return max_transform_feedback_separate_attribs_; + } + + bool needs_emulation() const { + return needs_emulation_; + } + + bool lost_context() const { + return lost_context_; + } + + private: + // Info for each transform feedback in the system. + base::hash_map<GLuint, + scoped_refptr<TransformFeedback> > transform_feedbacks_; + + GLuint max_transform_feedback_separate_attribs_; + + bool needs_emulation_; + bool lost_context_; + + DISALLOW_COPY_AND_ASSIGN(TransformFeedbackManager); +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_TRANSFORM_FEEDBACK_MANAGER_H_ diff --git a/chromium/gpu/command_buffer/service/transform_feedback_manager_unittest.cc b/chromium/gpu/command_buffer/service/transform_feedback_manager_unittest.cc new file mode 100644 index 00000000000..47e879f459f --- /dev/null +++ b/chromium/gpu/command_buffer/service/transform_feedback_manager_unittest.cc @@ -0,0 +1,63 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gpu_service_test.h" +#include "gpu/command_buffer/service/test_helper.h" +#include "gpu/command_buffer/service/transform_feedback_manager.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_mock.h" + +using ::testing::_; + +namespace gpu { +namespace gles2 { + +namespace { +const GLuint kTransformFeedbackClientId = 76; +const GLuint kTransformFeedbackServiceId = 1076; +} // anonymous + +class TransformFeedbackManagerTest : public GpuServiceTest { + public: + TransformFeedbackManagerTest() { + } + + ~TransformFeedbackManagerTest() override {} + + protected: + void SetUp() override { + const GLuint kMaxTransformFeedbackSeparateAttribs = 16; + GpuServiceTest::SetUpWithGLVersion("4.1", ""); + manager_.reset(new TransformFeedbackManager( + kMaxTransformFeedbackSeparateAttribs, true)); + } + + void TearDown() override { + manager_.reset(); + GpuServiceTest::TearDown(); + } + + std::unique_ptr<TransformFeedbackManager> manager_; +}; + +TEST_F(TransformFeedbackManagerTest, LifeTime) { + manager_->CreateTransformFeedback( + kTransformFeedbackClientId, kTransformFeedbackServiceId); + scoped_refptr<TransformFeedback> transform_feedback = + manager_->GetTransformFeedback(kTransformFeedbackClientId); + EXPECT_TRUE(transform_feedback.get()); + + manager_->RemoveTransformFeedback(kTransformFeedbackClientId); + EXPECT_FALSE(manager_->GetTransformFeedback(kTransformFeedbackClientId)); + + EXPECT_CALL(*gl_, DeleteTransformFeedbacks(1, _)) + .Times(1) + .RetiresOnSaturation(); + transform_feedback = nullptr; +} + +} // namespace gles2 +} // namespace gpu + + diff --git a/chromium/gpu/command_buffer/service/valuebuffer_manager.cc b/chromium/gpu/command_buffer/service/valuebuffer_manager.cc deleted file mode 100644 index d2af500589d..00000000000 --- a/chromium/gpu/command_buffer/service/valuebuffer_manager.cc +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdint.h> - -#include "gpu/command_buffer/service/gl_utils.h" -#include "gpu/command_buffer/service/program_manager.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" - -namespace gpu { -namespace gles2 { - -SubscriptionRefSet::Observer::~Observer() { -} - -SubscriptionRefSet::SubscriptionRefSet() { -} - -SubscriptionRefSet::~SubscriptionRefSet() { - // Make sure no valuebuffers are still holding references to targets - DCHECK(reference_set_.empty()); -} - -void SubscriptionRefSet::AddSubscription(unsigned int target) { - RefSet::iterator it = reference_set_.find(target); - if (it == reference_set_.end()) { - reference_set_.insert(std::make_pair(target, 1)); - FOR_EACH_OBSERVER(Observer, observers_, OnAddSubscription(target)); - } else { - ++it->second; - } -} - -void SubscriptionRefSet::RemoveSubscription(unsigned int target) { - RefSet::iterator it = reference_set_.find(target); - DCHECK(it != reference_set_.end()); - if (it->second == 1) { - reference_set_.erase(it); - FOR_EACH_OBSERVER(Observer, observers_, OnRemoveSubscription(target)); - } else { - --it->second; - } -} - -void SubscriptionRefSet::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void SubscriptionRefSet::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - -Valuebuffer::Valuebuffer(ValuebufferManager* manager, unsigned int client_id) - : manager_(manager), client_id_(client_id), has_been_bound_(false) { - manager_->StartTracking(this); - active_state_map_ = new ValueStateMap(); -} - -Valuebuffer::~Valuebuffer() { - if (manager_) { - for (SubscriptionSet::const_iterator it = subscriptions_.begin(); - it != subscriptions_.end(); ++it) { - manager_->NotifyRemoveSubscription(*it); - } - manager_->StopTracking(this); - manager_ = NULL; - } -} - -void Valuebuffer::AddSubscription(unsigned int subscription) { - if (subscriptions_.find(subscription) == subscriptions_.end()) { - subscriptions_.insert(subscription); - manager_->NotifyAddSubscription(subscription); - } -} - -void Valuebuffer::RemoveSubscription(unsigned int subscription) { - SubscriptionSet::iterator it = subscriptions_.find(subscription); - if (subscriptions_.find(subscription) != subscriptions_.end()) { - subscriptions_.erase(it); - manager_->NotifyRemoveSubscription(subscription); - } -} - -bool Valuebuffer::IsSubscribed(unsigned int subscription) { - return subscriptions_.find(subscription) != subscriptions_.end(); -} - -const ValueState* Valuebuffer::GetState(unsigned int target) const { - return active_state_map_->GetState(target); -} - -void Valuebuffer::UpdateState(const ValueStateMap* pending_state) { - DCHECK(pending_state); - for (SubscriptionSet::const_iterator it = subscriptions_.begin(); - it != subscriptions_.end(); ++it) { - const ValueState *state = pending_state->GetState(*it); - if (state != NULL) { - active_state_map_->UpdateState(*it, *state); - } - } -} - -ValuebufferManager::ValuebufferManager(SubscriptionRefSet* ref_set, - ValueStateMap* state_map) - : valuebuffer_count_(0), - pending_state_map_(state_map), - subscription_ref_set_(ref_set) { -} - -ValuebufferManager::~ValuebufferManager() { - DCHECK(valuebuffer_map_.empty()); - // If this triggers, that means something is keeping a reference to - // a Valuebuffer belonging to this. - CHECK_EQ(valuebuffer_count_, 0u); -} - -void ValuebufferManager::Destroy() { - valuebuffer_map_.clear(); -} - -void ValuebufferManager::StartTracking(Valuebuffer* /* valuebuffer */) { - ++valuebuffer_count_; -} - -void ValuebufferManager::StopTracking(Valuebuffer* /* valuebuffer */) { - --valuebuffer_count_; -} - -void ValuebufferManager::NotifyAddSubscription(unsigned int target) { - subscription_ref_set_->AddSubscription(target); -} -void ValuebufferManager::NotifyRemoveSubscription(unsigned int target) { - subscription_ref_set_->RemoveSubscription(target); -} - -void ValuebufferManager::CreateValuebuffer(unsigned int client_id) { - scoped_refptr<Valuebuffer> valuebuffer(new Valuebuffer(this, client_id)); - std::pair<ValuebufferMap::iterator, bool> result = - valuebuffer_map_.insert(std::make_pair(client_id, valuebuffer)); - DCHECK(result.second); -} - -Valuebuffer* ValuebufferManager::GetValuebuffer(unsigned int client_id) { - ValuebufferMap::iterator it = valuebuffer_map_.find(client_id); - return it != valuebuffer_map_.end() ? it->second.get() : NULL; -} - -void ValuebufferManager::RemoveValuebuffer(unsigned int client_id) { - ValuebufferMap::iterator it = valuebuffer_map_.find(client_id); - if (it != valuebuffer_map_.end()) { - Valuebuffer* valuebuffer = it->second.get(); - valuebuffer->MarkAsDeleted(); - valuebuffer_map_.erase(it); - } -} - -void ValuebufferManager::UpdateValuebufferState(Valuebuffer* valuebuffer) { - DCHECK(valuebuffer); - valuebuffer->UpdateState(pending_state_map_.get()); -} - -uint32_t ValuebufferManager::ApiTypeForSubscriptionTarget(unsigned int target) { - switch (target) { - case GL_MOUSE_POSITION_CHROMIUM: - return Program::kUniform2i; - } - NOTREACHED() << "Unhandled uniform subscription target " << target; - return Program::kUniformNone; -} - -} // namespace gles2 -} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/valuebuffer_manager.h b/chromium/gpu/command_buffer/service/valuebuffer_manager.h deleted file mode 100644 index 0d6782d7538..00000000000 --- a/chromium/gpu/command_buffer/service/valuebuffer_manager.h +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_COMMAND_BUFFER_SERVICE_VALUEBUFFER_MANAGER_H_ -#define GPU_COMMAND_BUFFER_SERVICE_VALUEBUFFER_MANAGER_H_ - -#include <stdint.h> - -#include "base/containers/hash_tables.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "gpu/command_buffer/common/value_state.h" -#include "gpu/gpu_export.h" - -namespace gpu { -class GpuChannel; -} - -namespace gpu { -namespace gles2 { - -class ValuebufferManager; - -class GPU_EXPORT SubscriptionRefSet - : public base::RefCounted<SubscriptionRefSet> { - public: - class GPU_EXPORT Observer { - public: - virtual ~Observer(); - - virtual void OnAddSubscription(unsigned int target) = 0; - virtual void OnRemoveSubscription(unsigned int target) = 0; - }; - - SubscriptionRefSet(); - - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); - - protected: - virtual ~SubscriptionRefSet(); - - private: - friend class base::RefCounted<SubscriptionRefSet>; - friend class ValuebufferManager; - - typedef base::hash_map<unsigned int, int> RefSet; - - void AddSubscription(unsigned int target); - void RemoveSubscription(unsigned int target); - - RefSet reference_set_; - - base::ObserverList<Observer, true> observers_; - - DISALLOW_COPY_AND_ASSIGN(SubscriptionRefSet); -}; - -class GPU_EXPORT Valuebuffer : public base::RefCounted<Valuebuffer> { - public: - Valuebuffer(ValuebufferManager* manager, unsigned int client_id); - - unsigned int client_id() const { return client_id_; } - - bool IsDeleted() const { return client_id_ == 0; } - - void MarkAsValid() { has_been_bound_ = true; } - - bool IsValid() const { return has_been_bound_ && !IsDeleted(); } - - void AddSubscription(unsigned int subscription); - void RemoveSubscription(unsigned int subscription); - - // Returns true if this Valuebuffer is subscribed to subscription - bool IsSubscribed(unsigned int subscription); - - // Returns the active state for a given target in this Valuebuffer - // returns NULL if target state doesn't exist - const ValueState* GetState(unsigned int target) const; - - private: - friend class ValuebufferManager; - friend class base::RefCounted<Valuebuffer>; - - typedef base::hash_set<unsigned int> SubscriptionSet; - - ~Valuebuffer(); - - void UpdateState(const ValueStateMap* pending_state); - - void MarkAsDeleted() { client_id_ = 0; } - - // ValuebufferManager that owns this Valuebuffer. - ValuebufferManager* manager_; - - // Client side Valuebuffer id. - unsigned int client_id_; - - // Whether this Valuebuffer has ever been bound. - bool has_been_bound_; - - SubscriptionSet subscriptions_; - - scoped_refptr<ValueStateMap> active_state_map_; -}; - -class GPU_EXPORT ValuebufferManager { - public: - ValuebufferManager(SubscriptionRefSet* ref_set, ValueStateMap* state_map); - ~ValuebufferManager(); - - // Must call before destruction. - void Destroy(); - - // Creates a Valuebuffer for the given Valuebuffer ids. - void CreateValuebuffer(unsigned int client_id); - - // Gets the Valuebuffer for the given Valuebuffer id. - Valuebuffer* GetValuebuffer(unsigned int client_id); - - // Removes a Valuebuffer for the given Valuebuffer id. - void RemoveValuebuffer(unsigned int client_id); - - // Updates the value state for the given Valuebuffer - void UpdateValuebufferState(Valuebuffer* valuebuffer); - - static uint32_t ApiTypeForSubscriptionTarget(unsigned int target); - - private: - friend class Valuebuffer; - - typedef base::hash_map<unsigned int, scoped_refptr<Valuebuffer>> - ValuebufferMap; - - void StartTracking(Valuebuffer* valuebuffer); - void StopTracking(Valuebuffer* valuebuffer); - - void NotifyAddSubscription(unsigned int target); - void NotifyRemoveSubscription(unsigned int target); - - // Counts the number of Valuebuffer allocated with 'this' as its manager. - // Allows to check no Valuebuffer will outlive this. - unsigned int valuebuffer_count_; - - // Info for each Valuebuffer in the system. - ValuebufferMap valuebuffer_map_; - - // Current value state in the system - // Updated by GpuChannel - scoped_refptr<ValueStateMap> pending_state_map_; - - // Subscription targets which are currently subscribed and how - // many value buffers are currently subscribed to each - scoped_refptr<SubscriptionRefSet> subscription_ref_set_; - - DISALLOW_COPY_AND_ASSIGN(ValuebufferManager); -}; - -} // namespace gles2 -} // namespace gpu - -#endif // GPU_COMMAND_BUFFER_SERVICE_VALUEBUFFER_MANAGER_H_ diff --git a/chromium/gpu/command_buffer/service/valuebuffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/valuebuffer_manager_unittest.cc deleted file mode 100644 index c5d0c6c0f98..00000000000 --- a/chromium/gpu/command_buffer/service/valuebuffer_manager_unittest.cc +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gpu/command_buffer/service/valuebuffer_manager.h" - -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "gpu/command_buffer/common/gles2_cmd_format.h" -#include "gpu/command_buffer/common/gles2_cmd_utils.h" -#include "gpu/command_buffer/common/value_state.h" -#include "gpu/command_buffer/service/common_decoder.h" -#include "gpu/command_buffer/service/feature_info.h" -#include "gpu/command_buffer/service/gpu_service_test.h" -#include "gpu/command_buffer/service/mocks.h" -#include "gpu/command_buffer/service/test_helper.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/gl/gl_bindings.h" -#include "ui/gl/gl_mock.h" - -namespace gpu { -namespace gles2 { - -class MockSubscriptionRefSetObserver : public SubscriptionRefSet::Observer { - public: - MOCK_METHOD1(OnAddSubscription, void(unsigned int target)); - MOCK_METHOD1(OnRemoveSubscription, void(unsigned int target)); -}; - -class ValuebufferManagerTest : public GpuServiceTest { - public: - ValuebufferManagerTest() {} - ~ValuebufferManagerTest() override {} - - void SetUp() override { - GpuServiceTest::SetUp(); - subscription_ref_set_ = new SubscriptionRefSet(); - pending_state_map_ = new ValueStateMap(); - subscription_ref_set_->AddObserver(&mock_observer_); - manager_.reset(new ValuebufferManager(subscription_ref_set_.get(), - pending_state_map_.get())); - } - - void TearDown() override { - manager_->Destroy(); - subscription_ref_set_->RemoveObserver(&mock_observer_); - GpuServiceTest::TearDown(); - } - - protected: - MockSubscriptionRefSetObserver mock_observer_; - - scoped_refptr<SubscriptionRefSet> subscription_ref_set_; - scoped_refptr<ValueStateMap> pending_state_map_; - scoped_ptr<ValuebufferManager> manager_; -}; - -TEST_F(ValuebufferManagerTest, Basic) { - const GLuint kClient1Id = 1; - const GLuint kClient2Id = 2; - // Check we can create a Valuebuffer - manager_->CreateValuebuffer(kClient1Id); - Valuebuffer* valuebuffer0 = manager_->GetValuebuffer(kClient1Id); - ASSERT_TRUE(valuebuffer0 != NULL); - EXPECT_EQ(kClient1Id, valuebuffer0->client_id()); - // Check we get nothing for a non-existent Valuebuffer. - // Check trying to a remove non-existent Valuebuffer does not crash - manager_->RemoveValuebuffer(kClient2Id); - // Check we can't get the renderbuffer after we remove it. - manager_->RemoveValuebuffer(kClient1Id); - EXPECT_TRUE(manager_->GetValuebuffer(kClient1Id) == NULL); -} - -TEST_F(ValuebufferManagerTest, Destroy) { - const GLuint kClient1Id = 1; - // Check we can create Valuebuffer. - manager_->CreateValuebuffer(kClient1Id); - Valuebuffer* valuebuffer0 = manager_->GetValuebuffer(kClient1Id); - ASSERT_TRUE(valuebuffer0 != NULL); - EXPECT_EQ(kClient1Id, valuebuffer0->client_id()); - manager_->Destroy(); - // Check the resources were released. - Valuebuffer* valuebuffer1 = manager_->GetValuebuffer(kClient1Id); - ASSERT_TRUE(valuebuffer1 == NULL); -} - -TEST_F(ValuebufferManagerTest, ValueBuffer) { - const GLuint kClient1Id = 1; - // Check we can create a Valuebuffer - manager_->CreateValuebuffer(kClient1Id); - Valuebuffer* valuebuffer0 = manager_->GetValuebuffer(kClient1Id); - ASSERT_TRUE(valuebuffer0 != NULL); - EXPECT_EQ(kClient1Id, valuebuffer0->client_id()); - EXPECT_FALSE(valuebuffer0->IsValid()); -} - -TEST_F(ValuebufferManagerTest, UpdateState) { - const GLuint kClient1Id = 1; - ValueState valuestate1; - valuestate1.int_value[0] = 111; - ValueState valuestate2; - valuestate2.int_value[0] = 222; - manager_->CreateValuebuffer(kClient1Id); - Valuebuffer* valuebuffer0 = manager_->GetValuebuffer(kClient1Id); - ASSERT_TRUE(valuebuffer0 != NULL); - EXPECT_EQ(kClient1Id, valuebuffer0->client_id()); - valuebuffer0->AddSubscription(GL_MOUSE_POSITION_CHROMIUM); - ASSERT_TRUE(valuebuffer0->GetState(GL_MOUSE_POSITION_CHROMIUM) == NULL); - pending_state_map_->UpdateState(GL_MOUSE_POSITION_CHROMIUM, valuestate1); - manager_->UpdateValuebufferState(valuebuffer0); - const ValueState* new_state1 = - valuebuffer0->GetState(GL_MOUSE_POSITION_CHROMIUM); - ASSERT_TRUE(new_state1 != NULL); - ASSERT_TRUE(new_state1->int_value[0] == 111); - // Ensure state changes - pending_state_map_->UpdateState(GL_MOUSE_POSITION_CHROMIUM, valuestate2); - manager_->UpdateValuebufferState(valuebuffer0); - const ValueState* new_state2 = - valuebuffer0->GetState(GL_MOUSE_POSITION_CHROMIUM); - ASSERT_TRUE(new_state2 != NULL); - ASSERT_TRUE(new_state2->int_value[0] == 222); -} - -TEST_F(ValuebufferManagerTest, NotifySubscriptionRefs) { - const GLuint kClientId1 = 1; - const GLuint kClientId2 = 2; - manager_->CreateValuebuffer(kClientId1); - Valuebuffer* valuebuffer1 = manager_->GetValuebuffer(kClientId1); - ASSERT_TRUE(valuebuffer1 != NULL); - manager_->CreateValuebuffer(kClientId2); - Valuebuffer* valuebuffer2 = manager_->GetValuebuffer(kClientId2); - ASSERT_TRUE(valuebuffer2 != NULL); - EXPECT_CALL(mock_observer_, OnAddSubscription(GL_MOUSE_POSITION_CHROMIUM)) - .Times(1); - valuebuffer1->AddSubscription(GL_MOUSE_POSITION_CHROMIUM); - EXPECT_CALL(mock_observer_, OnAddSubscription(GL_MOUSE_POSITION_CHROMIUM)) - .Times(0); - valuebuffer2->AddSubscription(GL_MOUSE_POSITION_CHROMIUM); - EXPECT_CALL(mock_observer_, OnRemoveSubscription(GL_MOUSE_POSITION_CHROMIUM)) - .Times(0); - valuebuffer1->RemoveSubscription(GL_MOUSE_POSITION_CHROMIUM); - // Ensure the manager still thinks a buffer has a reference to the - // subscription target. - EXPECT_CALL(mock_observer_, OnRemoveSubscription(GL_MOUSE_POSITION_CHROMIUM)) - .Times(1); - valuebuffer2->RemoveSubscription(GL_MOUSE_POSITION_CHROMIUM); -} - -} // namespace gles2 -} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/vertex_array_manager.h b/chromium/gpu/command_buffer/service/vertex_array_manager.h index 2c5268819e8..8221f30a363 100644 --- a/chromium/gpu/command_buffer/service/vertex_array_manager.h +++ b/chromium/gpu/command_buffer/service/vertex_array_manager.h @@ -11,7 +11,6 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/gpu_export.h" diff --git a/chromium/gpu/command_buffer/service/vertex_array_manager_unittest.cc b/chromium/gpu/command_buffer/service/vertex_array_manager_unittest.cc index 73f9bc7e207..a679cb5b64d 100644 --- a/chromium/gpu/command_buffer/service/vertex_array_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/vertex_array_manager_unittest.cc @@ -4,10 +4,11 @@ #include <stdint.h> +#include <memory> + #include "gpu/command_buffer/service/vertex_array_manager.h" #include "gpu/command_buffer/service/vertex_attrib_manager.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/test_helper.h" @@ -40,7 +41,7 @@ class VertexArrayManagerTest : public GpuServiceTest { GpuServiceTest::TearDown(); } - scoped_ptr<VertexArrayManager> manager_; + std::unique_ptr<VertexArrayManager> manager_; }; // GCC requires these declarations, but MSVC requires they not be present diff --git a/chromium/gpu/command_buffer/service/vertex_attrib_manager.cc b/chromium/gpu/command_buffer/service/vertex_attrib_manager.cc index 7ec12e8b308..76883dc0f3f 100644 --- a/chromium/gpu/command_buffer/service/vertex_attrib_manager.cc +++ b/chromium/gpu/command_buffer/service/vertex_attrib_manager.cc @@ -9,7 +9,6 @@ #include <list> #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" #include "build/build_config.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" 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 2e31c16254a..1492cb18a78 100644 --- a/chromium/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc @@ -6,7 +6,6 @@ #include <stdint.h> -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/buffer_manager.h" #include "gpu/command_buffer/service/error_state_mock.h" #include "gpu/command_buffer/service/feature_info.h" @@ -120,7 +119,8 @@ TEST_F(VertexAttribManagerTest, SetAttribInfo) { // The VertexAttribManager must be destroyed before the BufferManager // so it releases its buffers. manager_ = NULL; - buffer_manager.Destroy(false); + buffer_manager.MarkContextLost(); + buffer_manager.Destroy(); } TEST_F(VertexAttribManagerTest, HaveFixedAttribs) { @@ -181,7 +181,8 @@ TEST_F(VertexAttribManagerTest, CanAccess) { // The VertexAttribManager must be destroyed before the BufferManager // so it releases its buffers. manager_ = NULL; - buffer_manager.Destroy(false); + buffer_manager.MarkContextLost(); + buffer_manager.Destroy(); } TEST_F(VertexAttribManagerTest, Unbind) { @@ -218,7 +219,8 @@ TEST_F(VertexAttribManagerTest, Unbind) { // The VertexAttribManager must be destroyed before the BufferManager // so it releases its buffers. manager_ = NULL; - buffer_manager.Destroy(false); + buffer_manager.MarkContextLost(); + buffer_manager.Destroy(); } // TODO(gman): Test ValidateBindings diff --git a/chromium/gpu/command_buffer_common.gypi b/chromium/gpu/command_buffer_common.gypi index 43fc5966601..0b5bc21a381 100644 --- a/chromium/gpu/command_buffer_common.gypi +++ b/chromium/gpu/command_buffer_common.gypi @@ -37,7 +37,5 @@ 'command_buffer/common/sync_token.h', 'command_buffer/common/thread_local.h', 'command_buffer/common/time.h', - 'command_buffer/common/value_state.cc', - 'command_buffer/common/value_state.h', ], } diff --git a/chromium/gpu/command_buffer_service.gypi b/chromium/gpu/command_buffer_service.gypi index bb3112d84ef..6a86e49cc16 100644 --- a/chromium/gpu/command_buffer_service.gypi +++ b/chromium/gpu/command_buffer_service.gypi @@ -22,6 +22,7 @@ '../ui/gfx/gfx.gyp:gfx', '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/gl/gl.gyp:gl', + '../ui/gl/init/gl_init.gyp:gl_init', '<(angle_path)/src/angle.gyp:commit_id', '<(angle_path)/src/angle.gyp:translator', ], @@ -84,6 +85,8 @@ 'command_buffer/service/image_manager.h', 'command_buffer/service/in_process_command_buffer.cc', 'command_buffer/service/in_process_command_buffer.h', + 'command_buffer/service/indexed_buffer_binding_host.cc', + 'command_buffer/service/indexed_buffer_binding_host.h', 'command_buffer/service/logger.cc', 'command_buffer/service/logger.h', 'command_buffer/service/mailbox_manager.cc', @@ -113,8 +116,6 @@ 'command_buffer/service/shader_translator.h', 'command_buffer/service/shader_translator_cache.cc', 'command_buffer/service/shader_translator_cache.h', - 'command_buffer/service/stream_texture_manager_in_process_android.cc', - 'command_buffer/service/stream_texture_manager_in_process_android.h', 'command_buffer/service/sync_point_manager.cc', 'command_buffer/service/sync_point_manager.h', 'command_buffer/service/texture_definition.cc', @@ -123,8 +124,8 @@ 'command_buffer/service/texture_manager.h', 'command_buffer/service/transfer_buffer_manager.cc', 'command_buffer/service/transfer_buffer_manager.h', - 'command_buffer/service/valuebuffer_manager.cc', - 'command_buffer/service/valuebuffer_manager.h', + 'command_buffer/service/transform_feedback_manager.cc', + 'command_buffer/service/transform_feedback_manager.h', 'command_buffer/service/vertex_array_manager.cc', 'command_buffer/service/vertex_array_manager.h', 'command_buffer/service/vertex_attrib_manager.cc', diff --git a/chromium/gpu/command_buffer_traits.gypi b/chromium/gpu/command_buffer_traits.gypi index 2b261f19d2b..6be45451af3 100644 --- a/chromium/gpu/command_buffer_traits.gypi +++ b/chromium/gpu/command_buffer_traits.gypi @@ -14,7 +14,6 @@ 'sources': [ 'ipc/common/gpu_command_buffer_traits.cc', 'ipc/common/gpu_command_buffer_traits.h', - 'ipc/common/id_type_traits.h', 'ipc/common/memory_stats.cc', 'ipc/common/memory_stats.h', 'ipc/common/surface_handle.h', diff --git a/chromium/gpu/config/BUILD.gn b/chromium/gpu/config/BUILD.gn index d0434ea04fd..aa6fa7ea8f7 100644 --- a/chromium/gpu/config/BUILD.gn +++ b/chromium/gpu/config/BUILD.gn @@ -3,11 +3,13 @@ # found in the LICENSE file. import("//build/config/chrome_build.gni") +import("//build/config/chromecast_build.gni") import("//build/config/ui.gni") declare_args() { # Use the PCI lib to collect GPU information on Linux. - use_libpci = is_linux && !is_chromecast && (use_x11 || use_ozone) + use_libpci = is_linux && (!is_chromecast || is_cast_desktop_build) && + (use_x11 || use_ozone) } group("config") { @@ -39,6 +41,8 @@ source_set("config_sources") { "gpu_driver_bug_list.h", "gpu_driver_bug_list_json.cc", "gpu_driver_bug_workaround_type.h", + "gpu_driver_bug_workarounds.cc", + "gpu_driver_bug_workarounds.h", "gpu_dx_diagnostics_win.cc", "gpu_feature_type.h", "gpu_info.cc", @@ -73,6 +77,7 @@ source_set("config_sources") { "//base", "//third_party/re2", "//ui/gl", + "//ui/gl/init", ] # Prefer mesa GL headers to system headers, which cause problems on Win. @@ -92,9 +97,15 @@ source_set("config_sources") { ] } } + if (is_mac) { + libs = [ + "IOKit.framework", + "CoreFoundation.framework", + ] + } if (use_libpci) { defines = [ "USE_LIBPCI=1" ] - deps += [ "//build/linux:libpci" ] + deps += [ "//build/linux/libpci" ] } if (is_linux && use_x11) { configs += [ diff --git a/chromium/gpu/config/gpu_blacklist_unittest.cc b/chromium/gpu/config/gpu_blacklist_unittest.cc index 1c7211e6d01..b5e27e711fa 100644 --- a/chromium/gpu/config/gpu_blacklist_unittest.cc +++ b/chromium/gpu/config/gpu_blacklist_unittest.cc @@ -2,8 +2,10 @@ // 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/config/gpu_blacklist.h" + +#include <memory> + #include "gpu/config/gpu_control_list_jsons.h" #include "gpu/config/gpu_feature_type.h" #include "gpu/config/gpu_info.h" @@ -46,7 +48,7 @@ class GpuBlacklistTest : public testing::Test { " ]\n" "}"; - scoped_ptr<GpuBlacklist> blacklist(GpuBlacklist::Create()); + std::unique_ptr<GpuBlacklist> blacklist(GpuBlacklist::Create()); EXPECT_TRUE(blacklist->LoadList(json, GpuBlacklist::kAllOs)); std::set<int> type = blacklist->MakeDecision( GpuBlacklist::kOsMacosx, kOsVersion, gpu_info()); @@ -74,7 +76,7 @@ class GpuBlacklistTest : public testing::Test { }; TEST_F(GpuBlacklistTest, CurrentBlacklistValidation) { - scoped_ptr<GpuBlacklist> blacklist(GpuBlacklist::Create()); + std::unique_ptr<GpuBlacklist> blacklist(GpuBlacklist::Create()); EXPECT_TRUE(blacklist->LoadList( kSoftwareRenderingListJson, GpuBlacklist::kAllOs)); } diff --git a/chromium/gpu/config/gpu_control_list.cc b/chromium/gpu/config/gpu_control_list.cc index 09f6d1e6b79..a8ba402758b 100644 --- a/chromium/gpu/config/gpu_control_list.cc +++ b/chromium/gpu/config/gpu_control_list.cc @@ -738,17 +738,40 @@ GpuControlList::GpuControlListEntry::GetEntryFromValue( const base::ListValue* feature_value = NULL; if (value->GetList("features", &feature_value)) { std::vector<std::string> feature_list; + std::vector<std::string> feature_exception_list; for (size_t i = 0; i < feature_value->GetSize(); ++i) { std::string feature; + const base::DictionaryValue* features_info_value = NULL; if (feature_value->GetString(i, &feature)) { feature_list.push_back(feature); + } else if (feature_value->GetDictionary(i, &features_info_value)) { + const base::ListValue* exception_list_value = NULL; + if (features_info_value->size() > 1) { + LOG(WARNING) << "Malformed feature entry " << entry->id(); + return NULL; + } + if (features_info_value->GetList("exceptions", + &exception_list_value)) { + for (size_t i = 0; i < exception_list_value->GetSize(); ++i) { + std::string exception_feature; + if (exception_list_value->GetString(i, &exception_feature)) { + feature_exception_list.push_back(exception_feature); + } else { + LOG(WARNING) << "Malformed feature entry " << entry->id(); + return NULL; + } + } + } else { + LOG(WARNING) << "Malformed feature entry " << entry->id(); + return NULL; + } } else { LOG(WARNING) << "Malformed feature entry " << entry->id(); return NULL; } } - if (!entry->SetFeatures( - feature_list, feature_map, supports_feature_type_all)) { + if (!entry->SetFeatures(feature_list, feature_exception_list, feature_map, + supports_feature_type_all)) { LOG(WARNING) << "Malformed feature entry " << entry->id(); return NULL; } @@ -997,6 +1020,7 @@ void GpuControlList::GpuControlListEntry::SetInProcessGPUInfo(bool value) { bool GpuControlList::GpuControlListEntry::SetFeatures( const std::vector<std::string>& feature_strings, + const std::vector<std::string>& exception_strings, const FeatureMap& feature_map, bool supports_feature_type_all) { size_t size = feature_strings.size(); @@ -1007,15 +1031,20 @@ bool GpuControlList::GpuControlListEntry::SetFeatures( int feature = 0; if (supports_feature_type_all && feature_strings[i] == "all") { for (FeatureMap::const_iterator iter = feature_map.begin(); - iter != feature_map.end(); ++iter) - features_.insert(iter->second); + iter != feature_map.end(); ++iter) { + if (std::find(exception_strings.begin(), exception_strings.end(), + iter->first) == exception_strings.end()) + features_.insert(iter->second); + } continue; } if (!StringToFeature(feature_strings[i], &feature, feature_map)) { features_.clear(); return false; } - features_.insert(feature); + if (std::find(exception_strings.begin(), exception_strings.end(), + feature_strings[i]) == exception_strings.end()) + features_.insert(feature); } return true; } @@ -1363,7 +1392,7 @@ GpuControlList::~GpuControlList() { bool GpuControlList::LoadList( const std::string& json_context, GpuControlList::OsFilter os_filter) { - scoped_ptr<base::Value> root = base::JSONReader::Read(json_context); + std::unique_ptr<base::Value> root = base::JSONReader::Read(json_context); if (root.get() == NULL || !root->IsType(base::Value::TYPE_DICTIONARY)) return false; diff --git a/chromium/gpu/config/gpu_control_list.h b/chromium/gpu/config/gpu_control_list.h index 47282381af9..6cd133ffac7 100644 --- a/chromium/gpu/config/gpu_control_list.h +++ b/chromium/gpu/config/gpu_control_list.h @@ -8,13 +8,13 @@ #include <stddef.h> #include <stdint.h> +#include <memory> #include <set> #include <string> #include <vector> #include "base/containers/hash_tables.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/values.h" #include "build/build_config.h" #include "gpu/gpu_export.h" @@ -193,7 +193,7 @@ class GPU_EXPORT GpuControlList { private: OsType type_; - scoped_ptr<VersionInfo> version_info_; + std::unique_ptr<VersionInfo> version_info_; }; class GPU_EXPORT FloatInfo { @@ -404,6 +404,7 @@ class GPU_EXPORT GpuControlList { void SetInProcessGPUInfo(bool value); bool SetFeatures(const std::vector<std::string>& features, + const std::vector<std::string>& exceptions, const FeatureMap& feature_map, bool supports_feature_type_all); @@ -436,29 +437,29 @@ class GPU_EXPORT GpuControlList { std::vector<int> cr_bugs_; std::vector<int> webkit_bugs_; std::vector<std::string> disabled_extensions_; - scoped_ptr<OsInfo> os_info_; + std::unique_ptr<OsInfo> os_info_; uint32_t vendor_id_; std::vector<uint32_t> device_id_list_; MultiGpuStyle multi_gpu_style_; MultiGpuCategory multi_gpu_category_; GLType gl_type_; std::string driver_vendor_info_; - scoped_ptr<VersionInfo> driver_version_info_; - scoped_ptr<VersionInfo> driver_date_info_; - scoped_ptr<VersionInfo> gl_version_info_; + std::unique_ptr<VersionInfo> driver_version_info_; + std::unique_ptr<VersionInfo> driver_date_info_; + std::unique_ptr<VersionInfo> gl_version_info_; std::string gl_vendor_info_; std::string gl_renderer_info_; std::string gl_extensions_info_; - scoped_ptr<IntInfo> gl_reset_notification_strategy_info_; + std::unique_ptr<IntInfo> gl_reset_notification_strategy_info_; std::string cpu_brand_; - scoped_ptr<FloatInfo> perf_graphics_info_; - scoped_ptr<FloatInfo> perf_gaming_info_; - scoped_ptr<FloatInfo> perf_overall_info_; + std::unique_ptr<FloatInfo> perf_graphics_info_; + std::unique_ptr<FloatInfo> perf_gaming_info_; + std::unique_ptr<FloatInfo> perf_overall_info_; std::vector<std::string> machine_model_name_list_; - scoped_ptr<VersionInfo> machine_model_version_info_; - scoped_ptr<IntInfo> gpu_count_info_; - scoped_ptr<BoolInfo> direct_rendering_info_; - scoped_ptr<BoolInfo> in_process_gpu_info_; + std::unique_ptr<VersionInfo> machine_model_version_info_; + std::unique_ptr<IntInfo> gpu_count_info_; + std::unique_ptr<BoolInfo> direct_rendering_info_; + std::unique_ptr<BoolInfo> in_process_gpu_info_; std::set<int> features_; std::vector<ScopedGpuControlListEntry> exceptions_; }; diff --git a/chromium/gpu/config/gpu_control_list_entry_unittest.cc b/chromium/gpu/config/gpu_control_list_entry_unittest.cc index 91504c188db..9228b976ec1 100644 --- a/chromium/gpu/config/gpu_control_list_entry_unittest.cc +++ b/chromium/gpu/config/gpu_control_list_entry_unittest.cc @@ -4,6 +4,8 @@ #include <stddef.h> +#include <memory> + #include "base/json/json_reader.h" #include "gpu/config/gpu_control_list.h" #include "gpu/config/gpu_info.h" @@ -32,7 +34,7 @@ class GpuControlListEntryTest : public testing::Test { static ScopedEntry GetEntryFromString( const std::string& json, bool supports_feature_type_all) { - scoped_ptr<base::Value> root = base::JSONReader::Read(json); + std::unique_ptr<base::Value> root = base::JSONReader::Read(json); base::DictionaryValue* value = NULL; if (!root || !root->GetAsDictionary(&value)) return NULL; @@ -814,6 +816,53 @@ TEST_F(GpuControlListEntryTest, FeatureTypeAllEntry) { EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_2)); } +TEST_F(GpuControlListEntryTest, FeatureTypeAllEntryWithExceptions) { + const std::string json = LONG_STRING_CONST( + { + "id": 1, + "features": [ + "all", + {"exceptions" : [ + "test_feature_0" + ]} + ] + } + ); + bool supports_feature_type_all = true; + ScopedEntry entry(GetEntryFromString(json, supports_feature_type_all)); + EXPECT_TRUE(entry.get() != NULL); + EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_1)); + EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_2)); + EXPECT_EQ(2u, entry->features().size()); + + supports_feature_type_all = false; + entry = ScopedEntry(GetEntryFromString(json, supports_feature_type_all)); + EXPECT_TRUE(entry.get() == NULL); +} + +TEST_F(GpuControlListEntryTest, FeatureTypeAllEntryWithUnknownField) { + const std::string json = LONG_STRING_CONST( + { + "id": 1, + "features": [ + "all", { + "exceptions" : [ + "test_feature_0" + ], + "unknown_field" : 0 + } + ] + } + ); + bool supports_feature_type_all = true; + ScopedEntry entry(GetEntryFromString(json, supports_feature_type_all)); + EXPECT_TRUE(entry.get() == NULL); + + supports_feature_type_all = false; + entry = ScopedEntry(GetEntryFromString(json, supports_feature_type_all)); + EXPECT_TRUE(entry.get() == NULL); +} + TEST_F(GpuControlListEntryTest, InvalidVendorIdEntry) { const std::string json = LONG_STRING_CONST( { diff --git a/chromium/gpu/config/gpu_control_list_format.txt b/chromium/gpu/config/gpu_control_list_format.txt index 4e2df4275ae..7b23ad86dff 100644 --- a/chromium/gpu/config/gpu_control_list_format.txt +++ b/chromium/gpu/config/gpu_control_list_format.txt @@ -52,6 +52,8 @@ // 20. "features" is a list of gpu control list options, which can be // configured by a specific list. See its *_json.cc file for a list of // supported features. This field is mandatory. +// An "exceptions" list to the features can be added for convenience instead +// of listing all features except one. // 21. "description" has the description of the entry. // 22. "webkit_bugs" is an array of associated webkit bug numbers. // 23. "cr_bugs" is an array of associated webkit bug numbers. diff --git a/chromium/gpu/config/gpu_control_list_unittest.cc b/chromium/gpu/config/gpu_control_list_unittest.cc index ee8597b3bbd..f3a3c099d61 100644 --- a/chromium/gpu/config/gpu_control_list_unittest.cc +++ b/chromium/gpu/config/gpu_control_list_unittest.cc @@ -4,9 +4,9 @@ #include <stdint.h> +#include <memory> #include <vector> -#include "base/memory/scoped_ptr.h" #include "gpu/config/gpu_control_list.h" #include "gpu/config/gpu_info.h" #include "testing/gtest/include/gtest/gtest.h" @@ -68,7 +68,7 @@ class GpuControlListTest : public testing::Test { }; TEST_F(GpuControlListTest, DefaultControlListSettings) { - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); // Default control list settings: all feature are allowed. std::set<int> features = control_list->MakeDecision( GpuControlList::kOsMacosx, kOsVersion, gpu_info()); @@ -85,7 +85,7 @@ TEST_F(GpuControlListTest, EmptyControlList) { ] } ); - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_TRUE(control_list->LoadList(empty_list_json, GpuControlList::kAllOs)); @@ -124,7 +124,7 @@ TEST_F(GpuControlListTest, DetailedEntryAndInvalidJson) { ] } ); - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_TRUE(control_list->LoadList(exact_list_json, GpuControlList::kAllOs)); std::set<int> features = control_list->MakeDecision( @@ -162,7 +162,7 @@ TEST_F(GpuControlListTest, VendorOnAllOsEntry) { ] } ); - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); // ControlList entries won't be filtered to the current OS only upon loading. EXPECT_TRUE(control_list->LoadList(vendor_json, GpuControlList::kAllOs)); @@ -214,7 +214,7 @@ TEST_F(GpuControlListTest, UnknownField) { ] } ); - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_FALSE(control_list->LoadList( unknown_field_json, GpuControlList::kAllOs)); @@ -253,7 +253,7 @@ TEST_F(GpuControlListTest, UnknownExceptionField) { ] } ); - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_FALSE(control_list->LoadList( unknown_exception_field_json, GpuControlList::kAllOs)); @@ -275,7 +275,7 @@ TEST_F(GpuControlListTest, DisabledEntry) { ] } ); - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_TRUE(control_list->LoadList(disabled_json, GpuControlList::kAllOs)); std::set<int> features = control_list->MakeDecision( GpuControlList::kOsWin, kOsVersion, gpu_info()); @@ -313,7 +313,7 @@ TEST_F(GpuControlListTest, NeedsMoreInfo) { GPUInfo gpu_info; gpu_info.gpu.vendor_id = kNvidiaVendorId; - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs)); std::set<int> features = control_list->MakeDecision( @@ -360,7 +360,7 @@ TEST_F(GpuControlListTest, NeedsMoreInfoForExceptions) { GPUInfo gpu_info; gpu_info.gpu.vendor_id = kIntelVendorId; - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs)); // The case this entry does not apply. @@ -430,7 +430,7 @@ TEST_F(GpuControlListTest, IgnorableEntries) { GPUInfo gpu_info; gpu_info.gpu.vendor_id = kIntelVendorId; - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs)); std::set<int> features = control_list->MakeDecision( GpuControlList::kOsLinux, kOsVersion, gpu_info); @@ -478,7 +478,7 @@ TEST_F(GpuControlListTest, ExceptionWithoutVendorId) { gpu_info.gpu.device_id = 0x2a02; gpu_info.driver_version = "9.1"; - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs)); std::set<int> features = control_list->MakeDecision( @@ -521,7 +521,7 @@ TEST_F(GpuControlListTest, AMDSwitchable) { } ); - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs)); // Integrated GPU is active @@ -559,7 +559,7 @@ TEST_F(GpuControlListTest, AMDSwitchable) { } ); - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs)); // Discrete GPU is active @@ -614,7 +614,7 @@ TEST_F(GpuControlListTest, DisabledExtensionTest) { ] } ); - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_TRUE(control_list->LoadList(exact_list_json, GpuControlList::kAllOs)); GPUInfo gpu_info; @@ -648,7 +648,7 @@ TEST_F(GpuControlListTest, DisabledInProcessGPUTest) { ] } ); - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_TRUE(control_list->LoadList(exact_list_json, GpuControlList::kAllOs)); GPUInfo gpu_info; @@ -688,7 +688,7 @@ TEST_F(GpuControlListTest, SameGPUTwiceTest) { // Real case on Intel GMA* on Windows gpu_info.secondary_gpus.push_back(gpu_info.gpu); - scoped_ptr<GpuControlList> control_list(Create()); + std::unique_ptr<GpuControlList> control_list(Create()); EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs)); std::set<int> features = control_list->MakeDecision( GpuControlList::kOsWin, kOsVersion, gpu_info); diff --git a/chromium/gpu/config/gpu_driver_bug_list_json.cc b/chromium/gpu/config/gpu_driver_bug_list_json.cc index 209f2eeeb8d..4ab09ef8f32 100644 --- a/chromium/gpu/config/gpu_driver_bug_list_json.cc +++ b/chromium/gpu/config/gpu_driver_bug_list_json.cc @@ -19,7 +19,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( { "name": "gpu driver bug list", // Please update the version number whenever you change this file. - "version": "8.66", + "version": "8.68", "entries": [ { "id": 1, @@ -1071,17 +1071,6 @@ LONG_STRING_CONST( ] }, { - "id": 96, - "description": "glBindFramebuffer sometimes requires a glBegin/End to take effect", - "cr_bugs": [435786], - "os": { - "type": "macosx" - }, - "features": [ - "gl_begin_gl_end_on_fbo_change_to_backbuffer" - ] - }, - { "id": 97, "description": "Multisampling has poor performance in Intel BayTrail", "cr_bugs": [443517], @@ -1914,6 +1903,107 @@ LONG_STRING_CONST( ] }, { + "id": 159, + "cr_bugs": [570897], + "description": "Framebuffer discarding can hurt performance on non-tilers", + "os": { + "type": "linux" + }, + "vendor_id": "0x10de", + "gl_vendor": "NVIDIA.*", + "gl_type": "gl", + "features": [ + "disable_discard_framebuffer" + ] + }, + { + "id": 160, + "cr_bugs": [601753], + "description": "Framebuffer discarding not useful on NVIDIA Kepler architecture and later", + "os": { + "type": "linux" + }, + "vendor_id": "0x10de", + "gl_vendor": "NVIDIA.*", + "gl_type": "gles", + "gl_version": { + "op": ">=", + "value": "3.0" + }, + "features": [ + "disable_discard_framebuffer" + ] + }, + { + "id": 161, + "cr_bugs": [601753], + "description": "Framebuffer discarding not useful on NVIDIA Kepler architecture and later", + "os": { + "type": "chromeos" + }, + "vendor_id": "0x10de", + "gl_vendor": "NVIDIA.*", + "gl_type": "gles", + "gl_version": { + "op": ">=", + "value": "3.0" + }, + "features": [ + "disable_discard_framebuffer" + ] + }, + { + "id": 162, + "cr_bugs": [601753], + "description": "Framebuffer discarding not useful on NVIDIA Kepler architecture and later", + "os": { + "type": "android" + }, + "gl_vendor": "NVIDIA.*", + "gl_type": "gles", + "gl_version": { + "op": ">=", + "value": "3.0" + }, + "features": [ + "disable_discard_framebuffer" + ] + }, + { + "id": 163, + "cr_bugs": [607130], + "description": "Multisample renderbuffers with format GL_RGB8 have performance issues on Intel GPUs.", + "os": { + "type": "macosx" + }, + "vendor_id": "0x8086", + "features": [ + "disable_webgl_rgb_multisampling_usage" + ] + }, + { + "id": 164, + "cr_bugs": [595948], + "description": "glColorMask does not work for multisample renderbuffers on old AMD GPUs.", + "os": { + "type": "macosx" + }, + "vendor_id": "0x1002", + "device_id": ["0x68b8"], + "features": [ + "disable_webgl_multisampling_color_mask_usage" + ] + }, + { + "id": 165, + "cr_bugs": [596774], + "description": "Unpacking overlapping rows from unpack buffers is unstable on NVIDIA GL driver", + "gl_vendor": "NVIDIA.*", + "features": [ + "unpack_overlapping_rows_separately_unpack_buffer" + ] + }, + { "id": 166, "cr_bugs": [612474], "description": "Crash reports for glDiscardFramebuffer on Adreno 530", @@ -1924,6 +2014,31 @@ LONG_STRING_CONST( "features": [ "disable_discard_framebuffer" ] + }, + { + "id": 167, + "cr_bugs": [610516], + "description": "glEGLImageTargetTexture2DOES crashes on Mali-400", + "os": { + "type": "android" + }, + "gl_vendor": "ARM.*", + "gl_renderer": ".*Mali-4.*", + "features": [ + "avda_dont_copy_pictures" + ] + }, + { + "id": 168, + "description": "VirtualBox driver doesn't correctly support partial swaps.", + "cr_bugs": [613722], + "os": { + "type": "linux" + }, + "vendor_id": "0x80ee", + "features": [ + "disable_post_sub_buffers_for_onscreen_surfaces" + ] } ] } diff --git a/chromium/gpu/config/gpu_driver_bug_list_unittest.cc b/chromium/gpu/config/gpu_driver_bug_list_unittest.cc index e7eaaa510ff..09612d20ab8 100644 --- a/chromium/gpu/config/gpu_driver_bug_list_unittest.cc +++ b/chromium/gpu/config/gpu_driver_bug_list_unittest.cc @@ -4,9 +4,10 @@ #include <stdint.h> +#include <memory> + #include "base/command_line.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "gpu/config/gpu_control_list_jsons.h" #include "gpu/config/gpu_driver_bug_list.h" #include "gpu/config/gpu_driver_bug_workaround_type.h" @@ -47,13 +48,13 @@ class GpuDriverBugListTest : public testing::Test { }; TEST_F(GpuDriverBugListTest, CurrentDriverBugListValidation) { - scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); + std::unique_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); std::string json; EXPECT_TRUE(list->LoadList(kGpuDriverBugListJson, GpuControlList::kAllOs)); } TEST_F(GpuDriverBugListTest, CurrentListForARM) { - scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); + std::unique_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); EXPECT_TRUE(list->LoadList(kGpuDriverBugListJson, GpuControlList::kAllOs)); GPUInfo gpu_info; @@ -65,7 +66,7 @@ TEST_F(GpuDriverBugListTest, CurrentListForARM) { } TEST_F(GpuDriverBugListTest, CurrentListForImagination) { - scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); + std::unique_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); EXPECT_TRUE(list->LoadList(kGpuDriverBugListJson, GpuControlList::kAllOs)); GPUInfo gpu_info; @@ -103,7 +104,7 @@ TEST_F(GpuDriverBugListTest, GpuSwitching) { ] } ); - scoped_ptr<GpuDriverBugList> driver_bug_list(GpuDriverBugList::Create()); + std::unique_ptr<GpuDriverBugList> driver_bug_list(GpuDriverBugList::Create()); EXPECT_TRUE(driver_bug_list->LoadList(json, GpuControlList::kAllOs)); std::set<int> switching = driver_bug_list->MakeDecision( GpuControlList::kOsMacosx, "10.8", gpu_info()); @@ -179,7 +180,7 @@ TEST_F(GpuDriverBugListTest, NVIDIANumberingScheme) { } ); - scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); + std::unique_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); EXPECT_TRUE(list->LoadList(json, GpuControlList::kAllOs)); GPUInfo gpu_info; diff --git a/chromium/gpu/config/gpu_driver_bug_workaround_type.h b/chromium/gpu/config/gpu_driver_bug_workaround_type.h index 1583c523ee8..56141c2ac6d 100644 --- a/chromium/gpu/config/gpu_driver_bug_workaround_type.h +++ b/chromium/gpu/config/gpu_driver_bug_workaround_type.h @@ -9,6 +9,9 @@ #include "gpu/gpu_export.h" +// Clang format is toggled off here so that newlines can be kept consistent +// throughout the table. +// clang-format off #define GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) \ GPU_OP(AVDA_DONT_COPY_PICTURES, \ avda_dont_copy_pictures) \ @@ -58,6 +61,10 @@ disable_texture_storage) \ GPU_OP(DISABLE_TIMESTAMP_QUERIES, \ disable_timestamp_queries) \ + GPU_OP(DISABLE_WEBGL_MULTISAMPLING_COLOR_MASK_USAGE, \ + disable_webgl_multisampling_color_mask_usage) \ + GPU_OP(DISABLE_WEBGL_RGB_MULTISAMPLING_USAGE, \ + disable_webgl_rgb_multisampling_usage) \ GPU_OP(ETC1_POWER_OF_TWO_ONLY, \ etc1_power_of_two_only) \ GPU_OP(EXIT_ON_CONTEXT_LOST, \ @@ -70,8 +77,6 @@ force_discrete_gpu) \ GPU_OP(FORCE_INTEGRATED_GPU, \ force_integrated_gpu) \ - GPU_OP(GL_BEGIN_GL_END_ON_FBO_CHANGE_TO_BACKBUFFER, \ - gl_begin_gl_end_on_fbo_change_to_backbuffer) \ GPU_OP(GL_CLEAR_BROKEN, \ gl_clear_broken) \ GPU_OP(IGNORE_EGL_SYNC_FAILURES, \ @@ -142,6 +147,8 @@ unfold_short_circuit_as_ternary_operation) \ GPU_OP(UNPACK_ALIGNMENT_WORKAROUND_WITH_UNPACK_BUFFER, \ unpack_alignment_workaround_with_unpack_buffer) \ + GPU_OP(UNPACK_OVERLAPPING_ROWS_SEPARATELY_UNPACK_BUFFER, \ + unpack_overlapping_rows_separately_unpack_buffer) \ GPU_OP(IOSURFACE_READBACK_WORKAROUND, \ iosurface_readback_workaround) \ GPU_OP(UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX, \ @@ -162,6 +169,7 @@ wake_up_gpu_before_drawing) \ GPU_OP(USE_TESTING_GPU_DRIVER_WORKAROUND, \ use_gpu_driver_workaround_for_testing) \ +// clang-format on namespace gpu { diff --git a/chromium/gpu/config/gpu_driver_bug_workarounds.cc b/chromium/gpu/config/gpu_driver_bug_workarounds.cc new file mode 100644 index 00000000000..f9bf4c38c17 --- /dev/null +++ b/chromium/gpu/config/gpu_driver_bug_workarounds.cc @@ -0,0 +1,98 @@ +// Copyright 2016 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/config/gpu_driver_bug_workarounds.h" + +#include "base/command_line.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "gpu/config/gpu_switches.h" + +namespace { +// Process a string of wordaround type IDs (seperated by ',') and set up +// the corresponding Workaround flags. +void StringToWorkarounds(const std::string& types, + gpu::GpuDriverBugWorkarounds* workarounds) { + DCHECK(workarounds); + for (const base::StringPiece& piece : base::SplitStringPiece( + types, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { + int number = 0; + bool succeed = base::StringToInt(piece, &number); + DCHECK(succeed); + switch (number) { +#define GPU_OP(type, name) \ + case gpu::type: \ + workarounds->name = true; \ + break; + GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) +#undef GPU_OP + default: + NOTIMPLEMENTED(); + } + } + if (workarounds->max_texture_size_limit_4096) + workarounds->max_texture_size = 4096; + if (workarounds->max_cube_map_texture_size_limit_4096) + workarounds->max_cube_map_texture_size = 4096; + if (workarounds->max_cube_map_texture_size_limit_1024) + workarounds->max_cube_map_texture_size = 1024; + if (workarounds->max_cube_map_texture_size_limit_512) + workarounds->max_cube_map_texture_size = 512; + + if (workarounds->max_fragment_uniform_vectors_32) + workarounds->max_fragment_uniform_vectors = 32; + if (workarounds->max_varying_vectors_16) + 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_1048576) + workarounds->max_copy_texture_chromium_size = 1048576; + if (workarounds->max_copy_texture_chromium_size_262144) + workarounds->max_copy_texture_chromium_size = 262144; +} + +} // anonymous namespace + +namespace gpu { + +GpuDriverBugWorkarounds::GpuDriverBugWorkarounds() + : +#define GPU_OP(type, name) name(false), + GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) +#undef GPU_OP + max_texture_size(0), + max_cube_map_texture_size(0), + max_fragment_uniform_vectors(0), + max_varying_vectors(0), + max_vertex_uniform_vectors(0), + max_copy_texture_chromium_size(0) { +} + +GpuDriverBugWorkarounds::GpuDriverBugWorkarounds( + const base::CommandLine* command_line) + : +#define GPU_OP(type, name) name(false), + GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) +#undef GPU_OP + max_texture_size(0), + max_cube_map_texture_size(0), + max_fragment_uniform_vectors(0), + max_varying_vectors(0), + max_vertex_uniform_vectors(0), + max_copy_texture_chromium_size(0) { + if (!command_line) + return; + + std::string types = + command_line->GetSwitchValueASCII(switches::kGpuDriverBugWorkarounds); + StringToWorkarounds(types, this); +} + +GpuDriverBugWorkarounds::GpuDriverBugWorkarounds( + const GpuDriverBugWorkarounds& other) = default; + +GpuDriverBugWorkarounds::~GpuDriverBugWorkarounds() {} + +} // namespace gpu diff --git a/chromium/gpu/config/gpu_driver_bug_workarounds.h b/chromium/gpu/config/gpu_driver_bug_workarounds.h new file mode 100644 index 00000000000..6c90d1b3395 --- /dev/null +++ b/chromium/gpu/config/gpu_driver_bug_workarounds.h @@ -0,0 +1,46 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_CONFIG_GPU_DRIVER_BUG_WORKAROUNDS_H_ +#define GPU_CONFIG_GPU_DRIVER_BUG_WORKAROUNDS_H_ + +#include "base/macros.h" +#include "build/build_config.h" +#include "gpu/config/gpu_driver_bug_workaround_type.h" +#include "gpu/gpu_export.h" + +// Forwardly declare a few GL types to avoid including GL header files. +typedef int GLint; + +namespace base { +class CommandLine; +} + +namespace gpu { + +class GPU_EXPORT GpuDriverBugWorkarounds { + public: + GpuDriverBugWorkarounds(); + explicit GpuDriverBugWorkarounds(const base::CommandLine* command_line); + + GpuDriverBugWorkarounds(const GpuDriverBugWorkarounds& other); + + ~GpuDriverBugWorkarounds(); + +#define GPU_OP(type, name) bool name; + GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) +#undef GPU_OP + + // Note: 0 here means use driver limit. + GLint max_texture_size; + GLint max_cube_map_texture_size; + GLint max_fragment_uniform_vectors; + GLint max_varying_vectors; + GLint max_vertex_uniform_vectors; + GLint max_copy_texture_chromium_size; +}; + +} // namespace gpu + +#endif // GPU_CONFIG_GPU_DRIVER_BUG_WORKAROUNDS_H_ diff --git a/chromium/gpu/config/gpu_info.h b/chromium/gpu/config/gpu_info.h index d8a9ef57940..73a6a9ea07a 100644 --- a/chromium/gpu/config/gpu_info.h +++ b/chromium/gpu/config/gpu_info.h @@ -55,7 +55,10 @@ enum VideoCodecProfile { VP9PROFILE_PROFILE1, VP9PROFILE_PROFILE2, VP9PROFILE_PROFILE3, - VIDEO_CODEC_PROFILE_MAX = VP9PROFILE_PROFILE3, + HEVCPROFILE_MAIN, + HEVCPROFILE_MAIN10, + HEVCPROFILE_MAIN_STILL_PICTURE, + VIDEO_CODEC_PROFILE_MAX = HEVCPROFILE_MAIN_STILL_PICTURE, }; // Specification of a decoding profile supported by a hardware decoder. diff --git a/chromium/gpu/config/gpu_info_collector.cc b/chromium/gpu/config/gpu_info_collector.cc index 44df9f1550b..e07379c8dda 100644 --- a/chromium/gpu/config/gpu_info_collector.cc +++ b/chromium/gpu/config/gpu_info_collector.cc @@ -10,25 +10,27 @@ #include <string> #include <vector> +#include "base/command_line.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/metrics/sparse_histogram.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/trace_event/trace_event.h" +#include "gpu/config/gpu_switches.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_surface.h" #include "ui/gl/gl_version_info.h" +#include "ui/gl/init/gl_factory.h" namespace { scoped_refptr<gfx::GLSurface> InitializeGLSurface() { scoped_refptr<gfx::GLSurface> surface( - gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size())); + gl::init::CreateOffscreenGLSurface(gfx::Size())); if (!surface.get()) { LOG(ERROR) << "gfx::GLContext::CreateOffscreenGLSurface failed"; return NULL; @@ -38,13 +40,10 @@ scoped_refptr<gfx::GLSurface> InitializeGLSurface() { } scoped_refptr<gfx::GLContext> InitializeGLContext(gfx::GLSurface* surface) { - scoped_refptr<gfx::GLContext> context( - gfx::GLContext::CreateGLContext(NULL, - surface, - gfx::PreferIntegratedGpu)); + gl::init::CreateGLContext(nullptr, surface, gfx::PreferIntegratedGpu)); if (!context.get()) { - LOG(ERROR) << "gfx::GLContext::CreateGLContext failed"; + LOG(ERROR) << "gl::init::CreateGLContext failed"; return NULL; } @@ -118,8 +117,23 @@ CollectInfoResult CollectGraphicsInfoGL(GPUInfo* gpu_info) { gpu_info->gl_renderer = GetGLString(GL_RENDERER); gpu_info->gl_vendor = GetGLString(GL_VENDOR); - gpu_info->gl_extensions = gfx::GetGLExtensionsFromCurrentContext(); gpu_info->gl_version = GetGLString(GL_VERSION); + + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kGpuTestingGLVendor)) { + gpu_info->gl_vendor = + command_line->GetSwitchValueASCII(switches::kGpuTestingGLVendor); + } + if (command_line->HasSwitch(switches::kGpuTestingGLRenderer)) { + gpu_info->gl_renderer = + command_line->GetSwitchValueASCII(switches::kGpuTestingGLRenderer); + } + if (command_line->HasSwitch(switches::kGpuTestingGLVersion)) { + gpu_info->gl_version = + command_line->GetSwitchValueASCII(switches::kGpuTestingGLVersion); + } + + gpu_info->gl_extensions = gfx::GetGLExtensionsFromCurrentContext(); std::string glsl_version_string = GetGLString(GL_SHADING_LANGUAGE_VERSION); gfx::GLVersionInfo gl_info(gpu_info->gl_version.c_str(), @@ -215,17 +229,19 @@ void MergeGPUInfoGL(GPUInfo* basic_gpu_info, void IdentifyActiveGPU(GPUInfo* gpu_info) { const std::string kNVidiaName = "nvidia"; + const std::string kNouveauName = "nouveau"; const std::string kIntelName = "intel"; const std::string kAMDName = "amd"; const std::string kATIName = "ati"; - const std::string kVendorNames[] = { - kNVidiaName, kIntelName, kAMDName, kATIName}; + const std::string kVendorNames[] = {kNVidiaName, kNouveauName, kIntelName, + kAMDName, kATIName}; const uint32_t kNVidiaID = 0x10de; const uint32_t kIntelID = 0x8086; const uint32_t kAMDID = 0x1002; const uint32_t kATIID = 0x1002; - const uint32_t kVendorIDs[] = {kNVidiaID, kIntelID, kAMDID, kATIID}; + const uint32_t kVendorIDs[] = {kNVidiaID, kNVidiaID, kIntelID, kAMDID, + kATIID}; DCHECK(gpu_info); if (gpu_info->secondary_gpus.size() == 0) diff --git a/chromium/gpu/config/gpu_info_collector_linux.cc b/chromium/gpu/config/gpu_info_collector_linux.cc index 7fce931acf6..74bc169bed7 100644 --- a/chromium/gpu/config/gpu_info_collector_linux.cc +++ b/chromium/gpu/config/gpu_info_collector_linux.cc @@ -12,7 +12,6 @@ #include "base/command_line.h" #include "base/files/file_util.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" diff --git a/chromium/gpu/config/gpu_info_collector_mac.mm b/chromium/gpu/config/gpu_info_collector_mac.mm index f6d81fda599..0e7e010197a 100644 --- a/chromium/gpu/config/gpu_info_collector_mac.mm +++ b/chromium/gpu/config/gpu_info_collector_mac.mm @@ -10,7 +10,6 @@ #include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_ioobject.h" -#include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" diff --git a/chromium/gpu/config/gpu_info_collector_unittest.cc b/chromium/gpu/config/gpu_info_collector_unittest.cc index 3e35d00d236..3e698d4ce5b 100644 --- a/chromium/gpu/config/gpu_info_collector_unittest.cc +++ b/chromium/gpu/config/gpu_info_collector_unittest.cc @@ -5,7 +5,8 @@ #include <stddef.h> #include <stdint.h> -#include "base/memory/scoped_ptr.h" +#include <memory> + #include "base/strings/string_split.h" #include "gpu/config/gpu_info.h" #include "gpu/config/gpu_info_collector.h" @@ -173,7 +174,7 @@ class GPUInfoCollectorTest public: // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; + std::unique_ptr<::testing::StrictMock<::gfx::MockGLInterface>> gl_; GPUInfo test_values_; const char* gl_shading_language_version_ = nullptr; diff --git a/chromium/gpu/config/gpu_switches.cc b/chromium/gpu/config/gpu_switches.cc index 554582d81aa..6b7cee7cd1a 100644 --- a/chromium/gpu/config/gpu_switches.cc +++ b/chromium/gpu/config/gpu_switches.cc @@ -9,6 +9,18 @@ namespace switches { // Pass a set of GpuDriverBugWorkaroundType ids, seperated by ','. const char kGpuDriverBugWorkarounds[] = "gpu-driver-bug-workarounds"; +// Passes active gpu vendor id from browser process to GPU process. +const char kGpuActiveVendorID[] = "gpu-active-vendor-id"; + +// Passes active gpu device id from browser process to GPU process. +const char kGpuActiveDeviceID[] = "gpu-active-device-id"; + +// Passes secondary gpu vendor ids from browser process to GPU process. +const char kGpuSecondaryVendorIDs[] = "gpu-secondary-vendor-ids"; + +// Passes secondary gpu device ids from browser process to GPU process. +const char kGpuSecondaryDeviceIDs[] = "gpu-secondary-device-ids"; + // Testing switch to not launch the gpu process for full gpu info collection. const char kGpuTestingNoCompleteInfoCollection[] = "gpu-no-complete-info-collection"; @@ -22,6 +34,15 @@ const char kGpuTestingVendorId[] = "gpu-testing-vendor-id"; // Override gpu device id from the GpuInfoCollector. const char kGpuTestingDeviceId[] = "gpu-testing-device-id"; +// Override secondary gpu vendor ids from the GpuInfoCollector. +const char kGpuTestingSecondaryVendorIDs[] = "gpu-testing-secondary-vendor-ids"; + +// Override secondary gpu device ids from the GpuInfoCollector. +const char kGpuTestingSecondaryDeviceIDs[] = "gpu-testing-secondary-device-ids"; + +// Override gpu driver date from the GpuInfoCollector. +const char kGpuTestingDriverDate[] = "gpu-testing-driver-date"; + // Override gl vendor from the GpuInfoCollector. const char kGpuTestingGLVendor[] = "gpu-testing-gl-vendor"; diff --git a/chromium/gpu/config/gpu_switches.h b/chromium/gpu/config/gpu_switches.h index 8bf00f17c3b..b3501b0505b 100644 --- a/chromium/gpu/config/gpu_switches.h +++ b/chromium/gpu/config/gpu_switches.h @@ -10,10 +10,17 @@ namespace switches { GPU_EXPORT extern const char kGpuDriverBugWorkarounds[]; +GPU_EXPORT extern const char kGpuActiveVendorID[]; +GPU_EXPORT extern const char kGpuActiveDeviceID[]; +GPU_EXPORT extern const char kGpuSecondaryVendorIDs[]; +GPU_EXPORT extern const char kGpuSecondaryDeviceIDs[]; GPU_EXPORT extern const char kGpuTestingNoCompleteInfoCollection[]; GPU_EXPORT extern const char kGpuTestingOsVersion[]; GPU_EXPORT extern const char kGpuTestingVendorId[]; GPU_EXPORT extern const char kGpuTestingDeviceId[]; +GPU_EXPORT extern const char kGpuTestingSecondaryVendorIDs[]; +GPU_EXPORT extern const char kGpuTestingSecondaryDeviceIDs[]; +GPU_EXPORT extern const char kGpuTestingDriverDate[]; GPU_EXPORT extern const char kGpuTestingGLVendor[]; GPU_EXPORT extern const char kGpuTestingGLRenderer[]; GPU_EXPORT extern const char kGpuTestingGLVersion[]; diff --git a/chromium/gpu/config/gpu_test_config.cc b/chromium/gpu/config/gpu_test_config.cc index 3b0b37c3c73..5f0c7ad2b0e 100644 --- a/chromium/gpu/config/gpu_test_config.cc +++ b/chromium/gpu/config/gpu_test_config.cc @@ -13,9 +13,7 @@ #include "gpu/config/gpu_info_collector.h" #include "gpu/config/gpu_test_expectations_parser.h" -#if defined(OS_MACOSX) -#include "base/mac/mac_util.h" -#elif defined(OS_WIN) +#if defined(OS_WIN) #include "base/win/windows_version.h" #endif @@ -302,12 +300,7 @@ bool GPUTestBotConfig::CurrentConfigMatches( // static bool GPUTestBotConfig::GpuBlacklistedOnBot() { -#if defined(OS_MACOSX) - // Blacklist rule #81 disables all Gpu acceleration on Mac < 10.8 bots. - if (CurrentConfigMatches("MAC VMWARE") && base::mac::IsOSLionOrEarlier()) { - return true; - } -#elif defined(OS_WIN) +#if defined(OS_WIN) // Blacklist rule #79 disables all Gpu acceleration before Windows 7. if (base::win::GetVersion() <= base::win::VERSION_VISTA) { return true; diff --git a/chromium/gpu/config/gpu_util.cc b/chromium/gpu/config/gpu_util.cc index 34fac5870ca..995c87c7e44 100644 --- a/chromium/gpu/config/gpu_util.cc +++ b/chromium/gpu/config/gpu_util.cc @@ -4,6 +4,7 @@ #include "gpu/config/gpu_util.h" +#include <memory> #include <vector> #include "base/command_line.h" @@ -45,6 +46,18 @@ void StringToIntSet(const std::string& str, std::set<int>* list) { } } +// |str| is in the format of "0x040a;0x10de;...;hex32_N". +void StringToIds(const std::string& str, std::vector<uint32_t>* list) { + DCHECK(list); + for (const base::StringPiece& piece : base::SplitStringPiece( + str, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { + uint32_t id = 0; + bool succeed = base::HexStringToUInt(piece, &id); + DCHECK(succeed); + list->push_back(id); + } +} + } // namespace anonymous void MergeFeatureSets(std::set<int>* dst, const std::set<int>& src) { @@ -56,7 +69,7 @@ void MergeFeatureSets(std::set<int>* dst, const std::set<int>& src) { void ApplyGpuDriverBugWorkarounds(const GPUInfo& gpu_info, base::CommandLine* command_line) { - scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); + std::unique_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); list->LoadList(kGpuDriverBugListJson, GpuControlList::kCurrentOsOnly); std::set<int> workarounds = list->MakeDecision( @@ -95,4 +108,41 @@ void StringToFeatureSet( StringToIntSet(str, feature_set); } +void ParseSecondaryGpuDevicesFromCommandLine( + const base::CommandLine& command_line, + GPUInfo* gpu_info) { + DCHECK(gpu_info); + + const char* secondary_vendor_switch_key = switches::kGpuSecondaryVendorIDs; + const char* secondary_device_switch_key = switches::kGpuSecondaryDeviceIDs; + + if (command_line.HasSwitch(switches::kGpuTestingSecondaryVendorIDs) && + command_line.HasSwitch(switches::kGpuTestingSecondaryDeviceIDs)) { + secondary_vendor_switch_key = switches::kGpuTestingSecondaryVendorIDs; + secondary_device_switch_key = switches::kGpuTestingSecondaryDeviceIDs; + } + + if (!command_line.HasSwitch(secondary_vendor_switch_key) || + !command_line.HasSwitch(secondary_device_switch_key)) { + return; + } + + std::vector<uint32_t> vendor_ids; + std::vector<uint32_t> device_ids; + StringToIds(command_line.GetSwitchValueASCII(secondary_vendor_switch_key), + &vendor_ids); + StringToIds(command_line.GetSwitchValueASCII(secondary_device_switch_key), + &device_ids); + + DCHECK(vendor_ids.size() == device_ids.size()); + gpu_info->secondary_gpus.clear(); + for (size_t i = 0; i < vendor_ids.size() && i < device_ids.size(); ++i) { + gpu::GPUInfo::GPUDevice secondary_device; + secondary_device.active = false; + secondary_device.vendor_id = vendor_ids[i]; + secondary_device.device_id = device_ids[i]; + gpu_info->secondary_gpus.push_back(secondary_device); + } +} + } // namespace gpu diff --git a/chromium/gpu/config/gpu_util.h b/chromium/gpu/config/gpu_util.h index 6b89303d3bb..710c21d7b29 100644 --- a/chromium/gpu/config/gpu_util.h +++ b/chromium/gpu/config/gpu_util.h @@ -34,6 +34,12 @@ GPU_EXPORT void ApplyGpuDriverBugWorkarounds( GPU_EXPORT void StringToFeatureSet( const std::string& str, std::set<int>* feature_set); +// With provided command line, fill gpu_info->secondary_gpus with parsed +// secondary vendor and device ids. +GPU_EXPORT void ParseSecondaryGpuDevicesFromCommandLine( + const base::CommandLine& command_line, + GPUInfo* gpu_info); + } // namespace gpu #endif // GPU_CONFIG_GPU_UTIL_H_ diff --git a/chromium/gpu/config/gpu_util_unittest.cc b/chromium/gpu/config/gpu_util_unittest.cc index fb7fd2be94c..da52c18a279 100644 --- a/chromium/gpu/config/gpu_util_unittest.cc +++ b/chromium/gpu/config/gpu_util_unittest.cc @@ -3,12 +3,16 @@ // found in the LICENSE file. #include "gpu/config/gpu_util.h" -#include "base/memory/scoped_ptr.h" + +#include <memory> + #include "base/strings/string_split.h" +#include "base/strings/stringprintf.h" #include "gpu/config/gpu_control_list_jsons.h" #include "gpu/config/gpu_driver_bug_list.h" #include "gpu/config/gpu_info.h" #include "gpu/config/gpu_info_collector.h" +#include "gpu/config/gpu_switches.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_switches.h" @@ -79,7 +83,7 @@ TEST(GpuUtilTest, ApplyGpuDriverBugWorkarounds_DisabledExtensions) { GPUInfo gpu_info; CollectBasicGraphicsInfo(&gpu_info); - scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); + std::unique_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); list->LoadList(kGpuDriverBugListJson, GpuControlList::kCurrentOsOnly); list->MakeDecision(GpuControlList::kOsAny, std::string(), gpu_info); std::vector<std::string> expected_disabled_extensions = @@ -97,4 +101,112 @@ TEST(GpuUtilTest, EXPECT_EQ(expected_disabled_extensions, actual_disabled_extensions); } +TEST(GpuUtilTest, ParseSecondaryGpuDevicesFromCommandLine_Simple) { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + command_line.AppendSwitchASCII(switches::kGpuSecondaryVendorIDs, "0x10de"); + command_line.AppendSwitchASCII(switches::kGpuSecondaryDeviceIDs, "0x0de1"); + + GPUInfo gpu_info; + ParseSecondaryGpuDevicesFromCommandLine(command_line, &gpu_info); + + EXPECT_EQ(gpu_info.secondary_gpus.size(), 1ul); + EXPECT_EQ(gpu_info.secondary_gpus[0].vendor_id, 0x10deul); + EXPECT_EQ(gpu_info.secondary_gpus[0].device_id, 0x0de1ul); +} + +TEST(GpuUtilTest, ParseSecondaryGpuDevicesFromCommandLine_Multiple) { + std::vector<std::pair<uint32_t, uint32_t>> gpu_devices = { + {0x10de, 0x0de1}, {0x1002, 0x6779}, {0x8086, 0x040a}}; + + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + command_line.AppendSwitchASCII(switches::kGpuSecondaryVendorIDs, + "0x10de;0x1002;0x8086"); + command_line.AppendSwitchASCII(switches::kGpuSecondaryDeviceIDs, + "0x0de1;0x6779;0x040a"); + + GPUInfo gpu_info; + ParseSecondaryGpuDevicesFromCommandLine(command_line, &gpu_info); + EXPECT_EQ(gpu_info.secondary_gpus.size(), 3ul); + EXPECT_EQ(gpu_info.secondary_gpus.size(), gpu_devices.size()); + + for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) { + EXPECT_EQ(gpu_info.secondary_gpus[i].vendor_id, gpu_devices[i].first); + EXPECT_EQ(gpu_info.secondary_gpus[i].device_id, gpu_devices[i].second); + } +} + +TEST(GpuUtilTest, ParseSecondaryGpuDevicesFromCommandLine_Generated) { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + std::vector<std::pair<uint32_t, uint32_t>> gpu_devices; + + std::string vendor_ids_str; + std::string device_ids_str; + for (uint32_t i = 0x80000000; i > 1; i >>= 1) { + gpu_devices.push_back(std::pair<uint32_t, uint32_t>(i, i + 1)); + + if (!vendor_ids_str.empty()) + vendor_ids_str += ";"; + if (!device_ids_str.empty()) + device_ids_str += ";"; + vendor_ids_str += base::StringPrintf("0x%04x", i); + device_ids_str += base::StringPrintf("0x%04x", i + 1); + } + + command_line.AppendSwitchASCII(switches::kGpuSecondaryVendorIDs, + vendor_ids_str); + command_line.AppendSwitchASCII(switches::kGpuSecondaryDeviceIDs, + device_ids_str); + + GPUInfo gpu_info; + ParseSecondaryGpuDevicesFromCommandLine(command_line, &gpu_info); + + EXPECT_EQ(gpu_devices.size(), 31ul); + EXPECT_EQ(gpu_info.secondary_gpus.size(), gpu_devices.size()); + + for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) { + EXPECT_EQ(gpu_info.secondary_gpus[i].vendor_id, gpu_devices[i].first); + EXPECT_EQ(gpu_info.secondary_gpus[i].device_id, gpu_devices[i].second); + } +} + +TEST(GpuUtilTest, ParseSecondaryGpuDevicesFromCommandLine_Testing) { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + + command_line.AppendSwitchASCII(switches::kGpuSecondaryVendorIDs, "0x10de"); + command_line.AppendSwitchASCII(switches::kGpuSecondaryDeviceIDs, "0x0de1"); + + command_line.AppendSwitchASCII(switches::kGpuTestingSecondaryVendorIDs, + "0x10de;0x1002"); + command_line.AppendSwitchASCII(switches::kGpuTestingSecondaryDeviceIDs, + "0x0de1;0x6779"); + + GPUInfo gpu_info; + ParseSecondaryGpuDevicesFromCommandLine(command_line, &gpu_info); + + EXPECT_EQ(gpu_info.secondary_gpus.size(), 2ul); + EXPECT_EQ(gpu_info.secondary_gpus[0].vendor_id, 0x10deul); + EXPECT_EQ(gpu_info.secondary_gpus[0].device_id, 0x0de1ul); + EXPECT_EQ(gpu_info.secondary_gpus[1].vendor_id, 0x1002ul); + EXPECT_EQ(gpu_info.secondary_gpus[1].device_id, 0x6779ul); +} + +TEST(GpuUtilTest, ParseSecondaryGpuDevicesFromCommandLine_TestingClear) { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + + command_line.AppendSwitchASCII(switches::kGpuSecondaryVendorIDs, + "0x1002;0x10de"); + command_line.AppendSwitchASCII(switches::kGpuSecondaryDeviceIDs, + "0x6779;0x0de1"); + + GPUInfo gpu_info; + ParseSecondaryGpuDevicesFromCommandLine(command_line, &gpu_info); + EXPECT_EQ(gpu_info.secondary_gpus.size(), 2ul); + + command_line.AppendSwitchASCII(switches::kGpuTestingSecondaryVendorIDs, ""); + command_line.AppendSwitchASCII(switches::kGpuTestingSecondaryDeviceIDs, ""); + + ParseSecondaryGpuDevicesFromCommandLine(command_line, &gpu_info); + EXPECT_EQ(gpu_info.secondary_gpus.size(), 0ul); +} + } // namespace gpu diff --git a/chromium/gpu/config/software_rendering_list_json.cc b/chromium/gpu/config/software_rendering_list_json.cc index ed1dcd66c9f..b0d7df37243 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.18", + "version": "11.2", "entries": [ { "id": 1, @@ -33,7 +33,8 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "features": [ "webgl", "flash_3d", - "flash_stage3d" + "flash_stage3d", + "gpu_rasterization" ] }, { @@ -122,7 +123,8 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "features": [ "webgl", "flash_3d", - "flash_stage3d" + "flash_stage3d", + "gpu_rasterization" ] }, { @@ -397,7 +399,8 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "device_id": ["0x0863"], "multi_gpu_category": "any", "features": [ - "accelerated_2d_canvas" + "accelerated_2d_canvas", + "gpu_rasterization" ] }, { @@ -415,7 +418,8 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "device_id": ["0x6760", "0x6720"], "multi_gpu_category": "any", "features": [ - "webgl" + "webgl", + "gpu_rasterization" ] }, { @@ -518,7 +522,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( { "id": 50, "description": "Disable VMware software renderer on older Mesa", - "cr_bugs": [145531, 332596], + "cr_bugs": [145531, 332596, 571899], "os": { "type": "linux" }, @@ -531,6 +535,14 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "value": "9.2.1" }, "gl_renderer": ".*SVGA3D.*" + }, + { + "driver_vendor": "Mesa", + "driver_version": { + "op": ">=", + "value": "10.1.3" + }, + "gl_renderer": ".*Gallium.*llvmpipe.*" } ], "features": [ @@ -713,7 +725,8 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "device_id": ["0x0a29", "0x0861", "0x0863"], "multi_gpu_category": "any", "features": [ - "webgl" + "webgl", + "gpu_rasterization" ] }, { @@ -818,38 +831,6 @@ LONG_STRING_CONST( ] }, { - "id": 83, - "description": "Samsung Galaxy NOTE is too buggy to use for video decoding", - "cr_bugs": [308721], - "os": { - "type": "android", - "version": { - "op": "<", - "value": "4.4" - } - }, - "machine_model_name": ["GT-.*"], - "features": [ - "accelerated_video_decode" - ] - }, - { - "id": 85, - "description": "Samsung Galaxy S4 is too buggy to use for video decoding", - "cr_bugs": [329072], - "os": { - "type": "android", - "version": { - "op": "<", - "value": "4.4" - } - }, - "machine_model_name": ["SCH-.*"], - "features": [ - "accelerated_video_decode" - ] - }, - { "id": 86, "description": "Intel Graphics Media Accelerator 3150 causes the GPU process to hang running WebGL", "cr_bugs": [305431], @@ -1072,22 +1053,6 @@ LONG_STRING_CONST( ] }, { - "id": 101, - "description": "Samsung Galaxy Tab is too buggy to use for video decoding", - "cr_bugs": [408353], - "os": { - "type": "android", - "version": { - "op": "<", - "value": "4.4" - } - }, - "machine_model_name": ["SM-.*"], - "features": [ - "accelerated_video_decode" - ] - }, - { "id": 102, "description": "Accelerated 2D canvas and Ganesh broken on Galaxy Tab 2", "cr_bugs": [416910], @@ -1212,6 +1177,128 @@ LONG_STRING_CONST( "features": [ "accelerated_video_decode" ] + }, + { + "id": 110, + "description": "Only enable WebGL for the Mesa Gallium llvmpipe driver", + "cr_bugs": [571899], + "os": { + "type": "linux" + }, + "driver_vendor": "Mesa", + "gl_vendor": "VMware.*", + "gl_renderer": ".*Gallium.*llvmpipe.*", + "features": [ + "all", + {"exceptions": [ + "webgl" + ]} + ] + }, + { + "id": 111, + "description": "Apple Software Renderer used under VMWare experiences synchronization issues with GPU Raster", + "cr_bugs": [607829], + "os": { + "type": "macosx" + }, + "vendor_id": "0x15ad", + "multi_gpu_category": "any", + "features": [ + "gpu_rasterization" + ] + }, + { + "id": 112, + "description": "Some GPUs on Mac can perform poorly with GPU rasterization. Disable all known Intel GPUs other than Intel 6th and 7th Generation cards, which have been tested.", + "cr_bugs": [613272, 614468], + "os": { + "type": "macosx" + }, + "vendor_id": "0x8086", + "device_id": ["0x0126", "0x0116", "0x191e", "0x0046", "0x1912", + "0x2a02", "0x27a2", "0x2a42"], + "multi_gpu_category": "any", + "features": [ + "gpu_rasterization" + ] + }, + { + "id": 113, + "description": "Some GPUs on Mac can perform poorly with GPU rasterization. Disable all known NVidia GPUs other than the Geforce 6xx and 7xx series, which have been tested.", + "cr_bugs": [613272, 614468], + "os": { + "type": "macosx" + }, + "vendor_id": "0x10de", + "device_id": ["0x0863", "0x08a0", "0x0a29", "0x0869", "0x0867", + "0x08a3", "0x11a3", "0x08a2", "0x0407", "0x0861", + "0x08a4", "0x0647", "0x0640", "0x0866", "0x0655", + "0x062e", "0x0609", "0x1187", "0x13c2", "0x0602", + "0x1180", "0x1401", "0x0fc8", "0x0611", "0x1189", + "0x11c0", "0x0870", "0x0a65", "0x06dd", "0x0fc1", + "0x1380", "0x11c6", "0x104a", "0x1184", "0x0fc6", + "0x13c0", "0x1381", "0x05e3", "0x1183", "0x05fe", + "0x1004", "0x17c8", "0x11ba", "0x0a20", "0x0f00", + "0x0ca3", "0x06fd", "0x0f02", "0x0614", "0x0402", + "0x13bb", "0x0401", "0x0f01", "0x1287", "0x0615", + "0x1402", "0x019d", "0x0400", "0x0622", "0x06e4", + "0x06cd", "0x1201", "0x100a", "0x10c3", "0x1086", + "0x17c2", "0x1005", "0x0a23", "0x0de0", "0x1040", + "0x0421", "0x1282", "0x0e22", "0x0e23", "0x0610", + "0x11c8", "0x11c2", "0x1188", "0x0de9", "0x1200", + "0x1244", "0x0dc4", "0x0df8", "0x0641", "0x0613", + "0x11fa", "0x100c", "0x0de1", "0x0ca5", "0x0cb1", + "0x0a6c", "0x05ff", "0x05e2", "0x0a2d", "0x06c0", + "0x1288", "0x1048", "0x1081", "0x0dd8", "0x05e6", + "0x11c4", "0x0605", "0x1080", "0x042f", "0x0ca2", + "0x1245", "0x124d", "0x1284", "0x0191", "0x1050", + "0x0ffd", "0x0193", "0x061a", "0x0422", "0x1185", + "0x103a", "0x0fc2", "0x0194", "0x0df5", "0x040e", + "0x065b", "0x0de2", "0x0a75", "0x0601", "0x1087", + "0x019e", "0x104b", "0x107d", "0x1382", "0x042b", + "0x1049", "0x0df0", "0x11a1", "0x040f", "0x0de3", + "0x0fc0", "0x13d8", "0x0de4", "0x11e2", "0x0644", + "0x0fd1", "0x0dfa"], + "multi_gpu_category": "any", + "features": [ + "gpu_rasterization" + ] + }, + { + "id": 114, + "description": "Some GPUs on Mac can perform poorly with GPU rasterization. Disable all known AMD GPUs other than the R200, R300, and D series, which have been tested.", + "cr_bugs": [613272, 614468], + "os": { + "type": "macosx" + }, + "vendor_id": "0x1002", + "device_id": ["0x6741", "0x6740", "0x9488", "0x9583", "0x6720", + "0x6760", "0x68c0", "0x68a1", "0x944a", "0x94c8", + "0x6819", "0x68b8", "0x6920", "0x6938", "0x6640", + "0x9588", "0x6898", "0x9440", "0x6738", "0x6739", + "0x6818", "0x6758", "0x6779", "0x9490", "0x68d9", + "0x683f", "0x683d", "0x6899", "0x6759", "0x68e0", + "0x68d8", "0x68ba", "0x68f9", "0x9501", "0x68a0", + "0x6841", "0x6840", "0x9442", "0x6658", "0x68c8", + "0x68c1"], + "multi_gpu_category": "any", + "features": [ + "gpu_rasterization" + ] + }, + { + "id": 115, + "description": "Some GPUs on Mac can perform poorly with GPU rasterization. Disable untested Virtualbox GPU.", + "cr_bugs": [613272, 614468], + "os": { + "type": "macosx" + }, + "vendor_id": "0x80ee", + "multi_gpu_category": "any", + "features": [ + "gpu_rasterization" + ] } ] } diff --git a/chromium/gpu/gles2_conform_support/BUILD.gn b/chromium/gpu/gles2_conform_support/BUILD.gn index 2dd0e2a9e44..5867daf552d 100644 --- a/chromium/gpu/gles2_conform_support/BUILD.gn +++ b/chromium/gpu/gles2_conform_support/BUILD.gn @@ -57,6 +57,7 @@ executable("gles2_conform_support") { "//base", "//base/third_party/dynamic_annotations", "//build/config/sanitizers:deps", + "//build/win:default_exe_manifest", "//gpu/command_buffer/client:gles2_c_lib_nocheck", "//gpu/gles2_conform_support/egl", "//ui/gl", diff --git a/chromium/gpu/gles2_conform_support/egl/BUILD.gn b/chromium/gpu/gles2_conform_support/egl/BUILD.gn index 556f053f70a..f11dd0ad285 100644 --- a/chromium/gpu/gles2_conform_support/egl/BUILD.gn +++ b/chromium/gpu/gles2_conform_support/egl/BUILD.gn @@ -8,11 +8,17 @@ source_set("egl") { sources = [ "config.cc", "config.h", + "context.cc", + "context.h", "display.cc", "display.h", "egl.cc", "surface.cc", "surface.h", + "test_support.cc", + "test_support.h", + "thread_state.cc", + "thread_state.h", ] configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] @@ -28,6 +34,7 @@ source_set("egl") { "//gpu:command_buffer_gles2", "//gpu/command_buffer/client:gles2_c_lib_nocheck", "//gpu/command_buffer/client:gles2_implementation_no_check", + "//gpu/command_buffer/common:gles2_utils", "//gpu/command_buffer/service", "//ui/base", "//ui/gfx", diff --git a/chromium/gpu/gles2_conform_support/egl/config.cc b/chromium/gpu/gles2_conform_support/egl/config.cc index d6ce3072c98..53bd440d7cb 100644 --- a/chromium/gpu/gles2_conform_support/egl/config.cc +++ b/chromium/gpu/gles2_conform_support/egl/config.cc @@ -3,10 +3,11 @@ // found in the LICENSE file. #include "gpu/gles2_conform_support/egl/config.h" +#include "base/logging.h" namespace egl { -Config::Config() +Config::Config(EGLint surface_type) : buffer_size_(0), red_size_(0), green_size_(0), @@ -34,16 +35,37 @@ Config::Config() sample_buffers_(0), samples_(0), stencil_size_(0), - surface_type_(EGL_WINDOW_BIT), + surface_type_(surface_type), transparent_type_(EGL_NONE), transparent_red_value_(EGL_DONT_CARE), transparent_green_value_(EGL_DONT_CARE), transparent_blue_value_(EGL_DONT_CARE) { + DCHECK(surface_type == EGL_WINDOW_BIT || surface_type == EGL_PBUFFER_BIT); } Config::~Config() { } +bool Config::Matches(const EGLint* attrib_list) const { + DCHECK(ValidateAttributeList(attrib_list)); + if (attrib_list) { + for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) { + switch (attrib_list[i]) { + case EGL_SURFACE_TYPE: { + EGLint requested_surface_type = attrib_list[i + 1]; + if (requested_surface_type != EGL_DONT_CARE && + (requested_surface_type & surface_type_) != + requested_surface_type) + return false; + } + default: + break; + } + } + } + return true; +} + bool Config::GetAttrib(EGLint attribute, EGLint* value) const { // TODO(alokp): Find out how to get correct values. switch (attribute) { @@ -149,4 +171,52 @@ bool Config::GetAttrib(EGLint attribute, EGLint* value) const { return true; } +bool Config::ValidateAttributeList(const EGLint* attrib_list) { + if (attrib_list) { + for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) { + switch (attrib_list[i]) { + case EGL_ALPHA_MASK_SIZE: + case EGL_ALPHA_SIZE: + case EGL_BIND_TO_TEXTURE_RGB: + case EGL_BIND_TO_TEXTURE_RGBA: + case EGL_BLUE_SIZE: + case EGL_BUFFER_SIZE: + case EGL_COLOR_BUFFER_TYPE: + case EGL_CONFIG_CAVEAT: + case EGL_CONFIG_ID: + case EGL_CONFORMANT: + case EGL_DEPTH_SIZE: + case EGL_GREEN_SIZE: + case EGL_LEVEL: + case EGL_LUMINANCE_SIZE: + case EGL_MATCH_NATIVE_PIXMAP: + case EGL_NATIVE_RENDERABLE: + case EGL_MAX_SWAP_INTERVAL: + case EGL_MIN_SWAP_INTERVAL: + case EGL_RED_SIZE: + case EGL_SAMPLE_BUFFERS: + case EGL_SAMPLES: + case EGL_STENCIL_SIZE: + case EGL_RENDERABLE_TYPE: + case EGL_SURFACE_TYPE: + case EGL_MULTISAMPLE_RESOLVE_BOX_BIT: + case EGL_PBUFFER_BIT: + case EGL_PIXMAP_BIT: + case EGL_SWAP_BEHAVIOR_PRESERVED_BIT: + case EGL_VG_ALPHA_FORMAT_PRE_BIT: + case EGL_VG_COLORSPACE_LINEAR_BIT: + case EGL_WINDOW_BIT: + case EGL_TRANSPARENT_TYPE: + case EGL_TRANSPARENT_RED_VALUE: + case EGL_TRANSPARENT_GREEN_VALUE: + case EGL_TRANSPARENT_BLUE_VALUE: + break; + default: + return false; + } + } + } + return true; +} + } // namespace egl diff --git a/chromium/gpu/gles2_conform_support/egl/config.h b/chromium/gpu/gles2_conform_support/egl/config.h index 53bb5682181..1ce815648d9 100644 --- a/chromium/gpu/gles2_conform_support/egl/config.h +++ b/chromium/gpu/gles2_conform_support/egl/config.h @@ -13,10 +13,11 @@ namespace egl { class Config { public: - Config(); + explicit Config(EGLint surface_type); ~Config(); - + bool Matches(const EGLint* attrib_list) const; bool GetAttrib(EGLint attribute, EGLint* value) const; + static bool ValidateAttributeList(const EGLint* attrib_list); private: // Total color component bits in the color buffer. diff --git a/chromium/gpu/gles2_conform_support/egl/context.cc b/chromium/gpu/gles2_conform_support/egl/context.cc new file mode 100644 index 00000000000..4d9e592bbfc --- /dev/null +++ b/chromium/gpu/gles2_conform_support/egl/context.cc @@ -0,0 +1,395 @@ +// Copyright (c) 2016 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/gles2_conform_support/egl/context.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/command_line.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/gles2_lib.h" +#include "gpu/command_buffer/client/shared_memory_limits.h" +#include "gpu/command_buffer/client/transfer_buffer.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/memory_tracking.h" +#include "gpu/command_buffer/service/transfer_buffer_manager.h" +#include "gpu/gles2_conform_support/egl/config.h" +#include "gpu/gles2_conform_support/egl/display.h" +#include "gpu/gles2_conform_support/egl/surface.h" +#include "gpu/gles2_conform_support/egl/thread_state.h" +#include "ui/gl/init/gl_factory.h" + +// The slight complexification in this file comes from following properties: +// 1) Command buffer connection (context) can not be established without a +// GLSurface. EGL Context can be created independent of a surface. This is why +// the connection is created only during first MakeCurrent. +// 2) Command buffer MakeCurrent calls need the real gl context and surface be +// current. +// 3) Client can change real EGL context behind the scenes and then still expect +// command buffer MakeCurrent re-set the command buffer context. This is why all +// MakeCurrent calls must actually reset the real context, even though command +// buffer current context does not change. +// 4) EGL context can be destroyed without surface, but command buffer would +// need the surface to run various cleanups. If context is destroyed +// surfaceless, the context is marked lost before destruction. This is avoided +// if possible, since command buffer at the time of writing prints out debug +// text in this case. + +namespace { +const int32_t kCommandBufferSize = 1024 * 1024; +const int32_t kTransferBufferSize = 512 * 1024; +const bool kBindGeneratesResources = true; +const bool kLoseContextWhenOutOfMemory = false; +const bool kSupportClientSideArrays = true; +} + +namespace egl { +Context::Context(Display* display, const Config* config) + : display_(display), + config_(config), + is_current_in_some_thread_(false), + is_destroyed_(false), + gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()) { +} + +Context::~Context() { + // We might not have a surface, so we must lose the context. Cleanup will + // execute GL commands otherwise. TODO: if shared contexts are ever + // implemented, this will leak the GL resources. For pbuffer contexts, one + // could track the last current surface or create a surface for destroying + // purposes only. Other option would be to make the service usable without + // surface. + if (HasService()) { + if (!WasServiceContextLost()) + MarkServiceContextLost(); + DestroyService(); + } +} + +void Context::MarkDestroyed() { + is_destroyed_ = true; +} + +bool Context::SwapBuffers(Surface* current_surface) { + DCHECK(HasService() && is_current_in_some_thread_); + if (WasServiceContextLost()) + return false; + client_gl_context_->SwapBuffers(); + return true; +} + +bool Context::MakeCurrent(Context* current_context, + Surface* current_surface, + Context* new_context, + Surface* new_surface) { + if (!new_context && !current_context) { + return true; + } + bool cleanup_old_current_context = false; + if (current_context) { + if (current_context->Flush(current_surface->gl_surface())) + cleanup_old_current_context = new_context != current_context; + } + + if (new_context) { + if (!new_context->IsCompatibleSurface(new_surface)) + return false; + + if (new_context->HasService()) { + if (new_context->WasServiceContextLost()) + return false; + if (new_context != current_context) { + // If Flush did not set the current context, set it now. Otherwise + // calling into the decoder is not ok. + if (!new_context->gl_context_->MakeCurrent(new_surface->gl_surface())) { + new_context->MarkServiceContextLost(); + return false; + } + } + if (new_context != current_context || new_surface != current_surface) + new_context->decoder_->SetSurface(new_surface->gl_surface()); + if (!new_context->decoder_->MakeCurrent()) { + new_context->MarkServiceContextLost(); + return false; + } + } else { + if (!new_context->CreateService(new_surface->gl_surface())) { + return false; + } + } + } + + // The current_surface will be released when MakeCurrent succeeds. + // Cleanup in this case only. + if (cleanup_old_current_context) { + if (current_context->is_destroyed_ && current_surface != new_surface) { + current_context->gl_context_->MakeCurrent(current_surface->gl_surface()); + // If we are releasing the context and we have one ref, it means that the + // ref will be lost and the object will be destroyed. Destroy the service + // explicitly here, so that cleanup can happen and client GL + // implementation does not print errors. + current_context->DestroyService(); + } else { + current_context->decoder_->ReleaseSurface(); + } + } + + return true; +} + +bool Context::ValidateAttributeList(const EGLint* attrib_list) { + if (attrib_list) { + for (int i = 0; attrib_list[i] != EGL_NONE; attrib_list += 2) { + switch (attrib_list[i]) { + case EGL_CONTEXT_CLIENT_VERSION: + break; + default: + return false; + } + } + } + return true; +} + +void Context::SetGpuControlClient(gpu::GpuControlClient*) { + // The client is not currently called, so don't store it. +} + +gpu::Capabilities Context::GetCapabilities() { + return decoder_->GetCapabilities(); +} + +int32_t Context::CreateImage(ClientBuffer buffer, + size_t width, + size_t height, + unsigned internalformat) { + NOTIMPLEMENTED(); + return -1; +} + +void Context::DestroyImage(int32_t id) { + NOTIMPLEMENTED(); +} + +int32_t Context::CreateGpuMemoryBufferImage(size_t width, + size_t height, + unsigned internalformat, + unsigned usage) { + NOTIMPLEMENTED(); + return -1; +} + +void Context::SignalQuery(uint32_t query, const base::Closure& callback) { + NOTIMPLEMENTED(); +} + +void Context::SetLock(base::Lock*) { + NOTIMPLEMENTED(); +} + +void Context::EnsureWorkVisible() { + // This is only relevant for out-of-process command buffers. +} + +gpu::CommandBufferNamespace Context::GetNamespaceID() const { + return gpu::CommandBufferNamespace::IN_PROCESS; +} + +gpu::CommandBufferId Context::GetCommandBufferID() const { + return gpu::CommandBufferId(); +} + +int32_t Context::GetExtraCommandBufferData() const { + return 0; +} + +uint64_t Context::GenerateFenceSyncRelease() { + return display_->GenerateFenceSyncRelease(); +} + +bool Context::IsFenceSyncRelease(uint64_t release) { + return display_->IsFenceSyncRelease(release); +} + +bool Context::IsFenceSyncFlushed(uint64_t release) { + return display_->IsFenceSyncFlushed(release); +} + +bool Context::IsFenceSyncFlushReceived(uint64_t release) { + return display_->IsFenceSyncFlushReceived(release); +} + +void Context::SignalSyncToken(const gpu::SyncToken& sync_token, + const base::Closure& callback) { + NOTIMPLEMENTED(); +} + +bool Context::CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) { + return false; +} + +void Context::ApplyCurrentContext(gfx::GLSurface* current_surface) { + DCHECK(HasService()); + // The current_surface will be the same as + // the surface of the decoder. We can not DCHECK as there is + // no accessor. + if (!WasServiceContextLost()) { + if (!gl_context_->MakeCurrent(current_surface)) + MarkServiceContextLost(); + } + gles2::SetGLContext(client_gl_context_.get()); +} + +void Context::ApplyContextReleased() { + gles2::SetGLContext(nullptr); +} + +bool Context::CreateService(gfx::GLSurface* gl_surface) { + scoped_refptr<gpu::TransferBufferManager> transfer_buffer_manager( + new gpu::TransferBufferManager(nullptr)); + transfer_buffer_manager->Initialize(); + + std::unique_ptr<gpu::CommandBufferService> command_buffer( + new gpu::CommandBufferService(transfer_buffer_manager.get())); + + scoped_refptr<gpu::gles2::FeatureInfo> feature_info( + new gpu::gles2::FeatureInfo(gpu_driver_bug_workarounds_)); + scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup( + gpu_preferences_, nullptr, nullptr, + new gpu::gles2::ShaderTranslatorCache(gpu_preferences_), + new gpu::gles2::FramebufferCompletenessCache, feature_info, true)); + + std::unique_ptr<gpu::gles2::GLES2Decoder> decoder( + gpu::gles2::GLES2Decoder::Create(group.get())); + if (!decoder.get()) + return false; + + std::unique_ptr<gpu::CommandExecutor> command_executor( + new gpu::CommandExecutor(command_buffer.get(), decoder.get(), + decoder.get())); + + decoder->set_engine(command_executor.get()); + + scoped_refptr<gfx::GLContext> gl_context( + gl::init::CreateGLContext(nullptr, gl_surface, gfx::PreferDiscreteGpu)); + if (!gl_context) + return false; + + gl_context->MakeCurrent(gl_surface); + + gpu::gles2::ContextCreationAttribHelper helper; + config_->GetAttrib(EGL_ALPHA_SIZE, &helper.alpha_size); + config_->GetAttrib(EGL_DEPTH_SIZE, &helper.depth_size); + config_->GetAttrib(EGL_STENCIL_SIZE, &helper.stencil_size); + + helper.buffer_preserved = false; + helper.bind_generates_resource = kBindGeneratesResources; + helper.fail_if_major_perf_caveat = false; + helper.lose_context_when_out_of_memory = kLoseContextWhenOutOfMemory; + helper.context_type = gpu::gles2::CONTEXT_TYPE_OPENGLES2; + + if (!decoder->Initialize(gl_surface, gl_context.get(), + gl_surface->IsOffscreen(), gl_surface->GetSize(), + gpu::gles2::DisallowedFeatures(), helper)) { + return false; + } + + command_buffer->SetPutOffsetChangeCallback( + base::Bind(&gpu::CommandExecutor::PutChanged, + base::Unretained(command_executor.get()))); + command_buffer->SetGetBufferChangeCallback( + base::Bind(&gpu::CommandExecutor::SetGetBuffer, + base::Unretained(command_executor.get()))); + + std::unique_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper( + new gpu::gles2::GLES2CmdHelper(command_buffer.get())); + if (!gles2_cmd_helper->Initialize(kCommandBufferSize)) { + decoder->Destroy(true); + return false; + } + + std::unique_ptr<gpu::TransferBuffer> transfer_buffer( + new gpu::TransferBuffer(gles2_cmd_helper.get())); + + gles2_cmd_helper_.reset(gles2_cmd_helper.release()); + transfer_buffer_.reset(transfer_buffer.release()); + command_buffer_.reset(command_buffer.release()); + command_executor_.reset(command_executor.release()); + decoder_.reset(decoder.release()); + gl_context_ = gl_context.get(); + + std::unique_ptr<gpu::gles2::GLES2Implementation> context( + new gpu::gles2::GLES2Implementation( + gles2_cmd_helper_.get(), nullptr, transfer_buffer_.get(), + kBindGeneratesResources, kLoseContextWhenOutOfMemory, + kSupportClientSideArrays, this)); + + if (!context->Initialize(kTransferBufferSize, kTransferBufferSize / 2, + kTransferBufferSize * 2, + gpu::SharedMemoryLimits::kNoLimit)) { + DestroyService(); + return false; + } + + context->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets"); + context->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs"); + client_gl_context_.reset(context.release()); + return true; +} + +void Context::DestroyService() { + DCHECK(HasService()); + bool have_context = !WasServiceContextLost(); + // The client gl interface might still be set to current global + // interface. This will be cleaned up in ApplyContextReleased + // with AutoCurrentContextRestore. + client_gl_context_.reset(); + gl_context_ = nullptr; + + transfer_buffer_.reset(); + command_executor_.reset(); + if (decoder_) + decoder_->Destroy(have_context); + decoder_.reset(); + gles2_cmd_helper_.reset(); + command_buffer_.reset(); +} + +bool Context::HasService() const { + return decoder_ != nullptr; +} + +void Context::MarkServiceContextLost() { + decoder_->GetContextGroup()->LoseContexts(gpu::error::kMakeCurrentFailed); +} + +bool Context::WasServiceContextLost() const { + return decoder_->WasContextLost(); +} + +bool Context::IsCompatibleSurface(Surface* surface) const { + // Inspect current_surface->config() instead of gl_surface()->IsOffscreen() + // because GTF windowless window surfaces might be emulated with offscreen + // surfaces. + EGLint value = EGL_NONE; + config_->GetAttrib(EGL_SURFACE_TYPE, &value); + bool context_config_is_offscreen = (value & EGL_PBUFFER_BIT) != 0; + surface->config()->GetAttrib(EGL_SURFACE_TYPE, &value); + bool surface_config_is_offscreen = (value & EGL_PBUFFER_BIT) != 0; + return surface_config_is_offscreen == context_config_is_offscreen; +} + +bool Context::Flush(gfx::GLSurface* gl_surface) { + if (WasServiceContextLost()) + return false; + if (!gl_context_->MakeCurrent(gl_surface)) { + MarkServiceContextLost(); + return false; + } + client_gl_context_->Flush(); + return true; +} + +} // namespace egl diff --git a/chromium/gpu/gles2_conform_support/egl/context.h b/chromium/gpu/gles2_conform_support/egl/context.h new file mode 100644 index 00000000000..a5facf22dc5 --- /dev/null +++ b/chromium/gpu/gles2_conform_support/egl/context.h @@ -0,0 +1,123 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_GLES2_CONFORM_TEST_CONTEXT_H_ +#define GPU_GLES2_CONFORM_TEST_CONTEXT_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "gpu/command_buffer/client/gles2_cmd_helper.h" +#include "gpu/command_buffer/client/gpu_control.h" +#include "gpu/command_buffer/service/command_buffer_service.h" +#include "gpu/command_buffer/service/command_executor.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/gpu_preferences.h" +#include "gpu/config/gpu_driver_bug_workarounds.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_surface.h" +#include "ui/gl/gl_surface.h" +#include <EGL/egl.h> + +namespace gpu { +class TransferBuffer; +class TransferBufferManagerInterface; + +namespace gles2 { +class GLES2CmdHelper; +class GLES2Interface; +} // namespace gles2 +} // namespace gpu + +namespace egl { +class Display; +class Surface; +class Config; + +class Context : public base::RefCountedThreadSafe<Context>, + private gpu::GpuControl { + public: + Context(Display* display, const Config* config); + bool is_current_in_some_thread() const { return is_current_in_some_thread_; } + void set_is_current_in_some_thread(bool flag) { + is_current_in_some_thread_ = flag; + } + void MarkDestroyed(); + bool SwapBuffers(Surface* current_surface); + + static bool MakeCurrent(Context* current_context, + Surface* current_surface, + Context* new_context, + Surface* new_surface); + + static bool ValidateAttributeList(const EGLint* attrib_list); + + // GpuControl implementation. + void SetGpuControlClient(gpu::GpuControlClient*) override; + gpu::Capabilities GetCapabilities() override; + int32_t CreateImage(ClientBuffer buffer, + size_t width, + size_t height, + unsigned internalformat) override; + void DestroyImage(int32_t id) override; + int32_t CreateGpuMemoryBufferImage(size_t width, + size_t height, + unsigned internalformat, + unsigned usage) override; + void SignalQuery(uint32_t query, const base::Closure& callback) override; + void SetLock(base::Lock*) override; + void EnsureWorkVisible() override; + gpu::CommandBufferNamespace GetNamespaceID() const override; + gpu::CommandBufferId GetCommandBufferID() const override; + int32_t GetExtraCommandBufferData() const override; + uint64_t GenerateFenceSyncRelease() override; + bool IsFenceSyncRelease(uint64_t release) override; + bool IsFenceSyncFlushed(uint64_t release) override; + bool IsFenceSyncFlushReceived(uint64_t release) override; + void SignalSyncToken(const gpu::SyncToken& sync_token, + const base::Closure& callback) override; + bool CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) override; + + // Called by ThreadState to set the needed global variables when this context + // is current. + void ApplyCurrentContext(gfx::GLSurface* current_surface); + static void ApplyContextReleased(); + + private: + friend class base::RefCountedThreadSafe<Context>; + ~Context() override; + bool CreateService(gfx::GLSurface* gl_surface); + void DestroyService(); + // Returns true if the object has GL service, either a working one or one + // that has lost its GL context. + bool HasService() const; + void MarkServiceContextLost(); + bool WasServiceContextLost() const; + bool IsCompatibleSurface(Surface* surface) const; + bool Flush(gfx::GLSurface* gl_surface); + + Display* display_; + const Config* config_; + bool is_current_in_some_thread_; + bool is_destroyed_; + gpu::GpuPreferences gpu_preferences_; + const gpu::GpuDriverBugWorkarounds gpu_driver_bug_workarounds_; + std::unique_ptr<gpu::CommandBufferService> command_buffer_; + std::unique_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper_; + std::unique_ptr<gpu::gles2::GLES2Decoder> decoder_; + std::unique_ptr<gpu::CommandExecutor> command_executor_; + std::unique_ptr<gpu::TransferBuffer> transfer_buffer_; + + scoped_refptr<gfx::GLContext> gl_context_; + + std::unique_ptr<gpu::gles2::GLES2Interface> client_gl_context_; + DISALLOW_COPY_AND_ASSIGN(Context); +}; + +} // namespace egl + +#endif // GPU_GLES2_CONFORM_TEST_CONTEXT_H_ diff --git a/chromium/gpu/gles2_conform_support/egl/display.cc b/chromium/gpu/gles2_conform_support/egl/display.cc index 0223a86fb1a..f80820f6091 100644 --- a/chromium/gpu/gles2_conform_support/egl/display.cc +++ b/chromium/gpu/gles2_conform_support/egl/display.cc @@ -4,133 +4,116 @@ #include "gpu/gles2_conform_support/egl/display.h" -#include <stddef.h> -#include <stdint.h> - -#include <vector> -#include "base/at_exit.h" -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/lazy_instance.h" -#include "gpu/command_buffer/client/gles2_implementation.h" -#include "gpu/command_buffer/client/gles2_lib.h" -#include "gpu/command_buffer/client/transfer_buffer.h" -#include "gpu/command_buffer/common/value_state.h" -#include "gpu/command_buffer/service/context_group.h" -#include "gpu/command_buffer/service/mailbox_manager.h" -#include "gpu/command_buffer/service/memory_tracking.h" -#include "gpu/command_buffer/service/transfer_buffer_manager.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" #include "gpu/gles2_conform_support/egl/config.h" +#include "gpu/gles2_conform_support/egl/context.h" #include "gpu/gles2_conform_support/egl/surface.h" -#include "gpu/gles2_conform_support/egl/test_support.h" - -namespace { -const int32_t kCommandBufferSize = 1024 * 1024; -const int32_t kTransferBufferSize = 512 * 1024; -} +#include "gpu/gles2_conform_support/egl/thread_state.h" +#include "ui/gl/init/gl_factory.h" namespace egl { -#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) -// egl::Display is used for comformance tests and command_buffer_gles. We only -// need the exit manager for the command_buffer_gles library. -// TODO(hendrikw): Find a cleaner solution for this. -namespace { -base::LazyInstance<base::Lock>::Leaky g_exit_manager_lock; -int g_exit_manager_use_count; -base::AtExitManager* g_exit_manager; -void RefAtExitManager() { - base::AutoLock lock(g_exit_manager_lock.Get()); -#if defined(COMPONENT_BUILD) - if (g_command_buffer_gles_has_atexit_manager) { - return; - } -#endif - if (g_exit_manager_use_count == 0) { - g_exit_manager = new base::AtExitManager; - } - ++g_exit_manager_use_count; -} -void ReleaseAtExitManager() { - base::AutoLock lock(g_exit_manager_lock.Get()); -#if defined(COMPONENT_BUILD) - if (g_command_buffer_gles_has_atexit_manager) { - return; - } -#endif - --g_exit_manager_use_count; - if (g_exit_manager_use_count == 0) { - delete g_exit_manager; - g_exit_manager = nullptr; - } -} -} -#endif - -Display::Display(EGLNativeDisplayType display_id) - : display_id_(display_id), - is_initialized_(false), - create_offscreen_(false), - create_offscreen_width_(0), - create_offscreen_height_(0), - next_fence_sync_release_(1) { -#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) - RefAtExitManager(); -#endif + +Display::Display() + : is_initialized_(false), + next_create_window_surface_creates_pbuffer_(false), + window_surface_pbuffer_width_(0), + window_surface_pbuffer_height_(0) { } Display::~Display() { - gles2::Terminate(); -#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) - ReleaseAtExitManager(); -#endif + surfaces_.clear(); + contexts_.clear(); } - -bool Display::Initialize() { - gles2::Initialize(); - is_initialized_ = true; - return true; +void Display::SetNextCreateWindowSurfaceCreatesPBuffer(EGLint width, + EGLint height) { + next_create_window_surface_creates_pbuffer_ = true; + window_surface_pbuffer_width_ = width; + window_surface_pbuffer_height_ = height; } -bool Display::IsValidConfig(EGLConfig config) { - return (config != NULL) && (config == config_.get()); -} +EGLBoolean Display::Initialize(ThreadState* ts, EGLint* major, EGLint* minor) { + base::AutoLock auto_lock(lock_); + is_initialized_ = true; -bool Display::ChooseConfigs(EGLConfig* configs, - EGLint config_size, - EGLint* num_config) { - // TODO(alokp): Find out a way to find all configs. CommandBuffer currently - // does not support finding or choosing configs. - *num_config = 1; - if (configs != NULL) { - if (config_ == NULL) { - config_.reset(new Config); - } - configs[0] = config_.get(); + if (major) + *major = 1; + if (minor) + *minor = 4; + return ts->ReturnSuccess(EGL_TRUE); +} + +EGLBoolean Display::Terminate(ThreadState* ts) { + base::AutoLock auto_lock(lock_); + is_initialized_ = false; + surfaces_.clear(); + for (const auto& context : contexts_) + context->MarkDestroyed(); + contexts_.clear(); + return ts->ReturnSuccess(EGL_TRUE); +} + +const char* Display::QueryString(ThreadState* ts, EGLint name) { + base::AutoLock auto_lock(lock_); + if (!is_initialized_) + return ts->ReturnError<const char*>(EGL_NOT_INITIALIZED, nullptr); + switch (name) { + case EGL_CLIENT_APIS: + return ts->ReturnSuccess("OpenGL_ES"); + case EGL_EXTENSIONS: + return ts->ReturnSuccess(""); + case EGL_VENDOR: + return ts->ReturnSuccess("Google Inc."); + case EGL_VERSION: + return ts->ReturnSuccess("1.4"); + default: + return ts->ReturnError<const char*>(EGL_BAD_PARAMETER, nullptr); } - return true; } -bool Display::GetConfigs(EGLConfig* configs, - EGLint config_size, - EGLint* num_config) { - // TODO(alokp): Find out a way to find all configs. CommandBuffer currently - // does not support finding or choosing configs. - *num_config = 1; - if (configs != NULL) { - if (config_ == NULL) { - config_.reset(new Config); +EGLBoolean Display::ChooseConfig(ThreadState* ts, + const EGLint* attrib_list, + EGLConfig* configs, + EGLint config_size, + EGLint* num_config) { + base::AutoLock auto_lock(lock_); + if (!is_initialized_) + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); + if (num_config == nullptr) + return ts->ReturnError(EGL_BAD_PARAMETER, EGL_FALSE); + if (!Config::ValidateAttributeList(attrib_list)) + return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + InitializeConfigsIfNeeded(); + if (!configs) + config_size = 0; + *num_config = 0; + for (size_t i = 0; i < arraysize(configs_); ++i) { + if (configs_[i]->Matches(attrib_list)) { + if (*num_config < config_size) { + configs[*num_config] = configs_[i].get(); + } + ++*num_config; } - configs[0] = config_.get(); } - return true; -} - -bool Display::GetConfigAttrib(EGLConfig config, - EGLint attribute, - EGLint* value) { - const egl::Config* cfg = static_cast<egl::Config*>(config); - return cfg->GetAttrib(attribute, value); + return ts->ReturnSuccess(EGL_TRUE); +} + +EGLBoolean Display::GetConfigs(ThreadState* ts, + EGLConfig* configs, + EGLint config_size, + EGLint* num_config) { + base::AutoLock auto_lock(lock_); + if (!is_initialized_) + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); + if (num_config == nullptr) + return ts->ReturnError(EGL_BAD_PARAMETER, EGL_FALSE); + InitializeConfigsIfNeeded(); + if (!configs) + config_size = 0; + *num_config = arraysize(configs_); + size_t count = + std::min(arraysize(configs_), static_cast<size_t>(config_size)); + for (size_t i = 0; i < count; ++i) + configs[i] = configs_[i].get(); + return ts->ReturnSuccess(EGL_TRUE); } bool Display::IsValidNativeWindow(EGLNativeWindowType win) { @@ -142,244 +125,232 @@ bool Display::IsValidNativeWindow(EGLNativeWindowType win) { #endif // OS_WIN } -bool Display::IsValidSurface(EGLSurface surface) { - return (surface != NULL) && (surface == surface_.get()); +EGLBoolean Display::GetConfigAttrib(ThreadState* ts, + EGLConfig cfg, + EGLint attribute, + EGLint* value) { + base::AutoLock auto_lock(lock_); + if (!is_initialized_) + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); + const egl::Config* config = GetConfig(cfg); + if (!config) + return ts->ReturnError(EGL_BAD_CONFIG, EGL_FALSE); + if (!config->GetAttrib(attribute, value)) + return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + return ts->ReturnSuccess(EGL_TRUE); +} + +EGLSurface Display::CreatePbufferSurface(ThreadState* ts, + EGLConfig cfg, + const EGLint* attrib_list) { + base::AutoLock auto_lock(lock_); + if (!is_initialized_) + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_SURFACE); + const egl::Config* config = GetConfig(cfg); + if (!config) + return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE); + EGLint value = EGL_NONE; + config->GetAttrib(EGL_SURFACE_TYPE, &value); + if ((value & EGL_PBUFFER_BIT) == 0) + return ts->ReturnError(EGL_BAD_MATCH, EGL_NO_SURFACE); + if (!egl::Surface::ValidatePbufferAttributeList(attrib_list)) + return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + + int width = 1; + int height = 1; + if (attrib_list) { + for (const int32_t* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) { + switch (attr[0]) { + case EGL_WIDTH: + width = attr[1]; + break; + case EGL_HEIGHT: + height = attr[1]; + break; + } + } + } + return DoCreatePbufferSurface(ts, config, width, height); +} + +EGLSurface Display::DoCreatePbufferSurface(ThreadState* ts, + const Config* config, + EGLint width, + EGLint height) { + lock_.AssertAcquired(); + scoped_refptr<gfx::GLSurface> gl_surface; + gl_surface = gl::init::CreateOffscreenGLSurface(gfx::Size(width, height)); + if (!gl_surface) + return ts->ReturnError(EGL_BAD_ALLOC, nullptr); + surfaces_.emplace_back(new Surface(gl_surface.get(), config)); + return ts->ReturnSuccess<EGLSurface>(surfaces_.back().get()); } -EGLSurface Display::CreateWindowSurface(EGLConfig config, +EGLSurface Display::CreateWindowSurface(ThreadState* ts, + EGLConfig cfg, EGLNativeWindowType win, const EGLint* attrib_list) { - if (surface_ != NULL) { - // We do not support more than one window surface. - return EGL_NO_SURFACE; + base::AutoLock auto_lock(lock_); + if (!is_initialized_) + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_SURFACE); + const egl::Config* config = GetConfig(cfg); + if (!config) + return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE); + EGLint value = EGL_NONE; + config->GetAttrib(EGL_SURFACE_TYPE, &value); + if ((value & EGL_WINDOW_BIT) == 0) + return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE); + if (!next_create_window_surface_creates_pbuffer_ && !IsValidNativeWindow(win)) + return ts->ReturnError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + if (!Surface::ValidateWindowAttributeList(attrib_list)) + return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + if (next_create_window_surface_creates_pbuffer_) { + EGLSurface result = DoCreatePbufferSurface(ts, config, + window_surface_pbuffer_width_, + window_surface_pbuffer_height_); + next_create_window_surface_creates_pbuffer_ = false; + window_surface_pbuffer_width_ = 0; + window_surface_pbuffer_height_ = 0; + return result; } - - { - gpu::TransferBufferManager* manager = - new gpu::TransferBufferManager(nullptr); - transfer_buffer_manager_ = manager; - manager->Initialize(); - } - scoped_ptr<gpu::CommandBufferService> command_buffer( - new gpu::CommandBufferService(transfer_buffer_manager_.get())); - if (!command_buffer->Initialize()) - return NULL; - - scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup( - gpu_preferences_, NULL, NULL, - new gpu::gles2::ShaderTranslatorCache(gpu_preferences_), - new gpu::gles2::FramebufferCompletenessCache, NULL, NULL, NULL, true)); - - decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get())); - if (!decoder_.get()) - return EGL_NO_SURFACE; - - executor_.reset( - new gpu::CommandExecutor(command_buffer.get(), decoder_.get(), NULL)); - - decoder_->set_engine(executor_.get()); - gfx::Size size(create_offscreen_width_, create_offscreen_height_); - if (create_offscreen_) { - gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size); - create_offscreen_ = false; - create_offscreen_width_ = 0; - create_offscreen_height_ = 0; - } else { - gl_surface_ = gfx::GLSurface::CreateViewGLSurface(win); - } - if (!gl_surface_.get()) - return EGL_NO_SURFACE; - - gl_context_ = gfx::GLContext::CreateGLContext(NULL, - gl_surface_.get(), - gfx::PreferDiscreteGpu); - if (!gl_context_.get()) - return EGL_NO_SURFACE; - - gl_context_->MakeCurrent(gl_surface_.get()); - - EGLint depth_size = 0; - EGLint alpha_size = 0; - EGLint stencil_size = 0; - GetConfigAttrib(config, EGL_DEPTH_SIZE, &depth_size); - GetConfigAttrib(config, EGL_ALPHA_SIZE, &alpha_size); - GetConfigAttrib(config, EGL_STENCIL_SIZE, &stencil_size); - std::vector<int32_t> attribs; - attribs.push_back(EGL_DEPTH_SIZE); - attribs.push_back(depth_size); - attribs.push_back(EGL_ALPHA_SIZE); - attribs.push_back(alpha_size); - attribs.push_back(EGL_STENCIL_SIZE); - attribs.push_back(stencil_size); - // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null - attribs.push_back(EGL_NONE); - - if (!decoder_->Initialize(gl_surface_.get(), - gl_context_.get(), - gl_surface_->IsOffscreen(), - size, - gpu::gles2::DisallowedFeatures(), - attribs)) { - return EGL_NO_SURFACE; + scoped_refptr<gfx::GLSurface> gl_surface; + gl_surface = gl::init::CreateViewGLSurface(win); + if (!gl_surface) + return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + surfaces_.emplace_back(new Surface(gl_surface.get(), config)); + return ts->ReturnSuccess(surfaces_.back().get()); +} + +EGLBoolean Display::DestroySurface(ThreadState* ts, EGLSurface sfe) { + base::AutoLock auto_lock(lock_); + if (!is_initialized_) + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); + auto it = std::find(surfaces_.begin(), surfaces_.end(), sfe); + if (it == surfaces_.end()) + return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); + surfaces_.erase(it); + return ts->ReturnSuccess(EGL_TRUE); +} + +EGLBoolean Display::ReleaseCurrent(ThreadState* ts) { + base::AutoLock auto_lock(lock_); + if (!is_initialized_) + return ts->ReturnSuccess(EGL_TRUE); + ThreadState::AutoCurrentContextRestore accr(ts); + if (ts->current_context()) { + Context::MakeCurrent(ts->current_context(), ts->current_surface(), nullptr, + nullptr); + accr.SetCurrent(nullptr, nullptr); } - - command_buffer->SetPutOffsetChangeCallback(base::Bind( - &gpu::CommandExecutor::PutChanged, base::Unretained(executor_.get()))); - command_buffer->SetGetBufferChangeCallback(base::Bind( - &gpu::CommandExecutor::SetGetBuffer, base::Unretained(executor_.get()))); - - scoped_ptr<gpu::gles2::GLES2CmdHelper> cmd_helper( - new gpu::gles2::GLES2CmdHelper(command_buffer.get())); - if (!cmd_helper->Initialize(kCommandBufferSize)) - return NULL; - - scoped_ptr<gpu::TransferBuffer> transfer_buffer(new gpu::TransferBuffer( - cmd_helper.get())); - - command_buffer_.reset(command_buffer.release()); - transfer_buffer_.reset(transfer_buffer.release()); - gles2_cmd_helper_.reset(cmd_helper.release()); - surface_.reset(new Surface(win)); - - return surface_.get(); -} - -void Display::DestroySurface(EGLSurface surface) { - DCHECK(IsValidSurface(surface)); - executor_.reset(); - if (decoder_.get()) { - decoder_->Destroy(true); - } - decoder_.reset(); - gl_surface_ = NULL; - gl_context_ = NULL; - surface_.reset(); -} - -void Display::SwapBuffers(EGLSurface surface) { - DCHECK(IsValidSurface(surface)); - context_->SwapBuffers(); -} - -bool Display::IsValidContext(EGLContext ctx) { - return (ctx != NULL) && (ctx == context_.get()); -} - -EGLContext Display::CreateContext(EGLConfig config, + return ts->ReturnSuccess(EGL_TRUE); +} + +EGLBoolean Display::MakeCurrent(ThreadState* ts, + EGLSurface draw, + EGLSurface read, + EGLSurface ctx) { + base::AutoLock auto_lock(lock_); + if (!is_initialized_) + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); + ThreadState::AutoCurrentContextRestore accr(ts); + // Client might have called use because it changed some other gl binding + // global state. For example, the client might have called eglMakeCurrent on + // the same EGL as what command buffer uses. The client probably knows that + // this invalidates the internal state of command buffer, too. So reset the + // current context with accr in any case, regardless whether context or + // surface pointer changes. + Surface* new_surface = GetSurface(draw); + if (!new_surface) + return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); + new_surface = GetSurface(read); + if (!new_surface) + return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); + egl::Context* new_context = GetContext(ctx); + if (!new_context) + return ts->ReturnError(EGL_BAD_CONTEXT, EGL_FALSE); + if (draw != read) + return ts->ReturnError(EGL_BAD_MATCH, EGL_FALSE); + + Surface* current_surface = ts->current_surface(); + Context* current_context = ts->current_context(); + + if (current_context != new_context && + new_context->is_current_in_some_thread()) + return ts->ReturnError(EGL_BAD_ACCESS, EGL_FALSE); + + if (current_surface != new_surface && + new_surface->is_current_in_some_thread()) + return ts->ReturnError(EGL_BAD_ACCESS, EGL_FALSE); + + if (!Context::MakeCurrent(current_context, + current_context ? current_surface : nullptr, + new_context, new_context ? new_surface : nullptr)) + return ts->ReturnError(EGL_BAD_MATCH, EGL_FALSE); + + accr.SetCurrent(new_surface, new_context); + return ts->ReturnSuccess(EGL_TRUE); +} + +EGLBoolean Display::SwapBuffers(ThreadState* ts, EGLSurface sfe) { + base::AutoLock auto_lock(lock_); + if (!is_initialized_) + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); + egl::Surface* surface = GetSurface(sfe); + if (!surface) + return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); + if (ts->current_surface() != surface) + return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); + if (!ts->current_context()->SwapBuffers(surface)) + ts->ReturnError(EGL_CONTEXT_LOST, EGL_FALSE); + return ts->ReturnSuccess(EGL_TRUE); +} + +EGLContext Display::CreateContext(ThreadState* ts, + EGLConfig cfg, EGLContext share_ctx, const EGLint* attrib_list) { - DCHECK(IsValidConfig(config)); - // TODO(alokp): Add support for shared contexts. - if (share_ctx != NULL) - return EGL_NO_CONTEXT; - - DCHECK(command_buffer_ != NULL); - DCHECK(transfer_buffer_.get()); - - bool bind_generates_resources = true; - bool lose_context_when_out_of_memory = false; - bool support_client_side_arrays = true; - - context_.reset( - new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(), - NULL, - transfer_buffer_.get(), - bind_generates_resources, - lose_context_when_out_of_memory, - support_client_side_arrays, - this)); - - if (!context_->Initialize( - kTransferBufferSize, - kTransferBufferSize / 2, - kTransferBufferSize * 2, - gpu::gles2::GLES2Implementation::kNoLimit)) { - return EGL_NO_CONTEXT; - } - - context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets"); - context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs"); - - return context_.get(); -} - -void Display::DestroyContext(EGLContext ctx) { - DCHECK(IsValidContext(ctx)); - context_.reset(); - transfer_buffer_.reset(); -} - -bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) { - if (ctx == EGL_NO_CONTEXT) { - gles2::SetGLContext(NULL); - } else { - DCHECK(IsValidSurface(draw)); - DCHECK(IsValidSurface(read)); - DCHECK(IsValidContext(ctx)); - gles2::SetGLContext(context_.get()); - gl_context_->MakeCurrent(gl_surface_.get()); + base::AutoLock auto_lock(lock_); + if (!is_initialized_) + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_CONTEXT); + if (share_ctx != EGL_NO_CONTEXT) { + egl::Context* share_context = GetContext(share_ctx); + if (!share_context) + return ts->ReturnError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); + // TODO(alokp): Add support for shared contexts. + return ts->ReturnError(EGL_BAD_MATCH, EGL_NO_CONTEXT); } - return true; -} - -gpu::Capabilities Display::GetCapabilities() { - return decoder_->GetCapabilities(); -} - -int32_t Display::CreateImage(ClientBuffer buffer, - size_t width, - size_t height, - unsigned internalformat) { - NOTIMPLEMENTED(); - return -1; -} - -void Display::DestroyImage(int32_t id) { - NOTIMPLEMENTED(); -} - -int32_t Display::CreateGpuMemoryBufferImage(size_t width, - size_t height, - unsigned internalformat, - unsigned usage) { - NOTIMPLEMENTED(); - return -1; -} - -void Display::SignalQuery(uint32_t query, const base::Closure& callback) { - NOTIMPLEMENTED(); -} - -void Display::SetLock(base::Lock*) { - NOTIMPLEMENTED(); -} -bool Display::IsGpuChannelLost() { - NOTIMPLEMENTED(); - return false; -} - -void Display::EnsureWorkVisible() { - // This is only relevant for out-of-process command buffers. -} - -gpu::CommandBufferNamespace Display::GetNamespaceID() const { - return gpu::CommandBufferNamespace::IN_PROCESS; -} - -gpu::CommandBufferId Display::GetCommandBufferID() const { - return gpu::CommandBufferId(); -} - -int32_t Display::GetExtraCommandBufferData() const { - return 0; + if (!egl::Context::ValidateAttributeList(attrib_list)) + return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + const egl::Config* config = GetConfig(cfg); + if (!config) + return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_CONTEXT); + scoped_refptr<Context> context(new Context(this, config)); + if (!context) + return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + contexts_.emplace_back(context.get()); + return ts->ReturnSuccess<EGLContext>(context.get()); +} + +EGLBoolean Display::DestroyContext(ThreadState* ts, EGLContext ctx) { + base::AutoLock auto_lock(lock_); + if (!is_initialized_) + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); + auto it = std::find(contexts_.begin(), contexts_.end(), ctx); + if (it == contexts_.end()) + return ts->ReturnError(EGL_BAD_CONTEXT, EGL_FALSE); + (*it)->MarkDestroyed(); + contexts_.erase(it); + return ts->ReturnSuccess(EGL_TRUE); } uint64_t Display::GenerateFenceSyncRelease() { + base::AutoLock auto_lock(lock_); return next_fence_sync_release_++; } bool Display::IsFenceSyncRelease(uint64_t release) { + base::AutoLock auto_lock(lock_); return release > 0 && release < next_fence_sync_release_; } @@ -391,13 +362,41 @@ bool Display::IsFenceSyncFlushReceived(uint64_t release) { return IsFenceSyncRelease(release); } -void Display::SignalSyncToken(const gpu::SyncToken& sync_token, - const base::Closure& callback) { - NOTIMPLEMENTED(); +void Display::InitializeConfigsIfNeeded() { + lock_.AssertAcquired(); + if (!configs_[0]) { + // The interface offers separate configs for window and pbuffer. + // This way we can record the client intention at context creation time. + // The GL implementation (gfx::GLContext and gfx::GLSurface) needs this + // distinction when creating a context. + configs_[0].reset(new Config(EGL_WINDOW_BIT)); + configs_[1].reset(new Config(EGL_PBUFFER_BIT)); + } +} + +const Config* Display::GetConfig(EGLConfig cfg) { + lock_.AssertAcquired(); + for (const auto& config : configs_) { + if (config.get() == cfg) + return config.get(); + } + return nullptr; +} + +Surface* Display::GetSurface(EGLSurface surface) { + lock_.AssertAcquired(); + auto it = std::find(surfaces_.begin(), surfaces_.end(), surface); + if (it == surfaces_.end()) + return nullptr; + return it->get(); } -bool Display::CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) { - return false; +Context* Display::GetContext(EGLContext context) { + lock_.AssertAcquired(); + auto it = std::find(contexts_.begin(), contexts_.end(), context); + if (it == contexts_.end()) + return nullptr; + return it->get(); } } // namespace egl diff --git a/chromium/gpu/gles2_conform_support/egl/display.h b/chromium/gpu/gles2_conform_support/egl/display.h index e7effca80dc..5ac6e46f7ca 100644 --- a/chromium/gpu/gles2_conform_support/egl/display.h +++ b/chromium/gpu/gles2_conform_support/egl/display.h @@ -9,124 +9,99 @@ #include <stddef.h> #include <stdint.h> +#include <memory> +#include <vector> + #include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "gpu/command_buffer/client/gles2_cmd_helper.h" -#include "gpu/command_buffer/client/gpu_control.h" -#include "gpu/command_buffer/service/command_buffer_service.h" -#include "gpu/command_buffer/service/command_executor.h" -#include "gpu/command_buffer/service/gles2_cmd_decoder.h" -#include "gpu/command_buffer/service/gpu_preferences.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/gl/gl_context.h" -#include "ui/gl/gl_surface.h" - -namespace gpu { -class CommandBufferService; -class GpuControl; -class CommandExecutor; -class TransferBuffer; -class TransferBufferManagerInterface; - -namespace gles2 { -class GLES2CmdHelper; -class GLES2Implementation; -} // namespace gles2 -} // namespace gpu +#include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" namespace egl { class Config; +class Context; class Surface; +class ThreadState; -class Display : private gpu::GpuControl { +class Display { public: - explicit Display(EGLNativeDisplayType display_id); - ~Display() override; - - void SetCreateOffscreen(int width, int height) { - create_offscreen_ = true; - create_offscreen_width_ = width; - create_offscreen_height_ = height; - } + explicit Display(); + ~Display(); bool is_initialized() const { return is_initialized_; } - bool Initialize(); + + void ReleaseCurrentForReleaseThread(ThreadState*); + + // A function for windowless GTF tests. + void SetNextCreateWindowSurfaceCreatesPBuffer(EGLint width, EGLint height); + + EGLBoolean Initialize(ThreadState* ts, EGLint* major, EGLint* minor); + EGLBoolean Terminate(ThreadState* ts); + const char* QueryString(ThreadState* ts, EGLint name); // Config routines. - bool IsValidConfig(EGLConfig config); - bool ChooseConfigs( - EGLConfig* configs, EGLint config_size, EGLint* num_config); - bool GetConfigs(EGLConfig* configs, EGLint config_size, EGLint* num_config); - bool GetConfigAttrib(EGLConfig config, EGLint attribute, EGLint* value); + EGLBoolean GetConfigAttrib(ThreadState* ts, + EGLConfig cfg, + EGLint attribute, + EGLint* value); + EGLBoolean ChooseConfig(ThreadState* ts, + const EGLint* attrib_list, + EGLConfig* configs, + EGLint config_size, + EGLint* num_config); + EGLBoolean GetConfigs(ThreadState*, + EGLConfig*, + EGLint config_size, + EGLint* num_config); // Surface routines. - bool IsValidNativeWindow(EGLNativeWindowType win); - bool IsValidSurface(EGLSurface surface); - EGLSurface CreateWindowSurface(EGLConfig config, + static bool IsValidNativeWindow(EGLNativeWindowType); + EGLSurface CreatePbufferSurface(ThreadState*, + EGLConfig, + const EGLint* attrib_list); + EGLSurface CreateWindowSurface(ThreadState*, + EGLConfig, EGLNativeWindowType win, const EGLint* attrib_list); - void DestroySurface(EGLSurface surface); - void SwapBuffers(EGLSurface surface); + EGLBoolean DestroySurface(ThreadState*, EGLSurface); + EGLBoolean SwapBuffers(ThreadState*, EGLSurface); // Context routines. - bool IsValidContext(EGLContext ctx); - EGLContext CreateContext(EGLConfig config, - EGLContext share_ctx, + EGLContext CreateContext(ThreadState*, + EGLConfig, + EGLSurface share_ctx, const EGLint* attrib_list); - void DestroyContext(EGLContext ctx); - bool MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx); - - // GpuControl implementation. - gpu::Capabilities GetCapabilities() override; - int32_t CreateImage(ClientBuffer buffer, - size_t width, - size_t height, - unsigned internalformat) override; - void DestroyImage(int32_t id) override; - int32_t CreateGpuMemoryBufferImage(size_t width, - size_t height, - unsigned internalformat, - unsigned usage) override; - void SignalQuery(uint32_t query, const base::Closure& callback) override; - void SetLock(base::Lock*) override; - bool IsGpuChannelLost() override; - void EnsureWorkVisible() override; - gpu::CommandBufferNamespace GetNamespaceID() const override; - gpu::CommandBufferId GetCommandBufferID() const override; - int32_t GetExtraCommandBufferData() const override; - uint64_t GenerateFenceSyncRelease() override; - bool IsFenceSyncRelease(uint64_t release) override; - bool IsFenceSyncFlushed(uint64_t release) override; - bool IsFenceSyncFlushReceived(uint64_t release) override; - void SignalSyncToken(const gpu::SyncToken& sync_token, - const base::Closure& callback) override; - bool CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) override; + EGLBoolean DestroyContext(ThreadState*, EGLContext); - private: - EGLNativeDisplayType display_id_; + EGLBoolean ReleaseCurrent(ThreadState*); + EGLBoolean MakeCurrent(ThreadState*, EGLSurface, EGLSurface, EGLContext); - gpu::GpuPreferences gpu_preferences_; - bool is_initialized_; + uint64_t GenerateFenceSyncRelease(); + bool IsFenceSyncRelease(uint64_t release); + bool IsFenceSyncFlushed(uint64_t release); + bool IsFenceSyncFlushReceived(uint64_t release); - bool create_offscreen_; - int create_offscreen_width_; - int create_offscreen_height_; + private: + void InitializeConfigsIfNeeded(); + const Config* GetConfig(EGLConfig); + Surface* GetSurface(EGLSurface); + Context* GetContext(EGLContext); + EGLSurface DoCreatePbufferSurface(ThreadState* ts, + const Config* config, + EGLint width, + EGLint height); + + base::Lock lock_; + bool is_initialized_; uint64_t next_fence_sync_release_; - - scoped_refptr<gpu::TransferBufferManagerInterface> transfer_buffer_manager_; - scoped_ptr<gpu::CommandBufferService> command_buffer_; - scoped_ptr<gpu::CommandExecutor> executor_; - scoped_ptr<gpu::gles2::GLES2Decoder> decoder_; - scoped_refptr<gfx::GLContext> gl_context_; - scoped_refptr<gfx::GLSurface> gl_surface_; - scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper_; - scoped_ptr<gpu::TransferBuffer> transfer_buffer_; - - // TODO(alokp): Support more than one config, surface, and context. - scoped_ptr<Config> config_; - scoped_ptr<Surface> surface_; - scoped_ptr<gpu::gles2::GLES2Implementation> context_; + std::vector<scoped_refptr<Surface>> surfaces_; + std::vector<scoped_refptr<Context>> contexts_; + std::unique_ptr<Config> configs_[2]; + + // GTF windowless support. + bool next_create_window_surface_creates_pbuffer_; + EGLint window_surface_pbuffer_width_; + EGLint window_surface_pbuffer_height_; DISALLOW_COPY_AND_ASSIGN(Display); }; diff --git a/chromium/gpu/gles2_conform_support/egl/egl.cc b/chromium/gpu/gles2_conform_support/egl/egl.cc index 5a81954bd10..b14479bc3b9 100644 --- a/chromium/gpu/gles2_conform_support/egl/egl.cc +++ b/chromium/gpu/gles2_conform_support/egl/egl.cc @@ -5,184 +5,58 @@ #include <EGL/egl.h> #include <stdint.h> -#include "base/command_line.h" -#include "base/environment.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" #include "gpu/command_buffer/client/gles2_lib.h" -#include "gpu/command_buffer/service/gpu_switches.h" -#include "gpu/config/gpu_info_collector.h" -#include "gpu/config/gpu_util.h" +#include "gpu/gles2_conform_support/egl/config.h" +#include "gpu/gles2_conform_support/egl/context.h" #include "gpu/gles2_conform_support/egl/display.h" -#include "ui/gl/gl_context.h" -#include "ui/gl/gl_surface.h" - -#if REGAL_STATIC_EGL -extern "C" { - -typedef EGLContext RegalSystemContext; -#define REGAL_DECL -REGAL_DECL void RegalMakeCurrent( RegalSystemContext ctx ); - -} // extern "C" -#endif - -namespace { -void SetCurrentError(EGLint error_code) { -} - -template<typename T> -T EglError(EGLint error_code, T return_value) { - SetCurrentError(error_code); - return return_value; -} - -template<typename T> -T EglSuccess(T return_value) { - SetCurrentError(EGL_SUCCESS); - return return_value; -} - -EGLint ValidateDisplay(EGLDisplay dpy) { - if (dpy == EGL_NO_DISPLAY) - return EGL_BAD_DISPLAY; - - egl::Display* display = static_cast<egl::Display*>(dpy); - if (!display->is_initialized()) - return EGL_NOT_INITIALIZED; - - return EGL_SUCCESS; -} - -EGLint ValidateDisplayConfig(EGLDisplay dpy, EGLConfig config) { - EGLint error_code = ValidateDisplay(dpy); - if (error_code != EGL_SUCCESS) - return error_code; - - egl::Display* display = static_cast<egl::Display*>(dpy); - if (!display->IsValidConfig(config)) - return EGL_BAD_CONFIG; - - return EGL_SUCCESS; -} - -EGLint ValidateDisplaySurface(EGLDisplay dpy, EGLSurface surface) { - EGLint error_code = ValidateDisplay(dpy); - if (error_code != EGL_SUCCESS) - return error_code; - - egl::Display* display = static_cast<egl::Display*>(dpy); - if (!display->IsValidSurface(surface)) - return EGL_BAD_SURFACE; - - return EGL_SUCCESS; -} - -EGLint ValidateDisplayContext(EGLDisplay dpy, EGLContext context) { - EGLint error_code = ValidateDisplay(dpy); - if (error_code != EGL_SUCCESS) - return error_code; - - egl::Display* display = static_cast<egl::Display*>(dpy); - if (!display->IsValidContext(context)) - return EGL_BAD_CONTEXT; - - return EGL_SUCCESS; -} -} // namespace +#include "gpu/gles2_conform_support/egl/surface.h" +#include "gpu/gles2_conform_support/egl/thread_state.h" extern "C" { EGLAPI EGLint EGLAPIENTRY eglGetError() { - // TODO(alokp): Fix me. - return EGL_SUCCESS; + return egl::ThreadState::Get()->ConsumeErrorCode(); } EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) { - return new egl::Display(display_id); + if (display_id != EGL_DEFAULT_DISPLAY) + return EGL_NO_DISPLAY; + return egl::ThreadState::Get()->GetDefaultDisplay(); } EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) { - if (dpy == EGL_NO_DISPLAY) - return EglError(EGL_BAD_DISPLAY, EGL_FALSE); - - egl::Display* display = static_cast<egl::Display*>(dpy); - if (!display->Initialize()) - return EglError(EGL_NOT_INITIALIZED, EGL_FALSE); - - // eglInitialize can be called multiple times, prevent InitializeOneOff from - // being called multiple times. - if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) { - base::CommandLine::StringVector argv; - scoped_ptr<base::Environment> env(base::Environment::Create()); - std::string env_string; - env->GetVar("CHROME_COMMAND_BUFFER_GLES2_ARGS", &env_string); -#if defined(OS_WIN) - argv = base::SplitString(base::UTF8ToUTF16(env_string), - base::kWhitespaceUTF16, base::TRIM_WHITESPACE, - base::SPLIT_WANT_NONEMPTY); - argv.insert(argv.begin(), base::UTF8ToUTF16("dummy")); -#else - argv = base::SplitString(env_string, - base::kWhitespaceASCII, base::TRIM_WHITESPACE, - base::SPLIT_WANT_NONEMPTY); - argv.insert(argv.begin(), "dummy"); -#endif - base::CommandLine::Init(0, nullptr); - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - // Need to call both Init and InitFromArgv, since Windows does not use - // argc, argv in CommandLine::Init(argc, argv). - command_line->InitFromArgv(argv); - if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { - gpu::GPUInfo gpu_info; - gpu::CollectBasicGraphicsInfo(&gpu_info); - gpu::ApplyGpuDriverBugWorkarounds(gpu_info, command_line); - } - - gfx::GLSurface::InitializeOneOff(); - } - if (major) - *major = 1; - if (minor) - *minor = 4; - return EglSuccess(EGL_TRUE); + egl::ThreadState* ts = egl::ThreadState::Get(); + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); + return display->Initialize(ts, major, minor); } EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) { - EGLint error_code = ValidateDisplay(dpy); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_FALSE); - - egl::Display* display = static_cast<egl::Display*>(dpy); - delete display; - - // TODO: EGL specifies that the objects are marked for deletion and they will - // remain alive as long as "contexts or surfaces associated with display is - // current to any thread". - // Currently we delete the display here, and may also call exit handlers. - - return EglSuccess(EGL_TRUE); + egl::ThreadState* ts = egl::ThreadState::Get(); + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); + return display->Terminate(ts); } EGLAPI const char* EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) { - EGLint error_code = ValidateDisplay(dpy); - if (error_code != EGL_SUCCESS) - return EglError(error_code, static_cast<const char*>(NULL)); - - switch (name) { - case EGL_CLIENT_APIS: - return EglSuccess("OpenGL_ES"); - case EGL_EXTENSIONS: - return EglSuccess(""); - case EGL_VENDOR: - return EglSuccess("Google Inc."); - case EGL_VERSION: - return EglSuccess("1.4"); - default: - return EglError(EGL_BAD_PARAMETER, static_cast<const char*>(NULL)); + egl::ThreadState* ts = egl::ThreadState::Get(); + if (dpy == EGL_NO_DISPLAY) { + switch (name) { + case EGL_EXTENSIONS: + return ts->ReturnSuccess(""); + case EGL_VERSION: + return ts->ReturnSuccess("1.4"); + default: + break; + } } + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError<const char*>(EGL_BAD_DISPLAY, nullptr); + return display->QueryString(ts, name); } EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, @@ -190,103 +64,57 @@ EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config) { - EGLint error_code = ValidateDisplay(dpy); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_FALSE); - - if (num_config == NULL) - return EglError(EGL_BAD_PARAMETER, EGL_FALSE); - - egl::Display* display = static_cast<egl::Display*>(dpy); - if (!display->ChooseConfigs(configs, config_size, num_config)) - return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE); - - return EglSuccess(EGL_TRUE); + egl::ThreadState* ts = egl::ThreadState::Get(); + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); + return display->ChooseConfig(ts, attrib_list, configs, config_size, + num_config); } EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config) { - EGLint error_code = ValidateDisplay(dpy); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_FALSE); - - if (num_config == NULL) - return EglError(EGL_BAD_PARAMETER, EGL_FALSE); - - egl::Display* display = static_cast<egl::Display*>(dpy); - if (!display->GetConfigs(configs, config_size, num_config)) - return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE); - - return EglSuccess(EGL_TRUE); + egl::ThreadState* ts = egl::ThreadState::Get(); + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); + return display->GetConfigs(ts, configs, config_size, num_config); } EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, - EGLConfig config, + EGLConfig cfg, EGLint attribute, EGLint* value) { - EGLint error_code = ValidateDisplayConfig(dpy, config); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_FALSE); - - egl::Display* display = static_cast<egl::Display*>(dpy); - if (!display->GetConfigAttrib(config, attribute, value)) - return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE); - - return EglSuccess(EGL_TRUE); + egl::ThreadState* ts = egl::ThreadState::Get(); + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); + return display->GetConfigAttrib(ts, cfg, attribute, value); } EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, - EGLConfig config, + EGLConfig cfg, EGLNativeWindowType win, const EGLint* attrib_list) { - EGLint error_code = ValidateDisplayConfig(dpy, config); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_NO_SURFACE); - - egl::Display* display = static_cast<egl::Display*>(dpy); - if (!display->IsValidNativeWindow(win)) - return EglError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); - - EGLSurface surface = display->CreateWindowSurface(config, win, attrib_list); - if (surface == EGL_NO_SURFACE) - return EglError(EGL_BAD_ALLOC, EGL_NO_SURFACE); - - return EglSuccess(surface); + egl::ThreadState* ts = egl::ThreadState::Get(); + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + return display->CreateWindowSurface(ts, cfg, win, attrib_list); } EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, - EGLConfig config, + EGLConfig cfg, const EGLint* attrib_list) { - EGLint error_code = ValidateDisplayConfig(dpy, config); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_NO_SURFACE); - - egl::Display* display = static_cast<egl::Display*>(dpy); - int width = 1; - int height = 1; - if (attrib_list) { - for (const int32_t* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) { - switch (attr[0]) { - case EGL_WIDTH: - width = attr[1]; - break; - case EGL_HEIGHT: - height = attr[1]; - break; - } - } - } - display->SetCreateOffscreen(width, height); - - EGLSurface surface = display->CreateWindowSurface(config, 0, attrib_list); - if (surface == EGL_NO_SURFACE) - return EglError(EGL_BAD_ALLOC, EGL_NO_SURFACE); - - return EglSuccess(surface); + egl::ThreadState* ts = egl::ThreadState::Get(); + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + return display->CreatePbufferSurface(ts, cfg, attrib_list); } EGLAPI EGLSurface EGLAPIENTRY @@ -298,14 +126,12 @@ eglCreatePixmapSurface(EGLDisplay dpy, } EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, - EGLSurface surface) { - EGLint error_code = ValidateDisplaySurface(dpy, surface); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_FALSE); - - egl::Display* display = static_cast<egl::Display*>(dpy); - display->DestroySurface(surface); - return EglSuccess(EGL_TRUE); + EGLSurface sfe) { + egl::ThreadState* ts = egl::ThreadState::Get(); + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); + return display->DestroySurface(ts, sfe); } EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, @@ -328,7 +154,8 @@ EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void) { } EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void) { - return EGL_FALSE; + egl::ThreadState::ReleaseThread(); + return EGL_TRUE; } EGLAPI EGLSurface EGLAPIENTRY @@ -364,64 +191,42 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval) { } EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, - EGLConfig config, - EGLContext share_context, + EGLConfig cfg, + EGLContext share_ctx, const EGLint* attrib_list) { - EGLint error_code = ValidateDisplayConfig(dpy, config); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_NO_CONTEXT); - - if (share_context != EGL_NO_CONTEXT) { - error_code = ValidateDisplayContext(dpy, share_context); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_NO_CONTEXT); - } - - egl::Display* display = static_cast<egl::Display*>(dpy); - EGLContext context = display->CreateContext( - config, share_context, attrib_list); - if (context == EGL_NO_CONTEXT) - return EglError(EGL_BAD_ALLOC, EGL_NO_CONTEXT); - - return EglSuccess(context); + egl::ThreadState* ts = egl::ThreadState::Get(); + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_NO_CONTEXT); + return display->CreateContext(ts, cfg, share_ctx, attrib_list); } EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { - EGLint error_code = ValidateDisplayContext(dpy, ctx); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_FALSE); - - egl::Display* display = static_cast<egl::Display*>(dpy); - display->DestroyContext(ctx); - return EGL_TRUE; + egl::ThreadState* ts = egl::ThreadState::Get(); + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); + return display->DestroyContext(ts, ctx); } EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { - if (ctx != EGL_NO_CONTEXT) { - EGLint error_code = ValidateDisplaySurface(dpy, draw); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_FALSE); - error_code = ValidateDisplaySurface(dpy, read); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_FALSE); - error_code = ValidateDisplayContext(dpy, ctx); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_FALSE); + egl::ThreadState* ts = egl::ThreadState::Get(); + if (draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE && + ctx == EGL_NO_CONTEXT) { + egl::Display* display = + dpy == EGL_NO_DISPLAY ? ts->GetDefaultDisplay() : ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); + return display->ReleaseCurrent(ts); } - - egl::Display* display = static_cast<egl::Display*>(dpy); - if (!display->MakeCurrent(draw, read, ctx)) - return EglError(EGL_CONTEXT_LOST, EGL_FALSE); - -#if REGAL_STATIC_EGL - RegalMakeCurrent(ctx); -#endif - - return EGL_TRUE; + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); + return display->MakeCurrent(ts, draw, read, ctx); } EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext() { @@ -451,15 +256,12 @@ EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine) { return EGL_FALSE; } -EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, - EGLSurface surface) { - EGLint error_code = ValidateDisplaySurface(dpy, surface); - if (error_code != EGL_SUCCESS) - return EglError(error_code, EGL_FALSE); - - egl::Display* display = static_cast<egl::Display*>(dpy); - display->SwapBuffers(surface); - return EglSuccess(EGL_TRUE); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface sfe) { + egl::ThreadState* ts = egl::ThreadState::Get(); + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); + return display->SwapBuffers(ts, sfe); } EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, diff --git a/chromium/gpu/gles2_conform_support/egl/surface.cc b/chromium/gpu/gles2_conform_support/egl/surface.cc index 423fe2756f6..726d75349c5 100644 --- a/chromium/gpu/gles2_conform_support/egl/surface.cc +++ b/chromium/gpu/gles2_conform_support/egl/surface.cc @@ -3,13 +3,46 @@ // found in the LICENSE file. #include "gpu/gles2_conform_support/egl/surface.h" +#include "ui/gl/gl_surface.h" namespace egl { -Surface::Surface(EGLNativeWindowType win) : window_(win) { -} +Surface::Surface(gfx::GLSurface* gl_surface, const Config* config) + : is_current_in_some_thread_(false), + gl_surface_(gl_surface), + config_(config) {} Surface::~Surface() { } +gfx::GLSurface* Surface::gl_surface() const { + return gl_surface_.get(); +} + +const Config* Surface::config() const { + return config_; +} + +bool Surface::ValidatePbufferAttributeList(const EGLint* attrib_list) { + if (attrib_list) { + for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) { + switch (attrib_list[i]) { + case EGL_WIDTH: + case EGL_HEIGHT: + break; + default: + return false; + } + } + } + return true; +} + +bool Surface::ValidateWindowAttributeList(const EGLint* attrib_list) { + if (attrib_list) { + if (attrib_list[0] != EGL_NONE) + return false; + } + return true; +} } // namespace egl diff --git a/chromium/gpu/gles2_conform_support/egl/surface.h b/chromium/gpu/gles2_conform_support/egl/surface.h index 3db553efe56..3f429bd8096 100644 --- a/chromium/gpu/gles2_conform_support/egl/surface.h +++ b/chromium/gpu/gles2_conform_support/egl/surface.h @@ -8,19 +8,31 @@ #include <EGL/egl.h> #include "base/macros.h" - +#include "base/memory/ref_counted.h" +namespace gfx { +class GLSurface; +} namespace egl { +class Config; -class Surface { +class Surface : public base::RefCountedThreadSafe<Surface> { public: - explicit Surface(EGLNativeWindowType win); - ~Surface(); - - EGLNativeWindowType window() { return window_; } + explicit Surface(gfx::GLSurface* gl_surface, const Config* config); + void set_is_current_in_some_thread(bool flag) { + is_current_in_some_thread_ = flag; + } + bool is_current_in_some_thread() const { return is_current_in_some_thread_; } + gfx::GLSurface* gl_surface() const; + const Config* config() const; + static bool ValidatePbufferAttributeList(const EGLint* attrib_list); + static bool ValidateWindowAttributeList(const EGLint* attrib_list); private: - EGLNativeWindowType window_; - + friend class base::RefCountedThreadSafe<Surface>; + ~Surface(); + bool is_current_in_some_thread_; + scoped_refptr<gfx::GLSurface> gl_surface_; + const Config* config_; DISALLOW_COPY_AND_ASSIGN(Surface); }; diff --git a/chromium/gpu/gles2_conform_support/egl/test_support.cc b/chromium/gpu/gles2_conform_support/egl/test_support.cc index 938abcfd454..84fb3ef1377 100644 --- a/chromium/gpu/gles2_conform_support/egl/test_support.cc +++ b/chromium/gpu/gles2_conform_support/egl/test_support.cc @@ -3,7 +3,22 @@ // found in the LICENSE file. #include "test_support.h" +#include "gpu/gles2_conform_support/egl/display.h" +#include "gpu/gles2_conform_support/egl/thread_state.h" #if defined(COMPONENT_BUILD) && defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) bool g_command_buffer_gles_has_atexit_manager; #endif + +extern "C" { +EGLAPI void EGLAPIENTRY +CommandBufferGLESSetNextCreateWindowSurfaceCreatesPBuffer(EGLDisplay dpy, + EGLint width, + EGLint height) { + egl::ThreadState* ts = egl::ThreadState::Get(); + egl::Display* display = ts->GetDisplay(dpy); + if (!display) + return; + display->SetNextCreateWindowSurfaceCreatesPBuffer(width, height); +} +} diff --git a/chromium/gpu/gles2_conform_support/egl/test_support.h b/chromium/gpu/gles2_conform_support/egl/test_support.h index b1a70885bdc..f5cca7f53f6 100644 --- a/chromium/gpu/gles2_conform_support/egl/test_support.h +++ b/chromium/gpu/gles2_conform_support/egl/test_support.h @@ -5,6 +5,8 @@ #ifndef GPU_GLES2_CONFORM_SUPPORT_EGL_TEST_SUPPORT_H_ #define GPU_GLES2_CONFORM_SUPPORT_EGL_TEST_SUPPORT_H_ +#include <EGL/egl.h> + #if defined(COMPONENT_BUILD) && defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) // A variable used for communicating whether the app has initialized the global // variables. @@ -16,4 +18,15 @@ EGLAPI extern EGLAPIENTRY bool g_command_buffer_gles_has_atexit_manager; #endif +extern "C" { +// A function to support GTF windowless tests. gles2_conform_test_windowless and +// khronos_glcts_test_windowless create "windowless" native windows and render +// to those. The test runners do not at the moment implement creating said +// windowless native windows. This call sets the system so that it will create a +// pbuffer when eglCreateWindow is called. +EGLAPI EGLAPIENTRY void +CommandBufferGLESSetNextCreateWindowSurfaceCreatesPBuffer(EGLDisplay eglDisplay, + EGLint width, + EGLint height); +} #endif diff --git a/chromium/gpu/gles2_conform_support/egl/thread_state.cc b/chromium/gpu/gles2_conform_support/egl/thread_state.cc new file mode 100644 index 00000000000..13c5f89d7d2 --- /dev/null +++ b/chromium/gpu/gles2_conform_support/egl/thread_state.cc @@ -0,0 +1,199 @@ +// Copyright (c) 2016 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/gles2_conform_support/egl/thread_state.h" + +#include "base/at_exit.h" +#include "base/command_line.h" +#include "base/environment.h" +#include "base/lazy_instance.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "gpu/command_buffer/client/gles2_lib.h" +#include "gpu/command_buffer/common/thread_local.h" +#include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/config/gpu_info_collector.h" +#include "gpu/config/gpu_util.h" +#include "gpu/gles2_conform_support/egl/context.h" +#include "gpu/gles2_conform_support/egl/display.h" +#include "gpu/gles2_conform_support/egl/surface.h" +#include "gpu/gles2_conform_support/egl/test_support.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_surface.h" +#include "ui/gl/init/gl_factory.h" + +// Thread local key for ThreadState instance. Accessed when holding g_egl_lock +// only, since the initialization can not be Guaranteed otherwise. Not in +// anonymous namespace due to Mac OS X 10.6 linker. See gles2_lib.cc. +static gpu::ThreadLocalKey g_egl_thread_state_key; + +namespace { +base::LazyInstance<base::Lock>::Leaky g_egl_lock; +int g_egl_active_thread_count; + +egl::Display* g_egl_default_display; + +#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) +// egl::Display is used for comformance tests and command_buffer_gles. We only +// need the exit manager for the command_buffer_gles library. +base::AtExitManager* g_exit_manager; +#endif +} // namespace + +namespace egl { + +egl::ThreadState* ThreadState::Get() { + base::AutoLock lock(g_egl_lock.Get()); + if (g_egl_active_thread_count == 0) { +#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) +#if defined(COMPONENT_BUILD) + if (!g_command_buffer_gles_has_atexit_manager) + g_exit_manager = new base::AtExitManager; +#else + g_exit_manager = new base::AtExitManager; +#endif +#endif + gles2::Initialize(); + + if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) { + base::CommandLine::StringVector argv; + std::unique_ptr<base::Environment> env(base::Environment::Create()); + std::string env_string; + env->GetVar("CHROME_COMMAND_BUFFER_GLES2_ARGS", &env_string); +#if defined(OS_WIN) + argv = base::SplitString(base::UTF8ToUTF16(env_string), + base::kWhitespaceUTF16, base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); + argv.insert(argv.begin(), base::UTF8ToUTF16("dummy")); +#else + argv = + base::SplitString(env_string, base::kWhitespaceASCII, + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + argv.insert(argv.begin(), "dummy"); +#endif + base::CommandLine::Init(0, nullptr); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + // Need to call both Init and InitFromArgv, since Windows does not use + // argc, argv in CommandLine::Init(argc, argv). + command_line->InitFromArgv(argv); + if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { + gpu::GPUInfo gpu_info; + gpu::CollectBasicGraphicsInfo(&gpu_info); + gpu::ApplyGpuDriverBugWorkarounds(gpu_info, command_line); + } + + gl::init::InitializeGLOneOff(); + } + + g_egl_default_display = new egl::Display(); + g_egl_thread_state_key = gpu::ThreadLocalAlloc(); + } + egl::ThreadState* thread_state = static_cast<egl::ThreadState*>( + gpu::ThreadLocalGetValue(g_egl_thread_state_key)); + if (!thread_state) { + thread_state = new egl::ThreadState; + gpu::ThreadLocalSetValue(g_egl_thread_state_key, thread_state); + ++g_egl_active_thread_count; + } + return thread_state; +} + +void ThreadState::ReleaseThread() { + base::AutoLock lock(g_egl_lock.Get()); + if (g_egl_active_thread_count == 0) + return; + + egl::ThreadState* thread_state = static_cast<egl::ThreadState*>( + gpu::ThreadLocalGetValue(g_egl_thread_state_key)); + if (!thread_state) + return; + + --g_egl_active_thread_count; + if (g_egl_active_thread_count > 0) { + g_egl_default_display->ReleaseCurrent(thread_state); + delete thread_state; + } else { + gpu::ThreadLocalFree(g_egl_thread_state_key); + + // First delete the display object, so that it drops the possible refs to + // current context. + delete g_egl_default_display; + g_egl_default_display = nullptr; + + // We can use Surface and Context without lock, since there's no threads + // left anymore. Destroy the current context explicitly, in an attempt to + // reduce the number of error messages abandoned context would produce. + if (thread_state->current_context()) { + Context::MakeCurrent(thread_state->current_context(), + thread_state->current_surface(), nullptr, nullptr); + } + delete thread_state; + + gles2::Terminate(); +#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) +#if defined(COMPONENT_BUILD) + if (g_command_buffer_gles_has_atexit_manager) + delete g_exit_manager; +#else + delete g_exit_manager; +#endif + g_exit_manager = nullptr; +#endif + } +} + +ThreadState::ThreadState() : error_code_(EGL_SUCCESS) {} + +ThreadState::~ThreadState() {} + +EGLint ThreadState::ConsumeErrorCode() { + EGLint current_error_code = error_code_; + error_code_ = EGL_SUCCESS; + return current_error_code; +} + +Display* ThreadState::GetDisplay(EGLDisplay dpy) { + if (dpy == g_egl_default_display) + return g_egl_default_display; + return nullptr; +} + +Display* ThreadState::GetDefaultDisplay() { + return g_egl_default_display; +} + +void ThreadState::SetCurrent(Surface* surface, Context* context) { + DCHECK((surface == nullptr) == (context == nullptr)); + if (current_context_) { + current_context_->set_is_current_in_some_thread(false); + current_surface_->set_is_current_in_some_thread(false); + } + current_surface_ = surface; + current_context_ = context; + if (current_context_) { + current_context_->set_is_current_in_some_thread(true); + current_surface_->set_is_current_in_some_thread(true); + } +} + +ThreadState::AutoCurrentContextRestore::AutoCurrentContextRestore( + ThreadState* thread_state) + : thread_state_(thread_state) {} + +ThreadState::AutoCurrentContextRestore::~AutoCurrentContextRestore() { + if (Context* current_context = thread_state_->current_context()) { + current_context->ApplyCurrentContext( + thread_state_->current_surface()->gl_surface()); + } else { + Context::ApplyContextReleased(); + } +} + +void ThreadState::AutoCurrentContextRestore::SetCurrent(Surface* surface, + Context* context) { + thread_state_->SetCurrent(surface, context); +} + +} // namespace egl diff --git a/chromium/gpu/gles2_conform_support/egl/thread_state.h b/chromium/gpu/gles2_conform_support/egl/thread_state.h new file mode 100644 index 00000000000..963ac5c615c --- /dev/null +++ b/chromium/gpu/gles2_conform_support/egl/thread_state.h @@ -0,0 +1,70 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_GLES2_CONFORM_SUPPORT_EGL_STATE_H_ +#define GPU_GLES2_CONFORM_SUPPORT_EGL_STATE_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include <EGL/egl.h> + +namespace egl { + +class Context; +class Display; +class Surface; + +// Thread-local API state of EGL. +class ThreadState { + public: + // Factory getter for the class. Should only be called by the API layer, and + // then passed through Display in order to avoid lock issues. + static ThreadState* Get(); + static void ReleaseThread(); + + Surface* current_surface() const { return current_surface_.get(); } + Context* current_context() const { return current_context_.get(); } + + template <typename T> + T ReturnError(EGLint error, T return_value) { + error_code_ = error; + return return_value; + } + template <typename T> + T ReturnSuccess(T return_value) { + error_code_ = EGL_SUCCESS; + return return_value; + } + EGLint ConsumeErrorCode(); + + Display* GetDefaultDisplay(); + Display* GetDisplay(EGLDisplay); + + // RAII class for ensuring that ThreadState current context + // is reflected in the gfx:: and gles:: global variables. + class AutoCurrentContextRestore { + public: + AutoCurrentContextRestore(ThreadState*); + ~AutoCurrentContextRestore(); + void SetCurrent(Surface*, Context*); + + private: + ThreadState* thread_state_; + DISALLOW_COPY_AND_ASSIGN(AutoCurrentContextRestore); + }; + + private: + ThreadState(); + ~ThreadState(); + void SetCurrent(Surface*, Context*); + + EGLint error_code_; + scoped_refptr<Surface> current_surface_; + scoped_refptr<Context> current_context_; + DISALLOW_COPY_AND_ASSIGN(ThreadState); +}; + +} // namespace egl + +#endif diff --git a/chromium/gpu/gles2_conform_support/gles2_conform_support.gyp b/chromium/gpu/gles2_conform_support/gles2_conform_support.gyp index d4f18708910..5f97bba044a 100644 --- a/chromium/gpu/gles2_conform_support/gles2_conform_support.gyp +++ b/chromium/gpu/gles2_conform_support/gles2_conform_support.gyp @@ -27,6 +27,7 @@ 'type': 'static_library', 'dependencies': [ '../../base/base.gyp:base', + '../../gpu/command_buffer/command_buffer.gyp:gles2_utils', '../../gpu/gpu.gyp:command_buffer_service', '../../gpu/gpu.gyp:gles2_implementation_no_check', '../../gpu/gpu.gyp:gpu', @@ -34,15 +35,22 @@ '../../ui/base/ui_base.gyp:ui_base', '../../ui/gfx/gfx.gyp:gfx_geometry', '../../ui/gl/gl.gyp:gl', + '../../ui/gl/init/gl_init.gyp:gl_init', ], 'sources': [ 'egl/config.cc', 'egl/config.h', + 'egl/context.cc', + 'egl/context.h', 'egl/display.cc', 'egl/display.h', 'egl/egl.cc', 'egl/surface.cc', 'egl/surface.h', + 'egl/test_support.cc', + 'egl/test_support.h', + 'egl/thread_state.cc', + 'egl/thread_state.h', ], 'defines': [ 'EGLAPI=', diff --git a/chromium/gpu/gles2_conform_support/gles2_conform_test_expectations.txt b/chromium/gpu/gles2_conform_support/gles2_conform_test_expectations.txt index 1e78fe8dfc1..5a604e6ac52 100644 --- a/chromium/gpu/gles2_conform_support/gles2_conform_test_expectations.txt +++ b/chromium/gpu/gles2_conform_support/gles2_conform_test_expectations.txt @@ -24,6 +24,8 @@ // 91531 MAC WIN LINUX : conformance_more_* = SKIP // 91532 MAC NVIDIA 0x0640 : tex_image_and_sub_image_2d_with_video = PASS FAIL +612551 WIN LINUX MAC CHROMEOS : GL2ExtensionTests_egl_image_input_run = SKIP + 517966 WIN OPENGL : GL2FixedTests_blend_input_run = FAIL 517966 WIN OPENGL : GL2FixedTests_buffer_clear_input_run = FAIL 517966 WIN OPENGL : GL2FixedTests_buffer_color_input_run = FAIL diff --git a/chromium/gpu/gles2_conform_support/native/egl_native_windowless.cc b/chromium/gpu/gles2_conform_support/native/egl_native_windowless.cc index 725d0a05083..94d6dacac28 100644 --- a/chromium/gpu/gles2_conform_support/native/egl_native_windowless.cc +++ b/chromium/gpu/gles2_conform_support/native/egl_native_windowless.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "gpu/gles2_conform_support/egl/display.h" +#include "gpu/gles2_conform_support/egl/test_support.h" extern "C" { #if defined(GLES2_CONFORM_SUPPORT_ONLY) @@ -24,8 +24,8 @@ GTFbool GTFNativeCreateWindow(EGLNativeDisplayType nativeDisplay, EGLDisplay eglDisplay, EGLConfig eglConfig, const char* title, int width, int height, EGLNativeWindowType *pNativeWindow) { - egl::Display* display = static_cast<egl::Display*>(eglDisplay); - display->SetCreateOffscreen(width, height); + CommandBufferGLESSetNextCreateWindowSurfaceCreatesPBuffer(eglDisplay, width, + height); return GTFtrue; } diff --git a/chromium/gpu/gles2_conform_support/native/main.cc b/chromium/gpu/gles2_conform_support/native/main.cc index be1fa72dda0..672b21276a9 100644 --- a/chromium/gpu/gles2_conform_support/native/main.cc +++ b/chromium/gpu/gles2_conform_support/native/main.cc @@ -4,9 +4,10 @@ #include <stddef.h> +#include <memory> + #include "base/at_exit.h" #include "base/command_line.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #if defined(OS_MACOSX) #include "base/mac/scoped_nsautorelease_pool.h" @@ -36,7 +37,7 @@ int main(int argc, char *argv[]) { base::mac::ScopedNSAutoreleasePool pool; #endif - scoped_ptr<const char*[]> argsArray(new const char*[args.size()+1]); + std::unique_ptr<const char* []> argsArray(new const char*[args.size() + 1]); argsArray[0] = argv[0]; #if defined(OS_WIN) diff --git a/chromium/gpu/gpu.gyp b/chromium/gpu/gpu.gyp index 4968aa322c9..87e75f7e544 100644 --- a/chromium/gpu/gpu.gyp +++ b/chromium/gpu/gpu.gyp @@ -21,6 +21,7 @@ '../third_party/khronos/khronos.gyp:khronos_headers', '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/gl/gl.gyp:gl', + '../ui/gl/init/gl_init.gyp:gl_init', 'command_buffer/command_buffer.gyp:gles2_utils', 'gles2_cmd_helper', ], @@ -50,6 +51,7 @@ '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/gl/gl.gyp:gl', + '../ui/gl/init/gl_init.gyp:gl_init', ], 'defines': [ 'GL_IN_PROCESS_CONTEXT_IMPLEMENTATION', @@ -166,6 +168,7 @@ '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/gfx/gfx.gyp:gfx_test_support', '../ui/gl/gl.gyp:gl', + '../ui/gl/init/gl_init.gyp:gl_init', '../ui/gl/gl.gyp:gl_test_support', 'command_buffer/command_buffer.gyp:gles2_utils', 'command_buffer_client', @@ -214,6 +217,7 @@ 'command_buffer/service/framebuffer_manager_unittest.cc', 'command_buffer/service/gl_context_mock.cc', 'command_buffer/service/gl_context_mock.h', + 'command_buffer/service/gl_context_virtual_unittest.cc', 'command_buffer/service/gl_surface_mock.cc', 'command_buffer/service/gl_surface_mock.h', 'command_buffer/service/gles2_cmd_decoder_unittest.cc', @@ -237,11 +241,11 @@ 'command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc', 'command_buffer/service/gles2_cmd_decoder_unittest_programs.cc', 'command_buffer/service/gles2_cmd_decoder_unittest_textures.cc', - 'command_buffer/service/gles2_cmd_decoder_unittest_valuebuffer.cc', 'command_buffer/service/gpu_service_test.cc', 'command_buffer/service/gpu_service_test.h', 'command_buffer/service/gpu_tracer_unittest.cc', 'command_buffer/service/id_manager_unittest.cc', + 'command_buffer/service/indexed_buffer_binding_host_unittest.cc', 'command_buffer/service/mailbox_manager_unittest.cc', 'command_buffer/service/memory_program_cache_unittest.cc', 'command_buffer/service/mocks.cc', @@ -259,7 +263,7 @@ 'command_buffer/service/test_helper.h', 'command_buffer/service/texture_manager_unittest.cc', 'command_buffer/service/transfer_buffer_manager_unittest.cc', - 'command_buffer/service/valuebuffer_manager_unittest.cc', + 'command_buffer/service/transform_feedback_manager_unittest.cc', 'command_buffer/service/vertex_array_manager_unittest.cc', 'command_buffer/service/vertex_attrib_manager_unittest.cc', 'config/gpu_blacklist_unittest.cc', @@ -282,10 +286,13 @@ 'dependencies': [ '../testing/android/native_test.gyp:native_test_native_code', ], + 'sources+': [ + 'ipc/client/gpu_memory_buffer_impl_surface_texture_unittest.cc', + ], }], ['OS == "mac"', { 'sources+': [ - 'ipc/client/gpu_memory_buffer_impl_io_surface_unittest.cc', + 'ipc/client/gpu_memory_buffer_impl_io_surface_unittest.cc', ] }], ['use_ozone == 1', { @@ -293,7 +300,7 @@ '../ui/ozone/ozone.gyp:ozone', ], 'sources+': [ - 'ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap_unittest.cc', + 'ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap_unittest.cc', ] }], ], @@ -311,9 +318,15 @@ '../ipc/ipc.gyp:test_support_ipc', '../skia/skia.gyp:skia', '../testing/gtest.gyp:gtest', + '../testing/gmock.gyp:gmock', '../third_party/mesa/mesa.gyp:mesa_headers', '../ui/gfx/gfx.gyp:gfx_test_support', + '../ui/gl/gl.gyp:gl', + '../ui/gl/init/gl_init.gyp:gl_init', + '../ui/gl/gl.gyp:gl_unittest_utils', + '../ui/gl/gl.gyp:gl_test_support', '../url/url.gyp:url_lib', + 'command_buffer/command_buffer.gyp:gles2_utils', 'command_buffer_common', 'command_buffer_service', 'gpu_config', @@ -332,22 +345,17 @@ ], 'conditions': [ ['OS == "android"', { + 'dependencies': [ + '../testing/android/native_test.gyp:native_test_native_code', + ], 'sources': [ 'ipc/service/gpu_memory_buffer_factory_surface_texture_unittest.cc', ], }], ['OS == "mac"', { 'sources': [ - 'ipc/service/ca_layer_tree_unittest_mac.mm', 'ipc/service/gpu_memory_buffer_factory_io_surface_unittest.cc', ], - 'link_settings': { - 'libraries': [ - '$(SDKROOT)/System/Library/Frameworks/CoreMedia.framework', - '$(SDKROOT)/System/Library/Frameworks/AVFoundation.framework', - '$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework', - ], - }, }], ['use_ozone == 1', { 'sources': [ @@ -368,6 +376,7 @@ '../testing/perf/perf_test.gyp:perf_test', '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/gl/gl.gyp:gl', + '../ui/gl/init/gl_init.gyp:gl_init', 'command_buffer_service', ], 'sources': [ @@ -400,6 +409,7 @@ '../ui/gfx/gfx.gyp:gfx_test_support', '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/gl/gl.gyp:gl', + '../ui/gl/init/gl_init.gyp:gl_init', 'command_buffer/command_buffer.gyp:gles2_utils', 'command_buffer_client', 'command_buffer_common', @@ -497,6 +507,9 @@ 'target_name': 'gpu_ipc_service_test_support', 'type': 'static_library', 'dependencies': [ + # TODO(markdittmer): Shouldn't depend on client code for server tests. + # See crbug.com/608800. + 'gpu_ipc_client', ], 'include_dirs': [ '..', @@ -515,6 +528,8 @@ '../gpu/gpu.gyp:command_buffer_service', '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/gl/gl.gyp:gl', + '../ui/gl/init/gl_init.gyp:gl_init', + 'command_buffer/command_buffer.gyp:gles2_utils', 'gles2_c_lib', 'gles2_implementation', ], @@ -523,6 +538,8 @@ # TODO(hendrikw): Move egl out of gles2_conform_support. 'gles2_conform_support/egl/config.cc', 'gles2_conform_support/egl/config.h', + 'gles2_conform_support/egl/context.cc', + 'gles2_conform_support/egl/context.h', 'gles2_conform_support/egl/display.cc', 'gles2_conform_support/egl/display.h', 'gles2_conform_support/egl/egl.cc', @@ -530,18 +547,20 @@ 'gles2_conform_support/egl/surface.h', 'gles2_conform_support/egl/test_support.cc', 'gles2_conform_support/egl/test_support.h', + 'gles2_conform_support/egl/thread_state.cc', + 'gles2_conform_support/egl/thread_state.h', ], - 'defines': [ + 'defines': [ 'COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY', 'EGLAPIENTRY=', - ], + ], 'conditions': [ ['OS=="win"', { 'defines': [ 'EGLAPI=__declspec(dllexport)', ], }, { # OS!="win" - 'defines': [ + 'defines': [ 'EGLAPI=__attribute__((visibility(\"default\")))' ], }], @@ -564,7 +583,7 @@ 'command_buffer/tests/command_buffer_gles2_tests_main.cc', 'command_buffer/tests/egl_test.cc', ], - 'defines': [ + 'defines': [ 'COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY', 'EGLAPIENTRY=', ], @@ -574,7 +593,7 @@ 'EGLAPI=__declspec(dllimport)', ], }, { # OS!="win" - 'defines': [ + 'defines': [ 'EGLAPI=', ], }], @@ -954,6 +973,17 @@ ], }, { + 'target_name': 'gpu_ipc_service_unittests_apk', + 'type': 'none', + 'dependencies': [ + 'gpu_ipc_service_unittests', + ], + 'variables': { + 'test_suite_name': 'gpu_ipc_service_unittests', + }, + 'includes': [ '../build/apk_test.gypi' ], + }, + { 'target_name': 'gpu_unittests_apk', 'type': 'none', 'dependencies': [ @@ -1032,6 +1062,19 @@ ['test_isolation_mode != "noop"', { 'targets': [ { + 'target_name': 'gpu_ipc_service_unittests_run', + 'type': 'none', + 'dependencies': [ + 'gpu_ipc_service_unittests', + ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'gpu_ipc_service_unittests.isolate', + ], + }, + { 'target_name': 'gpu_unittests_run', 'type': 'none', 'dependencies': [ @@ -1141,6 +1184,19 @@ ], }, { + 'target_name': 'gpu_ipc_service_unittests_apk_run', + 'type': 'none', + 'dependencies': [ + 'gpu_ipc_service_unittests_apk', + ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'gpu_ipc_service_unittests_apk.isolate', + ], + }, + { 'target_name': 'gpu_unittests_apk_run', 'type': 'none', 'dependencies': [ diff --git a/chromium/gpu/gpu_config.gypi b/chromium/gpu/gpu_config.gypi index 68691997304..5907ce15959 100644 --- a/chromium/gpu/gpu_config.gypi +++ b/chromium/gpu/gpu_config.gypi @@ -7,6 +7,7 @@ '../third_party/re2/re2.gyp:re2', '../base/base.gyp:base', '../ui/gl/gl.gyp:gl', + '../ui/gl/init/gl_init.gyp:gl_init', ], 'include_dirs': [ '..', @@ -23,6 +24,8 @@ 'config/gpu_driver_bug_list.h', 'config/gpu_driver_bug_list_json.cc', 'config/gpu_driver_bug_workaround_type.h', + 'config/gpu_driver_bug_workarounds.cc', + 'config/gpu_driver_bug_workarounds.h', 'config/gpu_dx_diagnostics_win.cc', 'config/gpu_feature_type.h', 'config/gpu_info.cc', diff --git a/chromium/gpu/gpu_ipc_client.gypi b/chromium/gpu/gpu_ipc_client.gypi index 6ca3c0e0683..dfa6a99e8bb 100644 --- a/chromium/gpu/gpu_ipc_client.gypi +++ b/chromium/gpu/gpu_ipc_client.gypi @@ -11,8 +11,10 @@ '../ui/events/events.gyp:events_base', '../ui/events/events.gyp:events_ipc', '../ui/gfx/gfx.gyp:gfx_geometry', + '../ui/gfx/ipc/geometry/gfx_ipc_geometry.gyp:gfx_ipc_geometry', '../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc', '../ui/gl/gl.gyp:gl', + '../ui/gl/init/gl_init.gyp:gl_init', '../url/url.gyp:url_lib', '../url/ipc/url_ipc.gyp:url_ipc', ], @@ -43,12 +45,16 @@ 'sources+': [ 'ipc/client/gpu_memory_buffer_impl_surface_texture.cc', 'ipc/client/gpu_memory_buffer_impl_surface_texture.h', + 'ipc/client/android/in_process_surface_texture_manager.cc', + 'ipc/client/android/in_process_surface_texture_manager.h', ], }], ['OS == "mac"', { 'sources+': [ 'ipc/client/gpu_memory_buffer_impl_io_surface.cc', 'ipc/client/gpu_memory_buffer_impl_io_surface.h', + 'ipc/client/gpu_process_hosted_ca_layer_tree_params.cc', + 'ipc/client/gpu_process_hosted_ca_layer_tree_params.h', ], }], ['use_ozone == 1', { diff --git a/chromium/gpu/gpu_ipc_common.gypi b/chromium/gpu/gpu_ipc_common.gypi index 9e9ea60cfcd..3bf9ec55cf0 100644 --- a/chromium/gpu/gpu_ipc_common.gypi +++ b/chromium/gpu/gpu_ipc_common.gypi @@ -11,8 +11,10 @@ '../ui/events/events.gyp:events_base', '../ui/events/events.gyp:events_ipc', '../ui/gfx/gfx.gyp:gfx_geometry', + '../ui/gfx/ipc/geometry/gfx_ipc_geometry.gyp:gfx_ipc_geometry', '../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc', '../ui/gl/gl.gyp:gl', + '../ui/gl/init/gl_init.gyp:gl_init', '../url/url.gyp:url_lib', '../url/ipc/url_ipc.gyp:url_ipc', ], diff --git a/chromium/gpu/gpu_ipc_service.gypi b/chromium/gpu/gpu_ipc_service.gypi index 8865814582e..f2a86e2331b 100644 --- a/chromium/gpu/gpu_ipc_service.gypi +++ b/chromium/gpu/gpu_ipc_service.gypi @@ -11,6 +11,7 @@ '../ui/gfx/gfx.gyp:gfx', '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/gl/gl.gyp:gl', + '../ui/gl/init/gl_init.gyp:gl_init', '../url/url.gyp:url_lib', ], 'include_dirs': [ @@ -48,22 +49,15 @@ 'sources': [ 'ipc/service/image_transport_surface_overlay_mac.h', 'ipc/service/image_transport_surface_overlay_mac.mm', - 'ipc/service/ca_layer_partial_damage_tree_mac.h', - 'ipc/service/ca_layer_partial_damage_tree_mac.mm', - 'ipc/service/ca_layer_tree_mac.h', - 'ipc/service/ca_layer_tree_mac.mm', 'ipc/service/gpu_memory_buffer_factory_io_surface.cc', 'ipc/service/gpu_memory_buffer_factory_io_surface.h', 'ipc/service/image_transport_surface_mac.mm', ], 'dependencies': [ - '../skia/skia.gyp:skia', '../ui/accelerated_widget_mac/accelerated_widget_mac.gyp:accelerated_widget_mac', ], 'link_settings': { 'libraries': [ - '$(SDKROOT)/System/Library/Frameworks/AVFoundation.framework', - '$(SDKROOT)/System/Library/Frameworks/CoreMedia.framework', '$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework', ], }, diff --git a/chromium/gpu/gpu_ipc_service_unittests.isolate b/chromium/gpu/gpu_ipc_service_unittests.isolate new file mode 100644 index 00000000000..196acc6e142 --- /dev/null +++ b/chromium/gpu/gpu_ipc_service_unittests.isolate @@ -0,0 +1,63 @@ +# Copyright 2016 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. +{ + 'conditions': [ + ['use_x11==0', { + 'variables': { + 'command': [ + '../testing/test_env.py', + '<(PRODUCT_DIR)/gpu_ipc_service_unittests<(EXECUTABLE_SUFFIX)', + '--brave-new-test-launcher', + '--test-launcher-bot-mode', + '--asan=<(asan)', + '--msan=<(msan)', + '--tsan=<(tsan)', + ], + }, + }], + ['use_x11==1', { + 'variables': { + 'command': [ + '../testing/xvfb.py', + '<(PRODUCT_DIR)', + '<(PRODUCT_DIR)/gpu_ipc_service_unittests<(EXECUTABLE_SUFFIX)', + '--brave-new-test-launcher', + '--test-launcher-bot-mode', + '--asan=<(asan)', + '--msan=<(msan)', + '--tsan=<(tsan)', + ], + 'files': [ + '../testing/xvfb.py', + '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)', + ], + }, + }], + ['OS=="linux" or OS=="mac" or OS=="win"', { + 'variables': { + 'files': [ + '../testing/test_env.py', + ], + }, + }], + ['OS=="mac" and asan==1 and fastbuild==0', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/gpu_ipc_service_unittests.dSYM/', + ], + }, + }], + ['OS=="win" and (fastbuild==0 or fastbuild==1)', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/gpu_ipc_service_unittests.exe.pdb', + ], + }, + }], + ], + 'includes': [ + '../base/base.isolate', + '../ui/gl/gl.isolate', + ], +} diff --git a/chromium/gpu/gpu_ipc_service_unittests_apk.isolate b/chromium/gpu/gpu_ipc_service_unittests_apk.isolate new file mode 100644 index 00000000000..c74b673dd95 --- /dev/null +++ b/chromium/gpu/gpu_ipc_service_unittests_apk.isolate @@ -0,0 +1,18 @@ +# Copyright 2016 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. +{ + 'includes': [ + '../build/android/android.isolate', + ], + 'variables': { + 'command': [ + '<(PRODUCT_DIR)/bin/run_gpu_ipc_service_unittests', + '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats', + ], + 'files': [ + '<(PRODUCT_DIR)/bin/run_gpu_ipc_service_unittests', + '<(PRODUCT_DIR)/gpu_ipc_service_unittests_apk/', + ] + }, +} diff --git a/chromium/gpu/ipc/client/BUILD.gn b/chromium/gpu/ipc/client/BUILD.gn index f77d1feb712..2ccbcfbf19c 100644 --- a/chromium/gpu/ipc/client/BUILD.gn +++ b/chromium/gpu/ipc/client/BUILD.gn @@ -31,10 +31,14 @@ source_set("ipc_client_sources") { sources += [ "gpu_memory_buffer_impl_io_surface.cc", "gpu_memory_buffer_impl_io_surface.h", + "gpu_process_hosted_ca_layer_tree_params.cc", + "gpu_process_hosted_ca_layer_tree_params.h", ] } if (is_android) { sources += [ + "android/in_process_surface_texture_manager.cc", + "android/in_process_surface_texture_manager.h", "gpu_memory_buffer_impl_surface_texture.cc", "gpu_memory_buffer_impl_surface_texture.h", ] @@ -59,6 +63,7 @@ source_set("ipc_client_sources") { "//ipc", "//ui/events/ipc", "//ui/gfx/ipc", + "//ui/gfx/ipc/geometry", "//ui/gl", "//url/ipc:url_ipc", ] diff --git a/chromium/gpu/ipc/client/android/in_process_surface_texture_manager.cc b/chromium/gpu/ipc/client/android/in_process_surface_texture_manager.cc new file mode 100644 index 00000000000..563e59f5852 --- /dev/null +++ b/chromium/gpu/ipc/client/android/in_process_surface_texture_manager.cc @@ -0,0 +1,60 @@ +// 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 "gpu/ipc/client/android/in_process_surface_texture_manager.h" + +#include <android/native_window.h> +#include <android/native_window_jni.h> + +#include "base/android/jni_android.h" +#include "base/containers/scoped_ptr_hash_map.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" + +namespace gpu { + +// static +InProcessSurfaceTextureManager* InProcessSurfaceTextureManager::GetInstance() { + return base::Singleton< + InProcessSurfaceTextureManager, + base::LeakySingletonTraits<InProcessSurfaceTextureManager>>::get(); +} + +void InProcessSurfaceTextureManager::RegisterSurfaceTexture( + int surface_texture_id, + int client_id, + gfx::SurfaceTexture* surface_texture) { + base::AutoLock lock(lock_); + + DCHECK(surface_textures_.find(surface_texture_id) == surface_textures_.end()); + surface_textures_.add( + surface_texture_id, + base::WrapUnique(new gfx::ScopedJavaSurface(surface_texture))); +} + +void InProcessSurfaceTextureManager::UnregisterSurfaceTexture( + int surface_texture_id, + int client_id) { + base::AutoLock lock(lock_); + + DCHECK(surface_textures_.find(surface_texture_id) != surface_textures_.end()); + surface_textures_.erase(surface_texture_id); +} + +gfx::AcceleratedWidget +InProcessSurfaceTextureManager::AcquireNativeWidgetForSurfaceTexture( + int surface_texture_id) { + base::AutoLock lock(lock_); + + DCHECK(surface_textures_.find(surface_texture_id) != surface_textures_.end()); + JNIEnv* env = base::android::AttachCurrentThread(); + return ANativeWindow_fromSurface( + env, surface_textures_.get(surface_texture_id)->j_surface().obj()); +} + +InProcessSurfaceTextureManager::InProcessSurfaceTextureManager() {} + +InProcessSurfaceTextureManager::~InProcessSurfaceTextureManager() {} + +} // namespace gpu diff --git a/chromium/gpu/ipc/client/android/in_process_surface_texture_manager.h b/chromium/gpu/ipc/client/android/in_process_surface_texture_manager.h new file mode 100644 index 00000000000..358f480e0ee --- /dev/null +++ b/chromium/gpu/ipc/client/android/in_process_surface_texture_manager.h @@ -0,0 +1,48 @@ +// 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. + +#ifndef GPU_IPC_CLIENT_ANDROID_IN_PROCESS_SURFACE_TEXTURE_MANAGER_H_ +#define GPU_IPC_CLIENT_ANDROID_IN_PROCESS_SURFACE_TEXTURE_MANAGER_H_ + +#include <memory> + +#include "base/containers/scoped_ptr_hash_map.h" +#include "base/macros.h" +#include "base/memory/singleton.h" +#include "base/synchronization/lock.h" +#include "gpu/gpu_export.h" +#include "gpu/ipc/common/android/surface_texture_manager.h" +#include "ui/gl/android/scoped_java_surface.h" + +namespace gpu { + +class GPU_EXPORT InProcessSurfaceTextureManager : public SurfaceTextureManager { + public: + static GPU_EXPORT InProcessSurfaceTextureManager* GetInstance(); + + // Overridden from SurfaceTextureManager: + void RegisterSurfaceTexture(int surface_texture_id, + int client_id, + gfx::SurfaceTexture* surface_texture) override; + void UnregisterSurfaceTexture(int surface_texture_id, int client_id) override; + gfx::AcceleratedWidget AcquireNativeWidgetForSurfaceTexture( + int surface_texture_id) override; + + private: + friend struct base::DefaultSingletonTraits<InProcessSurfaceTextureManager>; + + InProcessSurfaceTextureManager(); + ~InProcessSurfaceTextureManager() override; + + using SurfaceTextureMap = + base::ScopedPtrHashMap<int, std::unique_ptr<gfx::ScopedJavaSurface>>; + SurfaceTextureMap surface_textures_; + base::Lock lock_; + + DISALLOW_COPY_AND_ASSIGN(InProcessSurfaceTextureManager); +}; + +} // namespace gpu + +#endif // GPU_IPC_CLIENT_ANDROID_IN_PROCESS_SURFACE_TEXTURE_MANAGER_H_ diff --git a/chromium/gpu/ipc/client/command_buffer_proxy_impl.cc b/chromium/gpu/ipc/client/command_buffer_proxy_impl.cc index 99474e6c272..a7237b146a7 100644 --- a/chromium/gpu/ipc/client/command_buffer_proxy_impl.cc +++ b/chromium/gpu/ipc/client/command_buffer_proxy_impl.cc @@ -8,11 +8,16 @@ #include <vector> #include "base/callback.h" +#include "base/location.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/memory/shared_memory.h" +#include "base/optional.h" +#include "base/profiler/scoped_tracker.h" #include "base/stl_util.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" +#include "gpu/command_buffer/client/gpu_control_client.h" #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" #include "gpu/command_buffer/common/cmd_buffer_common.h" #include "gpu/command_buffer/common/command_buffer_id.h" @@ -26,6 +31,10 @@ #include "ui/gfx/geometry/size.h" #include "ui/gl/gl_bindings.h" +#if defined(OS_MACOSX) +#include "gpu/ipc/client/gpu_process_hosted_ca_layer_tree_params.h" +#endif + namespace gpu { namespace { @@ -37,12 +46,12 @@ gpu::CommandBufferId CommandBufferProxyID(int channel_id, int32_t route_id) { } // namespace -CommandBufferProxyImpl::CommandBufferProxyImpl(GpuChannelHost* channel, +CommandBufferProxyImpl::CommandBufferProxyImpl(int channel_id, int32_t route_id, int32_t stream_id) : lock_(nullptr), - channel_(channel), - command_buffer_id_(CommandBufferProxyID(channel->channel_id(), route_id)), + gpu_control_client_(nullptr), + command_buffer_id_(CommandBufferProxyID(channel_id, route_id)), route_id_(route_id), stream_id_(stream_id), flush_count_(0), @@ -54,20 +63,54 @@ CommandBufferProxyImpl::CommandBufferProxyImpl(GpuChannelHost* channel, next_signal_id_(0), weak_this_(AsWeakPtr()), callback_thread_(base::ThreadTaskRunnerHandle::Get()) { - DCHECK(channel); - DCHECK(stream_id); + DCHECK(route_id); + DCHECK_NE(stream_id, GPU_STREAM_INVALID); +} + +// static +std::unique_ptr<CommandBufferProxyImpl> CommandBufferProxyImpl::Create( + scoped_refptr<GpuChannelHost> host, + gpu::SurfaceHandle surface_handle, + const gfx::Size& size, + CommandBufferProxyImpl* share_group, + int32_t stream_id, + gpu::GpuStreamPriority stream_priority, + const gpu::gles2::ContextCreationAttribHelper& attribs, + const GURL& active_url, + gfx::GpuPreference gpu_preference, + scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + DCHECK(!share_group || (stream_id == share_group->stream_id_)); + TRACE_EVENT1("gpu", "GpuChannelHost::CreateViewCommandBuffer", + "surface_handle", surface_handle); + + GPUCreateCommandBufferConfig init_params; + init_params.surface_handle = surface_handle; + init_params.size = size; + init_params.share_group_id = + share_group ? share_group->route_id_ : MSG_ROUTING_NONE; + init_params.stream_id = stream_id; + init_params.stream_priority = stream_priority; + init_params.attribs = attribs; + init_params.active_url = active_url; + init_params.gpu_preference = gpu_preference; + + int32_t route_id = host->GenerateRouteID(); + std::unique_ptr<CommandBufferProxyImpl> command_buffer = base::WrapUnique( + new CommandBufferProxyImpl(host->channel_id(), route_id, stream_id)); + if (!command_buffer->Initialize(std::move(host), std::move(init_params), + std::move(task_runner))) + return nullptr; + + return command_buffer; } CommandBufferProxyImpl::~CommandBufferProxyImpl() { FOR_EACH_OBSERVER(DeletionObserver, deletion_observers_, OnWillDeleteImpl()); - if (channel_) { - channel_->DestroyCommandBuffer(this); - channel_ = nullptr; - } + DisconnectChannel(); } bool CommandBufferProxyImpl::OnMessageReceived(const IPC::Message& message) { - scoped_ptr<base::AutoLock> lock; + std::unique_ptr<base::AutoLock> lock; if (lock_) lock.reset(new base::AutoLock(*lock_)); bool handled = true; @@ -83,59 +126,44 @@ bool CommandBufferProxyImpl::OnMessageReceived(const IPC::Message& message) { IPC_END_MESSAGE_MAP() if (!handled) { - DLOG(ERROR) << "Gpu process sent invalid message."; - InvalidGpuMessage(); + LOG(ERROR) << "Gpu process sent invalid message."; + OnGpuAsyncMessageError(gpu::error::kInvalidGpuMessage, + gpu::error::kLostContext); } return handled; } void CommandBufferProxyImpl::OnChannelError() { - scoped_ptr<base::AutoLock> lock; + std::unique_ptr<base::AutoLock> lock; if (lock_) lock.reset(new base::AutoLock(*lock_)); gpu::error::ContextLostReason context_lost_reason = gpu::error::kGpuChannelLost; if (shared_state_shm_ && shared_state_shm_->memory()) { - TryUpdateState(); // The GPU process might have intentionally been crashed // (exit_on_context_lost), so try to find out the original reason. + TryUpdateStateDontReportError(); if (last_state_.error == gpu::error::kLostContext) context_lost_reason = last_state_.context_lost_reason; } - OnDestroyed(context_lost_reason, gpu::error::kLostContext); + OnGpuAsyncMessageError(context_lost_reason, gpu::error::kLostContext); } void CommandBufferProxyImpl::OnDestroyed(gpu::error::ContextLostReason reason, gpu::error::Error error) { - CheckLock(); - // Prevent any further messages from being sent. - if (channel_) { - channel_->DestroyCommandBuffer(this); - channel_ = nullptr; - } - - // When the client sees that the context is lost, they should delete this - // CommandBufferProxyImpl and create a new one. - last_state_.error = error; - last_state_.context_lost_reason = reason; - - if (!context_lost_callback_.is_null()) { - context_lost_callback_.Run(); - // Avoid calling the error callback more than once. - context_lost_callback_.Reset(); - } + OnGpuAsyncMessageError(reason, error); } void CommandBufferProxyImpl::OnConsoleMessage( const GPUCommandBufferConsoleMessage& message) { - if (!console_message_callback_.is_null()) { - console_message_callback_.Run(message.message, message.id); - } + if (gpu_control_client_) + gpu_control_client_->OnGpuControlErrorMessage(message.message.c_str(), + message.id); } void CommandBufferProxyImpl::AddDeletionObserver(DeletionObserver* observer) { - scoped_ptr<base::AutoLock> lock; + std::unique_ptr<base::AutoLock> lock; if (lock_) lock.reset(new base::AutoLock(*lock_)); deletion_observers_.AddObserver(observer); @@ -143,7 +171,7 @@ void CommandBufferProxyImpl::AddDeletionObserver(DeletionObserver* observer) { void CommandBufferProxyImpl::RemoveDeletionObserver( DeletionObserver* observer) { - scoped_ptr<base::AutoLock> lock; + std::unique_ptr<base::AutoLock> lock; if (lock_) lock.reset(new base::AutoLock(*lock_)); deletion_observers_.RemoveObserver(observer); @@ -152,8 +180,9 @@ void CommandBufferProxyImpl::RemoveDeletionObserver( void CommandBufferProxyImpl::OnSignalAck(uint32_t id) { SignalTaskMap::iterator it = signal_tasks_.find(id); if (it == signal_tasks_.end()) { - DLOG(ERROR) << "Gpu process sent invalid SignalAck."; - InvalidGpuMessage(); + LOG(ERROR) << "Gpu process sent invalid SignalAck."; + OnGpuAsyncMessageError(gpu::error::kInvalidGpuMessage, + gpu::error::kLostContext); return; } base::Closure callback = it->second; @@ -161,17 +190,14 @@ void CommandBufferProxyImpl::OnSignalAck(uint32_t id) { callback.Run(); } -void CommandBufferProxyImpl::SetContextLostCallback( - const base::Closure& callback) { - CheckLock(); - context_lost_callback_ = callback; -} - -bool CommandBufferProxyImpl::Initialize() { +bool CommandBufferProxyImpl::Initialize( + scoped_refptr<GpuChannelHost> channel, + const GPUCreateCommandBufferConfig& config, + scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + DCHECK(!channel_); TRACE_EVENT0("gpu", "CommandBufferProxyImpl::Initialize"); - shared_state_shm_.reset(channel_->factory() - ->AllocateSharedMemory(sizeof(*shared_state())) - .release()); + shared_state_shm_ = + channel->factory()->AllocateSharedMemory(sizeof(*shared_state())); if (!shared_state_shm_) return false; @@ -182,24 +208,37 @@ bool CommandBufferProxyImpl::Initialize() { // This handle is owned by the GPU process and must be passed to it or it // will leak. In otherwords, do not early out on error between here and the - // sending of the Initialize IPC below. + // sending of the CreateCommandBuffer IPC below. base::SharedMemoryHandle handle = - channel_->ShareToGpuProcess(shared_state_shm_->handle()); + channel->ShareToGpuProcess(shared_state_shm_->handle()); if (!base::SharedMemory::IsHandleValid(handle)) return false; - bool result = false; - if (!Send(new GpuCommandBufferMsg_Initialize(route_id_, handle, &result, - &capabilities_))) { - LOG(ERROR) << "Could not send GpuCommandBufferMsg_Initialize."; - return false; - } - if (!result) { - LOG(ERROR) << "Failed to initialize command buffer service."; + // TODO(vadimt): Remove ScopedTracker below once crbug.com/125248 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "125248 CommandBufferProxyImpl::Initialize")); + + // Route must be added before sending the message, otherwise messages sent + // from the GPU process could race against adding ourselves to the filter. + channel->AddRouteWithTaskRunner(route_id_, AsWeakPtr(), + std::move(task_runner)); + + // We're blocking the UI thread, which is generally undesirable. + // In this case we need to wait for this before we can show any UI /anyway/, + // so it won't cause additional jank. + // TODO(piman): Make this asynchronous (http://crbug.com/125248). + bool result = false; + bool sent = channel->Send(new GpuChannelMsg_CreateCommandBuffer( + config, route_id_, handle, &result, &capabilities_)); + if (!sent || !result) { + DLOG(ERROR) << "Failed to send GpuChannelMsg_CreateCommandBuffer."; + channel->RemoveRoute(route_id_); return false; } + channel_ = std::move(channel); capabilities_.image = true; return true; @@ -246,6 +285,7 @@ void CommandBufferProxyImpl::Flush(int32_t put_offset) { } void CommandBufferProxyImpl::OrderingBarrier(int32_t put_offset) { + CheckLock(); if (last_state_.error != gpu::error::kNoError) return; @@ -303,12 +343,12 @@ void CommandBufferProxyImpl::WaitForTokenInRange(int32_t start, int32_t end) { gpu::CommandBuffer::State state; if (Send(new GpuCommandBufferMsg_WaitForTokenInRange(route_id_, start, end, &state))) - OnUpdateState(state); + SetStateFromSyncReply(state); } if (!InRange(start, end, last_state_.token) && last_state_.error == gpu::error::kNoError) { - DLOG(ERROR) << "GPU state invalid after WaitForTokenInRange."; - InvalidGpuReply(); + LOG(ERROR) << "GPU state invalid after WaitForTokenInRange."; + OnGpuSyncReplyError(); } } @@ -323,12 +363,12 @@ void CommandBufferProxyImpl::WaitForGetOffsetInRange(int32_t start, gpu::CommandBuffer::State state; if (Send(new GpuCommandBufferMsg_WaitForGetOffsetInRange(route_id_, start, end, &state))) - OnUpdateState(state); + SetStateFromSyncReply(state); } if (!InRange(start, end, last_state_.get_offset) && last_state_.error == gpu::error::kNoError) { - DLOG(ERROR) << "GPU state invalid after WaitForGetOffsetInRange."; - InvalidGpuReply(); + LOG(ERROR) << "GPU state invalid after WaitForGetOffsetInRange."; + OnGpuSyncReplyError(); } } @@ -352,18 +392,18 @@ scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::CreateTransferBuffer( int32_t new_id = channel_->ReserveTransferBufferId(); - scoped_ptr<base::SharedMemory> shared_memory( + std::unique_ptr<base::SharedMemory> shared_memory( channel_->factory()->AllocateSharedMemory(size)); if (!shared_memory) { if (last_state_.error == gpu::error::kNoError) - last_state_.error = gpu::error::kOutOfBounds; + OnClientError(gpu::error::kOutOfBounds); return NULL; } DCHECK(!shared_memory->memory()); if (!shared_memory->Map(size)) { if (last_state_.error == gpu::error::kNoError) - last_state_.error = gpu::error::kOutOfBounds; + OnClientError(gpu::error::kOutOfBounds); return NULL; } @@ -374,7 +414,7 @@ scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::CreateTransferBuffer( channel_->ShareToGpuProcess(shared_memory->handle()); if (!base::SharedMemory::IsHandleValid(handle)) { if (last_state_.error == gpu::error::kNoError) - last_state_.error = gpu::error::kLostContext; + OnClientError(gpu::error::kLostContext); return NULL; } @@ -394,6 +434,11 @@ void CommandBufferProxyImpl::DestroyTransferBuffer(int32_t id) { Send(new GpuCommandBufferMsg_DestroyTransferBuffer(route_id_, id)); } +void CommandBufferProxyImpl::SetGpuControlClient(GpuControlClient* client) { + CheckLock(); + gpu_control_client_ = client; +} + gpu::Capabilities CommandBufferProxyImpl::GetCapabilities() { return capabilities_; } @@ -427,7 +472,7 @@ int32_t CommandBufferProxyImpl::CreateImage(ClientBuffer buffer, image_fence_sync = GenerateFenceSyncRelease(); // Make sure fence syncs were flushed before CreateImage() was called. - DCHECK_LE(image_fence_sync - 1, flushed_fence_sync_release_); + DCHECK_EQ(image_fence_sync, flushed_fence_sync_release_ + 1); } DCHECK(gpu::IsGpuMemoryBufferFormatSupported(gpu_memory_buffer->GetFormat(), @@ -476,11 +521,11 @@ int32_t CommandBufferProxyImpl::CreateGpuMemoryBufferImage( unsigned internal_format, unsigned usage) { CheckLock(); - scoped_ptr<gfx::GpuMemoryBuffer> buffer( + std::unique_ptr<gfx::GpuMemoryBuffer> buffer( channel_->gpu_memory_buffer_manager()->AllocateGpuMemoryBuffer( gfx::Size(width, height), gpu::DefaultBufferFormatForImageFormat(internal_format), - gfx::BufferUsage::SCANOUT, 0 /* surface_id */)); + gfx::BufferUsage::SCANOUT, gpu::kNullSurfaceHandle)); if (!buffer) return -1; @@ -507,10 +552,6 @@ void CommandBufferProxyImpl::SetLock(base::Lock* lock) { lock_ = lock; } -bool CommandBufferProxyImpl::IsGpuChannelLost() { - return !channel_ || channel_->IsLost(); -} - void CommandBufferProxyImpl::EnsureWorkVisible() { if (channel_) channel_->ValidateFlushIDReachedServer(stream_id_, true); @@ -529,14 +570,17 @@ int32_t CommandBufferProxyImpl::GetExtraCommandBufferData() const { } uint64_t CommandBufferProxyImpl::GenerateFenceSyncRelease() { + CheckLock(); return next_fence_sync_release_++; } bool CommandBufferProxyImpl::IsFenceSyncRelease(uint64_t release) { + CheckLock(); return release != 0 && release < next_fence_sync_release_; } bool CommandBufferProxyImpl::IsFenceSyncFlushed(uint64_t release) { + CheckLock(); return release != 0 && release <= flushed_fence_sync_release_; } @@ -590,7 +634,7 @@ bool CommandBufferProxyImpl::CanWaitUnverifiedSyncToken( // If waiting on a different stream, flush pending commands on that stream. const int32_t release_stream_id = sync_token->extra_data_field(); - if (release_stream_id == 0) + if (release_stream_id == gpu::GPU_STREAM_INVALID) return false; if (release_stream_id != stream_id_) @@ -650,25 +694,30 @@ bool CommandBufferProxyImpl::Send(IPC::Message* msg) { // OnChannelError is called after returning to the message loop in case // it is referenced elsewhere. DVLOG(1) << "CommandBufferProxyImpl::Send failed. Losing context."; - last_state_.error = gpu::error::kLostContext; + OnClientError(gpu::error::kLostContext); return false; } -void CommandBufferProxyImpl::OnUpdateState( +void CommandBufferProxyImpl::SetStateFromSyncReply( const gpu::CommandBuffer::State& state) { + DCHECK(last_state_.error == gpu::error::kNoError); // Handle wraparound. It works as long as we don't have more than 2B state // updates in flight across which reordering occurs. if (state.generation - last_state_.generation < 0x80000000U) last_state_ = state; + if (last_state_.error != gpu::error::kNoError) + OnGpuStateError(); } -void CommandBufferProxyImpl::SetOnConsoleMessageCallback( - const GpuConsoleMessageCallback& callback) { - CheckLock(); - console_message_callback_ = callback; +void CommandBufferProxyImpl::TryUpdateState() { + if (last_state_.error == gpu::error::kNoError) { + shared_state()->Read(&last_state_); + if (last_state_.error != gpu::error::kNoError) + OnGpuStateError(); + } } -void CommandBufferProxyImpl::TryUpdateState() { +void CommandBufferProxyImpl::TryUpdateStateDontReportError() { if (last_state_.error == gpu::error::kNoError) shared_state()->Read(&last_state_); } @@ -690,16 +739,33 @@ gpu::CommandBufferSharedState* CommandBufferProxyImpl::shared_state() const { } void CommandBufferProxyImpl::OnSwapBuffersCompleted( - const std::vector<ui::LatencyInfo>& latency_info, - gfx::SwapResult result) { + const GpuCommandBufferMsg_SwapBuffersCompleted_Params& params) { +#if defined(OS_MACOSX) + gpu::GpuProcessHostedCALayerTreeParamsMac params_mac; + params_mac.surface_handle = params.surface_handle; + params_mac.ca_context_id = params.ca_context_id; + params_mac.fullscreen_low_power_ca_context_valid = + params.fullscreen_low_power_ca_context_valid; + params_mac.fullscreen_low_power_ca_context_id = + params.fullscreen_low_power_ca_context_id; + params_mac.io_surface.reset(IOSurfaceLookupFromMachPort(params.io_surface)); + params_mac.pixel_size = params.pixel_size; + params_mac.scale_factor = params.scale_factor; + gpu::GpuProcessHostedCALayerTreeParamsMac* mac_frame_ptr = ¶ms_mac; +#else + gpu::GpuProcessHostedCALayerTreeParamsMac* mac_frame_ptr = nullptr; +#endif + if (!swap_buffers_completion_callback_.is_null()) { if (!ui::LatencyInfo::Verify( - latency_info, "CommandBufferProxyImpl::OnSwapBuffersCompleted")) { + params.latency_info, + "CommandBufferProxyImpl::OnSwapBuffersCompleted")) { swap_buffers_completion_callback_.Run(std::vector<ui::LatencyInfo>(), - result); - return; + params.result, mac_frame_ptr); + } else { + swap_buffers_completion_callback_.Run(params.latency_info, params.result, + mac_frame_ptr); } - swap_buffers_completion_callback_.Run(latency_info, result); } } @@ -709,27 +775,77 @@ void CommandBufferProxyImpl::OnUpdateVSyncParameters(base::TimeTicks timebase, update_vsync_parameters_completion_callback_.Run(timebase, interval); } -void CommandBufferProxyImpl::InvalidGpuMessage() { - LOG(ERROR) << "Received invalid message from the GPU process."; - OnDestroyed(gpu::error::kInvalidGpuMessage, gpu::error::kLostContext); +void CommandBufferProxyImpl::OnGpuSyncReplyError() { + last_state_.error = gpu::error::kLostContext; + last_state_.context_lost_reason = gpu::error::kInvalidGpuMessage; + // This method may be inside a callstack from the GpuControlClient (we got a + // bad reply to something we are sending to the GPU process). So avoid + // re-entering the GpuControlClient here. + DisconnectChannelInFreshCallStack(); } -void CommandBufferProxyImpl::InvalidGpuReply() { +void CommandBufferProxyImpl::OnGpuAsyncMessageError( + gpu::error::ContextLostReason reason, + gpu::error::Error error) { CheckLock(); - LOG(ERROR) << "Received invalid reply from the GPU process."; - last_state_.error = gpu::error::kLostContext; - last_state_.context_lost_reason = gpu::error::kInvalidGpuMessage; + last_state_.error = error; + last_state_.context_lost_reason = reason; + // This method only occurs when receiving IPC messages, so we know it's not in + // a callstack from the GpuControlClient. + DisconnectChannel(); +} + +void CommandBufferProxyImpl::OnGpuStateError() { + DCHECK(last_state_.error != gpu::error::kNoError); + // This method may be inside a callstack from the GpuControlClient (we + // encountered an error while trying to perform some action). So avoid + // re-entering the GpuControlClient here. + DisconnectChannelInFreshCallStack(); +} + +void CommandBufferProxyImpl::OnClientError(gpu::error::Error error) { + CheckLock(); + last_state_.error = error; + last_state_.context_lost_reason = gpu::error::kUnknown; + // This method may be inside a callstack from the GpuControlClient (we + // encountered an error while trying to perform some action). So avoid + // re-entering the GpuControlClient here. + DisconnectChannelInFreshCallStack(); +} + +void CommandBufferProxyImpl::DisconnectChannelInFreshCallStack() { + CheckLock(); + // Inform the GpuControlClient of the lost state immediately, though this may + // be a re-entrant call to the client so we use the MaybeReentrant variant. + if (gpu_control_client_) + gpu_control_client_->OnGpuControlLostContextMaybeReentrant(); + // Create a fresh call stack to keep the |channel_| alive while we unwind the + // stack in case things will use it, and give the GpuChannelClient a chance to + // act fully on the lost context. callback_thread_->PostTask( - FROM_HERE, - base::Bind(&CommandBufferProxyImpl::InvalidGpuReplyOnClientThread, - weak_this_)); + FROM_HERE, base::Bind(&CommandBufferProxyImpl::LockAndDisconnectChannel, + weak_this_)); } -void CommandBufferProxyImpl::InvalidGpuReplyOnClientThread() { - scoped_ptr<base::AutoLock> lock; +void CommandBufferProxyImpl::LockAndDisconnectChannel() { + base::Optional<base::AutoLock> hold; if (lock_) - lock.reset(new base::AutoLock(*lock_)); - OnDestroyed(gpu::error::kInvalidGpuMessage, gpu::error::kLostContext); + hold.emplace(*lock_); + DisconnectChannel(); +} + +void CommandBufferProxyImpl::DisconnectChannel() { + CheckLock(); + // Prevent any further messages from being sent, and ensure we only call + // the client for lost context a single time. + if (!channel_) + return; + channel_->FlushPendingStream(stream_id_); + channel_->Send(new GpuChannelMsg_DestroyCommandBuffer(route_id_)); + channel_->RemoveRoute(route_id_); + channel_ = nullptr; + if (gpu_control_client_) + gpu_control_client_->OnGpuControlLostContext(); } } // namespace gpu diff --git a/chromium/gpu/ipc/client/command_buffer_proxy_impl.h b/chromium/gpu/ipc/client/command_buffer_proxy_impl.h index cd72f782884..41ea4eaa2f9 100644 --- a/chromium/gpu/ipc/client/command_buffer_proxy_impl.h +++ b/chromium/gpu/ipc/client/command_buffer_proxy_impl.h @@ -9,6 +9,7 @@ #include <stdint.h> #include <map> +#include <memory> #include <queue> #include <string> @@ -20,25 +21,41 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" +#include "base/threading/thread_checker.h" #include "gpu/command_buffer/client/gpu_control.h" #include "gpu/command_buffer/common/command_buffer.h" #include "gpu/command_buffer/common/command_buffer_id.h" #include "gpu/command_buffer/common/command_buffer_shared.h" #include "gpu/command_buffer/common/gpu_memory_allocation.h" #include "gpu/gpu_export.h" +#include "gpu/ipc/common/gpu_stream_constants.h" +#include "gpu/ipc/common/surface_handle.h" #include "ipc/ipc_listener.h" #include "ui/events/latency_info.h" #include "ui/gfx/swap_result.h" +#include "ui/gl/gpu_preference.h" struct GPUCommandBufferConsoleMessage; +struct GPUCreateCommandBufferConfig; +struct GpuCommandBufferMsg_SwapBuffersCompleted_Params; +class GURL; namespace base { class SharedMemory; } +namespace gfx { +class Size; +} + namespace gpu { +struct GpuProcessHostedCALayerTreeParamsMac; struct Mailbox; struct SyncToken; + +namespace gles2 { +struct ContextCreationAttribHelper; +} } namespace gpu { @@ -64,9 +81,18 @@ class GPU_EXPORT CommandBufferProxyImpl typedef base::Callback<void(const std::string& msg, int id)> GpuConsoleMessageCallback; - CommandBufferProxyImpl(GpuChannelHost* channel, - int32_t route_id, - int32_t stream_id); + // Create and connect to a command buffer in the GPU process. + static std::unique_ptr<CommandBufferProxyImpl> Create( + scoped_refptr<GpuChannelHost> host, + gpu::SurfaceHandle surface_handle, + const gfx::Size& size, + CommandBufferProxyImpl* share_group, + int32_t stream_id, + gpu::GpuStreamPriority stream_priority, + const gpu::gles2::ContextCreationAttribHelper& attribs, + const GURL& active_url, + gfx::GpuPreference gpu_preference, + scoped_refptr<base::SingleThreadTaskRunner> task_runner); ~CommandBufferProxyImpl() override; // IPC::Listener implementation: @@ -74,7 +100,6 @@ class GPU_EXPORT CommandBufferProxyImpl void OnChannelError() override; // CommandBuffer implementation: - bool Initialize() override; State GetLastState() override; int32_t GetLastToken() override; void Flush(int32_t put_offset) override; @@ -87,6 +112,7 @@ class GPU_EXPORT CommandBufferProxyImpl void DestroyTransferBuffer(int32_t id) override; // gpu::GpuControl implementation: + void SetGpuControlClient(GpuControlClient* client) override; gpu::Capabilities GetCapabilities() override; int32_t CreateImage(ClientBuffer buffer, size_t width, @@ -99,7 +125,6 @@ class GPU_EXPORT CommandBufferProxyImpl unsigned usage) override; void SignalQuery(uint32_t query, const base::Closure& callback) override; void SetLock(base::Lock* lock) override; - bool IsGpuChannelLost() override; void EnsureWorkVisible() override; gpu::CommandBufferNamespace GetNamespaceID() const override; gpu::CommandBufferId GetCommandBufferID() const override; @@ -113,7 +138,6 @@ class GPU_EXPORT CommandBufferProxyImpl bool CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) override; bool ProduceFrontBuffer(const gpu::Mailbox& mailbox); - void SetContextLostCallback(const base::Closure& callback); void AddDeletionObserver(DeletionObserver* observer); void RemoveDeletionObserver(DeletionObserver* observer); @@ -123,9 +147,10 @@ class GPU_EXPORT CommandBufferProxyImpl void SetOnConsoleMessageCallback(const GpuConsoleMessageCallback& callback); void SetLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info); - using SwapBuffersCompletionCallback = - base::Callback<void(const std::vector<ui::LatencyInfo>& latency_info, - gfx::SwapResult result)>; + using SwapBuffersCompletionCallback = base::Callback<void( + const std::vector<ui::LatencyInfo>& latency_info, + gfx::SwapResult result, + const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac)>; void SetSwapBuffersCompletionCallback( const SwapBuffersCompletionCallback& callback); @@ -142,9 +167,7 @@ class GPU_EXPORT CommandBufferProxyImpl int32_t route_id() const { return route_id_; } - int32_t stream_id() const { return stream_id_; } - - GpuChannelHost* channel() const { return channel_; } + const scoped_refptr<GpuChannelHost>& channel() const { return channel_; } base::SharedMemoryHandle GetSharedStateHandle() const { return shared_state_shm_->handle(); @@ -155,9 +178,17 @@ class GPU_EXPORT CommandBufferProxyImpl typedef std::map<int32_t, scoped_refptr<gpu::Buffer>> TransferBufferMap; typedef base::hash_map<uint32_t, base::Closure> SignalTaskMap; + CommandBufferProxyImpl(int channel_id, int32_t route_id, int32_t stream_id); + bool Initialize(scoped_refptr<GpuChannelHost> channel, + const GPUCreateCommandBufferConfig& config, + scoped_refptr<base::SingleThreadTaskRunner> task_runner); + void CheckLock() { - if (lock_) + if (lock_) { lock_->AssertAcquired(); + } else { + DCHECK(lockless_thread_checker_.CalledOnValidThread()); + } } // Send an IPC message over the GPU channel. This is private to fully @@ -166,36 +197,58 @@ class GPU_EXPORT CommandBufferProxyImpl bool Send(IPC::Message* msg); // Message handlers: - void OnUpdateState(const gpu::CommandBuffer::State& state); void OnDestroyed(gpu::error::ContextLostReason reason, gpu::error::Error error); void OnConsoleMessage(const GPUCommandBufferConsoleMessage& message); void OnSignalAck(uint32_t id); - void OnSwapBuffersCompleted(const std::vector<ui::LatencyInfo>& latency_info, - gfx::SwapResult result); + void OnSwapBuffersCompleted( + const GpuCommandBufferMsg_SwapBuffersCompleted_Params& params); void OnUpdateVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval); - // Try to read an updated copy of the state from shared memory. - void TryUpdateState(); - // Updates the highest verified release fence sync. void UpdateVerifiedReleases(uint32_t verified_flush); - // Loses the context after we received an invalid message from the GPU - // process. Will call the lost context callback reentrantly if any. - void InvalidGpuMessage(); + // Try to read an updated copy of the state from shared memory, and calls + // OnGpuStateError() if the new state has an error. + void TryUpdateState(); + // Like the above but does not call the error event handler if the new state + // has an error. + void TryUpdateStateDontReportError(); + // Sets the state, and calls OnGpuStateError() if the new state has an error. + void SetStateFromSyncReply(const gpu::CommandBuffer::State& state); // Loses the context after we received an invalid reply from the GPU - // process. Will post a task to call the lost context callback if any. - void InvalidGpuReply(); + // process. + void OnGpuSyncReplyError(); + + // Loses the context when receiving a message from the GPU process. + void OnGpuAsyncMessageError(gpu::error::ContextLostReason reason, + gpu::error::Error error); + + // Loses the context after we receive an error state from the GPU process. + void OnGpuStateError(); - void InvalidGpuReplyOnClientThread(); + // Sets an error on the last_state_ and loses the context due to client-side + // errors. + void OnClientError(gpu::error::Error error); + + // Helper methods, don't call these directly. + void DisconnectChannelInFreshCallStack(); + void LockAndDisconnectChannel(); + void DisconnectChannel(); // The shared memory area used to update state. gpu::CommandBufferSharedState* shared_state() const; + // There should be a lock_ if this is going to be used across multiple + // threads, or we guarantee it is used by a single thread by using a thread + // checker if no lock_ is set. base::Lock* lock_; + base::ThreadChecker lockless_thread_checker_; + + // Client that wants to listen for important events on the GpuControl. + gpu::GpuControlClient* gpu_control_client_; // Unowned list of DeletionObservers. base::ObserverList<DeletionObserver> deletion_observers_; @@ -204,11 +257,9 @@ class GPU_EXPORT CommandBufferProxyImpl State last_state_; // The shared memory area used to update state. - scoped_ptr<base::SharedMemory> shared_state_shm_; + std::unique_ptr<base::SharedMemory> shared_state_shm_; - // |*this| is owned by |*channel_| and so is always outlived by it, so using a - // raw pointer is ok. - GpuChannelHost* channel_; + scoped_refptr<GpuChannelHost> channel_; const gpu::CommandBufferId command_buffer_id_; const int32_t route_id_; const int32_t stream_id_; @@ -228,8 +279,6 @@ class GPU_EXPORT CommandBufferProxyImpl // Last verified fence sync. uint64_t verified_fence_sync_release_; - base::Closure context_lost_callback_; - GpuConsoleMessageCallback console_message_callback_; // Tasks to be invoked in SignalSyncPoint responses. diff --git a/chromium/gpu/ipc/client/gpu_channel_host.cc b/chromium/gpu/ipc/client/gpu_channel_host.cc index 54ad6a936fe..ddadbdf684a 100644 --- a/chromium/gpu/ipc/client/gpu_channel_host.cc +++ b/chromium/gpu/ipc/client/gpu_channel_host.cc @@ -9,15 +9,11 @@ #include "base/atomic_sequence_num.h" #include "base/bind.h" -#include "base/location.h" -#include "base/posix/eintr_wrapper.h" -#include "base/profiler/scoped_tracker.h" #include "base/single_thread_task_runner.h" -#include "base/thread_task_runner_handle.h" #include "base/threading/thread_restrictions.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" -#include "gpu/ipc/client/command_buffer_proxy_impl.h" #include "gpu/ipc/common/gpu_messages.h" #include "gpu/ipc/common/gpu_param_traits_macros.h" #include "ipc/ipc_sync_message_filter.h" @@ -100,7 +96,7 @@ void GpuChannelHost::Connect(const IPC::ChannelHandle& channel_handle, bool GpuChannelHost::Send(IPC::Message* msg) { // Callee takes ownership of message, regardless of whether Send is // successful. See IPC::Sender. - scoped_ptr<IPC::Message> message(msg); + std::unique_ptr<IPC::Message> message(msg); // The GPU process never sends synchronous IPCs so clear the unblock flag to // preserve order. message->set_unblock(false); @@ -188,74 +184,6 @@ void GpuChannelHost::InternalFlush(StreamFlushInfo* flush_info) { flush_info->flushed_stream_flush_id = flush_info->flush_id; } -scoped_ptr<CommandBufferProxyImpl> GpuChannelHost::CreateCommandBuffer( - gpu::SurfaceHandle surface_handle, - const gfx::Size& size, - CommandBufferProxyImpl* share_group, - int32_t stream_id, - gpu::GpuStreamPriority stream_priority, - const std::vector<int32_t>& attribs, - const GURL& active_url, - gfx::GpuPreference gpu_preference) { - DCHECK(!share_group || (stream_id == share_group->stream_id())); - TRACE_EVENT1("gpu", "GpuChannelHost::CreateViewCommandBuffer", - "surface_handle", surface_handle); - - GPUCreateCommandBufferConfig init_params; - init_params.share_group_id = - share_group ? share_group->route_id() : MSG_ROUTING_NONE; - init_params.stream_id = stream_id; - init_params.stream_priority = stream_priority; - init_params.attribs = attribs; - init_params.active_url = active_url; - init_params.gpu_preference = gpu_preference; - - int32_t route_id = GenerateRouteID(); - - // TODO(vadimt): Remove ScopedTracker below once crbug.com/125248 is fixed. - tracked_objects::ScopedTracker tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "125248 GpuChannelHost::CreateCommandBuffer")); - - // We're blocking the UI thread, which is generally undesirable. - // In this case we need to wait for this before we can show any UI /anyway/, - // so it won't cause additional jank. - // TODO(piman): Make this asynchronous (http://crbug.com/125248). - - bool succeeded = false; - if (!Send(new GpuChannelMsg_CreateCommandBuffer( - surface_handle, size, init_params, route_id, &succeeded))) { - LOG(ERROR) << "Failed to send GpuChannelMsg_CreateCommandBuffer."; - return nullptr; - } - - if (!succeeded) { - LOG(ERROR) << "GpuChannelMsg_CreateCommandBuffer returned failure."; - return nullptr; - } - - scoped_ptr<CommandBufferProxyImpl> command_buffer = - make_scoped_ptr(new CommandBufferProxyImpl(this, route_id, stream_id)); - AddRoute(route_id, command_buffer->AsWeakPtr()); - - return command_buffer; -} - -void GpuChannelHost::DestroyCommandBuffer( - CommandBufferProxyImpl* command_buffer) { - TRACE_EVENT0("gpu", "GpuChannelHost::DestroyCommandBuffer"); - - int32_t route_id = command_buffer->route_id(); - int32_t stream_id = command_buffer->stream_id(); - Send(new GpuChannelMsg_DestroyCommandBuffer(route_id)); - RemoveRoute(route_id); - - AutoLock lock(context_lock_); - StreamFlushInfo& flush_info = stream_flush_info_[stream_id]; - if (flush_info.flush_pending && flush_info.route_id == route_id) - flush_info.flush_pending = false; -} - void GpuChannelHost::DestroyChannel() { DCHECK(factory_->IsMainThread()); AutoLock lock(context_lock_); @@ -335,8 +263,8 @@ int32_t GpuChannelHost::GenerateRouteID() { int32_t GpuChannelHost::GenerateStreamID() { const int32_t stream_id = next_stream_id_.GetNext(); - DCHECK_NE(0, stream_id); - DCHECK_NE(kDefaultStreamId, stream_id); + DCHECK_NE(gpu::GPU_STREAM_INVALID, stream_id); + DCHECK_NE(gpu::GPU_STREAM_DEFAULT, stream_id); return stream_id; } diff --git a/chromium/gpu/ipc/client/gpu_channel_host.h b/chromium/gpu/ipc/client/gpu_channel_host.h index be04133199c..94fb98d71d6 100644 --- a/chromium/gpu/ipc/client/gpu_channel_host.h +++ b/chromium/gpu/ipc/client/gpu_channel_host.h @@ -8,6 +8,7 @@ #include <stddef.h> #include <stdint.h> +#include <memory> #include <string> #include <vector> @@ -15,24 +16,18 @@ #include "base/containers/scoped_ptr_hash_map.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/process/process.h" #include "base/synchronization/lock.h" #include "gpu/config/gpu_info.h" #include "gpu/gpu_export.h" #include "gpu/ipc/common/gpu_stream_constants.h" -#include "gpu/ipc/common/surface_handle.h" #include "ipc/ipc_channel_handle.h" #include "ipc/ipc_sync_channel.h" #include "ipc/message_filter.h" #include "ipc/message_router.h" #include "ui/events/latency_info.h" -#include "ui/gfx/geometry/size.h" #include "ui/gfx/gpu_memory_buffer.h" -#include "ui/gl/gpu_preference.h" - -class GURL; namespace base { class WaitableEvent; @@ -47,8 +42,6 @@ class GpuMemoryBufferManager; } namespace gpu { -class CommandBufferProxyImpl; -class GpuChannelHost; class GPU_EXPORT GpuChannelHostFactory { public: @@ -57,7 +50,8 @@ class GPU_EXPORT GpuChannelHostFactory { virtual bool IsMainThread() = 0; virtual scoped_refptr<base::SingleThreadTaskRunner> GetIOThreadTaskRunner() = 0; - virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory(size_t size) = 0; + virtual std::unique_ptr<base::SharedMemory> AllocateSharedMemory( + size_t size) = 0; }; // Encapsulates an IPC channel between the client and one GPU process. @@ -77,10 +71,6 @@ class GPU_EXPORT GpuChannelHost base::WaitableEvent* shutdown_event, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager); - static const int32_t kDefaultStreamId = gpu::GPU_STREAM_DEFAULT; - static const gpu::GpuStreamPriority kDefaultStreamPriority = - gpu::GpuStreamPriority::NORMAL; - bool IsLost() const { DCHECK(channel_filter_.get()); return channel_filter_->IsLost(); @@ -107,20 +97,6 @@ class GPU_EXPORT GpuChannelHost void FlushPendingStream(int32_t stream_id); - // Create and connect to a command buffer in the GPU process. - scoped_ptr<CommandBufferProxyImpl> CreateCommandBuffer( - gpu::SurfaceHandle surface_handle, - const gfx::Size& size, - CommandBufferProxyImpl* share_group, - int32_t stream_id, - gpu::GpuStreamPriority stream_priority, - const std::vector<int32_t>& attribs, - const GURL& active_url, - gfx::GpuPreference gpu_preference); - - // Destroy a command buffer created by this channel. - void DestroyCommandBuffer(CommandBufferProxyImpl* command_buffer); - // Destroy this channel. Must be called on the main thread, before // destruction. void DestroyChannel(); @@ -289,7 +265,7 @@ class GPU_EXPORT GpuChannelHost // Protects channel_ and stream_flush_info_. mutable base::Lock context_lock_; - scoped_ptr<IPC::SyncChannel> channel_; + std::unique_ptr<IPC::SyncChannel> channel_; base::hash_map<int32_t, StreamFlushInfo> stream_flush_info_; DISALLOW_COPY_AND_ASSIGN(GpuChannelHost); diff --git a/chromium/gpu/ipc/client/gpu_context_tests.h b/chromium/gpu/ipc/client/gpu_context_tests.h new file mode 100644 index 00000000000..cced50c00b9 --- /dev/null +++ b/chromium/gpu/ipc/client/gpu_context_tests.h @@ -0,0 +1,138 @@ +// Copyright 2013 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. + +// These tests are run twice: +// Once in a gpu test with an in-process command buffer. +// Once in a browsertest with an out-of-process command buffer and gpu-process. + +#include "base/bind.h" +#include "base/run_loop.h" +#include "gpu/GLES2/gl2extchromium.h" +#include "gpu/command_buffer/client/context_support.h" +#include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/command_buffer/common/sync_token.h" + +namespace { + +class SignalTest : public ContextTestBase { + public: + static void RunOnlyOnce(base::Closure cb, int* tmp) { + CHECK_EQ(*tmp, 0); + ++*tmp; + cb.Run(); + } + + // These tests should time out if the callback doesn't get called. + void TestSignalSyncToken(const gpu::SyncToken& sync_token) { + base::RunLoop run_loop; + context_support_->SignalSyncToken(sync_token, run_loop.QuitClosure()); + run_loop.Run(); + } + + // These tests should time out if the callback doesn't get called. + void TestSignalQuery(GLuint query) { + base::RunLoop run_loop; + context_support_->SignalQuery( + query, base::Bind(&RunOnlyOnce, run_loop.QuitClosure(), + base::Owned(new int(0)))); + run_loop.Run(); + } +}; + +CONTEXT_TEST_F(SignalTest, BasicSignalSyncTokenTest) { +#if defined(OS_WIN) + // The IPC version of ContextTestBase::SetUpOnMainThread does not succeed on + // some platforms. + if (!gl_) + return; +#endif + + const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM(); + gl_->ShallowFlushCHROMIUM(); + + gpu::SyncToken sync_token; + gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + + TestSignalSyncToken(sync_token); +}; + +CONTEXT_TEST_F(SignalTest, EmptySignalSyncTokenTest) { +#if defined(OS_WIN) + // The IPC version of ContextTestBase::SetUpOnMainThread does not succeed on + // some platforms. + if (!gl_) + return; +#endif + + // Signalling something that doesn't exist should run the callback + // immediately. + gpu::SyncToken sync_token; + TestSignalSyncToken(sync_token); +}; + +CONTEXT_TEST_F(SignalTest, InvalidSignalSyncTokenTest) { +#if defined(OS_WIN) + // The IPC version of ContextTestBase::SetUpOnMainThread does not succeed on + // some platforms. + if (!gl_) + return; +#endif + + // Signalling something that doesn't exist should run the callback + // immediately. + gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, + gpu::CommandBufferId::FromUnsafeValue(1297824234), + 9123743439); + TestSignalSyncToken(sync_token); +}; + +CONTEXT_TEST_F(SignalTest, BasicSignalQueryTest) { +#if defined(OS_WIN) + // The IPC version of ContextTestBase::SetUpOnMainThread does not succeed on + // some platforms. + if (!gl_) + return; +#endif + + unsigned query; + gl_->GenQueriesEXT(1, &query); + gl_->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, query); + gl_->Finish(); + gl_->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); + TestSignalQuery(query); + gl_->DeleteQueriesEXT(1, &query); +}; + +CONTEXT_TEST_F(SignalTest, SignalQueryUnboundTest) { +#if defined(OS_WIN) + // The IPC version of ContextTestBase::SetUpOnMainThread does not succeed on + // some platforms. + if (!gl_) + return; +#endif + + GLuint query; + gl_->GenQueriesEXT(1, &query); + TestSignalQuery(query); + gl_->DeleteQueriesEXT(1, &query); +}; + +CONTEXT_TEST_F(SignalTest, InvalidSignalQueryUnboundTest) { +#if defined(OS_WIN) + // The IPC version of ContextTestBase::SetUpOnMainThread does not succeed on + // some platforms. + if (!gl_) + return; +#endif + + // Signalling something that doesn't exist should run the callback + // immediately. + TestSignalQuery(928729087); + TestSignalQuery(928729086); + TestSignalQuery(928729085); + TestSignalQuery(928729083); + TestSignalQuery(928729082); + TestSignalQuery(928729081); +}; +}; diff --git a/chromium/gpu/ipc/client/gpu_in_process_context_tests.cc b/chromium/gpu/ipc/client/gpu_in_process_context_tests.cc new file mode 100644 index 00000000000..ffe1f82b5f8 --- /dev/null +++ b/chromium/gpu/ipc/client/gpu_in_process_context_tests.cc @@ -0,0 +1,62 @@ +// Copyright 2013 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 <stdio.h> + +#include <cmath> +#include <memory> +#include <string> +#include <vector> + +#include "gpu/command_buffer/client/gl_in_process_context.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/shared_memory_limits.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_surface.h" + +namespace { + +class ContextTestBase : public testing::Test { + public: + void SetUp() override { + gpu::gles2::ContextCreationAttribHelper attributes; + attributes.alpha_size = 8; + attributes.depth_size = 24; + attributes.red_size = 8; + attributes.green_size = 8; + attributes.blue_size = 8; + attributes.stencil_size = 8; + attributes.samples = 4; + attributes.sample_buffers = 1; + attributes.bind_generates_resource = false; + + context_.reset(gpu::GLInProcessContext::Create( + nullptr, /* service */ + nullptr, /* surface */ + true, /* offscreen */ + gfx::kNullAcceleratedWidget, /* window */ + gfx::Size(1, 1), /* size */ + nullptr, /* share_context */ + attributes, gfx::PreferDiscreteGpu, gpu::SharedMemoryLimits(), + nullptr, /* gpu_memory_buffer_manager */ + nullptr /* image_factory */)); + gl_ = context_->GetImplementation(); + context_support_ = context_->GetImplementation(); + } + + void TearDown() override { context_.reset(NULL); } + + protected: + gpu::gles2::GLES2Interface* gl_; + gpu::ContextSupport* context_support_; + + private: + std::unique_ptr<gpu::GLInProcessContext> context_; +}; + +} // namespace + +// Include the actual tests. +#define CONTEXT_TEST_F TEST_F +#include "gpu/ipc/client/gpu_context_tests.h" diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl.cc b/chromium/gpu/ipc/client/gpu_memory_buffer_impl.cc index a1867d67f8d..e2ac46e28fb 100644 --- a/chromium/gpu/ipc/client/gpu_memory_buffer_impl.cc +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl.cc @@ -38,7 +38,7 @@ GpuMemoryBufferImpl::~GpuMemoryBufferImpl() { } // static -scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::CreateFromHandle( +std::unique_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::CreateFromHandle( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, gfx::BufferFormat format, diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl.h b/chromium/gpu/ipc/client/gpu_memory_buffer_impl.h index f8b8fc0c8d4..8439d0f401d 100644 --- a/chromium/gpu/ipc/client/gpu_memory_buffer_impl.h +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl.h @@ -5,9 +5,10 @@ #ifndef GPU_IPC_CLIENT_GPU_MEMORY_BUFFER_IMPL_H_ #define GPU_IPC_CLIENT_GPU_MEMORY_BUFFER_IMPL_H_ +#include <memory> + #include "base/callback.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/common/sync_token.h" #include "gpu/gpu_export.h" #include "ui/gfx/geometry/size.h" @@ -26,7 +27,7 @@ class GPU_EXPORT GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer { // should match what was used to allocate the |handle|. |callback| is // called when instance is deleted, which is not necessarily on the same // thread as this function was called on and instance was created on. - static scoped_ptr<GpuMemoryBufferImpl> CreateFromHandle( + static std::unique_ptr<GpuMemoryBufferImpl> CreateFromHandle( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, gfx::BufferFormat format, diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.cc b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.cc index 7c2bb9f3654..b6d5c369d64 100644 --- a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.cc +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.cc @@ -5,6 +5,7 @@ #include "gpu/ipc/client/gpu_memory_buffer_impl_io_surface.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "gpu/ipc/common/gpu_memory_buffer_support.h" #include "ui/gfx/buffer_format_util.h" #include "ui/gfx/mac/io_surface.h" @@ -43,7 +44,7 @@ GpuMemoryBufferImplIOSurface::GpuMemoryBufferImplIOSurface( GpuMemoryBufferImplIOSurface::~GpuMemoryBufferImplIOSurface() {} // static -scoped_ptr<GpuMemoryBufferImplIOSurface> +std::unique_ptr<GpuMemoryBufferImplIOSurface> GpuMemoryBufferImplIOSurface::CreateFromHandle( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, @@ -55,7 +56,7 @@ GpuMemoryBufferImplIOSurface::CreateFromHandle( if (!io_surface) return nullptr; - return make_scoped_ptr( + return base::WrapUnique( new GpuMemoryBufferImplIOSurface(handle.id, size, format, callback, io_surface.release(), LockFlags(usage))); } diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.h b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.h index 1102274eafb..3a5a343a124 100644 --- a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.h +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.h @@ -9,6 +9,8 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/mac/scoped_cftyperef.h" #include "base/macros.h" #include "gpu/gpu_export.h" @@ -21,7 +23,7 @@ class GPU_EXPORT GpuMemoryBufferImplIOSurface : public GpuMemoryBufferImpl { public: ~GpuMemoryBufferImplIOSurface() override; - static scoped_ptr<GpuMemoryBufferImplIOSurface> CreateFromHandle( + static std::unique_ptr<GpuMemoryBufferImplIOSurface> CreateFromHandle( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, gfx::BufferFormat format, diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc index 7554f3ee51f..c676e39d0d5 100644 --- a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc @@ -6,6 +6,7 @@ #include <utility> +#include "base/memory/ptr_util.h" #include "gpu/ipc/common/gpu_memory_buffer_support.h" #include "ui/gfx/buffer_format_util.h" #include "ui/ozone/public/client_native_pixmap_factory.h" @@ -28,7 +29,7 @@ GpuMemoryBufferImplOzoneNativePixmap::GpuMemoryBufferImplOzoneNativePixmap( const gfx::Size& size, gfx::BufferFormat format, const DestructionCallback& callback, - scoped_ptr<ui::ClientNativePixmap> pixmap) + std::unique_ptr<ui::ClientNativePixmap> pixmap) : GpuMemoryBufferImpl(id, size, format, callback), pixmap_(std::move(pixmap)), data_(nullptr) {} @@ -36,18 +37,18 @@ GpuMemoryBufferImplOzoneNativePixmap::GpuMemoryBufferImplOzoneNativePixmap( GpuMemoryBufferImplOzoneNativePixmap::~GpuMemoryBufferImplOzoneNativePixmap() {} // static -scoped_ptr<GpuMemoryBufferImplOzoneNativePixmap> +std::unique_ptr<GpuMemoryBufferImplOzoneNativePixmap> GpuMemoryBufferImplOzoneNativePixmap::CreateFromHandle( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, gfx::BufferFormat format, gfx::BufferUsage usage, const DestructionCallback& callback) { - scoped_ptr<ui::ClientNativePixmap> native_pixmap = + std::unique_ptr<ui::ClientNativePixmap> native_pixmap = ui::ClientNativePixmapFactory::GetInstance()->ImportFromHandle( handle.native_pixmap_handle, size, usage); DCHECK(native_pixmap); - return make_scoped_ptr(new GpuMemoryBufferImplOzoneNativePixmap( + return base::WrapUnique(new GpuMemoryBufferImplOzoneNativePixmap( handle.id, size, format, callback, std::move(native_pixmap))); } @@ -68,7 +69,8 @@ base::Closure GpuMemoryBufferImplOzoneNativePixmap::AllocateForTesting( scoped_refptr<ui::NativePixmap> pixmap = ui::OzonePlatform::GetInstance() ->GetSurfaceFactoryOzone() - ->CreateNativePixmap(gfx::kNullPluginWindow, size, format, usage); + ->CreateNativePixmap(gfx::kNullAcceleratedWidget, size, format, + usage); handle->type = gfx::OZONE_NATIVE_PIXMAP; handle->native_pixmap_handle = pixmap->ExportHandle(); return base::Bind(&FreeNativePixmapForTesting, pixmap); diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap.h b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap.h index 3ec59e90b89..44b53df5a7b 100644 --- a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap.h +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap.h @@ -7,6 +7,8 @@ #include <stddef.h> +#include <memory> + #include "base/macros.h" #include "gpu/gpu_export.h" #include "gpu/ipc/client/gpu_memory_buffer_impl.h" @@ -23,7 +25,7 @@ class GPU_EXPORT GpuMemoryBufferImplOzoneNativePixmap public: ~GpuMemoryBufferImplOzoneNativePixmap() override; - static scoped_ptr<GpuMemoryBufferImplOzoneNativePixmap> CreateFromHandle( + static std::unique_ptr<GpuMemoryBufferImplOzoneNativePixmap> CreateFromHandle( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, gfx::BufferFormat format, @@ -51,9 +53,9 @@ class GPU_EXPORT GpuMemoryBufferImplOzoneNativePixmap const gfx::Size& size, gfx::BufferFormat format, const DestructionCallback& callback, - scoped_ptr<ui::ClientNativePixmap> native_pixmap); + std::unique_ptr<ui::ClientNativePixmap> native_pixmap); - scoped_ptr<ui::ClientNativePixmap> pixmap_; + std::unique_ptr<ui::ClientNativePixmap> pixmap_; void* data_; DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplOzoneNativePixmap); diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc index ef817243863..576a15c748b 100644 --- a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc @@ -8,6 +8,7 @@ #include <utility> #include "base/bind.h" +#include "base/memory/ptr_util.h" #include "base/numerics/safe_math.h" #include "base/process/memory.h" #include "ui/gfx/buffer_format_util.h" @@ -25,7 +26,7 @@ GpuMemoryBufferImplSharedMemory::GpuMemoryBufferImplSharedMemory( const gfx::Size& size, gfx::BufferFormat format, const DestructionCallback& callback, - scoped_ptr<base::SharedMemory> shared_memory, + std::unique_ptr<base::SharedMemory> shared_memory, size_t offset, int stride) : GpuMemoryBufferImpl(id, size, format, callback), @@ -38,7 +39,7 @@ GpuMemoryBufferImplSharedMemory::GpuMemoryBufferImplSharedMemory( GpuMemoryBufferImplSharedMemory::~GpuMemoryBufferImplSharedMemory() {} // static -scoped_ptr<GpuMemoryBufferImplSharedMemory> +std::unique_ptr<GpuMemoryBufferImplSharedMemory> GpuMemoryBufferImplSharedMemory::Create(gfx::GpuMemoryBufferId id, const gfx::Size& size, gfx::BufferFormat format, @@ -47,11 +48,11 @@ GpuMemoryBufferImplSharedMemory::Create(gfx::GpuMemoryBufferId id, if (!gfx::BufferSizeForBufferFormatChecked(size, format, &buffer_size)) return nullptr; - scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); + std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); if (!shared_memory->CreateAndMapAnonymous(buffer_size)) return nullptr; - return make_scoped_ptr(new GpuMemoryBufferImplSharedMemory( + return base::WrapUnique(new GpuMemoryBufferImplSharedMemory( id, size, format, callback, std::move(shared_memory), 0, gfx::RowSizeForBufferFormat(size.width(), format, 0))); } @@ -82,7 +83,7 @@ GpuMemoryBufferImplSharedMemory::AllocateForChildProcess( } // static -scoped_ptr<GpuMemoryBufferImplSharedMemory> +std::unique_ptr<GpuMemoryBufferImplSharedMemory> GpuMemoryBufferImplSharedMemory::CreateFromHandle( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, @@ -91,9 +92,9 @@ GpuMemoryBufferImplSharedMemory::CreateFromHandle( const DestructionCallback& callback) { DCHECK(base::SharedMemory::IsHandleValid(handle.handle)); - return make_scoped_ptr(new GpuMemoryBufferImplSharedMemory( + return base::WrapUnique(new GpuMemoryBufferImplSharedMemory( handle.id, size, format, callback, - make_scoped_ptr(new base::SharedMemory(handle.handle, false)), + base::WrapUnique(new base::SharedMemory(handle.handle, false)), handle.offset, handle.stride)); } @@ -132,6 +133,7 @@ bool GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat( // by the block size. return size.width() % 4 == 0 && size.height() % 4 == 0; case gfx::BufferFormat::R_8: + case gfx::BufferFormat::BGR_565: case gfx::BufferFormat::RGBA_4444: case gfx::BufferFormat::RGBA_8888: case gfx::BufferFormat::RGBX_8888: diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h index 3271c1a6f74..0ad9e3fa80c 100644 --- a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h @@ -7,6 +7,8 @@ #include <stddef.h> +#include <memory> + #include "base/macros.h" #include "gpu/gpu_export.h" #include "gpu/ipc/client/gpu_memory_buffer_impl.h" @@ -18,7 +20,7 @@ class GPU_EXPORT GpuMemoryBufferImplSharedMemory : public GpuMemoryBufferImpl { public: ~GpuMemoryBufferImplSharedMemory() override; - static scoped_ptr<GpuMemoryBufferImplSharedMemory> Create( + static std::unique_ptr<GpuMemoryBufferImplSharedMemory> Create( gfx::GpuMemoryBufferId id, const gfx::Size& size, gfx::BufferFormat format, @@ -30,7 +32,7 @@ class GPU_EXPORT GpuMemoryBufferImplSharedMemory : public GpuMemoryBufferImpl { gfx::BufferFormat format, base::ProcessHandle child_process); - static scoped_ptr<GpuMemoryBufferImplSharedMemory> CreateFromHandle( + static std::unique_ptr<GpuMemoryBufferImplSharedMemory> CreateFromHandle( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, gfx::BufferFormat format, @@ -56,15 +58,16 @@ class GPU_EXPORT GpuMemoryBufferImplSharedMemory : public GpuMemoryBufferImpl { gfx::GpuMemoryBufferHandle GetHandle() const override; private: - GpuMemoryBufferImplSharedMemory(gfx::GpuMemoryBufferId id, - const gfx::Size& size, - gfx::BufferFormat format, - const DestructionCallback& callback, - scoped_ptr<base::SharedMemory> shared_memory, - size_t offset, - int stride); - - scoped_ptr<base::SharedMemory> shared_memory_; + GpuMemoryBufferImplSharedMemory( + gfx::GpuMemoryBufferId id, + const gfx::Size& size, + gfx::BufferFormat format, + const DestructionCallback& callback, + std::unique_ptr<base::SharedMemory> shared_memory, + size_t offset, + int stride); + + std::unique_ptr<base::SharedMemory> shared_memory_; size_t offset_; int stride_; diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc index 3f9d8984f09..257b64e750c 100644 --- a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> + #include "gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h" #include "gpu/ipc/client/gpu_memory_buffer_impl_test_template.h" @@ -23,7 +25,7 @@ TEST(GpuMemoryBufferImplSharedMemoryTest, Create) { for (auto format : gfx::GetBufferFormatsForTesting()) { bool destroyed = false; - scoped_ptr<GpuMemoryBufferImplSharedMemory> buffer( + std::unique_ptr<GpuMemoryBufferImplSharedMemory> buffer( GpuMemoryBufferImplSharedMemory::Create( kBufferId, buffer_size, format, base::Bind(&BufferDestroyed, base::Unretained(&destroyed)))); diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_surface_texture.cc b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_surface_texture.cc index 5ff527e2daf..0fca294568e 100644 --- a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_surface_texture.cc +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_surface_texture.cc @@ -5,6 +5,7 @@ #include "gpu/ipc/client/gpu_memory_buffer_impl_surface_texture.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/trace_event/trace_event.h" #include "gpu/ipc/common/android/surface_texture_manager.h" #include "gpu/ipc/common/gpu_memory_buffer_support.h" @@ -25,6 +26,7 @@ int WindowFormat(gfx::BufferFormat format) { case gfx::BufferFormat::DXT5: case gfx::BufferFormat::ETC1: case gfx::BufferFormat::R_8: + case gfx::BufferFormat::BGR_565: case gfx::BufferFormat::RGBA_4444: case gfx::BufferFormat::RGBX_8888: case gfx::BufferFormat::BGRX_8888: @@ -62,7 +64,7 @@ GpuMemoryBufferImplSurfaceTexture::~GpuMemoryBufferImplSurfaceTexture() { } // static -scoped_ptr<GpuMemoryBufferImplSurfaceTexture> +std::unique_ptr<GpuMemoryBufferImplSurfaceTexture> GpuMemoryBufferImplSurfaceTexture::CreateFromHandle( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, @@ -78,7 +80,7 @@ GpuMemoryBufferImplSurfaceTexture::CreateFromHandle( ANativeWindow_setBuffersGeometry(native_window, size.width(), size.height(), WindowFormat(format)); - return make_scoped_ptr(new GpuMemoryBufferImplSurfaceTexture( + return base::WrapUnique(new GpuMemoryBufferImplSurfaceTexture( handle.id, size, format, callback, native_window)); } diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_surface_texture.h b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_surface_texture.h index e93b61415f6..3e4f862a0a3 100644 --- a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_surface_texture.h +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_surface_texture.h @@ -8,6 +8,8 @@ #include <android/native_window.h> #include <stddef.h> +#include <memory> + #include "base/macros.h" #include "gpu/gpu_export.h" #include "gpu/ipc/client/gpu_memory_buffer_impl.h" @@ -20,7 +22,7 @@ class GPU_EXPORT GpuMemoryBufferImplSurfaceTexture public: ~GpuMemoryBufferImplSurfaceTexture() override; - static scoped_ptr<GpuMemoryBufferImplSurfaceTexture> CreateFromHandle( + static std::unique_ptr<GpuMemoryBufferImplSurfaceTexture> CreateFromHandle( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, gfx::BufferFormat format, diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_surface_texture_unittest.cc b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_surface_texture_unittest.cc new file mode 100644 index 00000000000..a3edc70bd8b --- /dev/null +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_surface_texture_unittest.cc @@ -0,0 +1,16 @@ +// 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 "gpu/ipc/client/gpu_memory_buffer_impl_surface_texture.h" +#include "gpu/ipc/client/gpu_memory_buffer_impl_test_template.h" + +namespace gpu { +namespace { + +INSTANTIATE_TYPED_TEST_CASE_P(GpuMemoryBufferImplSurfaceTexture, + GpuMemoryBufferImplTest, + GpuMemoryBufferImplSurfaceTexture); + +} // namespace +} // namespace gpu diff --git a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_test_template.h b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_test_template.h index fa9b1dbcd9b..e0936980bb2 100644 --- a/chromium/gpu/ipc/client/gpu_memory_buffer_impl_test_template.h +++ b/chromium/gpu/ipc/client/gpu_memory_buffer_impl_test_template.h @@ -11,6 +11,8 @@ #include <stddef.h> #include <string.h> +#include <memory> + #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/buffer_format_util.h" @@ -61,7 +63,7 @@ TYPED_TEST_P(GpuMemoryBufferImplTest, CreateFromHandle) { GpuMemoryBufferImpl::DestructionCallback destroy_callback = TestFixture::AllocateGpuMemoryBuffer(kBufferSize, format, usage, &handle, &destroyed); - scoped_ptr<TypeParam> buffer(TypeParam::CreateFromHandle( + std::unique_ptr<TypeParam> buffer(TypeParam::CreateFromHandle( handle, kBufferSize, format, usage, destroy_callback)); ASSERT_TRUE(buffer); EXPECT_EQ(buffer->GetFormat(), format); @@ -88,7 +90,7 @@ TYPED_TEST_P(GpuMemoryBufferImplTest, Map) { TestFixture::AllocateGpuMemoryBuffer( kBufferSize, format, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, &handle, nullptr); - scoped_ptr<TypeParam> buffer(TypeParam::CreateFromHandle( + std::unique_ptr<TypeParam> buffer(TypeParam::CreateFromHandle( handle, kBufferSize, format, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, destroy_callback)); ASSERT_TRUE(buffer); @@ -104,7 +106,7 @@ TYPED_TEST_P(GpuMemoryBufferImplTest, Map) { gfx::RowSizeForBufferFormat(kBufferSize.width(), format, plane); EXPECT_GT(row_size_in_bytes, 0u); - scoped_ptr<char[]> data(new char[row_size_in_bytes]); + std::unique_ptr<char[]> data(new char[row_size_in_bytes]); memset(data.get(), 0x2a + plane, row_size_in_bytes); size_t height = kBufferSize.height() / @@ -139,7 +141,7 @@ TYPED_TEST_P(GpuMemoryBufferImplTest, PersistentMap) { kBufferSize, format, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT, &handle, nullptr); - scoped_ptr<TypeParam> buffer(TypeParam::CreateFromHandle( + std::unique_ptr<TypeParam> buffer(TypeParam::CreateFromHandle( handle, kBufferSize, format, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT, destroy_callback)); @@ -155,7 +157,7 @@ TYPED_TEST_P(GpuMemoryBufferImplTest, PersistentMap) { gfx::RowSizeForBufferFormat(kBufferSize.width(), format, plane); EXPECT_GT(row_size_in_bytes, 0u); - scoped_ptr<char[]> data(new char[row_size_in_bytes]); + std::unique_ptr<char[]> data(new char[row_size_in_bytes]); memset(data.get(), 0x2a + plane, row_size_in_bytes); size_t height = kBufferSize.height() / @@ -179,7 +181,7 @@ TYPED_TEST_P(GpuMemoryBufferImplTest, PersistentMap) { const size_t row_size_in_bytes = gfx::RowSizeForBufferFormat(kBufferSize.width(), format, plane); - scoped_ptr<char[]> data(new char[row_size_in_bytes]); + std::unique_ptr<char[]> data(new char[row_size_in_bytes]); memset(data.get(), 0x2a + plane, row_size_in_bytes); size_t height = kBufferSize.height() / diff --git a/chromium/gpu/ipc/client/gpu_process_hosted_ca_layer_tree_params.cc b/chromium/gpu/ipc/client/gpu_process_hosted_ca_layer_tree_params.cc new file mode 100644 index 00000000000..1d1997c1165 --- /dev/null +++ b/chromium/gpu/ipc/client/gpu_process_hosted_ca_layer_tree_params.cc @@ -0,0 +1,13 @@ +// Copyright 2016 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/ipc/client/gpu_process_hosted_ca_layer_tree_params.h" + +namespace gpu { + +GpuProcessHostedCALayerTreeParamsMac::GpuProcessHostedCALayerTreeParamsMac() {} + +GpuProcessHostedCALayerTreeParamsMac::~GpuProcessHostedCALayerTreeParamsMac() {} + +} // namespace gpu diff --git a/chromium/gpu/ipc/client/gpu_process_hosted_ca_layer_tree_params.h b/chromium/gpu/ipc/client/gpu_process_hosted_ca_layer_tree_params.h new file mode 100644 index 00000000000..bc87b509613 --- /dev/null +++ b/chromium/gpu/ipc/client/gpu_process_hosted_ca_layer_tree_params.h @@ -0,0 +1,27 @@ +// Copyright 2016 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 <IOSurface/IOSurface.h> + +#include "base/mac/scoped_cftyperef.h" +#include "gpu/gpu_export.h" +#include "ui/base/cocoa/remote_layer_api.h" +#include "ui/gfx/geometry/size.h" + +namespace gpu { + +struct GPU_EXPORT GpuProcessHostedCALayerTreeParamsMac { + GpuProcessHostedCALayerTreeParamsMac(); + ~GpuProcessHostedCALayerTreeParamsMac(); + + int surface_handle = 0; + CAContextID ca_context_id = 0; + bool fullscreen_low_power_ca_context_valid = false; + CAContextID fullscreen_low_power_ca_context_id = 0; + base::ScopedCFTypeRef<IOSurfaceRef> io_surface; + gfx::Size pixel_size; + float scale_factor = 1; +}; + +} // namespace gpu diff --git a/chromium/gpu/ipc/common/BUILD.gn b/chromium/gpu/ipc/common/BUILD.gn index c596e265f53..d1f101c0f3d 100644 --- a/chromium/gpu/ipc/common/BUILD.gn +++ b/chromium/gpu/ipc/common/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/ui.gni") +import("//mojo/public/tools/bindings/mojom.gni") group("common") { if (is_component_build) { @@ -38,7 +39,6 @@ source_set("command_buffer_traits_sources") { "gpu_command_buffer_traits.cc", "gpu_command_buffer_traits.h", "gpu_command_buffer_traits_multi.h", - "id_type_traits.h", ] configs += [ @@ -46,11 +46,16 @@ source_set("command_buffer_traits_sources") { "//third_party/khronos:khronos_headers", ] - deps = [ - "//base", + public_deps = [ "//gpu/command_buffer/common:common_sources", "//ipc", ] + + deps = [ + "//base", + "//ui/gfx/ipc", + "//ui/gfx/ipc/geometry", + ] } source_set("ipc_common_sources") { @@ -80,14 +85,19 @@ source_set("ipc_common_sources") { "//third_party/khronos:khronos_headers", ] - deps = [ + public_deps = [ ":command_buffer_traits_sources", + "//gpu/command_buffer/common:gles2_utils", + ] + + deps = [ "//base", "//gpu/command_buffer/common:common_sources", "//gpu/config:config_sources", "//ipc", "//ui/events/ipc", "//ui/gfx/ipc", + "//ui/gfx/ipc/geometry", "//ui/gl", "//url/ipc:url_ipc", ] @@ -105,3 +115,13 @@ source_set("ipc_common_sources") { deps += [ "//ui/ozone" ] } } + +mojom("interfaces") { + sources = [ + "capabilities.mojom", + "command_buffer.mojom", + "mailbox.mojom", + "mailbox_holder.mojom", + "sync_token.mojom", + ] +} diff --git a/chromium/gpu/command_buffer/common/capabilities.mojom b/chromium/gpu/ipc/common/capabilities.mojom index fd35409e940..fd35409e940 100644 --- a/chromium/gpu/command_buffer/common/capabilities.mojom +++ b/chromium/gpu/ipc/common/capabilities.mojom diff --git a/chromium/gpu/ipc/common/capabilities.typemap b/chromium/gpu/ipc/common/capabilities.typemap new file mode 100644 index 00000000000..c518ba92c8f --- /dev/null +++ b/chromium/gpu/ipc/common/capabilities.typemap @@ -0,0 +1,12 @@ +# Copyright 2016 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. + +mojom = "//gpu/ipc/common/capabilities.mojom" +public_headers = [ "//gpu/command_buffer/common/capabilities.h" ] +traits_headers = [ "//gpu/ipc/common/gpu_command_buffer_traits.h" ] +deps = [ + "//gpu/ipc/common:command_buffer_traits", +] + +type_mappings = [ "gpu.mojom.Capabilities=gpu::Capabilities" ] diff --git a/chromium/gpu/command_buffer/common/command_buffer.mojom b/chromium/gpu/ipc/common/command_buffer.mojom index e3677b7df6a..e3677b7df6a 100644 --- a/chromium/gpu/command_buffer/common/command_buffer.mojom +++ b/chromium/gpu/ipc/common/command_buffer.mojom diff --git a/chromium/gpu/ipc/common/command_buffer.typemap b/chromium/gpu/ipc/common/command_buffer.typemap new file mode 100644 index 00000000000..154169269c9 --- /dev/null +++ b/chromium/gpu/ipc/common/command_buffer.typemap @@ -0,0 +1,12 @@ +# Copyright 2016 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. + +mojom = "//gpu/ipc/common/command_buffer.mojom" +public_headers = [ "//gpu/command_buffer/common/command_buffer.h" ] +traits_headers = [ "//gpu/ipc/common/gpu_command_buffer_traits.h" ] +deps = [ + "//gpu/ipc/common:command_buffer_traits", +] + +type_mappings = [ "gpu.mojom.CommandBufferState=gpu::CommandBuffer::State" ] diff --git a/chromium/gpu/ipc/common/gpu_command_buffer_traits.cc b/chromium/gpu/ipc/common/gpu_command_buffer_traits.cc index f5d4728d260..e7105f3d2f4 100644 --- a/chromium/gpu/ipc/common/gpu_command_buffer_traits.cc +++ b/chromium/gpu/ipc/common/gpu_command_buffer_traits.cc @@ -10,7 +10,6 @@ #include "gpu/command_buffer/common/command_buffer_id.h" #include "gpu/command_buffer/common/mailbox_holder.h" #include "gpu/command_buffer/common/sync_token.h" -#include "gpu/command_buffer/common/value_state.h" // Generate param traits size methods. #include "ipc/param_traits_size_macros.h" @@ -176,36 +175,4 @@ void ParamTraits<gpu::MailboxHolder>::Log(const param_type& p, std::string* l) { *l += base::StringPrintf(":%04x@", p.texture_target); } -void ParamTraits<gpu::ValueState>::GetSize(base::PickleSizer* s, - const param_type& p) { - s->AddData(sizeof(gpu::ValueState)); -} - -void ParamTraits<gpu::ValueState>::Write(base::Pickle* m, const param_type& p) { - m->WriteData(reinterpret_cast<const char*>(&p), - sizeof(gpu::ValueState)); -} - -bool ParamTraits<gpu::ValueState>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - int length; - const char* data = NULL; - if (!iter->ReadData(&data, &length) || length != sizeof(gpu::ValueState)) - return false; - DCHECK(data); - memcpy(p, data, sizeof(gpu::ValueState)); - return true; -} - -void ParamTraits<gpu::ValueState>::Log(const param_type& p, std::string* l) { - l->append("<ValueState ("); - for (int value : p.int_value) - *l += base::StringPrintf("%i ", value); - l->append(" int values "); - for (float value : p.float_value) - *l += base::StringPrintf("%f ", value); - l->append(" float values)>"); -} - } // namespace IPC diff --git a/chromium/gpu/ipc/common/gpu_command_buffer_traits.h b/chromium/gpu/ipc/common/gpu_command_buffer_traits.h index 1bf5314eb50..11209470f71 100644 --- a/chromium/gpu/ipc/common/gpu_command_buffer_traits.h +++ b/chromium/gpu/ipc/common/gpu_command_buffer_traits.h @@ -2,27 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef GPU_IPC_GPU_PARAM_TRAITS_H_ -#define GPU_IPC_GPU_PARAM_TRAITS_H_ +#ifndef GPU_IPC_COMMON_GPU_COMMAND_BUFFER_TRAITS_H_ +#define GPU_IPC_COMMON_GPU_COMMAND_BUFFER_TRAITS_H_ #include "gpu/command_buffer/common/command_buffer.h" +#include "gpu/command_buffer/common/id_type.h" #include "gpu/gpu_export.h" #include "gpu/ipc/common/gpu_command_buffer_traits_multi.h" -#include "gpu/ipc/common/id_type_traits.h" #include "ipc/ipc_message_utils.h" +#include "ipc/ipc_param_traits.h" namespace gpu { struct Mailbox; struct MailboxHolder; struct SyncToken; -union ValueState; } namespace IPC { template <> struct GPU_EXPORT ParamTraits<gpu::CommandBuffer::State> { - typedef gpu::CommandBuffer::State param_type; + using param_type = gpu::CommandBuffer::State; static void GetSize(base::PickleSizer* s, const param_type& p); static void Write(base::Pickle* m, const param_type& p); static bool Read(const base::Pickle* m, @@ -33,7 +33,7 @@ struct GPU_EXPORT ParamTraits<gpu::CommandBuffer::State> { template <> struct GPU_EXPORT ParamTraits<gpu::SyncToken> { - typedef gpu::SyncToken param_type; + using param_type = gpu::SyncToken; static void GetSize(base::PickleSizer* s, const param_type& p); static void Write(base::Pickle* m, const param_type& p); static bool Read(const base::Pickle* m, @@ -44,7 +44,7 @@ struct GPU_EXPORT ParamTraits<gpu::SyncToken> { template<> struct GPU_EXPORT ParamTraits<gpu::Mailbox> { - typedef gpu::Mailbox param_type; + using param_type = gpu::Mailbox; static void GetSize(base::PickleSizer* s, const param_type& p); static void Write(base::Pickle* m, const param_type& p); static bool Read(const base::Pickle* m, @@ -55,7 +55,7 @@ struct GPU_EXPORT ParamTraits<gpu::Mailbox> { template <> struct GPU_EXPORT ParamTraits<gpu::MailboxHolder> { - typedef gpu::MailboxHolder param_type; + using param_type = gpu::MailboxHolder; static void GetSize(base::PickleSizer* s, const param_type& p); static void Write(base::Pickle* m, const param_type& p); static bool Read(const base::Pickle* m, @@ -64,17 +64,29 @@ struct GPU_EXPORT ParamTraits<gpu::MailboxHolder> { static void Log(const param_type& p, std::string* l); }; -template <> -struct GPU_EXPORT ParamTraits<gpu::ValueState> { - typedef gpu::ValueState param_type; - static void GetSize(base::PickleSizer* s, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); +template <typename TypeMarker, typename WrappedType, WrappedType kInvalidValue> +struct ParamTraits<gpu::IdType<TypeMarker, WrappedType, kInvalidValue>> { + using param_type = gpu::IdType<TypeMarker, WrappedType, kInvalidValue>; + static void GetSize(base::PickleSizer* sizer, const param_type& p) { + GetParamSize(sizer, p.GetUnsafeValue()); + } + static void Write(base::Pickle* m, const param_type& p) { + WriteParam(m, p.GetUnsafeValue()); + } static bool Read(const base::Pickle* m, base::PickleIterator* iter, - param_type* p); - static void Log(const param_type& p, std::string* l); + param_type* r) { + WrappedType value; + if (!ReadParam(m, iter, &value)) + return false; + *r = param_type::FromUnsafeValue(value); + return true; + } + static void Log(const param_type& p, std::string* l) { + LogParam(p.GetUnsafeValue(), l); + } }; } // namespace IPC -#endif // GPU_IPC_GPU_PARAM_TRAITS_H_ +#endif // GPU_IPC_COMMON_GPU_COMMAND_BUFFER_TRAITS_H_ diff --git a/chromium/gpu/ipc/common/gpu_command_buffer_traits_multi.h b/chromium/gpu/ipc/common/gpu_command_buffer_traits_multi.h index 140737368d5..c969d5eacd9 100644 --- a/chromium/gpu/ipc/common/gpu_command_buffer_traits_multi.h +++ b/chromium/gpu/ipc/common/gpu_command_buffer_traits_multi.h @@ -3,6 +3,7 @@ // found in the LICENSE file. // Multiply-included message file, hence no include guard here. + #include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/common/constants.h" #include "gpu/gpu_export.h" @@ -110,7 +111,10 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::Capabilities) IPC_STRUCT_TRAITS_MEMBER(timer_queries) IPC_STRUCT_TRAITS_MEMBER(surfaceless) IPC_STRUCT_TRAITS_MEMBER(flips_vertically) + IPC_STRUCT_TRAITS_MEMBER(disable_webgl_multisampling_color_mask_usage) + IPC_STRUCT_TRAITS_MEMBER(disable_webgl_rgb_multisampling_usage) IPC_STRUCT_TRAITS_MEMBER(msaa_is_slow) + IPC_STRUCT_TRAITS_MEMBER(chromium_image_rgb_emulation) IPC_STRUCT_TRAITS_MEMBER(major_version) IPC_STRUCT_TRAITS_MEMBER(minor_version) diff --git a/chromium/gpu/ipc/common/gpu_memory_buffer_support.cc b/chromium/gpu/ipc/common/gpu_memory_buffer_support.cc index 0d1c510f361..1cb386f94d7 100644 --- a/chromium/gpu/ipc/common/gpu_memory_buffer_support.cc +++ b/chromium/gpu/ipc/common/gpu_memory_buffer_support.cc @@ -33,7 +33,8 @@ bool IsNativeGpuMemoryBufferConfigurationSupported(gfx::BufferFormat format, case gfx::BufferUsage::GPU_READ: case gfx::BufferUsage::SCANOUT: return format == gfx::BufferFormat::BGRA_8888 || - format == gfx::BufferFormat::RGBA_8888; + format == gfx::BufferFormat::RGBA_8888 || + format == gfx::BufferFormat::BGRX_8888; case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE: case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT: return format == gfx::BufferFormat::R_8 || diff --git a/chromium/gpu/ipc/common/gpu_message_generator.cc b/chromium/gpu/ipc/common/gpu_message_generator.cc index ab8f4890948..46a9d7fbf5b 100644 --- a/chromium/gpu/ipc/common/gpu_message_generator.cc +++ b/chromium/gpu/ipc/common/gpu_message_generator.cc @@ -14,6 +14,12 @@ #include "ipc/struct_destructor_macros.h" #include "gpu/ipc/common/gpu_message_generator.h" +// Generate param traits size methods. +#include "ipc/param_traits_size_macros.h" +namespace IPC { +#include "gpu/ipc/common/gpu_message_generator.h" +} + // Generate param traits write methods. #include "ipc/param_traits_write_macros.h" namespace IPC { diff --git a/chromium/gpu/ipc/common/gpu_messages.h b/chromium/gpu/ipc/common/gpu_messages.h index 449d151c529..6fc53494abf 100644 --- a/chromium/gpu/ipc/common/gpu_messages.h +++ b/chromium/gpu/ipc/common/gpu_messages.h @@ -18,7 +18,6 @@ #include "gpu/command_buffer/common/gpu_memory_allocation.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/sync_token.h" -#include "gpu/command_buffer/common/value_state.h" #include "gpu/config/gpu_info.h" #include "gpu/gpu_export.h" #include "gpu/ipc/common/gpu_command_buffer_traits.h" @@ -30,6 +29,7 @@ #include "ui/events/latency_info.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/gpu_memory_buffer.h" +#include "ui/gfx/ipc/geometry/gfx_param_traits.h" #include "ui/gfx/ipc/gfx_param_traits.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/swap_result.h" @@ -53,10 +53,12 @@ IPC_STRUCT_BEGIN(GPUCommandBufferConsoleMessage) IPC_STRUCT_END() IPC_STRUCT_BEGIN(GPUCreateCommandBufferConfig) + IPC_STRUCT_MEMBER(gpu::SurfaceHandle, surface_handle) + IPC_STRUCT_MEMBER(gfx::Size, size) IPC_STRUCT_MEMBER(int32_t, share_group_id) IPC_STRUCT_MEMBER(int32_t, stream_id) IPC_STRUCT_MEMBER(gpu::GpuStreamPriority, stream_priority) - IPC_STRUCT_MEMBER(std::vector<int>, attribs) + IPC_STRUCT_MEMBER(gpu::gles2::ContextCreationAttribHelper, attribs) IPC_STRUCT_MEMBER(GURL, active_url) IPC_STRUCT_MEMBER(gfx::GpuPreference, gpu_preference) IPC_STRUCT_END() @@ -70,6 +72,25 @@ IPC_STRUCT_BEGIN(GpuCommandBufferMsg_CreateImage_Params) IPC_STRUCT_MEMBER(uint64_t, image_release_count) IPC_STRUCT_END() +IPC_STRUCT_BEGIN(GpuCommandBufferMsg_SwapBuffersCompleted_Params) +#if defined(OS_MACOSX) + // Mac-specific parameters used to present CALayers hosted in the GPU process. + // TODO(ccameron): Remove these parameters once the CALayer tree is hosted in + // the browser process. + // https://crbug.com/604052 + IPC_STRUCT_MEMBER(gpu::SurfaceHandle, surface_handle) + // Only one of ca_context_id or io_surface may be non-0. + IPC_STRUCT_MEMBER(CAContextID, ca_context_id) + IPC_STRUCT_MEMBER(bool, fullscreen_low_power_ca_context_valid) + IPC_STRUCT_MEMBER(CAContextID, fullscreen_low_power_ca_context_id) + IPC_STRUCT_MEMBER(gfx::ScopedRefCountedIOSurfaceMachPort, io_surface) + IPC_STRUCT_MEMBER(gfx::Size, pixel_size) + IPC_STRUCT_MEMBER(float, scale_factor) +#endif + IPC_STRUCT_MEMBER(std::vector<ui::LatencyInfo>, latency_info) + IPC_STRUCT_MEMBER(gfx::SwapResult, result) +IPC_STRUCT_END() + //------------------------------------------------------------------------------ // GPU Channel Messages // These are messages from a renderer process to the GPU process. @@ -79,12 +100,12 @@ IPC_STRUCT_END() // ignored, and it will render directly to the native surface (only the browser // process is allowed to create those). Otherwise it will create an offscreen // backbuffer of dimensions |size|. -IPC_SYNC_MESSAGE_CONTROL4_1(GpuChannelMsg_CreateCommandBuffer, - gpu::SurfaceHandle /* surface_handle */, - gfx::Size /* size */, +IPC_SYNC_MESSAGE_CONTROL3_2(GpuChannelMsg_CreateCommandBuffer, GPUCreateCommandBufferConfig /* init_params */, int32_t /* route_id */, - bool /* succeeded */) + base::SharedMemoryHandle /* shared_state */, + bool /* result */, + gpu::Capabilities /* capabilities */) // The CommandBufferProxy sends this to the GpuCommandBufferStub in its // destructor, so that the stub deletes the actual CommandBufferService @@ -126,13 +147,6 @@ IPC_MESSAGE_ROUTED0(GpuStreamTextureMsg_FrameAvailable) // GPU Command Buffer Messages // These are messages between a renderer process to the GPU process relating to // a single OpenGL context. -// Initialize a command buffer with the given number of command entries. -// Returns the shared memory handle for the command buffer mapped to the -// calling process. -IPC_SYNC_MESSAGE_ROUTED1_2(GpuCommandBufferMsg_Initialize, - base::SharedMemoryHandle /* shared_state */, - bool /* result */, - gpu::Capabilities /* capabilities */) // Sets the shared memory buffer used for commands. IPC_SYNC_MESSAGE_ROUTED1_0(GpuCommandBufferMsg_SetGetBuffer, @@ -185,9 +199,9 @@ IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_Destroyed, gpu::error::Error /* error */) // Tells the browser that SwapBuffers returned and passes latency info -IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_SwapBuffersCompleted, - std::vector<ui::LatencyInfo> /* latency_info */, - gfx::SwapResult /* result */) +IPC_MESSAGE_ROUTED1( + GpuCommandBufferMsg_SwapBuffersCompleted, + GpuCommandBufferMsg_SwapBuffersCompleted_Params /* params */) // Tells the browser about updated parameters for vsync alignment. IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_UpdateVSyncParameters, diff --git a/chromium/gpu/ipc/common/gpu_param_traits.cc b/chromium/gpu/ipc/common/gpu_param_traits.cc index efc298788ba..b5f35b20d64 100644 --- a/chromium/gpu/ipc/common/gpu_param_traits.cc +++ b/chromium/gpu/ipc/common/gpu_param_traits.cc @@ -5,6 +5,13 @@ // Get basic type definitions. #include "gpu/ipc/common/gpu_param_traits.h" +// Generate param traits size methods. +#include "ipc/param_traits_size_macros.h" +namespace IPC { +#undef GPU_IPC_COMMON_GPU_PARAM_TRAITS_MACROS_H_ +#include "gpu/ipc/common/gpu_param_traits_macros.h" +} + // Generate param traits write methods. #include "ipc/param_traits_write_macros.h" namespace IPC { diff --git a/chromium/gpu/ipc/common/gpu_param_traits_macros.h b/chromium/gpu/ipc/common/gpu_param_traits_macros.h index 52025c031bf..0aa3c580660 100644 --- a/chromium/gpu/ipc/common/gpu_param_traits_macros.h +++ b/chromium/gpu/ipc/common/gpu_param_traits_macros.h @@ -6,14 +6,14 @@ #define GPU_IPC_COMMON_GPU_PARAM_TRAITS_MACROS_H_ #include "gpu/command_buffer/common/constants.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/common/gpu_memory_allocation.h" #include "gpu/config/gpu_info.h" #include "gpu/gpu_export.h" #include "gpu/ipc/common/gpu_stream_constants.h" #include "ipc/ipc_message_macros.h" -#include "ui/gfx/gpu_memory_buffer.h" +#include "ui/gfx/ipc/geometry/gfx_param_traits.h" #include "ui/gfx/ipc/gfx_param_traits.h" -#include "ui/gfx/swap_result.h" #include "ui/gl/gpu_preference.h" #include "url/ipc/url_param_traits.h" @@ -39,29 +39,8 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::VideoEncodeAcceleratorSupportedProfile) IPC_STRUCT_TRAITS_MEMBER(max_framerate_denominator) IPC_STRUCT_TRAITS_END() -IPC_ENUM_TRAITS_MAX_VALUE(gfx::GpuMemoryBufferType, - gfx::GPU_MEMORY_BUFFER_TYPE_LAST) - -IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferHandle) - IPC_STRUCT_TRAITS_MEMBER(id) - IPC_STRUCT_TRAITS_MEMBER(type) - IPC_STRUCT_TRAITS_MEMBER(handle) - IPC_STRUCT_TRAITS_MEMBER(offset) - IPC_STRUCT_TRAITS_MEMBER(stride) -#if defined(USE_OZONE) - IPC_STRUCT_TRAITS_MEMBER(native_pixmap_handle) -#elif defined(OS_MACOSX) - IPC_STRUCT_TRAITS_MEMBER(mach_port) -#endif -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferId) - IPC_STRUCT_TRAITS_MEMBER(id) -IPC_STRUCT_TRAITS_END() - IPC_ENUM_TRAITS_MAX_VALUE(gfx::GpuPreference, gfx::GpuPreferenceLast) IPC_ENUM_TRAITS_MAX_VALUE(gpu::GpuStreamPriority, gpu::GpuStreamPriority::LAST) -IPC_ENUM_TRAITS_MAX_VALUE(gfx::SwapResult, gfx::SwapResult::SWAP_RESULT_LAST) IPC_ENUM_TRAITS_MAX_VALUE(gpu::MemoryAllocation::PriorityCutoff, gpu::MemoryAllocation::CUTOFF_LAST) IPC_ENUM_TRAITS_MAX_VALUE(gpu::error::ContextLostReason, @@ -72,6 +51,8 @@ IPC_ENUM_TRAITS_MIN_MAX_VALUE(gpu::CollectInfoResult, IPC_ENUM_TRAITS_MIN_MAX_VALUE(gpu::VideoCodecProfile, gpu::VIDEO_CODEC_PROFILE_MIN, gpu::VIDEO_CODEC_PROFILE_MAX) +IPC_ENUM_TRAITS_MAX_VALUE(gpu::gles2::ContextType, + gpu::gles2::CONTEXT_TYPE_LAST) IPC_STRUCT_TRAITS_BEGIN(gpu::DxDiagNode) IPC_STRUCT_TRAITS_MEMBER(values) @@ -132,4 +113,21 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::MemoryAllocation) IPC_STRUCT_TRAITS_MEMBER(priority_cutoff_when_visible) IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(gpu::gles2::ContextCreationAttribHelper) + IPC_STRUCT_TRAITS_MEMBER(alpha_size) + IPC_STRUCT_TRAITS_MEMBER(blue_size) + IPC_STRUCT_TRAITS_MEMBER(green_size) + IPC_STRUCT_TRAITS_MEMBER(red_size) + IPC_STRUCT_TRAITS_MEMBER(depth_size) + IPC_STRUCT_TRAITS_MEMBER(stencil_size) + IPC_STRUCT_TRAITS_MEMBER(samples) + IPC_STRUCT_TRAITS_MEMBER(sample_buffers) + IPC_STRUCT_TRAITS_MEMBER(buffer_preserved) + IPC_STRUCT_TRAITS_MEMBER(bind_generates_resource) + IPC_STRUCT_TRAITS_MEMBER(fail_if_major_perf_caveat) + IPC_STRUCT_TRAITS_MEMBER(lose_context_when_out_of_memory) + IPC_STRUCT_TRAITS_MEMBER(context_type) +IPC_STRUCT_TRAITS_END() + + #endif // GPU_IPC_COMMON_GPU_PARAM_TRAITS_MACROS_H_ diff --git a/chromium/gpu/ipc/common/gpu_surface_lookup.h b/chromium/gpu/ipc/common/gpu_surface_lookup.h index 2be3e2e6c19..9cd476a53a1 100644 --- a/chromium/gpu/ipc/common/gpu_surface_lookup.h +++ b/chromium/gpu/ipc/common/gpu_surface_lookup.h @@ -7,6 +7,7 @@ #include "base/macros.h" #include "gpu/gpu_export.h" +#include "gpu/ipc/common/surface_handle.h" #include "ui/gfx/native_widget_types.h" #if defined(OS_ANDROID) @@ -25,7 +26,8 @@ class GPU_EXPORT GpuSurfaceLookup { static GpuSurfaceLookup* GetInstance(); static void InitInstance(GpuSurfaceLookup* lookup); - virtual gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) = 0; + virtual gfx::AcceleratedWidget AcquireNativeWidget( + gpu::SurfaceHandle surface_handle) = 0; #if defined(OS_ANDROID) virtual gfx::ScopedJavaSurface AcquireJavaSurface(int surface_id) = 0; diff --git a/chromium/gpu/ipc/common/id_type_traits.h b/chromium/gpu/ipc/common/id_type_traits.h deleted file mode 100644 index d2decb7187f..00000000000 --- a/chromium/gpu/ipc/common/id_type_traits.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_IPC_ID_TYPE_TRAITS_H_ -#define GPU_IPC_ID_TYPE_TRAITS_H_ - -#include <string> - -#include "base/pickle.h" -#include "gpu/command_buffer/common/id_type.h" -#include "ipc/ipc_message_utils.h" -#include "ipc/ipc_param_traits.h" - -namespace IPC { - -template <typename TypeMarker, typename WrappedType, WrappedType kInvalidValue> -struct ParamTraits<gpu::IdType<TypeMarker, WrappedType, kInvalidValue>> { - using param_type = gpu::IdType<TypeMarker, WrappedType, kInvalidValue>; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, p.GetUnsafeValue()); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, p.GetUnsafeValue()); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - WrappedType value; - if (!ReadParam(m, iter, &value)) - return false; - *r = param_type::FromUnsafeValue(value); - return true; - } - static void Log(const param_type& p, std::string* l) { - LogParam(p.GetUnsafeValue(), l); - } -}; - -} // namespace IPC - -#endif // GPU_IPC_ID_TYPE_TRAITS_H_ diff --git a/chromium/gpu/command_buffer/common/mailbox.mojom b/chromium/gpu/ipc/common/mailbox.mojom index 43df62bc82d..43df62bc82d 100644 --- a/chromium/gpu/command_buffer/common/mailbox.mojom +++ b/chromium/gpu/ipc/common/mailbox.mojom diff --git a/chromium/gpu/ipc/common/mailbox.typemap b/chromium/gpu/ipc/common/mailbox.typemap new file mode 100644 index 00000000000..5072f0e7faf --- /dev/null +++ b/chromium/gpu/ipc/common/mailbox.typemap @@ -0,0 +1,12 @@ +# Copyright 2016 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. + +mojom = "//gpu/ipc/common/mailbox.mojom" +public_headers = [ "//gpu/command_buffer/common/mailbox.h" ] +traits_headers = [ "//gpu/ipc/common/gpu_command_buffer_traits.h" ] +deps = [ + "//gpu/ipc/common:command_buffer_traits", +] + +type_mappings = [ "gpu.mojom.Mailbox=gpu::Mailbox" ] diff --git a/chromium/gpu/command_buffer/common/mailbox_holder.mojom b/chromium/gpu/ipc/common/mailbox_holder.mojom index 773f40256ca..773f40256ca 100644 --- a/chromium/gpu/command_buffer/common/mailbox_holder.mojom +++ b/chromium/gpu/ipc/common/mailbox_holder.mojom diff --git a/chromium/gpu/ipc/common/mailbox_holder.typemap b/chromium/gpu/ipc/common/mailbox_holder.typemap new file mode 100644 index 00000000000..a0a8ee4a28c --- /dev/null +++ b/chromium/gpu/ipc/common/mailbox_holder.typemap @@ -0,0 +1,12 @@ +# Copyright 2016 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. + +mojom = "//gpu/ipc/common/mailbox_holder.mojom" +public_headers = [ "//gpu/command_buffer/common/mailbox_holder.h" ] +traits_headers = [ "//gpu/ipc/common/gpu_command_buffer_traits.h" ] +deps = [ + "//gpu/ipc/common:command_buffer_traits", +] + +type_mappings = [ "gpu.mojom.MailboxHolder=gpu::MailboxHolder" ] diff --git a/chromium/gpu/ipc/common/surface_handle.h b/chromium/gpu/ipc/common/surface_handle.h index 4c951cf8cb8..a0009b2ab03 100644 --- a/chromium/gpu/ipc/common/surface_handle.h +++ b/chromium/gpu/ipc/common/surface_handle.h @@ -5,14 +5,37 @@ #ifndef GPU_IPC_COMMON_SURFACE_HANDLE_H_ #define GPU_IPC_COMMON_SURFACE_HANDLE_H_ +#include <stdint.h> + #include "build/build_config.h" + +#if (defined(OS_WIN) || defined(USE_X11) || defined(USE_OZONE)) && \ + !defined(OS_NACL) #include "ui/gfx/native_widget_types.h" +#define GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW +#endif namespace gpu { -// TODO(piman): remove PluginWindowHandle and move here when NPAPI is gone. -using SurfaceHandle = gfx::PluginWindowHandle; -const SurfaceHandle kNullSurfaceHandle = gfx::kNullPluginWindow; +// SurfaceHandle is the native type used to reference a native surface in the +// GPU process so that we can create "view" contexts on it. + +// On Windows, Linux and Chrome OS, we can use a AcceleratedWidget across +// processes, so SurfaceHandle is exactly that. +// On Mac and Android, there is no type we can directly access across processes, +// so we go through the GpuSurfaceTracker, and SurfaceHandle is a (scalar) +// handle generated by that. +// On NaCl, we don't have native surfaces per se, but we need SurfaceHandle to +// be defined, because some APIs that use it are referenced there. +#if defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) +using SurfaceHandle = gfx::AcceleratedWidget; +const SurfaceHandle kNullSurfaceHandle = gfx::kNullAcceleratedWidget; +#elif defined(OS_MACOSX) || defined(OS_ANDROID) || defined(OS_NACL) +using SurfaceHandle = int32_t; +const SurfaceHandle kNullSurfaceHandle = 0; +#else +#error Platform not supported. +#endif } // namespace gpu diff --git a/chromium/gpu/command_buffer/common/sync_token.mojom b/chromium/gpu/ipc/common/sync_token.mojom index 248ad315f86..248ad315f86 100644 --- a/chromium/gpu/command_buffer/common/sync_token.mojom +++ b/chromium/gpu/ipc/common/sync_token.mojom diff --git a/chromium/gpu/ipc/common/sync_token.typemap b/chromium/gpu/ipc/common/sync_token.typemap new file mode 100644 index 00000000000..63acf600633 --- /dev/null +++ b/chromium/gpu/ipc/common/sync_token.typemap @@ -0,0 +1,12 @@ +# Copyright 2016 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. + +mojom = "//gpu/ipc/common/sync_token.mojom" +public_headers = [ "//gpu/command_buffer/common/sync_token.h" ] +traits_headers = [ "//gpu/ipc/common/gpu_command_buffer_traits.h" ] +deps = [ + "//gpu/ipc/common:command_buffer_traits", +] + +type_mappings = [ "gpu.mojom.SyncToken=gpu::SyncToken" ] diff --git a/chromium/gpu/ipc/common/typemaps.gni b/chromium/gpu/ipc/common/typemaps.gni new file mode 100644 index 00000000000..1eac9c78d65 --- /dev/null +++ b/chromium/gpu/ipc/common/typemaps.gni @@ -0,0 +1,11 @@ +# Copyright 2016 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. + +typemaps = [ + "//gpu/ipc/common/capabilities.typemap", + "//gpu/ipc/common/command_buffer.typemap", + "//gpu/ipc/common/mailbox.typemap", + "//gpu/ipc/common/mailbox_holder.typemap", + "//gpu/ipc/common/sync_token.typemap", +] diff --git a/chromium/gpu/ipc/service/BUILD.gn b/chromium/gpu/ipc/service/BUILD.gn index 7f022f84398..a28a24d133c 100644 --- a/chromium/gpu/ipc/service/BUILD.gn +++ b/chromium/gpu/ipc/service/BUILD.gn @@ -50,11 +50,13 @@ source_set("ipc_service_sources") { "//ui/gfx", "//ui/gfx/geometry", "//ui/gl", + "//ui/gl/init", "//url", ] deps = [ "//gpu/command_buffer/common:common_sources", "//gpu/command_buffer/service:service_sources", + "//gpu/config:config_sources", "//gpu/ipc/common:ipc_common_sources", ] libs = [] @@ -67,25 +69,17 @@ source_set("ipc_service_sources") { } if (is_mac) { sources += [ - "ca_layer_partial_damage_tree_mac.h", - "ca_layer_partial_damage_tree_mac.mm", - "ca_layer_tree_mac.h", - "ca_layer_tree_mac.mm", "gpu_memory_buffer_factory_io_surface.cc", "gpu_memory_buffer_factory_io_surface.h", "image_transport_surface_mac.mm", "image_transport_surface_overlay_mac.h", "image_transport_surface_overlay_mac.mm", ] - deps += [ - "//skia", - "//ui/accelerated_widget_mac", - ] + deps += [ "//ui/accelerated_widget_mac" ] lib_dirs = [ "$mac_sdk_path/usr/lib" ] libs += [ - "AVFoundation.framework", - "CoreMedia.framework", "QuartzCore.framework", + "CoreGraphics.framework", ] } if (is_android) { @@ -123,6 +117,9 @@ source_set("test_support") { "//testing/gtest:gtest", ] deps = [ + # TODO(markdittmer): Shouldn't depend on client code for server tests. + # See crbug.com/608800. + "//gpu/ipc/client", "//gpu/ipc/common", ] } @@ -142,31 +139,27 @@ test("gpu_ipc_service_unittests") { "//base/test:run_all_unittests", "//base/test:test_support", "//gpu/command_buffer/common", + "//gpu/command_buffer/common:gles2_utils", "//gpu/command_buffer/service", "//gpu/config", "//gpu/ipc/common", "//ipc:test_support", "//skia", + "//testing/gmock", "//testing/gtest", "//third_party/mesa:mesa_headers", "//ui/gfx:test_support", + "//ui/gl:gl_unittest_utils", + "//ui/gl:test_support", "//url", ] libs = [] if (is_android) { sources += [ "gpu_memory_buffer_factory_surface_texture_unittest.cc" ] + deps += [ "//ui/android:ui_java" ] } if (is_mac) { - sources += [ - "ca_layer_tree_unittest_mac.mm", - "gpu_memory_buffer_factory_io_surface_unittest.cc", - ] - deps += [ "//ui/accelerated_widget_mac" ] - libs += [ - "AVFoundation.framework", - "CoreMedia.framework", - "QuartzCore.framework", - ] + sources += [ "gpu_memory_buffer_factory_io_surface_unittest.cc" ] } if (use_ozone) { sources += [ "gpu_memory_buffer_factory_ozone_native_pixmap_unittest.cc" ] diff --git a/chromium/gpu/ipc/service/OWNERS b/chromium/gpu/ipc/service/OWNERS new file mode 100644 index 00000000000..caa4fba639c --- /dev/null +++ b/chromium/gpu/ipc/service/OWNERS @@ -0,0 +1,2 @@ +# Mac stuff. +per-file *_mac*=ccameron@chromium.org diff --git a/chromium/gpu/ipc/service/ca_layer_partial_damage_tree_mac.h b/chromium/gpu/ipc/service/ca_layer_partial_damage_tree_mac.h deleted file mode 100644 index 3d36bf755bb..00000000000 --- a/chromium/gpu/ipc/service/ca_layer_partial_damage_tree_mac.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_IPC_SERVICE_CA_LAYER_PARTIAL_DAMAGE_TREE_MAC_H_ -#define GPU_IPC_SERVICE_CA_LAYER_PARTIAL_DAMAGE_TREE_MAC_H_ - -#include <IOSurface/IOSurface.h> -#include <QuartzCore/QuartzCore.h> -#include <deque> - -#include "base/mac/scoped_cftyperef.h" -#include "base/memory/scoped_ptr.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/rect_f.h" - -namespace gpu { - -class CALayerPartialDamageTree { - public: - CALayerPartialDamageTree(bool allow_partial_swap, - base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::Rect& pixel_frame_rect); - ~CALayerPartialDamageTree(); - - base::ScopedCFTypeRef<IOSurfaceRef> RootLayerIOSurface(); - void CommitCALayers(CALayer* superlayer, - scoped_ptr<CALayerPartialDamageTree> old_tree, - float scale_factor, - const gfx::Rect& pixel_damage_rect); - - private: - class OverlayPlane; - - // This will populate |partial_damage_planes_|, potentially re-using the - // CALayers and |partial_damage_planes_| from |old_tree|. After this function - // completes, the back() of |partial_damage_planes_| is the plane that will - // be updated this frame (and if it is empty, then the root plane will be - // updated). - void UpdatePartialDamagePlanes(CALayerPartialDamageTree* old_tree, - const gfx::Rect& pixel_damage_rect); - - void UpdateRootAndPartialDamagePlanes( - scoped_ptr<CALayerPartialDamageTree> old_tree, - const gfx::Rect& pixel_damage_rect); - - void UpdateCALayers(CALayer* superlayer, float scale_factor); - - const bool allow_partial_swap_; - scoped_ptr<OverlayPlane> root_plane_; - std::deque<scoped_ptr<OverlayPlane>> partial_damage_planes_; -}; - -} // content - -#endif // GPU_IPC_SERVICE_CA_LAYER_PARTIAL_DAMAGE_TREE_MAC_H_ diff --git a/chromium/gpu/ipc/service/ca_layer_partial_damage_tree_mac.mm b/chromium/gpu/ipc/service/ca_layer_partial_damage_tree_mac.mm deleted file mode 100644 index 25cd39dd656..00000000000 --- a/chromium/gpu/ipc/service/ca_layer_partial_damage_tree_mac.mm +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright 2016 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/ipc/service/ca_layer_partial_damage_tree_mac.h" - -#include "base/command_line.h" -#include "base/mac/scoped_nsobject.h" -#include "base/mac/sdk_forward_declarations.h" -#include "base/trace_event/trace_event.h" -#include "ui/base/ui_base_switches.h" -#include "ui/gfx/transform.h" - -@interface CALayer(Private) --(void)setContentsChanged; -@end - -namespace gpu { -namespace { - -// When selecting a CALayer to re-use for partial damage, this is the maximum -// fraction of the merged layer's pixels that may be not-updated by the swap -// before we consider the CALayer to not be a good enough match, and create a -// new one. -const float kMaximumPartialDamageWasteFraction = 1.2f; - -// The maximum number of partial damage layers that may be created before we -// give up and remove them all (doing full damage in the process). -const size_t kMaximumPartialDamageLayers = 8; - -} // namespace - -class CALayerPartialDamageTree::OverlayPlane { - public: - OverlayPlane(base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::Rect& pixel_frame_rect, - const gfx::RectF& contents_rect) - : io_surface(io_surface), - contents_rect(contents_rect), - pixel_frame_rect(pixel_frame_rect), - layer_needs_update(true) {} - - ~OverlayPlane() { - [ca_layer setContents:nil]; - [ca_layer removeFromSuperlayer]; - ca_layer.reset(); - } - - const base::ScopedCFTypeRef<IOSurfaceRef> io_surface; - const gfx::RectF contents_rect; - const gfx::Rect pixel_frame_rect; - bool layer_needs_update; - base::scoped_nsobject<CALayer> ca_layer; - - void TakeCALayerFrom(OverlayPlane* other_plane) { - ca_layer.swap(other_plane->ca_layer); - } - - void UpdateProperties(float scale_factor) { - if (layer_needs_update) { - [ca_layer setOpaque:YES]; - - id new_contents = static_cast<id>(io_surface.get()); - if ([ca_layer contents] == new_contents) - [ca_layer setContentsChanged]; - else - [ca_layer setContents:new_contents]; - [ca_layer setContentsRect:contents_rect.ToCGRect()]; - - [ca_layer setAnchorPoint:CGPointZero]; - - if ([ca_layer respondsToSelector:(@selector(setContentsScale:))]) - [ca_layer setContentsScale:scale_factor]; - gfx::RectF dip_frame_rect = gfx::RectF(pixel_frame_rect); - dip_frame_rect.Scale(1 / scale_factor); - [ca_layer setBounds:CGRectMake(0, 0, dip_frame_rect.width(), - dip_frame_rect.height())]; - [ca_layer - setPosition:CGPointMake(dip_frame_rect.x(), dip_frame_rect.y())]; - } - static bool show_borders = - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kShowMacOverlayBorders); - if (show_borders) { - base::ScopedCFTypeRef<CGColorRef> color; - if (!layer_needs_update) { - // Green represents contents that are unchanged across frames. - color.reset(CGColorCreateGenericRGB(0, 1, 0, 1)); - } else { - // Red represents damaged contents. - color.reset(CGColorCreateGenericRGB(1, 0, 0, 1)); - } - [ca_layer setBorderWidth:1]; - [ca_layer setBorderColor:color]; - } - layer_needs_update = false; - } - - private: -}; - -void CALayerPartialDamageTree::UpdatePartialDamagePlanes( - CALayerPartialDamageTree* old_tree, - const gfx::Rect& pixel_damage_rect) { - // Don't create partial damage layers if partial swap is disabled. - if (!allow_partial_swap_) - return; - // Only create partial damage layers when building on top of an existing tree. - if (!old_tree) - return; - // If the frame size has changed, discard all of the old partial damage - // layers. - if (old_tree->root_plane_->pixel_frame_rect != root_plane_->pixel_frame_rect) - return; - // If there is full damage, discard all of the old partial damage layers. - if (pixel_damage_rect == root_plane_->pixel_frame_rect) - return; - - // If there is no damage, don't change anything. - if (pixel_damage_rect.IsEmpty()) { - std::swap(partial_damage_planes_, old_tree->partial_damage_planes_); - return; - } - - // Find the last partial damage plane to re-use the CALayer from. Grow the - // new rect for this layer to include this damage, and all nearby partial - // damage layers. - scoped_ptr<OverlayPlane> plane_for_swap; - { - auto plane_to_reuse_iter = old_tree->partial_damage_planes_.end(); - gfx::Rect plane_to_reuse_enlarged_pixel_damage_rect; - - for (auto old_plane_iter = old_tree->partial_damage_planes_.begin(); - old_plane_iter != old_tree->partial_damage_planes_.end(); - ++old_plane_iter) { - gfx::Rect enlarged_pixel_damage_rect = - (*old_plane_iter)->pixel_frame_rect; - enlarged_pixel_damage_rect.Union(pixel_damage_rect); - - // Compute the fraction of the pixels that would not be updated by this - // swap. If it is too big, try another layer. - float waste_fraction = enlarged_pixel_damage_rect.size().GetArea() * 1.f / - pixel_damage_rect.size().GetArea(); - if (waste_fraction > kMaximumPartialDamageWasteFraction) - continue; - - plane_to_reuse_iter = old_plane_iter; - plane_to_reuse_enlarged_pixel_damage_rect.Union( - enlarged_pixel_damage_rect); - } - if (plane_to_reuse_iter != old_tree->partial_damage_planes_.end()) { - gfx::RectF enlarged_contents_rect = - gfx::RectF(plane_to_reuse_enlarged_pixel_damage_rect); - enlarged_contents_rect.Scale(1. / root_plane_->pixel_frame_rect.width(), - 1. / root_plane_->pixel_frame_rect.height()); - - plane_for_swap.reset(new OverlayPlane( - root_plane_->io_surface, plane_to_reuse_enlarged_pixel_damage_rect, - enlarged_contents_rect)); - - plane_for_swap->TakeCALayerFrom((*plane_to_reuse_iter).get()); - if (*plane_to_reuse_iter != old_tree->partial_damage_planes_.back()) { - CALayer* superlayer = [plane_for_swap->ca_layer superlayer]; - [plane_for_swap->ca_layer removeFromSuperlayer]; - [superlayer addSublayer:plane_for_swap->ca_layer]; - } - } - } - - // If we haven't found an appropriate layer to re-use, create a new one, if - // we haven't already created too many. - if (!plane_for_swap.get() && - old_tree->partial_damage_planes_.size() < kMaximumPartialDamageLayers) { - gfx::RectF contents_rect = gfx::RectF(pixel_damage_rect); - contents_rect.Scale(1. / root_plane_->pixel_frame_rect.width(), - 1. / root_plane_->pixel_frame_rect.height()); - plane_for_swap.reset(new OverlayPlane(root_plane_->io_surface, - pixel_damage_rect, contents_rect)); - } - - // And if we still don't have a layer, do full damage. - if (!plane_for_swap.get()) - return; - - // Walk all old partial damage planes. Remove anything that is now completely - // covered, and move everything else into the new |partial_damage_planes_|. - for (auto& old_plane : old_tree->partial_damage_planes_) { - if (!old_plane.get()) - continue; - // Intersect the planes' frames with the new root plane to ensure that - // they don't get kept alive inappropriately. - gfx::Rect old_plane_frame_rect = old_plane->pixel_frame_rect; - old_plane_frame_rect.Intersect(root_plane_->pixel_frame_rect); - - bool old_plane_covered_by_swap = false; - if (plane_for_swap.get() && - plane_for_swap->pixel_frame_rect.Contains(old_plane_frame_rect)) { - old_plane_covered_by_swap = true; - } - if (!old_plane_covered_by_swap) { - DCHECK(old_plane->ca_layer); - partial_damage_planes_.push_back(std::move(old_plane)); - } - } - - partial_damage_planes_.push_back(std::move(plane_for_swap)); -} - -void CALayerPartialDamageTree::UpdateRootAndPartialDamagePlanes( - scoped_ptr<CALayerPartialDamageTree> old_tree, - const gfx::Rect& pixel_damage_rect) { - // First update the partial damage tree. - UpdatePartialDamagePlanes(old_tree.get(), pixel_damage_rect); - if (old_tree) { - if (partial_damage_planes_.empty()) { - // If there are no partial damage planes, then we will be updating the - // root layer. Take the CALayer from the old tree. - root_plane_->TakeCALayerFrom(old_tree->root_plane_.get()); - } else { - // If there is a partial damage tree, then just take the old plane - // from the previous frame, so that there is no update to it. - root_plane_.swap(old_tree->root_plane_); - } - } -} - -void CALayerPartialDamageTree::UpdateCALayers(CALayer* superlayer, - float scale_factor) { - if (!allow_partial_swap_) { - DCHECK(partial_damage_planes_.empty()); - return; - } - - // Allocate and update CALayers for the backbuffer and partial damage layers. - if (!root_plane_->ca_layer) { - DCHECK(partial_damage_planes_.empty()); - root_plane_->ca_layer.reset([[CALayer alloc] init]); - [superlayer setSublayers:nil]; - [superlayer addSublayer:root_plane_->ca_layer]; - } - // Excessive logging to debug white screens (crbug.com/583805). - // TODO(ccameron): change this back to a DLOG. - if ([root_plane_->ca_layer superlayer] != superlayer) { - LOG(ERROR) << "CALayerPartialDamageTree root layer not attached to tree."; - } - for (auto& plane : partial_damage_planes_) { - if (!plane->ca_layer) { - DCHECK(plane == partial_damage_planes_.back()); - plane->ca_layer.reset([[CALayer alloc] init]); - } - if (![plane->ca_layer superlayer]) { - DCHECK(plane == partial_damage_planes_.back()); - [superlayer addSublayer:plane->ca_layer]; - } - } - root_plane_->UpdateProperties(scale_factor); - for (auto& plane : partial_damage_planes_) - plane->UpdateProperties(scale_factor); -} - -CALayerPartialDamageTree::CALayerPartialDamageTree( - bool allow_partial_swap, - base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::Rect& pixel_frame_rect) - : allow_partial_swap_(allow_partial_swap) { - root_plane_.reset( - new OverlayPlane(io_surface, pixel_frame_rect, gfx::RectF(0, 0, 1, 1))); -} - -CALayerPartialDamageTree::~CALayerPartialDamageTree() {} - -base::ScopedCFTypeRef<IOSurfaceRef> -CALayerPartialDamageTree::RootLayerIOSurface() { - return root_plane_->io_surface; -} - -void CALayerPartialDamageTree::CommitCALayers( - CALayer* superlayer, - scoped_ptr<CALayerPartialDamageTree> old_tree, - float scale_factor, - const gfx::Rect& pixel_damage_rect) { - TRACE_EVENT0("gpu", "CALayerPartialDamageTree::CommitCALayers"); - UpdateRootAndPartialDamagePlanes(std::move(old_tree), pixel_damage_rect); - UpdateCALayers(superlayer, scale_factor); -} - -} // namespace gpu diff --git a/chromium/gpu/ipc/service/ca_layer_tree_mac.h b/chromium/gpu/ipc/service/ca_layer_tree_mac.h deleted file mode 100644 index 36aad0d2a57..00000000000 --- a/chromium/gpu/ipc/service/ca_layer_tree_mac.h +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_IPC_SERVICE_CA_LAYER_TREE_MAC_H_ -#define GPU_IPC_SERVICE_CA_LAYER_TREE_MAC_H_ - -#include <IOSurface/IOSurface.h> -#include <QuartzCore/QuartzCore.h> -#include <deque> -#include <vector> - -#include "base/mac/scoped_cftyperef.h" -#include "base/mac/scoped_nsobject.h" -#include "base/memory/scoped_ptr.h" -#include "gpu/gpu_export.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/rect_f.h" -#include "ui/gfx/mac/io_surface.h" -#include "ui/gfx/transform.h" - -@class AVSampleBufferDisplayLayer; - -namespace gpu { - -// The CALayerTree will construct a hierarchy of CALayers from a linear list, -// using the algorithm and structure referenced described in -// https://docs.google.com/document/d/1DtSN9zzvCF44_FQPM7ie01UxGHagQ66zfF5L9HnigQY/edit?usp=sharing -class GPU_EXPORT CALayerTree { - public: - CALayerTree(); - - // This will remove all CALayers from this tree from their superlayer. - ~CALayerTree(); - - // Append the description of a new CALayer to the tree. This will not - // create any new CALayers until CommitScheduledCALayers is called. This - // cannot be called anymore after CommitScheduledCALayers has been called. - bool ScheduleCALayer(bool is_clipped, - const gfx::Rect& clip_rect, - unsigned sorting_context_id, - const gfx::Transform& transform, - base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::RectF& contents_rect, - const gfx::Rect& rect, - unsigned background_color, - unsigned edge_aa_mask, - float opacity); - - // Create a CALayer tree for the scheduled layers, and set |superlayer| to - // have only this tree as its sublayers. If |old_tree| is non-null, then try - // to re-use the CALayers of |old_tree| as much as possible. |old_tree| will - // be destroyed at the end of the function, and any CALayers in it which were - // not re-used by |this| will be removed from the CALayer hierarchy. - void CommitScheduledCALayers(CALayer* superlayer, - scoped_ptr<CALayerTree> old_tree, - float scale_factor); - - private: - struct RootLayer; - struct ClipAndSortingLayer; - struct TransformLayer; - struct ContentLayer; - - struct RootLayer { - RootLayer(); - - // This will remove |ca_layer| from its superlayer, if |ca_layer| is - // non-nil. - ~RootLayer(); - - // Append a new content layer, without modifying the actual CALayer - // structure. - bool AddContentLayer(bool is_clipped, - const gfx::Rect& clip_rect, - unsigned sorting_context_id, - const gfx::Transform& transform, - base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::RectF& contents_rect, - const gfx::Rect& rect, - unsigned background_color, - unsigned edge_aa_mask, - float opacity); - - // Allocate CALayers for this layer and its children, and set their - // properties appropriately. Re-use the CALayers from |old_layer| if - // possible. If re-using a CALayer from |old_layer|, reset its |ca_layer| - // to nil, so that its destructor will not remove an active CALayer. - void CommitToCA(CALayer* superlayer, - RootLayer* old_layer, - float scale_factor); - - std::vector<ClipAndSortingLayer> clip_and_sorting_layers; - base::scoped_nsobject<CALayer> ca_layer; - - private: - DISALLOW_COPY_AND_ASSIGN(RootLayer); - }; - struct ClipAndSortingLayer { - ClipAndSortingLayer(bool is_clipped, - gfx::Rect clip_rect, - unsigned sorting_context_id, - bool is_singleton_sorting_context); - ClipAndSortingLayer(ClipAndSortingLayer&& layer); - - // See the behavior of RootLayer for the effects of these functions on the - // |ca_layer| member and |old_layer| argument. - ~ClipAndSortingLayer(); - void AddContentLayer(const gfx::Transform& transform, - base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::RectF& contents_rect, - const gfx::Rect& rect, - unsigned background_color, - unsigned edge_aa_mask, - float opacity); - void CommitToCA(CALayer* superlayer, - ClipAndSortingLayer* old_layer, - float scale_factor); - - std::vector<TransformLayer> transform_layers; - bool is_clipped = false; - gfx::Rect clip_rect; - unsigned sorting_context_id = 0; - bool is_singleton_sorting_context = false; - base::scoped_nsobject<CALayer> ca_layer; - - private: - DISALLOW_COPY_AND_ASSIGN(ClipAndSortingLayer); - }; - struct TransformLayer { - TransformLayer(const gfx::Transform& transform); - TransformLayer(TransformLayer&& layer); - - // See the behavior of RootLayer for the effects of these functions on the - // |ca_layer| member and |old_layer| argument. - ~TransformLayer(); - void AddContentLayer(base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::RectF& contents_rect, - const gfx::Rect& rect, - unsigned background_color, - unsigned edge_aa_mask, - float opacity); - void CommitToCA(CALayer* superlayer, - TransformLayer* old_layer, - float scale_factor); - - gfx::Transform transform; - std::vector<ContentLayer> content_layers; - base::scoped_nsobject<CALayer> ca_layer; - - private: - DISALLOW_COPY_AND_ASSIGN(TransformLayer); - }; - struct ContentLayer { - ContentLayer(base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::RectF& contents_rect, - const gfx::Rect& rect, - unsigned background_color, - unsigned edge_aa_mask, - float opacity); - ContentLayer(ContentLayer&& layer); - - // See the behavior of RootLayer for the effects of these functions on the - // |ca_layer| member and |old_layer| argument. - ~ContentLayer(); - void CommitToCA(CALayer* parent, - ContentLayer* old_layer, - float scale_factor); - - // Ensure that the IOSurface be marked as in-use as soon as it is received. - // When they are committed to the window server, that will also increment - // their use count. - const gfx::ScopedInUseIOSurface io_surface; - gfx::RectF contents_rect; - gfx::Rect rect; - unsigned background_color = 0; - // Note that the CoreAnimation edge antialiasing mask is not the same as - // the edge antialiasing mask passed to the constructor. - CAEdgeAntialiasingMask ca_edge_aa_mask = 0; - float opacity = 1; - base::scoped_nsobject<CALayer> ca_layer; - - // If this layer's contents can be represented as an - // AVSampleBufferDisplayLayer, then |ca_layer| will point to |av_layer|. - base::scoped_nsobject<AVSampleBufferDisplayLayer> av_layer; - bool use_av_layer = false; - - private: - DISALLOW_COPY_AND_ASSIGN(ContentLayer); - }; - - RootLayer root_layer_; - float scale_factor_ = 1; - bool has_committed_ = false; - - private: - DISALLOW_COPY_AND_ASSIGN(CALayerTree); -}; - -} // namespace gpu - -#endif // GPU_IPC_SERVICE_CA_LAYER_TREE_MAC_H_ diff --git a/chromium/gpu/ipc/service/ca_layer_tree_mac.mm b/chromium/gpu/ipc/service/ca_layer_tree_mac.mm deleted file mode 100644 index ea0efd1b9b3..00000000000 --- a/chromium/gpu/ipc/service/ca_layer_tree_mac.mm +++ /dev/null @@ -1,571 +0,0 @@ -// Copyright 2016 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/ipc/service/ca_layer_tree_mac.h" - -#include <AVFoundation/AVFoundation.h> -#include <CoreMedia/CoreMedia.h> -#include <CoreVideo/CoreVideo.h> - -#include "base/command_line.h" -#include "base/mac/sdk_forward_declarations.h" -#include "base/trace_event/trace_event.h" -#include "gpu/GLES2/gl2extchromium.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/base/cocoa/animation_utils.h" -#include "ui/base/ui_base_switches.h" -#include "ui/gfx/geometry/dip_util.h" - -#if !defined(MAC_OS_X_VERSION_10_8) || \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8 -extern NSString* const AVLayerVideoGravityResize; -extern "C" void NSAccessibilityPostNotificationWithUserInfo( - id object, - NSString* notification, - NSDictionary* user_info); -extern "C" OSStatus CMSampleBufferCreateForImageBuffer( - CFAllocatorRef, - CVImageBufferRef, - Boolean dataReady, - CMSampleBufferMakeDataReadyCallback, - void*, - CMVideoFormatDescriptionRef, - const CMSampleTimingInfo*, - CMSampleBufferRef*); -extern "C" CFArrayRef CMSampleBufferGetSampleAttachmentsArray(CMSampleBufferRef, - Boolean); -extern "C" OSStatus CMVideoFormatDescriptionCreateForImageBuffer( - CFAllocatorRef, - CVImageBufferRef, - CMVideoFormatDescriptionRef*); -extern "C" CMTime CMTimeMake(int64_t, int32_t); -extern CFStringRef const kCMSampleAttachmentKey_DisplayImmediately; -extern const CMTime kCMTimeInvalid; -#endif // MAC_OS_X_VERSION_10_8 - -namespace gpu { - -namespace { - -// This will enqueue |io_surface| to be drawn by |av_layer| by wrapping -// |io_surface| in a CVPixelBuffer. This will increase the in-use count -// of and retain |io_surface| until it is no longer being displayed. -bool AVSampleBufferDisplayLayerEnqueueIOSurface( - AVSampleBufferDisplayLayer* av_layer, - IOSurfaceRef io_surface) { - OSStatus os_status = noErr; - CVReturn cv_return = kCVReturnSuccess; - - base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer; - cv_return = CVPixelBufferCreateWithIOSurface( - nullptr, io_surface, nullptr, cv_pixel_buffer.InitializeInto()); - if (cv_return != kCVReturnSuccess) { - LOG(ERROR) << "CVPixelBufferCreateWithIOSurface failed with " << cv_return; - return false; - } - - base::ScopedCFTypeRef<CMVideoFormatDescriptionRef> video_info; - os_status = CMVideoFormatDescriptionCreateForImageBuffer( - nullptr, cv_pixel_buffer, video_info.InitializeInto()); - if (os_status != noErr) { - LOG(ERROR) << "CMVideoFormatDescriptionCreateForImageBuffer failed with " - << os_status; - return false; - } - - // The frame time doesn't matter because we will specify to display - // immediately. - CMTime frame_time = CMTimeMake(0, 1); - CMSampleTimingInfo timing_info = {frame_time, frame_time, kCMTimeInvalid}; - - base::ScopedCFTypeRef<CMSampleBufferRef> sample_buffer; - os_status = CMSampleBufferCreateForImageBuffer( - nullptr, cv_pixel_buffer, YES, nullptr, nullptr, video_info, &timing_info, - sample_buffer.InitializeInto()); - if (os_status != noErr) { - LOG(ERROR) << "CMSampleBufferCreateForImageBuffer failed with " - << os_status; - return false; - } - - // Specify to display immediately via the sample buffer attachments. - CFArrayRef attachments = - CMSampleBufferGetSampleAttachmentsArray(sample_buffer, YES); - if (!attachments) { - LOG(ERROR) << "CMSampleBufferGetSampleAttachmentsArray failed"; - return false; - } - if (CFArrayGetCount(attachments) < 1) { - LOG(ERROR) << "CMSampleBufferGetSampleAttachmentsArray result was empty"; - return false; - } - CFMutableDictionaryRef attachments_dictionary = - reinterpret_cast<CFMutableDictionaryRef>( - const_cast<void*>(CFArrayGetValueAtIndex(attachments, 0))); - if (!attachments_dictionary) { - LOG(ERROR) << "Failed to get attachments dictionary"; - return false; - } - CFDictionarySetValue(attachments_dictionary, - kCMSampleAttachmentKey_DisplayImmediately, - kCFBooleanTrue); - - [av_layer enqueueSampleBuffer:sample_buffer]; - return true; -} - -} // namespace - -CALayerTree::CALayerTree() {} -CALayerTree::~CALayerTree() {} - -bool CALayerTree::ScheduleCALayer( - bool is_clipped, - const gfx::Rect& clip_rect, - unsigned sorting_context_id, - const gfx::Transform& transform, - base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::RectF& contents_rect, - const gfx::Rect& rect, - unsigned background_color, - unsigned edge_aa_mask, - float opacity) { - // Excessive logging to debug white screens (crbug.com/583805). - // TODO(ccameron): change this back to a DLOG. - if (has_committed_) { - LOG(ERROR) << "ScheduleCALayer called after CommitScheduledCALayers."; - return false; - } - return root_layer_.AddContentLayer(is_clipped, clip_rect, sorting_context_id, - transform, io_surface, contents_rect, rect, - background_color, edge_aa_mask, opacity); -} - -void CALayerTree::CommitScheduledCALayers(CALayer* superlayer, - scoped_ptr<CALayerTree> old_tree, - float scale_factor) { - TRACE_EVENT0("gpu", "CALayerTree::CommitScheduledCALayers"); - RootLayer* old_root_layer = nullptr; - if (old_tree) { - DCHECK(old_tree->has_committed_); - if (old_tree->scale_factor_ == scale_factor) - old_root_layer = &old_tree->root_layer_; - } - - root_layer_.CommitToCA(superlayer, old_root_layer, scale_factor); - // If there are any extra CALayers in |old_tree| that were not stolen by this - // tree, they will be removed from the CALayer tree in this deallocation. - old_tree.reset(); - has_committed_ = true; - scale_factor_ = scale_factor; -} - -CALayerTree::RootLayer::RootLayer() {} - -// Note that for all destructors, the the CALayer will have been reset to nil if -// another layer has taken it. -CALayerTree::RootLayer::~RootLayer() { - [ca_layer removeFromSuperlayer]; -} - -CALayerTree::ClipAndSortingLayer::ClipAndSortingLayer( - bool is_clipped, - gfx::Rect clip_rect, - unsigned sorting_context_id, - bool is_singleton_sorting_context) - : is_clipped(is_clipped), - clip_rect(clip_rect), - sorting_context_id(sorting_context_id), - is_singleton_sorting_context(is_singleton_sorting_context) {} - -CALayerTree::ClipAndSortingLayer::ClipAndSortingLayer( - ClipAndSortingLayer&& layer) - : transform_layers(std::move(layer.transform_layers)), - is_clipped(layer.is_clipped), - clip_rect(layer.clip_rect), - sorting_context_id(layer.sorting_context_id), - is_singleton_sorting_context( - layer.is_singleton_sorting_context), - ca_layer(layer.ca_layer) { - // Ensure that the ca_layer be reset, so that when the destructor is called, - // the layer hierarchy is unaffected. - // TODO(ccameron): Add a move constructor for scoped_nsobject to do this - // automatically. - layer.ca_layer.reset(); -} - -CALayerTree::ClipAndSortingLayer::~ClipAndSortingLayer() { - [ca_layer removeFromSuperlayer]; -} - -CALayerTree::TransformLayer::TransformLayer(const gfx::Transform& transform) - : transform(transform) {} - -CALayerTree::TransformLayer::TransformLayer(TransformLayer&& layer) - : transform(layer.transform), - content_layers(std::move(layer.content_layers)), - ca_layer(layer.ca_layer) { - layer.ca_layer.reset(); -} - -CALayerTree::TransformLayer::~TransformLayer() { - [ca_layer removeFromSuperlayer]; -} - -CALayerTree::ContentLayer::ContentLayer( - base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::RectF& contents_rect, - const gfx::Rect& rect, - unsigned background_color, - unsigned edge_aa_mask, - float opacity) - : io_surface(io_surface), - contents_rect(contents_rect), - rect(rect), - background_color(background_color), - ca_edge_aa_mask(0), - opacity(opacity) { - // Because the root layer has setGeometryFlipped:YES, there is some ambiguity - // about what exactly top and bottom mean. This ambiguity is resolved in - // different ways for solid color CALayers and for CALayers that have content - // (surprise!). For CALayers with IOSurface content, the top edge in the AA - // mask refers to what appears as the bottom edge on-screen. For CALayers - // without content (solid color layers), the top edge in the AA mask is the - // top edge on-screen. - // https://crbug.com/567946 - if (edge_aa_mask & GL_CA_LAYER_EDGE_LEFT_CHROMIUM) - ca_edge_aa_mask |= kCALayerLeftEdge; - if (edge_aa_mask & GL_CA_LAYER_EDGE_RIGHT_CHROMIUM) - ca_edge_aa_mask |= kCALayerRightEdge; - if (io_surface) { - if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM) - ca_edge_aa_mask |= kCALayerBottomEdge; - if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM) - ca_edge_aa_mask |= kCALayerTopEdge; - } else { - if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM) - ca_edge_aa_mask |= kCALayerTopEdge; - if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM) - ca_edge_aa_mask |= kCALayerBottomEdge; - } - - // Only allow 4:2:0 frames which fill the layer's contents to be promoted to - // AV layers. - if (IOSurfaceGetPixelFormat(io_surface) == - kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange && - contents_rect == gfx::RectF(0, 0, 1, 1)) { - // Leave AVFoundation disabled for now while crashing and flashing bugs are - // being investigated. - // https://crbug.com/598243, https://crbug.com/598388 - use_av_layer = false; - } -} - -CALayerTree::ContentLayer::ContentLayer(ContentLayer&& layer) - : io_surface(layer.io_surface), - contents_rect(layer.contents_rect), - rect(layer.rect), - background_color(layer.background_color), - ca_edge_aa_mask(layer.ca_edge_aa_mask), - opacity(layer.opacity), - ca_layer(std::move(layer.ca_layer)), - av_layer(std::move(layer.av_layer)), - use_av_layer(layer.use_av_layer) { - DCHECK(!layer.ca_layer); - DCHECK(!layer.av_layer); -} - -CALayerTree::ContentLayer::~ContentLayer() { - [ca_layer removeFromSuperlayer]; -} - -bool CALayerTree::RootLayer::AddContentLayer( - bool is_clipped, - const gfx::Rect& clip_rect, - unsigned sorting_context_id, - const gfx::Transform& transform, - base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::RectF& contents_rect, - const gfx::Rect& rect, - unsigned background_color, - unsigned edge_aa_mask, - float opacity) { - bool needs_new_clip_and_sorting_layer = true; - - // In sorting_context_id 0, all quads are listed in back-to-front order. - // This is accomplished by having the CALayers be siblings of each other. - // If a quad has a 3D transform, it is necessary to put it in its own sorting - // context, so that it will not intersect with quads before and after it. - bool is_singleton_sorting_context = - !sorting_context_id && !transform.IsFlat(); - - if (!clip_and_sorting_layers.empty()) { - ClipAndSortingLayer& current_layer = clip_and_sorting_layers.back(); - // It is in error to change the clipping settings within a non-zero sorting - // context. The result will be incorrect layering and intersection. - if (sorting_context_id && - current_layer.sorting_context_id == sorting_context_id && - (current_layer.is_clipped != is_clipped || - current_layer.clip_rect != clip_rect)) { - // Excessive logging to debug white screens (crbug.com/583805). - // TODO(ccameron): change this back to a DLOG. - LOG(ERROR) << "CALayer changed clip inside non-zero sorting context."; - return false; - } - if (!is_singleton_sorting_context && - !current_layer.is_singleton_sorting_context && - current_layer.is_clipped == is_clipped && - current_layer.clip_rect == clip_rect && - current_layer.sorting_context_id == sorting_context_id) { - needs_new_clip_and_sorting_layer = false; - } - } - if (needs_new_clip_and_sorting_layer) { - clip_and_sorting_layers.push_back( - ClipAndSortingLayer(is_clipped, clip_rect, sorting_context_id, - is_singleton_sorting_context)); - } - clip_and_sorting_layers.back().AddContentLayer( - transform, io_surface, contents_rect, rect, background_color, - edge_aa_mask, opacity); - return true; -} - -void CALayerTree::ClipAndSortingLayer::AddContentLayer( - const gfx::Transform& transform, - base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::RectF& contents_rect, - const gfx::Rect& rect, - unsigned background_color, - unsigned edge_aa_mask, - float opacity) { - bool needs_new_transform_layer = true; - if (!transform_layers.empty()) { - const TransformLayer& current_layer = transform_layers.back(); - if (current_layer.transform == transform) - needs_new_transform_layer = false; - } - if (needs_new_transform_layer) - transform_layers.push_back(TransformLayer(transform)); - transform_layers.back().AddContentLayer( - io_surface, contents_rect, rect, background_color, edge_aa_mask, opacity); -} - -void CALayerTree::TransformLayer::AddContentLayer( - base::ScopedCFTypeRef<IOSurfaceRef> io_surface, - const gfx::RectF& contents_rect, - const gfx::Rect& rect, - unsigned background_color, - unsigned edge_aa_mask, - float opacity) { - content_layers.push_back(ContentLayer(io_surface, contents_rect, rect, - background_color, edge_aa_mask, - opacity)); -} - -void CALayerTree::RootLayer::CommitToCA(CALayer* superlayer, - RootLayer* old_layer, - float scale_factor) { - if (old_layer) { - DCHECK(old_layer->ca_layer); - std::swap(ca_layer, old_layer->ca_layer); - } else { - ca_layer.reset([[CALayer alloc] init]); - [ca_layer setAnchorPoint:CGPointZero]; - [superlayer setSublayers:nil]; - [superlayer addSublayer:ca_layer]; - [superlayer setBorderWidth:0]; - } - // Excessive logging to debug white screens (crbug.com/583805). - // TODO(ccameron): change this back to a DCHECK. - if ([ca_layer superlayer] != superlayer) { - LOG(ERROR) << "CALayerTree root layer not attached to tree."; - } - - for (size_t i = 0; i < clip_and_sorting_layers.size(); ++i) { - ClipAndSortingLayer* old_clip_and_sorting_layer = nullptr; - if (old_layer && i < old_layer->clip_and_sorting_layers.size()) { - old_clip_and_sorting_layer = &old_layer->clip_and_sorting_layers[i]; - } - clip_and_sorting_layers[i].CommitToCA( - ca_layer.get(), old_clip_and_sorting_layer, scale_factor); - } -} - -void CALayerTree::ClipAndSortingLayer::CommitToCA( - CALayer* superlayer, - ClipAndSortingLayer* old_layer, - float scale_factor) { - bool update_is_clipped = true; - bool update_clip_rect = true; - if (old_layer) { - DCHECK(old_layer->ca_layer); - std::swap(ca_layer, old_layer->ca_layer); - update_is_clipped = old_layer->is_clipped != is_clipped; - update_clip_rect = update_is_clipped || old_layer->clip_rect != clip_rect; - } else { - ca_layer.reset([[CALayer alloc] init]); - [ca_layer setAnchorPoint:CGPointZero]; - [superlayer addSublayer:ca_layer]; - } - // Excessive logging to debug white screens (crbug.com/583805). - // TODO(ccameron): change this back to a DCHECK. - if ([ca_layer superlayer] != superlayer) { - LOG(ERROR) << "CALayerTree root layer not attached to tree."; - } - - if (update_is_clipped) - [ca_layer setMasksToBounds:is_clipped]; - - if (update_clip_rect) { - if (is_clipped) { - gfx::RectF dip_clip_rect = gfx::RectF(clip_rect); - dip_clip_rect.Scale(1 / scale_factor); - [ca_layer setPosition:CGPointMake(dip_clip_rect.x(), dip_clip_rect.y())]; - [ca_layer setBounds:CGRectMake(0, 0, dip_clip_rect.width(), - dip_clip_rect.height())]; - [ca_layer - setSublayerTransform:CATransform3DMakeTranslation( - -dip_clip_rect.x(), -dip_clip_rect.y(), 0)]; - } else { - [ca_layer setPosition:CGPointZero]; - [ca_layer setBounds:CGRectZero]; - [ca_layer setSublayerTransform:CATransform3DIdentity]; - } - } - - for (size_t i = 0; i < transform_layers.size(); ++i) { - TransformLayer* old_transform_layer = nullptr; - if (old_layer && i < old_layer->transform_layers.size()) - old_transform_layer = &old_layer->transform_layers[i]; - transform_layers[i].CommitToCA(ca_layer.get(), old_transform_layer, - scale_factor); - } -} - -void CALayerTree::TransformLayer::CommitToCA(CALayer* superlayer, - TransformLayer* old_layer, - float scale_factor) { - bool update_transform = true; - if (old_layer) { - DCHECK(old_layer->ca_layer); - std::swap(ca_layer, old_layer->ca_layer); - update_transform = old_layer->transform != transform; - } else { - ca_layer.reset([[CATransformLayer alloc] init]); - [superlayer addSublayer:ca_layer]; - } - DCHECK_EQ([ca_layer superlayer], superlayer); - - if (update_transform) { - gfx::Transform pre_scale; - gfx::Transform post_scale; - pre_scale.Scale(1 / scale_factor, 1 / scale_factor); - post_scale.Scale(scale_factor, scale_factor); - gfx::Transform conjugated_transform = pre_scale * transform * post_scale; - - CATransform3D ca_transform; - conjugated_transform.matrix().asColMajord(&ca_transform.m11); - [ca_layer setTransform:ca_transform]; - } - - for (size_t i = 0; i < content_layers.size(); ++i) { - ContentLayer* old_content_layer = nullptr; - if (old_layer && i < old_layer->content_layers.size()) - old_content_layer = &old_layer->content_layers[i]; - content_layers[i].CommitToCA(ca_layer.get(), old_content_layer, - scale_factor); - } -} - -void CALayerTree::ContentLayer::CommitToCA(CALayer* superlayer, - ContentLayer* old_layer, - float scale_factor) { - bool update_contents = true; - bool update_contents_rect = true; - bool update_rect = true; - bool update_background_color = true; - bool update_ca_edge_aa_mask = true; - bool update_opacity = true; - if (old_layer && old_layer->use_av_layer == use_av_layer) { - DCHECK(old_layer->ca_layer); - std::swap(ca_layer, old_layer->ca_layer); - std::swap(av_layer, old_layer->av_layer); - update_contents = old_layer->io_surface != io_surface; - update_contents_rect = old_layer->contents_rect != contents_rect; - update_rect = old_layer->rect != rect; - update_background_color = old_layer->background_color != background_color; - update_ca_edge_aa_mask = old_layer->ca_edge_aa_mask != ca_edge_aa_mask; - update_opacity = old_layer->opacity != opacity; - } else { - if (use_av_layer) { - av_layer.reset([[AVSampleBufferDisplayLayer alloc] init]); - ca_layer.reset([av_layer retain]); - [av_layer setVideoGravity:AVLayerVideoGravityResize]; - } else { - ca_layer.reset([[CALayer alloc] init]); - } - [ca_layer setAnchorPoint:CGPointZero]; - [superlayer addSublayer:ca_layer]; - } - DCHECK_EQ([ca_layer superlayer], superlayer); - bool update_anything = update_contents || update_contents_rect || - update_rect || update_background_color || - update_ca_edge_aa_mask || update_opacity; - if (use_av_layer) { - if (update_contents) - AVSampleBufferDisplayLayerEnqueueIOSurface(av_layer, io_surface); - } else { - if (update_contents) { - [ca_layer setContents:static_cast<id>(io_surface.get())]; - if ([ca_layer respondsToSelector:(@selector(setContentsScale:))]) - [ca_layer setContentsScale:scale_factor]; - } - if (update_contents_rect) - [ca_layer setContentsRect:contents_rect.ToCGRect()]; - } - if (update_rect) { - gfx::RectF dip_rect = gfx::RectF(rect); - dip_rect.Scale(1 / scale_factor); - [ca_layer setPosition:CGPointMake(dip_rect.x(), dip_rect.y())]; - [ca_layer setBounds:CGRectMake(0, 0, dip_rect.width(), dip_rect.height())]; - } - if (update_background_color) { - CGFloat rgba_color_components[4] = { - SkColorGetR(background_color) / 255., - SkColorGetG(background_color) / 255., - SkColorGetB(background_color) / 255., - SkColorGetA(background_color) / 255., - }; - base::ScopedCFTypeRef<CGColorRef> srgb_background_color(CGColorCreate( - CGColorSpaceCreateWithName(kCGColorSpaceSRGB), rgba_color_components)); - [ca_layer setBackgroundColor:srgb_background_color]; - } - if (update_ca_edge_aa_mask) - [ca_layer setEdgeAntialiasingMask:ca_edge_aa_mask]; - if (update_opacity) - [ca_layer setOpacity:opacity]; - - static bool show_borders = base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kShowMacOverlayBorders); - if (show_borders) { - base::ScopedCFTypeRef<CGColorRef> color; - if (update_anything) { - if (use_av_layer) { - // Green represents an AV layer that changed this frame. - color.reset(CGColorCreateGenericRGB(0, 1, 0, 1)); - } else { - // Pink represents a CALayer that changed this frame. - color.reset(CGColorCreateGenericRGB(1, 0, 1, 1)); - } - } else { - // Grey represents a CALayer that has not changed. - color.reset(CGColorCreateGenericRGB(0, 0, 0, 0.1)); - } - [ca_layer setBorderWidth:1]; - [ca_layer setBorderColor:color]; - } -} - -} // namespace gpu diff --git a/chromium/gpu/ipc/service/ca_layer_tree_unittest_mac.mm b/chromium/gpu/ipc/service/ca_layer_tree_unittest_mac.mm deleted file mode 100644 index 18059833306..00000000000 --- a/chromium/gpu/ipc/service/ca_layer_tree_unittest_mac.mm +++ /dev/null @@ -1,852 +0,0 @@ -// Copyright 2016 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/mac/sdk_forward_declarations.h" -#include "gpu/GLES2/gl2extchromium.h" -#include "gpu/ipc/service/ca_layer_tree_mac.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/geometry/dip_util.h" -#include "ui/gfx/mac/io_surface.h" - -namespace gpu { - -class CALayerTreeTest : public testing::Test { - protected: - void SetUp() override { - superlayer_.reset([[CALayer alloc] init]); - } - - base::scoped_nsobject<CALayer> superlayer_; -}; - -// Test updating each layer's properties. -TEST_F(CALayerTreeTest, PropertyUpdates) { - base::ScopedCFTypeRef<IOSurfaceRef> io_surface(gfx::CreateIOSurface( - gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888)); - bool is_clipped = true; - gfx::Rect clip_rect(2, 4, 8, 16); - int sorting_context_id = 0; - gfx::Transform transform; - transform.Translate(10, 20); - gfx::RectF contents_rect(0.0f, 0.25f, 0.5f, 0.75f); - gfx::Rect rect(16, 32, 64, 128); - unsigned background_color = SkColorSetARGB(0xFF, 0xFF, 0, 0); - unsigned edge_aa_mask = GL_CA_LAYER_EDGE_LEFT_CHROMIUM; - float opacity = 0.5f; - float scale_factor = 1.0f; - bool result = false; - - scoped_ptr<CALayerTree> ca_layer_tree; - CALayer* root_layer = nil; - CALayer* clip_and_sorting_layer = nil; - CALayer* transform_layer = nil; - CALayer* content_layer = nil; - - // Validate the initial values. - { - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_id, - transform, - io_surface, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - root_layer = [[superlayer_ sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[root_layer sublayers] count]); - clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[transform_layer sublayers] count]); - content_layer = [[transform_layer sublayers] objectAtIndex:0]; - - // Validate the clip and sorting context layer. - EXPECT_TRUE([clip_and_sorting_layer masksToBounds]); - EXPECT_EQ(gfx::Rect(clip_rect.size()), - gfx::Rect([clip_and_sorting_layer bounds])); - EXPECT_EQ(clip_rect.origin(), - gfx::Point([clip_and_sorting_layer position])); - EXPECT_EQ(-clip_rect.origin().x(), - [clip_and_sorting_layer sublayerTransform].m41); - EXPECT_EQ(-clip_rect.origin().y(), - [clip_and_sorting_layer sublayerTransform].m42); - - // Validate the transform layer. - EXPECT_EQ(transform.matrix().get(3, 0), - [transform_layer sublayerTransform].m41); - EXPECT_EQ(transform.matrix().get(3, 1), - [transform_layer sublayerTransform].m42); - - // Validate the content layer. - EXPECT_EQ(static_cast<id>(io_surface.get()), [content_layer contents]); - EXPECT_EQ(contents_rect, gfx::RectF([content_layer contentsRect])); - EXPECT_EQ(rect.origin(), gfx::Point([content_layer position])); - EXPECT_EQ(gfx::Rect(rect.size()), gfx::Rect([content_layer bounds])); - EXPECT_EQ(kCALayerLeftEdge, [content_layer edgeAntialiasingMask]); - EXPECT_EQ(opacity, [content_layer opacity]); - if ([content_layer respondsToSelector:(@selector(contentsScale))]) - EXPECT_EQ(scale_factor, [content_layer contentsScale]); - } - - // Update just the clip rect and re-commit. - { - clip_rect = gfx::Rect(4, 8, 16, 32); - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_id, - transform, - io_surface, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[root_layer sublayers] count]); - EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - EXPECT_EQ(transform_layer, - [[clip_and_sorting_layer sublayers] objectAtIndex:0]); - - // Validate the clip and sorting context layer. - EXPECT_TRUE([clip_and_sorting_layer masksToBounds]); - EXPECT_EQ(gfx::Rect(clip_rect.size()), - gfx::Rect([clip_and_sorting_layer bounds])); - EXPECT_EQ(clip_rect.origin(), - gfx::Point([clip_and_sorting_layer position])); - EXPECT_EQ(-clip_rect.origin().x(), - [clip_and_sorting_layer sublayerTransform].m41); - EXPECT_EQ(-clip_rect.origin().y(), - [clip_and_sorting_layer sublayerTransform].m42); - } - - // Disable clipping and re-commit. - { - is_clipped = false; - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_id, - transform, - io_surface, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[root_layer sublayers] count]); - EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - EXPECT_EQ(transform_layer, - [[clip_and_sorting_layer sublayers] objectAtIndex:0]); - - // Validate the clip and sorting context layer. - EXPECT_FALSE([clip_and_sorting_layer masksToBounds]); - EXPECT_EQ(gfx::Rect(), gfx::Rect([clip_and_sorting_layer bounds])); - EXPECT_EQ(gfx::Point(), gfx::Point([clip_and_sorting_layer position])); - EXPECT_EQ(0.0, [clip_and_sorting_layer sublayerTransform].m41); - EXPECT_EQ(0.0, [clip_and_sorting_layer sublayerTransform].m42); - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - } - - // Change the transform and re-commit. - { - transform.Translate(5, 5); - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_id, - transform, - io_surface, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[root_layer sublayers] count]); - EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - EXPECT_EQ(transform_layer, - [[clip_and_sorting_layer sublayers] objectAtIndex:0]); - - // Validate the transform layer. - EXPECT_EQ(transform.matrix().get(3, 0), - [transform_layer sublayerTransform].m41); - EXPECT_EQ(transform.matrix().get(3, 1), - [transform_layer sublayerTransform].m42); - } - - // Change the edge antialiasing mask and commit. - { - edge_aa_mask = GL_CA_LAYER_EDGE_TOP_CHROMIUM; - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_id, - transform, - io_surface, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[root_layer sublayers] count]); - EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - EXPECT_EQ(transform_layer, - [[clip_and_sorting_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[transform_layer sublayers] count]); - EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); - - // Validate the content layer. Note that top and bottom edges flip. - EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); - } - - // Change the contents and commit. - { - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_id, - transform, - nullptr, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[root_layer sublayers] count]); - EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - EXPECT_EQ(transform_layer, - [[clip_and_sorting_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[transform_layer sublayers] count]); - EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); - - // Validate the content layer. Note that edge anti-aliasing no longer flips. - EXPECT_EQ(nil, [content_layer contents]); - EXPECT_EQ(kCALayerTopEdge, [content_layer edgeAntialiasingMask]); - } - - // Change the rect size. - { - rect = gfx::Rect(rect.origin(), gfx::Size(32, 16)); - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_id, - transform, - nullptr, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[root_layer sublayers] count]); - EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - EXPECT_EQ(transform_layer, - [[clip_and_sorting_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[transform_layer sublayers] count]); - EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); - - // Validate the content layer. - EXPECT_EQ(rect.origin(), gfx::Point([content_layer position])); - EXPECT_EQ(gfx::Rect(rect.size()), gfx::Rect([content_layer bounds])); - } - - // Change the rect position. - { - rect = gfx::Rect(gfx::Point(16, 4), rect.size()); - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_id, - transform, - nullptr, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[root_layer sublayers] count]); - EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - EXPECT_EQ(transform_layer, - [[clip_and_sorting_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[transform_layer sublayers] count]); - EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); - - // Validate the content layer. - EXPECT_EQ(rect.origin(), gfx::Point([content_layer position])); - EXPECT_EQ(gfx::Rect(rect.size()), gfx::Rect([content_layer bounds])); - } - - // Change the opacity. - { - opacity = 1.0f; - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_id, - transform, - nullptr, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[root_layer sublayers] count]); - EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - EXPECT_EQ(transform_layer, - [[clip_and_sorting_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[transform_layer sublayers] count]); - EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); - - // Validate the content layer. - EXPECT_EQ(opacity, [content_layer opacity]); - } - - // Add the clipping and IOSurface contents back. - { - is_clipped = true; - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_id, - transform, - io_surface, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[root_layer sublayers] count]); - EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - EXPECT_EQ(transform_layer, - [[clip_and_sorting_layer sublayers] objectAtIndex:0]); - EXPECT_EQ(1u, [[transform_layer sublayers] count]); - EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); - - // Validate the content layer. - EXPECT_EQ(static_cast<id>(io_surface.get()), [content_layer contents]); - EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); - } - - // Change the scale factor. This should result in a new tree being created. - { - scale_factor = 2.0f; - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_id, - transform, - io_surface, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - EXPECT_NE(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); - root_layer = [[superlayer_ sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[root_layer sublayers] count]); - EXPECT_NE(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); - clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - EXPECT_NE(transform_layer, - [[clip_and_sorting_layer sublayers] objectAtIndex:0]); - transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[transform_layer sublayers] count]); - EXPECT_NE(content_layer, [[transform_layer sublayers] objectAtIndex:0]); - content_layer = [[transform_layer sublayers] objectAtIndex:0]; - - // Validate the clip and sorting context layer. - EXPECT_TRUE([clip_and_sorting_layer masksToBounds]); - EXPECT_EQ(gfx::ConvertRectToDIP(scale_factor, gfx::Rect(clip_rect.size())), - gfx::Rect([clip_and_sorting_layer bounds])); - EXPECT_EQ(gfx::ConvertPointToDIP(scale_factor, clip_rect.origin()), - gfx::Point([clip_and_sorting_layer position])); - EXPECT_EQ(-clip_rect.origin().x() / scale_factor, - [clip_and_sorting_layer sublayerTransform].m41); - EXPECT_EQ(-clip_rect.origin().y() / scale_factor, - [clip_and_sorting_layer sublayerTransform].m42); - - // Validate the transform layer. - EXPECT_EQ(transform.matrix().get(3, 0) / scale_factor, - [transform_layer sublayerTransform].m41); - EXPECT_EQ(transform.matrix().get(3, 1) / scale_factor, - [transform_layer sublayerTransform].m42); - - // Validate the content layer. - EXPECT_EQ(static_cast<id>(io_surface.get()), [content_layer contents]); - EXPECT_EQ(contents_rect, gfx::RectF([content_layer contentsRect])); - EXPECT_EQ(gfx::ConvertPointToDIP(scale_factor, rect.origin()), - gfx::Point([content_layer position])); - EXPECT_EQ(gfx::ConvertRectToDIP(scale_factor, gfx::Rect(rect.size())), - gfx::Rect([content_layer bounds])); - EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); - EXPECT_EQ(opacity, [content_layer opacity]); - if ([content_layer respondsToSelector:(@selector(contentsScale))]) - EXPECT_EQ(scale_factor, [content_layer contentsScale]); - } -} - -// Verify that sorting context zero is split at non-flat transforms. -TEST_F(CALayerTreeTest, SplitSortingContextZero) { - bool is_clipped = false; - gfx::Rect clip_rect; - int sorting_context_id = 0; - gfx::RectF contents_rect(0, 0, 1, 1); - gfx::Rect rect(0, 0, 256, 256); - unsigned background_color = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF); - unsigned edge_aa_mask = 0; - float opacity = 1.0f; - float scale_factor = 1.0f; - - // We'll use the IOSurface contents to identify the content layers. - base::ScopedCFTypeRef<IOSurfaceRef> io_surfaces[5]; - for (size_t i = 0; i < 5; ++i) { - io_surfaces[i].reset(gfx::CreateIOSurface( - gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888)); - } - - // Have 5 transforms: - // * 2 flat but different (1 sorting context layer, 2 transform layers) - // * 1 non-flat (new sorting context layer) - // * 2 flat and the same (new sorting context layer, 1 transform layer) - gfx::Transform transforms[5]; - transforms[0].Translate(10, 10); - transforms[1].RotateAboutZAxis(45.0f); - transforms[2].RotateAboutYAxis(45.0f); - transforms[3].Translate(10, 10); - transforms[4].Translate(10, 10); - - // Schedule and commit the layers. - scoped_ptr<CALayerTree> ca_layer_tree(new CALayerTree); - for (size_t i = 0; i < 5; ++i) { - bool result = ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_id, - transforms[i], - io_surfaces[i], - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - } - ca_layer_tree->CommitScheduledCALayers(superlayer_, nullptr, scale_factor); - - // Validate the root layer. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - CALayer* root_layer = [[superlayer_ sublayers] objectAtIndex:0]; - - // Validate that we have 3 sorting context layers. - EXPECT_EQ(3u, [[root_layer sublayers] count]); - CALayer* clip_and_sorting_layer_0 = [[root_layer sublayers] objectAtIndex:0]; - CALayer* clip_and_sorting_layer_1 = [[root_layer sublayers] objectAtIndex:1]; - CALayer* clip_and_sorting_layer_2 = [[root_layer sublayers] objectAtIndex:2]; - - // Validate that the first sorting context has 2 transform layers each with - // one content layer. - EXPECT_EQ(2u, [[clip_and_sorting_layer_0 sublayers] count]); - CALayer* transform_layer_0_0 = - [[clip_and_sorting_layer_0 sublayers] objectAtIndex:0]; - CALayer* transform_layer_0_1 = - [[clip_and_sorting_layer_0 sublayers] objectAtIndex:1]; - EXPECT_EQ(1u, [[transform_layer_0_0 sublayers] count]); - CALayer* content_layer_0 = [[transform_layer_0_0 sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[transform_layer_0_1 sublayers] count]); - CALayer* content_layer_1 = [[transform_layer_0_1 sublayers] objectAtIndex:0]; - - // Validate that the second sorting context has 1 transform layer with one - // content layer. - EXPECT_EQ(1u, [[clip_and_sorting_layer_1 sublayers] count]); - CALayer* transform_layer_1_0 = - [[clip_and_sorting_layer_1 sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[transform_layer_1_0 sublayers] count]); - CALayer* content_layer_2 = [[transform_layer_1_0 sublayers] objectAtIndex:0]; - - // Validate that the third sorting context has 1 transform layer with two - // content layers. - EXPECT_EQ(1u, [[clip_and_sorting_layer_2 sublayers] count]); - CALayer* transform_layer_2_0 = - [[clip_and_sorting_layer_2 sublayers] objectAtIndex:0]; - EXPECT_EQ(2u, [[transform_layer_2_0 sublayers] count]); - CALayer* content_layer_3 = [[transform_layer_2_0 sublayers] objectAtIndex:0]; - CALayer* content_layer_4 = [[transform_layer_2_0 sublayers] objectAtIndex:1]; - - // Validate that the layers come out in order. - EXPECT_EQ(static_cast<id>(io_surfaces[0].get()), [content_layer_0 contents]); - EXPECT_EQ(static_cast<id>(io_surfaces[1].get()), [content_layer_1 contents]); - EXPECT_EQ(static_cast<id>(io_surfaces[2].get()), [content_layer_2 contents]); - EXPECT_EQ(static_cast<id>(io_surfaces[3].get()), [content_layer_3 contents]); - EXPECT_EQ(static_cast<id>(io_surfaces[4].get()), [content_layer_4 contents]); -} - -// Verify that sorting contexts are allocated appropriately. -TEST_F(CALayerTreeTest, SortingContexts) { - bool is_clipped = false; - gfx::Rect clip_rect; - int sorting_context_ids[3] = {3, -1, 0}; - gfx::RectF contents_rect(0, 0, 1, 1); - gfx::Rect rect(0, 0, 256, 256); - gfx::Transform transform; - unsigned background_color = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF); - unsigned edge_aa_mask = 0; - float opacity = 1.0f; - float scale_factor = 1.0f; - - // We'll use the IOSurface contents to identify the content layers. - base::ScopedCFTypeRef<IOSurfaceRef> io_surfaces[3]; - for (size_t i = 0; i < 3; ++i) { - io_surfaces[i].reset(gfx::CreateIOSurface( - gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888)); - } - - // Schedule and commit the layers. - scoped_ptr<CALayerTree> ca_layer_tree(new CALayerTree); - for (size_t i = 0; i < 3; ++i) { - bool result = ca_layer_tree->ScheduleCALayer( - is_clipped, - clip_rect, - sorting_context_ids[i], - transform, - io_surfaces[i], - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - } - ca_layer_tree->CommitScheduledCALayers(superlayer_, nullptr, scale_factor); - - // Validate the root layer. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - CALayer* root_layer = [[superlayer_ sublayers] objectAtIndex:0]; - - // Validate that we have 3 sorting context layers. - EXPECT_EQ(3u, [[root_layer sublayers] count]); - CALayer* clip_and_sorting_layer_0 = [[root_layer sublayers] objectAtIndex:0]; - CALayer* clip_and_sorting_layer_1 = [[root_layer sublayers] objectAtIndex:1]; - CALayer* clip_and_sorting_layer_2 = [[root_layer sublayers] objectAtIndex:2]; - - // Validate that each sorting context has 1 transform layer. - EXPECT_EQ(1u, [[clip_and_sorting_layer_0 sublayers] count]); - CALayer* transform_layer_0 = - [[clip_and_sorting_layer_0 sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[clip_and_sorting_layer_1 sublayers] count]); - CALayer* transform_layer_1 = - [[clip_and_sorting_layer_1 sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[clip_and_sorting_layer_2 sublayers] count]); - CALayer* transform_layer_2 = - [[clip_and_sorting_layer_2 sublayers] objectAtIndex:0]; - - // Validate that each transform has 1 content layer. - EXPECT_EQ(1u, [[transform_layer_0 sublayers] count]); - CALayer* content_layer_0 = [[transform_layer_0 sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[transform_layer_1 sublayers] count]); - CALayer* content_layer_1 = [[transform_layer_1 sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[transform_layer_2 sublayers] count]); - CALayer* content_layer_2 = [[transform_layer_2 sublayers] objectAtIndex:0]; - - // Validate that the layers come out in order. - EXPECT_EQ(static_cast<id>(io_surfaces[0].get()), [content_layer_0 contents]); - EXPECT_EQ(static_cast<id>(io_surfaces[1].get()), [content_layer_1 contents]); - EXPECT_EQ(static_cast<id>(io_surfaces[2].get()), [content_layer_2 contents]); -} - -// Verify that sorting contexts must all have the same clipping properties. -TEST_F(CALayerTreeTest, SortingContextMustHaveConsistentClip) { - base::ScopedCFTypeRef<IOSurfaceRef> io_surface; - gfx::RectF contents_rect(0, 0, 1, 1); - gfx::Rect rect(0, 0, 256, 256); - gfx::Transform transform; - unsigned background_color = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF); - unsigned edge_aa_mask = 0; - float opacity = 1.0f; - - // Vary the clipping parameters within sorting contexts. - bool is_clippeds[3] = { true, true, false}; - gfx::Rect clip_rects[3] = { - gfx::Rect(0, 0, 16, 16), - gfx::Rect(4, 8, 16, 32), - gfx::Rect(0, 0, 16, 16) - }; - - scoped_ptr<CALayerTree> ca_layer_tree(new CALayerTree); - // First send the various clip parameters to sorting context zero. This is - // legitimate. - for (size_t i = 0; i < 3; ++i) { - int sorting_context_id = 0; - bool result = ca_layer_tree->ScheduleCALayer( - is_clippeds[i], - clip_rects[i], - sorting_context_id, - transform, - io_surface, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - } - // Next send the various clip parameters to a non-zero sorting context. This - // will fail when we try to change the clip within the sorting context. - for (size_t i = 0; i < 3; ++i) { - int sorting_context_id = 3; - bool result = ca_layer_tree->ScheduleCALayer( - is_clippeds[i], - clip_rects[i], - sorting_context_id, - transform, - io_surface, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - if (i == 0) - EXPECT_TRUE(result); - else - EXPECT_FALSE(result); - } - // Try once more with the original clip and verify it works. - { - int sorting_context_id = 3; - bool result = ca_layer_tree->ScheduleCALayer( - is_clippeds[0], - clip_rects[0], - sorting_context_id, - transform, - io_surface, - contents_rect, - rect, - background_color, - edge_aa_mask, - opacity); - EXPECT_TRUE(result); - } -} - -// Test updating each layer's properties. -TEST_F(CALayerTreeTest, AVLayer) { - base::ScopedCFTypeRef<IOSurfaceRef> io_surface(gfx::CreateIOSurface( - gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR)); - bool is_clipped = true; - gfx::Rect clip_rect(2, 4, 8, 16); - int sorting_context_id = 0; - gfx::Transform transform; - gfx::RectF contents_rect(0.0f, 0.0f, 1.0f, 1.0f); - gfx::Rect rect(16, 32, 64, 128); - unsigned background_color = SkColorSetARGB(0xFF, 0xFF, 0, 0); - unsigned edge_aa_mask = GL_CA_LAYER_EDGE_LEFT_CHROMIUM; - float opacity = 0.5f; - float scale_factor = 1.0f; - bool result = false; - - scoped_ptr<CALayerTree> ca_layer_tree; - CALayer* root_layer = nil; - CALayer* clip_and_sorting_layer = nil; - CALayer* transform_layer = nil; - CALayer* content_layer1 = nil; - CALayer* content_layer2 = nil; - CALayer* content_layer3 = nil; - - // Validate the initial values. - { - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, clip_rect, sorting_context_id, transform, io_surface, - contents_rect, rect, background_color, edge_aa_mask, opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - root_layer = [[superlayer_ sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[root_layer sublayers] count]); - clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[transform_layer sublayers] count]); - content_layer1 = [[transform_layer sublayers] objectAtIndex:0]; - - // Validate the content layer. - EXPECT_FALSE([content_layer1 - isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); - } - - io_surface.reset(gfx::CreateIOSurface(gfx::Size(256, 256), - gfx::BufferFormat::YUV_420_BIPLANAR)); - - // Pass another frame. - { - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, clip_rect, sorting_context_id, transform, io_surface, - contents_rect, rect, background_color, edge_aa_mask, opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - root_layer = [[superlayer_ sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[root_layer sublayers] count]); - clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[transform_layer sublayers] count]); - content_layer2 = [[transform_layer sublayers] objectAtIndex:0]; - - // Validate the content layer. - EXPECT_FALSE([content_layer2 - isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); - EXPECT_EQ(content_layer2, content_layer1); - } - - io_surface.reset(gfx::CreateIOSurface(gfx::Size(256, 256), - gfx::BufferFormat::YUV_420_BIPLANAR)); - - // Pass a frame that is clipped. - contents_rect = gfx::RectF(0, 0, 1, 0.9); - { - scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); - result = new_ca_layer_tree->ScheduleCALayer( - is_clipped, clip_rect, sorting_context_id, transform, io_surface, - contents_rect, rect, background_color, edge_aa_mask, opacity); - EXPECT_TRUE(result); - new_ca_layer_tree->CommitScheduledCALayers( - superlayer_, std::move(ca_layer_tree), scale_factor); - std::swap(new_ca_layer_tree, ca_layer_tree); - - // Validate the tree structure. - EXPECT_EQ(1u, [[superlayer_ sublayers] count]); - root_layer = [[superlayer_ sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[root_layer sublayers] count]); - clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); - transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; - EXPECT_EQ(1u, [[transform_layer sublayers] count]); - content_layer3 = [[transform_layer sublayers] objectAtIndex:0]; - - // Validate the content layer. - EXPECT_FALSE([content_layer3 - isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); - EXPECT_EQ(content_layer3, content_layer2); - } -} - -} // namespace gpu diff --git a/chromium/gpu/ipc/service/child_window_surface_win.cc b/chromium/gpu/ipc/service/child_window_surface_win.cc index 535451ef1b8..874b878e140 100644 --- a/chromium/gpu/ipc/service/child_window_surface_win.cc +++ b/chromium/gpu/ipc/service/child_window_surface_win.cc @@ -4,6 +4,8 @@ #include "gpu/ipc/service/child_window_surface_win.h" +#include <memory> + #include "base/compiler_specific.h" #include "base/win/scoped_hdc.h" #include "base/win/wrapped_window_proc.h" @@ -160,7 +162,7 @@ bool ChildWindowSurfaceWin::Resize(const gfx::Size& size, alpha_ = has_alpha; config_ = nullptr; - scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current; + std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current; gfx::GLContext* current_context = gfx::GLContext::GetCurrent(); bool was_current = current_context && current_context->IsCurrent(this); if (was_current) { diff --git a/chromium/gpu/ipc/service/gpu_channel.cc b/chromium/gpu/ipc/service/gpu_channel.cc index 7661318de18..1a777631b29 100644 --- a/chromium/gpu/ipc/service/gpu_channel.cc +++ b/chromium/gpu/ipc/service/gpu_channel.cc @@ -24,19 +24,17 @@ #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/synchronization/lock.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/timer/timer.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "gpu/command_buffer/common/mailbox.h" -#include "gpu/command_buffer/common/value_state.h" #include "gpu/command_buffer/service/command_executor.h" #include "gpu/command_buffer/service/image_factory.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/sync_point_manager.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" #include "gpu/ipc/common/gpu_messages.h" #include "gpu/ipc/service/gpu_channel_manager.h" #include "gpu/ipc/service/gpu_channel_manager_delegate.h" @@ -194,7 +192,7 @@ bool GpuChannelMessageQueue::PushBackMessage(const IPC::Message& message) { uint32_t order_num = sync_point_order_data_->GenerateUnprocessedOrderNumber( sync_point_manager_); - scoped_ptr<GpuChannelMessage> msg( + std::unique_ptr<GpuChannelMessage> msg( new GpuChannelMessage(message, order_num, base::TimeTicks::Now())); if (channel_messages_.empty()) { @@ -602,8 +600,6 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, io_task_runner_(io_task_runner), share_group_(share_group), mailbox_manager_(mailbox), - subscription_ref_set_(new gles2::SubscriptionRefSet), - pending_valuebuffer_state_(new ValueStateMap), watchdog_(watchdog), allow_view_command_buffers_(allow_view_command_buffers), allow_real_time_streams_(allow_real_time_streams), @@ -616,8 +612,6 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, scoped_refptr<GpuChannelMessageQueue> control_queue = CreateStream(GPU_STREAM_DEFAULT, GpuStreamPriority::HIGH); AddRouteToStream(MSG_ROUTING_CONTROL, GPU_STREAM_DEFAULT); - - subscription_ref_set_->AddObserver(this); } GpuChannel::~GpuChannel() { @@ -627,7 +621,6 @@ GpuChannel::~GpuChannel() { for (auto& kv : streams_) kv.second->Disable(); - subscription_ref_set_->RemoveObserver(this); if (preempting_flag_.get()) preempting_flag_->Reset(); } @@ -711,14 +704,6 @@ bool GpuChannel::Send(IPC::Message* message) { return channel_->Send(message); } -void GpuChannel::OnAddSubscription(unsigned int target) { - gpu_channel_manager()->delegate()->AddSubscription(client_id_, target); -} - -void GpuChannel::OnRemoveSubscription(unsigned int target) { - gpu_channel_manager()->delegate()->RemoveSubscription(client_id_, target); -} - void GpuChannel::OnStreamRescheduled(int32_t stream_id, bool scheduled) { scoped_refptr<GpuChannelMessageQueue> queue = LookupStream(stream_id); DCHECK(queue); @@ -905,19 +890,36 @@ const GpuCommandBufferStub* GpuChannel::GetOneStub() const { #endif void GpuChannel::OnCreateCommandBuffer( - SurfaceHandle surface_handle, - const gfx::Size& size, const GPUCreateCommandBufferConfig& init_params, int32_t route_id, - bool* succeeded) { + base::SharedMemoryHandle shared_state_handle, + bool* result, + gpu::Capabilities* capabilities) { TRACE_EVENT2("gpu", "GpuChannel::OnCreateCommandBuffer", "route_id", route_id, - "offscreen", (surface_handle == kNullSurfaceHandle)); - *succeeded = false; - if (surface_handle != kNullSurfaceHandle && + "offscreen", (init_params.surface_handle == kNullSurfaceHandle)); + std::unique_ptr<base::SharedMemory> shared_state_shm( + new base::SharedMemory(shared_state_handle, false)); + std::unique_ptr<GpuCommandBufferStub> stub = + CreateCommandBuffer(init_params, route_id, std::move(shared_state_shm)); + if (stub) { + *result = true; + *capabilities = stub->decoder()->GetCapabilities(); + stubs_.set(route_id, std::move(stub)); + } else { + *result = false; + *capabilities = gpu::Capabilities(); + } +} + +std::unique_ptr<GpuCommandBufferStub> GpuChannel::CreateCommandBuffer( + const GPUCreateCommandBufferConfig& init_params, + int32_t route_id, + std::unique_ptr<base::SharedMemory> shared_state_shm) { + if (init_params.surface_handle != kNullSurfaceHandle && !allow_view_command_buffers_) { DLOG(ERROR) << "GpuChannel::CreateCommandBuffer(): attempt to create a " "view context on a non-priviledged channel"; - return; + return nullptr; } int32_t share_group_id = init_params.share_group_id; @@ -925,51 +927,65 @@ void GpuChannel::OnCreateCommandBuffer( if (!share_group && share_group_id != MSG_ROUTING_NONE) { DLOG(ERROR) - << "GpuChannel::OnCreateCommandBuffer(): invalid share group id"; - return; + << "GpuChannel::CreateCommandBuffer(): invalid share group id"; + return nullptr; } int32_t stream_id = init_params.stream_id; if (share_group && stream_id != share_group->stream_id()) { - DLOG(ERROR) << "GpuChannel::OnCreateCommandBuffer(): stream id does not " + DLOG(ERROR) << "GpuChannel::CreateCommandBuffer(): stream id does not " "match share group stream id"; - return; + return nullptr; } GpuStreamPriority stream_priority = init_params.stream_priority; if (!allow_real_time_streams_ && stream_priority == GpuStreamPriority::REAL_TIME) { - DLOG(ERROR) << "GpuChannel::OnCreateCommandBuffer(): real time stream " + DLOG(ERROR) << "GpuChannel::CreateCommandBuffer(): real time stream " "priority not allowed"; - return; + return nullptr; } - scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub( - this, sync_point_manager_, task_runner_.get(), share_group, - surface_handle, mailbox_manager_.get(), preempted_flag_.get(), - subscription_ref_set_.get(), pending_valuebuffer_state_.get(), size, - disallowed_features_, init_params.attribs, init_params.gpu_preference, - init_params.stream_id, route_id, watchdog_, init_params.active_url)); + if (share_group && !share_group->decoder()) { + // This should catch test errors where we did not Initialize the + // share_group's CommandBuffer. + DLOG(ERROR) << "GpuChannel::CreateCommandBuffer(): shared context was " + "not initialized"; + return nullptr; + } + + if (share_group && share_group->decoder()->WasContextLost()) { + DLOG(ERROR) << "GpuChannel::CreateCommandBuffer(): shared context was " + "already lost"; + return nullptr; + } scoped_refptr<GpuChannelMessageQueue> queue = LookupStream(stream_id); if (!queue) queue = CreateStream(stream_id, stream_priority); + std::unique_ptr<GpuCommandBufferStub> stub(GpuCommandBufferStub::Create( + this, share_group, init_params, route_id, std::move(shared_state_shm))); + + if (!stub) { + DestroyStreamIfNecessary(queue); + return nullptr; + } + if (!AddRoute(route_id, stream_id, stub.get())) { DestroyStreamIfNecessary(queue); - DLOG(ERROR) << "GpuChannel::OnCreateCommandBuffer(): failed to add route"; - return; + DLOG(ERROR) << "GpuChannel::CreateCommandBuffer(): failed to add route"; + return nullptr; } - stubs_.set(route_id, std::move(stub)); - *succeeded = true; + return stub; } void GpuChannel::OnDestroyCommandBuffer(int32_t route_id) { TRACE_EVENT1("gpu", "GpuChannel::OnDestroyCommandBuffer", "route_id", route_id); - scoped_ptr<GpuCommandBufferStub> stub = stubs_.take_and_erase(route_id); + std::unique_ptr<GpuCommandBufferStub> stub = stubs_.take_and_erase(route_id); // In case the renderer is currently blocked waiting for a sync reply from the // stub, we need to make sure to reschedule the correct stream here. if (stub && !stub->IsScheduled()) { @@ -982,16 +998,9 @@ void GpuChannel::OnDestroyCommandBuffer(int32_t route_id) { void GpuChannel::OnGetDriverBugWorkArounds( std::vector<std::string>* gpu_driver_bug_workarounds) { - // TODO(j.isorce): http://crbug.com/599964 Do the extraction of workarounds in - // the GpuChannelManager constructor. Currently it is done in the FeatureInfo - // constructor. There is no need to extract them from the command-line every - // time a new FeatureInfo is created (i.e. per ContextGroup) since parsing - // result is a constant. - scoped_refptr<gpu::gles2::FeatureInfo> feature_info = - new gpu::gles2::FeatureInfo; gpu_driver_bug_workarounds->clear(); -#define GPU_OP(type, name) \ - if (feature_info->workarounds().name) \ +#define GPU_OP(type, name) \ + if (gpu_channel_manager_->gpu_driver_bug_workarounds().name) \ gpu_driver_bug_workarounds->push_back(#name); GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) #undef GPU_OP @@ -1064,9 +1073,4 @@ scoped_refptr<gl::GLImage> GpuChannel::CreateImageForGpuMemoryBuffer( } } -void GpuChannel::HandleUpdateValueState( - unsigned int target, const ValueState& state) { - pending_valuebuffer_state_->UpdateState(target, state); -} - } // namespace gpu diff --git a/chromium/gpu/ipc/service/gpu_channel.h b/chromium/gpu/ipc/service/gpu_channel.h index 8090b40b8a6..1712e08769a 100644 --- a/chromium/gpu/ipc/service/gpu_channel.h +++ b/chromium/gpu/ipc/service/gpu_channel.h @@ -8,19 +8,18 @@ #include <stddef.h> #include <stdint.h> +#include <memory> #include <string> #include "base/containers/hash_tables.h" #include "base/containers/scoped_ptr_hash_map.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/process/process.h" #include "base/threading/thread_checker.h" #include "base/trace_event/memory_dump_provider.h" #include "build/build_config.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" #include "gpu/gpu_export.h" #include "gpu/ipc/common/gpu_stream_constants.h" #include "gpu/ipc/service/gpu_command_buffer_stub.h" @@ -47,23 +46,16 @@ namespace gpu { class PreemptionFlag; class SyncPointOrderData; class SyncPointManager; -union ValueState; -class ValueStateMap; class GpuChannelManager; class GpuChannelMessageFilter; class GpuChannelMessageQueue; class GpuWatchdog; -namespace gles2 { -class SubscriptionRefSet; -} - // Encapsulates an IPC channel between the GPU process and one renderer // process. On the renderer side there's a corresponding GpuChannelHost. class GPU_EXPORT GpuChannel : public IPC::Listener, - public IPC::Sender, - public gles2::SubscriptionRefSet::Observer { + public IPC::Sender { public: // Takes ownership of the renderer process handle. GpuChannel(GpuChannelManager* gpu_channel_manager, @@ -92,6 +84,22 @@ class GPU_EXPORT GpuChannel return gpu_channel_manager_; } + SyncPointManager* sync_point_manager() const { return sync_point_manager_; } + + GpuWatchdog* watchdog() const { return watchdog_; } + + const scoped_refptr<gles2::MailboxManager>& mailbox_manager() const { + return mailbox_manager_; + } + + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner() const { + return task_runner_; + } + + const scoped_refptr<PreemptionFlag>& preempted_flag() const { + return preempted_flag_; + } + const std::string& channel_id() const { return channel_id_; } virtual base::ProcessId GetClientPID() const; @@ -113,10 +121,6 @@ class GPU_EXPORT GpuChannel // IPC::Sender implementation: bool Send(IPC::Message* msg) override; - // SubscriptionRefSet::Observer implementation - void OnAddSubscription(unsigned int target) override; - void OnRemoveSubscription(unsigned int target) override; - void OnStreamRescheduled(int32_t stream_id, bool scheduled); gfx::GLShareGroup* share_group() const { return share_group_.get(); } @@ -146,16 +150,8 @@ class GPU_EXPORT GpuChannel gfx::BufferFormat format, uint32_t internalformat); - void HandleUpdateValueState(unsigned int target, - const ValueState& state); - GpuChannelMessageFilter* filter() const { return filter_.get(); } - // Visible for testing. - const ValueStateMap* pending_valuebuffer_state() const { - return pending_valuebuffer_state_.get(); - } - // Returns the global order number for the last processed IPC message. uint32_t GetProcessedOrderNum() const; @@ -181,7 +177,7 @@ class GPU_EXPORT GpuChannel scoped_refptr<GpuChannelMessageFilter> filter_; // Map of routing id to command buffer stub. - base::ScopedPtrHashMap<int32_t, scoped_ptr<GpuCommandBufferStub>> stubs_; + base::ScopedPtrHashMap<int32_t, std::unique_ptr<GpuCommandBufferStub>> stubs_; private: bool OnControlMessageReceived(const IPC::Message& msg); @@ -208,15 +204,20 @@ class GPU_EXPORT GpuChannel void RemoveRouteFromStream(int32_t route_id); // Message handlers for control messages. - void OnCreateCommandBuffer(SurfaceHandle surface_handle, - const gfx::Size& size, - const GPUCreateCommandBufferConfig& init_params, + void OnCreateCommandBuffer(const GPUCreateCommandBufferConfig& init_params, int32_t route_id, - bool* succeeded); + base::SharedMemoryHandle shared_state_shm, + bool* result, + gpu::Capabilities* capabilities); void OnDestroyCommandBuffer(int32_t route_id); void OnGetDriverBugWorkArounds( std::vector<std::string>* gpu_driver_bug_workarounds); + std::unique_ptr<GpuCommandBufferStub> CreateCommandBuffer( + const GPUCreateCommandBufferConfig& init_params, + int32_t route_id, + std::unique_ptr<base::SharedMemory> shared_state_shm); + // The lifetime of objects of this class is managed by a GpuChannelManager. // The GpuChannelManager destroy all the GpuChannels that they own when they // are destroyed. So a raw pointer is safe. @@ -226,7 +227,7 @@ class GPU_EXPORT GpuChannel // message loop. SyncPointManager* const sync_point_manager_; - scoped_ptr<IPC::SyncChannel> channel_; + std::unique_ptr<IPC::SyncChannel> channel_; IPC::Listener* unhandled_message_listener_; @@ -260,11 +261,6 @@ class GPU_EXPORT GpuChannel scoped_refptr<gles2::MailboxManager> mailbox_manager_; - scoped_refptr<gles2::SubscriptionRefSet> subscription_ref_set_; - - scoped_refptr<ValueStateMap> pending_valuebuffer_state_; - - gles2::DisallowedFeatures disallowed_features_; GpuWatchdog* const watchdog_; // Map of stream id to appropriate message queue. @@ -453,7 +449,7 @@ class GpuChannelMessageQueue bool enabled_; bool scheduled_; GpuChannel* const channel_; - std::deque<scoped_ptr<GpuChannelMessage>> channel_messages_; + std::deque<std::unique_ptr<GpuChannelMessage>> channel_messages_; mutable base::Lock channel_lock_; // The following are accessed on the IO thread only. @@ -464,7 +460,7 @@ class GpuChannelMessageQueue // It is reset when we transition to IDLE. base::TimeDelta max_preemption_time_; // This timer is used and runs tasks on the IO thread. - scoped_ptr<base::OneShotTimer> timer_; + std::unique_ptr<base::OneShotTimer> timer_; base::ThreadChecker io_thread_checker_; // Keeps track of sync point related state such as message order numbers. diff --git a/chromium/gpu/ipc/service/gpu_channel_manager.cc b/chromium/gpu/ipc/service/gpu_channel_manager.cc index 8a1f8a4dd08..04487ede931 100644 --- a/chromium/gpu/ipc/service/gpu_channel_manager.cc +++ b/chromium/gpu/ipc/service/gpu_channel_manager.cc @@ -8,12 +8,13 @@ #include <utility> #include "base/bind.h" +#include "base/command_line.h" #include "base/location.h" +#include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "gpu/command_buffer/common/sync_token.h" -#include "gpu/command_buffer/common/value_state.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_program_cache.h" @@ -26,6 +27,7 @@ #include "gpu/ipc/service/gpu_memory_manager.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_share_group.h" +#include "ui/gl/init/gl_factory.h" namespace gpu { @@ -52,6 +54,7 @@ GpuChannelManager::GpuChannelManager( : task_runner_(task_runner), io_task_runner_(io_task_runner), gpu_preferences_(gpu_preferences), + gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()), delegate_(delegate), watchdog_(watchdog), shutdown_event_(shutdown_event), @@ -113,42 +116,18 @@ void GpuChannelManager::RemoveChannel(int client_id) { gpu_channels_.erase(client_id); } -#if defined(OS_MACOSX) -void GpuChannelManager::AddBufferPresentedCallback( - int32_t surface_id, - const BufferPresentedCallback& callback) { - DCHECK(buffer_presented_callback_map_.find(surface_id) == - buffer_presented_callback_map_.end()); - buffer_presented_callback_map_[surface_id] = callback; -} - -void GpuChannelManager::RemoveBufferPresentedCallback(int32_t surface_id) { - auto it = buffer_presented_callback_map_.find(surface_id); - DCHECK(it != buffer_presented_callback_map_.end()); - buffer_presented_callback_map_.erase(it); -} - -void GpuChannelManager::BufferPresented(int32_t surface_id, - const base::TimeTicks& vsync_timebase, - const base::TimeDelta& vsync_interval) { - auto it = buffer_presented_callback_map_.find(surface_id); - if (it != buffer_presented_callback_map_.end()) - it->second.Run(surface_id, vsync_timebase, vsync_interval); -} -#endif - GpuChannel* GpuChannelManager::LookupChannel(int32_t client_id) const { const auto& it = gpu_channels_.find(client_id); return it != gpu_channels_.end() ? it->second : nullptr; } -scoped_ptr<GpuChannel> GpuChannelManager::CreateGpuChannel( +std::unique_ptr<GpuChannel> GpuChannelManager::CreateGpuChannel( int client_id, uint64_t client_tracing_id, bool preempts, bool allow_view_command_buffers, bool allow_real_time_streams) { - return make_scoped_ptr( + return base::WrapUnique( new GpuChannel(this, sync_point_manager(), watchdog_, share_group(), mailbox_manager(), preempts ? preemption_flag() : nullptr, preempts ? nullptr : preemption_flag(), task_runner_.get(), @@ -162,7 +141,7 @@ IPC::ChannelHandle GpuChannelManager::EstablishChannel( bool preempts, bool allow_view_command_buffers, bool allow_real_time_streams) { - scoped_ptr<GpuChannel> channel( + std::unique_ptr<GpuChannel> channel( CreateGpuChannel(client_id, client_tracing_id, preempts, allow_view_command_buffers, allow_real_time_streams)); IPC::ChannelHandle channel_handle = channel->Init(shutdown_event_); @@ -206,16 +185,6 @@ void GpuChannelManager::DestroyGpuMemoryBuffer( InternalDestroyGpuMemoryBuffer(id, client_id); } -void GpuChannelManager::UpdateValueState(int client_id, - unsigned int target, - const ValueState& state) { - // Only pass updated state to the channel corresponding to the - // render_widget_host where the event originated. - auto it = gpu_channels_.find(client_id); - if (it != gpu_channels_.end()) - it->second->HandleUpdateValueState(target, state); -} - void GpuChannelManager::PopulateShaderCache(const std::string& program_proto) { if (program_cache()) program_cache()->LoadProgram(program_proto); @@ -266,7 +235,7 @@ void GpuChannelManager::DestroyAllChannels() { gfx::GLSurface* GpuChannelManager::GetDefaultOffscreenSurface() { if (!default_offscreen_surface_.get()) { default_offscreen_surface_ = - gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size()); + gl::init::CreateOffscreenGLSurface(gfx::Size()); } return default_offscreen_surface_.get(); } diff --git a/chromium/gpu/ipc/service/gpu_channel_manager.h b/chromium/gpu/ipc/service/gpu_channel_manager.h index 9b39cda81be..8300fc75d33 100644 --- a/chromium/gpu/ipc/service/gpu_channel_manager.h +++ b/chromium/gpu/ipc/service/gpu_channel_manager.h @@ -8,16 +8,17 @@ #include <stdint.h> #include <deque> +#include <memory> #include <string> #include <vector> #include "base/containers/scoped_ptr_hash_map.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "build/build_config.h" #include "gpu/command_buffer/common/constants.h" +#include "gpu/config/gpu_driver_bug_workarounds.h" #include "gpu/gpu_export.h" #include "gpu/ipc/service/gpu_memory_manager.h" #include "ui/gfx/gpu_memory_buffer.h" @@ -25,11 +26,6 @@ #include "ui/gl/gl_surface.h" #include "url/gurl.h" -#if defined(OS_MACOSX) -#include "base/callback.h" -#include "base/containers/hash_tables.h" -#endif - namespace base { class WaitableEvent; } @@ -44,7 +40,6 @@ class PreemptionFlag; class SyncPointClient; class SyncPointManager; struct SyncToken; -union ValueState; namespace gles2 { class FramebufferCompletenessCache; class MailboxManager; @@ -68,11 +63,6 @@ class GpuWatchdog; // browser process to them based on the corresponding renderer ID. class GPU_EXPORT GpuChannelManager { public: -#if defined(OS_MACOSX) - typedef base::Callback< - void(int32_t, const base::TimeTicks&, const base::TimeDelta&)> - BufferPresentedCallback; -#endif GpuChannelManager(const GpuPreferences& gpu_preferences, GpuChannelManagerDelegate* delegate, GpuWatchdog* watchdog, @@ -95,9 +85,6 @@ class GPU_EXPORT GpuChannelManager { void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id, const SyncToken& sync_token); - void UpdateValueState(int client_id, - unsigned int target, - const ValueState& state); #if defined(OS_ANDROID) void WakeUpGpu(); #endif @@ -109,18 +96,12 @@ class GPU_EXPORT GpuChannelManager { void LoseAllContexts(); void MaybeExitOnContextLost(); -#if defined(OS_MACOSX) - void AddBufferPresentedCallback(int32_t routing_id, - const BufferPresentedCallback& callback); - void RemoveBufferPresentedCallback(int32_t routing_id); - void BufferPresented(int32_t surface_id, - const base::TimeTicks& vsync_timebase, - const base::TimeDelta& vsync_interval); -#endif - const GpuPreferences& gpu_preferences() const { return gpu_preferences_; } + const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds() const { + return gpu_driver_bug_workarounds_; + } gles2::ProgramCache* program_cache(); gles2::ShaderTranslatorCache* shader_translator_cache(); gles2::FramebufferCompletenessCache* framebuffer_completeness_cache(); @@ -152,7 +133,7 @@ class GPU_EXPORT GpuChannelManager { } protected: - virtual scoped_ptr<GpuChannel> CreateGpuChannel( + virtual std::unique_ptr<GpuChannel> CreateGpuChannel( int client_id, uint64_t client_tracing_id, bool preempts, @@ -177,7 +158,7 @@ class GPU_EXPORT GpuChannelManager { // These objects manage channels to individual renderer processes there is // one channel for each renderer process that has connected to this GPU // process. - base::ScopedPtrHashMap<int32_t, scoped_ptr<GpuChannel>> gpu_channels_; + base::ScopedPtrHashMap<int32_t, std::unique_ptr<GpuChannel>> gpu_channels_; private: void InternalDestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id); @@ -189,12 +170,9 @@ class GPU_EXPORT GpuChannelManager { #endif const GpuPreferences& gpu_preferences_; + GpuDriverBugWorkarounds gpu_driver_bug_workarounds_; GpuChannelManagerDelegate* const delegate_; -#if defined(OS_MACOSX) - base::hash_map<int32_t, BufferPresentedCallback> - buffer_presented_callback_map_; -#endif GpuWatchdog* watchdog_; @@ -206,8 +184,8 @@ class GPU_EXPORT GpuChannelManager { GpuMemoryManager gpu_memory_manager_; // SyncPointManager guaranteed to outlive running MessageLoop. SyncPointManager* sync_point_manager_; - scoped_ptr<SyncPointClient> sync_point_client_waiter_; - scoped_ptr<gles2::ProgramCache> program_cache_; + std::unique_ptr<SyncPointClient> sync_point_client_waiter_; + std::unique_ptr<gles2::ProgramCache> program_cache_; scoped_refptr<gles2::ShaderTranslatorCache> shader_translator_cache_; scoped_refptr<gles2::FramebufferCompletenessCache> framebuffer_completeness_cache_; diff --git a/chromium/gpu/ipc/service/gpu_channel_manager_delegate.h b/chromium/gpu/ipc/service/gpu_channel_manager_delegate.h index 83f2dc11526..3e9da6b93ed 100644 --- a/chromium/gpu/ipc/service/gpu_channel_manager_delegate.h +++ b/chromium/gpu/ipc/service/gpu_channel_manager_delegate.h @@ -8,12 +8,6 @@ #include "gpu/command_buffer/common/constants.h" #include "gpu/ipc/common/surface_handle.h" -#if defined(OS_MACOSX) -#include "ui/base/cocoa/remote_layer_api.h" -#include "ui/events/latency_info.h" -#include "ui/gfx/mac/io_surface.h" -#endif - class GURL; namespace IPC { @@ -26,10 +20,6 @@ struct GPUMemoryUmaStats; class GpuChannelManagerDelegate { public: - // Tells the delegate that a context has subscribed to a new target and - // the browser should start sending the corresponding information - virtual void AddSubscription(int32_t client_id, unsigned int target) = 0; - // Tells the delegate that an offscreen context was created for the provided // |active_url|. virtual void DidCreateOffscreenContext(const GURL& active_url) = 0; @@ -49,10 +39,6 @@ class GpuChannelManagerDelegate { // Tells the delegate about GPU memory usage statistics for UMA logging. virtual void GpuMemoryUmaStats(const GPUMemoryUmaStats& params) = 0; - // Tells the delegate that no contexts are subscribed to the target anymore - // so the delegate should stop sending the corresponding information. - virtual void RemoveSubscription(int32_t client_id, unsigned int target) = 0; - // Tells the delegate to cache the given shader information in persistent // storage. The embedder is expected to repopulate the in-memory cache through // the respective GpuChannelManager API. @@ -60,17 +46,6 @@ class GpuChannelManagerDelegate { const std::string& key, const std::string& shader) = 0; -#if defined(OS_MACOSX) - // Tells the delegate that an accelerated surface has swapped. - virtual void SendAcceleratedSurfaceBuffersSwapped( - int32_t surface_id, - CAContextID ca_context_id, - const gfx::ScopedRefCountedIOSurfaceMachPort& io_surface, - const gfx::Size& size, - float scale_factor, - std::vector<ui::LatencyInfo> latency_info) = 0; -#endif - #if defined(OS_WIN) virtual void SendAcceleratedSurfaceCreatedChildWindow( SurfaceHandle parent_window, diff --git a/chromium/gpu/ipc/service/gpu_channel_manager_unittest.cc b/chromium/gpu/ipc/service/gpu_channel_manager_unittest.cc index aa13068e265..eddcf8cb979 100644 --- a/chromium/gpu/ipc/service/gpu_channel_manager_unittest.cc +++ b/chromium/gpu/ipc/service/gpu_channel_manager_unittest.cc @@ -5,15 +5,11 @@ #include <stddef.h> #include <stdint.h> -#include "gpu/command_buffer/common/value_state.h" #include "gpu/command_buffer/service/gl_utils.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" #include "gpu/ipc/service/gpu_channel.h" #include "gpu/ipc/service/gpu_channel_manager.h" #include "gpu/ipc/service/gpu_channel_test_common.h" -using gpu::gles2::ValuebufferManager; - namespace gpu { class GpuChannelManagerTest : public GpuChannelTestCommon { @@ -39,62 +35,4 @@ TEST_F(GpuChannelManagerTest, EstablishChannel) { EXPECT_EQ(channel_handle.name, channel->channel_id()); } -TEST_F(GpuChannelManagerTest, SecureValueStateForwarding) { - int32_t kClientId1 = 111; - uint64_t kClientTracingId1 = 11111; - int32_t kClientId2 = 222; - uint64_t kClientTracingId2 = 22222; - ValueState value_state1; - value_state1.int_value[0] = 1111; - value_state1.int_value[1] = 0; - value_state1.int_value[2] = 0; - value_state1.int_value[3] = 0; - ValueState value_state2; - value_state2.int_value[0] = 3333; - value_state2.int_value[1] = 0; - value_state2.int_value[2] = 0; - value_state2.int_value[3] = 0; - - ASSERT_TRUE(channel_manager()); - - // Initialize gpu channels - channel_manager()->EstablishChannel(kClientId1, kClientTracingId1, - false /* preempts */, - false /* allow_view_command_buffer */, - false /* allow_real_time_streams */); - GpuChannel* channel1 = channel_manager()->LookupChannel(kClientId1); - ASSERT_TRUE(channel1); - - channel_manager()->EstablishChannel(kClientId2, kClientTracingId2, - false /* preempts */, - false /* allow_view_command_buffers */, - false /* allow_real_time_streams */); - GpuChannel* channel2 = channel_manager()->LookupChannel(kClientId2); - ASSERT_TRUE(channel2); - - EXPECT_NE(channel1, channel2); - - // Make sure value states are only accessible by proper channels - channel_manager()->UpdateValueState(kClientId1, GL_MOUSE_POSITION_CHROMIUM, - value_state1); - channel_manager()->UpdateValueState(kClientId2, GL_MOUSE_POSITION_CHROMIUM, - value_state2); - - const ValueStateMap* pending_value_buffer_state1 = - channel1->pending_valuebuffer_state(); - const ValueStateMap* pending_value_buffer_state2 = - channel2->pending_valuebuffer_state(); - EXPECT_NE(pending_value_buffer_state1, pending_value_buffer_state2); - - const ValueState* state1 = - pending_value_buffer_state1->GetState(GL_MOUSE_POSITION_CHROMIUM); - const ValueState* state2 = - pending_value_buffer_state2->GetState(GL_MOUSE_POSITION_CHROMIUM); - EXPECT_NE(state1, state2); - - EXPECT_EQ(state1->int_value[0], value_state1.int_value[0]); - EXPECT_EQ(state2->int_value[0], value_state2.int_value[0]); - EXPECT_NE(state1->int_value[0], state2->int_value[0]); -} - } // namespace gpu diff --git a/chromium/gpu/ipc/service/gpu_channel_test_common.cc b/chromium/gpu/ipc/service/gpu_channel_test_common.cc index ae2021245fb..46ac857a7db 100644 --- a/chromium/gpu/ipc/service/gpu_channel_test_common.cc +++ b/chromium/gpu/ipc/service/gpu_channel_test_common.cc @@ -4,8 +4,9 @@ #include "gpu/ipc/service/gpu_channel_test_common.h" +#include "base/memory/ptr_util.h" #include "base/test/test_simple_task_runner.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "gpu/command_buffer/service/sync_point_manager.h" #include "gpu/ipc/service/gpu_channel_manager_delegate.h" #include "ipc/ipc_test_sink.h" @@ -19,9 +20,6 @@ TestGpuChannelManagerDelegate::~TestGpuChannelManagerDelegate() {} void TestGpuChannelManagerDelegate::SetActiveURL(const GURL& url) {} -void TestGpuChannelManagerDelegate::AddSubscription(int32_t client_id, - unsigned int target) {} - void TestGpuChannelManagerDelegate::DidCreateOffscreenContext( const GURL& active_url) {} @@ -38,24 +36,11 @@ void TestGpuChannelManagerDelegate::DidLoseContext( void TestGpuChannelManagerDelegate::GpuMemoryUmaStats( const GPUMemoryUmaStats& params) {} -void TestGpuChannelManagerDelegate::RemoveSubscription(int32_t client_id, - unsigned int target) {} - void TestGpuChannelManagerDelegate::StoreShaderToDisk( int32_t client_id, const std::string& key, const std::string& shader) {} -#if defined(OS_MACOSX) -void TestGpuChannelManagerDelegate::SendAcceleratedSurfaceBuffersSwapped( - int32_t surface_id, - CAContextID ca_context_id, - const gfx::ScopedRefCountedIOSurfaceMachPort& io_surface, - const gfx::Size& size, - float scale_factor, - std::vector<ui::LatencyInfo> latency_info) {} -#endif - #if defined(OS_WIN) void TestGpuChannelManagerDelegate::SendAcceleratedSurfaceCreatedChildWindow( SurfaceHandle parent_window, @@ -84,13 +69,13 @@ TestGpuChannelManager::~TestGpuChannelManager() { gpu_channels_.clear(); } -scoped_ptr<GpuChannel> TestGpuChannelManager::CreateGpuChannel( +std::unique_ptr<GpuChannel> TestGpuChannelManager::CreateGpuChannel( int client_id, uint64_t client_tracing_id, bool preempts, bool allow_view_command_buffers, bool allow_real_time_streams) { - return make_scoped_ptr(new TestGpuChannel( + return base::WrapUnique(new TestGpuChannel( this, sync_point_manager(), share_group(), mailbox_manager(), preempts ? preemption_flag() : nullptr, preempts ? nullptr : preemption_flag(), task_runner_.get(), @@ -149,21 +134,24 @@ GpuChannelTestCommon::GpuChannelTestCommon() : task_runner_(new base::TestSimpleTaskRunner), io_task_runner_(new base::TestSimpleTaskRunner), sync_point_manager_(new SyncPointManager(false)), - channel_manager_delegate_(new TestGpuChannelManagerDelegate()), - channel_manager_( - new TestGpuChannelManager(gpu_preferences_, - channel_manager_delegate_.get(), - task_runner_.get(), - io_task_runner_.get(), - sync_point_manager_.get(), - nullptr)) {} + channel_manager_delegate_(new TestGpuChannelManagerDelegate()) {} GpuChannelTestCommon::~GpuChannelTestCommon() { - // Destroying channels causes tasks to run on the IO task runner. - channel_manager_ = nullptr; // Clear pending tasks to avoid refptr cycles that get flagged by ASAN. task_runner_->ClearPendingTasks(); io_task_runner_->ClearPendingTasks(); } +void GpuChannelTestCommon::SetUp() { + channel_manager_.reset(new TestGpuChannelManager( + gpu_preferences_, channel_manager_delegate_.get(), task_runner_.get(), + io_task_runner_.get(), sync_point_manager_.get(), nullptr)); +} + +void GpuChannelTestCommon::TearDown() { + // Destroying channels causes tasks to run on the IO task runner. + channel_manager_ = nullptr; +} + + } // namespace gpu diff --git a/chromium/gpu/ipc/service/gpu_channel_test_common.h b/chromium/gpu/ipc/service/gpu_channel_test_common.h index 70918b845cf..0f7d3a4b98b 100644 --- a/chromium/gpu/ipc/service/gpu_channel_test_common.h +++ b/chromium/gpu/ipc/service/gpu_channel_test_common.h @@ -4,7 +4,8 @@ #include <stdint.h> -#include "base/memory/scoped_ptr.h" +#include <memory> + #include "gpu/command_buffer/service/gpu_preferences.h" #include "gpu/ipc/service/gpu_channel.h" #include "gpu/ipc/service/gpu_channel_manager.h" @@ -34,7 +35,6 @@ class TestGpuChannelManagerDelegate : public GpuChannelManagerDelegate { private: // GpuChannelManagerDelegate implementation: void SetActiveURL(const GURL& url) override; - void AddSubscription(int32_t client_id, unsigned int target) override; void DidCreateOffscreenContext(const GURL& active_url) override; void DidDestroyChannel(int client_id) override; void DidDestroyOffscreenContext(const GURL& active_url) override; @@ -42,19 +42,9 @@ class TestGpuChannelManagerDelegate : public GpuChannelManagerDelegate { error::ContextLostReason reason, const GURL& active_url) override; void GpuMemoryUmaStats(const GPUMemoryUmaStats& params) override; - void RemoveSubscription(int32_t client_id, unsigned int target) override; void StoreShaderToDisk(int32_t client_id, const std::string& key, const std::string& shader) override; -#if defined(OS_MACOSX) - void SendAcceleratedSurfaceBuffersSwapped( - int32_t surface_id, - CAContextID ca_context_id, - const gfx::ScopedRefCountedIOSurfaceMachPort& io_surface, - const gfx::Size& size, - float scale_factor, - std::vector<ui::LatencyInfo> latency_info) override; -#endif #if defined(OS_WIN) void SendAcceleratedSurfaceCreatedChildWindow( SurfaceHandle parent_window, @@ -75,7 +65,7 @@ class TestGpuChannelManager : public GpuChannelManager { ~TestGpuChannelManager() override; protected: - scoped_ptr<GpuChannel> CreateGpuChannel( + std::unique_ptr<GpuChannel> CreateGpuChannel( int client_id, uint64_t client_tracing_id, bool preempts, @@ -116,6 +106,9 @@ class GpuChannelTestCommon : public testing::Test { GpuChannelTestCommon(); ~GpuChannelTestCommon() override; + void SetUp() override; + void TearDown() override; + protected: GpuChannelManager* channel_manager() { return channel_manager_.get(); } TestGpuChannelManagerDelegate* channel_manager_delegate() { @@ -127,9 +120,9 @@ class GpuChannelTestCommon : public testing::Test { GpuPreferences gpu_preferences_; scoped_refptr<base::TestSimpleTaskRunner> task_runner_; scoped_refptr<base::TestSimpleTaskRunner> io_task_runner_; - scoped_ptr<SyncPointManager> sync_point_manager_; - scoped_ptr<TestGpuChannelManagerDelegate> channel_manager_delegate_; - scoped_ptr<GpuChannelManager> channel_manager_; + std::unique_ptr<SyncPointManager> sync_point_manager_; + std::unique_ptr<TestGpuChannelManagerDelegate> channel_manager_delegate_; + std::unique_ptr<GpuChannelManager> channel_manager_; }; } // namespace gpu diff --git a/chromium/gpu/ipc/service/gpu_channel_unittest.cc b/chromium/gpu/ipc/service/gpu_channel_unittest.cc index 71c9d3a7dd7..591519f823a 100644 --- a/chromium/gpu/ipc/service/gpu_channel_unittest.cc +++ b/chromium/gpu/ipc/service/gpu_channel_unittest.cc @@ -4,20 +4,141 @@ #include <stdint.h> -#include "base/test/test_simple_task_runner.h" +#include "base/memory/shared_memory.h" +#include "base/test/test_message_loop.h" #include "gpu/ipc/common/gpu_messages.h" #include "gpu/ipc/service/gpu_channel.h" #include "gpu/ipc/service/gpu_channel_manager.h" #include "gpu/ipc/service/gpu_channel_test_common.h" #include "ipc/ipc_test_sink.h" +#include "ui/gl/gl_context_stub_with_extensions.h" +#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface_stub.h" +#include "ui/gl/test/gl_surface_test_support.h" namespace gpu { +static constexpr int kFakeTextureIds[] = {1, 2}; + class GpuChannelTest : public GpuChannelTestCommon { public: GpuChannelTest() : GpuChannelTestCommon() {} ~GpuChannelTest() override {} + void SetUp() override { + // We need GL bindings to actually initialize command buffers. + gfx::SetGLGetProcAddressProc(gfx::MockGLInterface::GetGLProcAddress); + gfx::GLSurfaceTestSupport::InitializeOneOffWithMockBindings(); + + // This GLInterface is a stub for the gl driver. + gl_interface_.reset(new testing::NiceMock<gfx::MockGLInterface>); + gfx::MockGLInterface::SetGLInterface(gl_interface_.get()); + + using testing::AnyNumber; + using testing::NotNull; + using testing::Return; + using testing::SetArgPointee; + using testing::SetArrayArgument; + // We need it to return non-null strings in order for things to not crash. + EXPECT_CALL(*gl_interface_, GetString(GL_RENDERER)) + .Times(AnyNumber()) + .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>(""))); + EXPECT_CALL(*gl_interface_, GetString(GL_VERSION)) + .Times(AnyNumber()) + .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>("2.0"))); + EXPECT_CALL(*gl_interface_, GetString(GL_EXTENSIONS)) + .Times(AnyNumber()) + .WillRepeatedly(Return( + reinterpret_cast<const GLubyte*>("GL_EXT_framebuffer_object "))); + // And we need some values to be large enough to initialize ContextGroup. + EXPECT_CALL(*gl_interface_, + GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(512)); + EXPECT_CALL(*gl_interface_, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(8)); + EXPECT_CALL(*gl_interface_, + GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(8)); + EXPECT_CALL(*gl_interface_, + GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(8)); + EXPECT_CALL(*gl_interface_, GetIntegerv(GL_MAX_TEXTURE_SIZE, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(2048)); + EXPECT_CALL(*gl_interface_, + GetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(2048)); + EXPECT_CALL(*gl_interface_, GetIntegerv(GL_MAX_VARYING_FLOATS, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(8 * 4)); + EXPECT_CALL(*gl_interface_, + GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(128 * 4)); + EXPECT_CALL(*gl_interface_, + GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(16 * 4)); + EXPECT_CALL(*gl_interface_, + GetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(32)); + EXPECT_CALL(*gl_interface_, GetIntegerv(GL_MAX_VIEWPORT_DIMS, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(1024 << 8)); + EXPECT_CALL(*gl_interface_, GetIntegerv(GL_ALPHA_BITS, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(8)); + EXPECT_CALL(*gl_interface_, GetIntegerv(GL_DEPTH_BITS, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(24)); + EXPECT_CALL(*gl_interface_, GetIntegerv(GL_STENCIL_BITS, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(8)); + // Allow generating non-0 resources so code does not DCHECK. + EXPECT_CALL(*gl_interface_, GenFramebuffersEXT(1, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly(SetArgPointee<1>(1)); + EXPECT_CALL(*gl_interface_, GenTextures(1, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly( + SetArrayArgument<1>(kFakeTextureIds, kFakeTextureIds + 1)); + EXPECT_CALL(*gl_interface_, GenTextures(2, NotNull())) + .Times(AnyNumber()) + .WillRepeatedly( + SetArrayArgument<1>(kFakeTextureIds, kFakeTextureIds + 2)); + // And errors should be squashed. + EXPECT_CALL(*gl_interface_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) + .Times(AnyNumber()) + .WillRepeatedly(Return(GL_FRAMEBUFFER_COMPLETE)); + + // Dynamic bindings must be set up for the GLES2DecoderImpl, which requires + // a GLContext. Use a GLContextStub which does nothing but call through to + // our |gl_interface| above. + stub_context_ = new gfx::GLContextStub; + stub_surface_ = new gfx::GLSurfaceStub; + stub_context_->MakeCurrent(stub_surface_.get()); + gfx::GLSurfaceTestSupport::InitializeDynamicMockBindings( + stub_context_.get()); + + GpuChannelTestCommon::SetUp(); + } + + void TearDown() override { + GpuChannelTestCommon::TearDown(); + + stub_context_ = nullptr; + stub_surface_ = nullptr; + gfx::MockGLInterface::SetGLInterface(nullptr); + gfx::ClearGLBindings(); + gl_interface_ = nullptr; + } + GpuChannel* CreateChannel(int32_t client_id, bool allow_view_command_buffers, bool allow_real_time_streams) { @@ -31,18 +152,23 @@ class GpuChannelTest : public GpuChannelTestCommon { void HandleMessage(GpuChannel* channel, IPC::Message* msg) { TestGpuChannel* test_channel = static_cast<TestGpuChannel*>(channel); - test_channel->HandleMessageForTesting(*msg); + // Some IPCs (such as GpuCommandBufferMsg_Initialize) will generate more + // delayed responses, drop those if they exist. + test_channel->sink()->ClearMessages(); + + test_channel->HandleMessageForTesting(*msg); if (msg->is_sync()) { const IPC::Message* reply_msg = test_channel->sink()->GetMessageAt(0); - ASSERT_TRUE(reply_msg); + CHECK(reply_msg); + CHECK(!reply_msg->is_reply_error()); - EXPECT_TRUE(IPC::SyncMessage::IsMessageReplyTo( + CHECK(IPC::SyncMessage::IsMessageReplyTo( *reply_msg, IPC::SyncMessage::GetMessageId(*msg))); IPC::MessageReplyDeserializer* deserializer = static_cast<IPC::SyncMessage*>(msg)->GetReplyDeserializer(); - ASSERT_TRUE(deserializer); + CHECK(deserializer); deserializer->SerializeOutputParameters(*reply_msg); delete deserializer; @@ -52,11 +178,25 @@ class GpuChannelTest : public GpuChannelTestCommon { delete msg; } + + base::SharedMemoryHandle GetSharedHandle() { + base::SharedMemory shared_memory; + shared_memory.CreateAnonymous(10); + base::SharedMemoryHandle shmem_handle; + shared_memory.ShareToProcess(base::GetCurrentProcessHandle(), + &shmem_handle); + return shmem_handle; + } + + private: + base::TestMessageLoop message_loop_; + std::unique_ptr<gfx::MockGLInterface> gl_interface_; + scoped_refptr<gfx::GLContextStub> stub_context_; + scoped_refptr<gfx::GLSurfaceStub> stub_surface_; }; #if defined(OS_WIN) -const SurfaceHandle kFakeSurfaceHandle = - reinterpret_cast<SurfaceHandle>(1); +const SurfaceHandle kFakeSurfaceHandle = reinterpret_cast<SurfaceHandle>(1); #else const SurfaceHandle kFakeSurfaceHandle = 1; #endif @@ -73,17 +213,20 @@ TEST_F(GpuChannelTest, CreateViewCommandBufferAllowed) { int32_t kRouteId = 1; GPUCreateCommandBufferConfig init_params; + init_params.surface_handle = surface_handle; + init_params.size = gfx::Size(); init_params.share_group_id = MSG_ROUTING_NONE; init_params.stream_id = 0; init_params.stream_priority = GpuStreamPriority::NORMAL; - init_params.attribs = std::vector<int>(); + init_params.attribs = gles2::ContextCreationAttribHelper(); init_params.active_url = GURL(); init_params.gpu_preference = gfx::PreferIntegratedGpu; - bool succeeded = false; + bool result = false; + gpu::Capabilities capabilities; HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer( - surface_handle, gfx::Size(), init_params, kRouteId, - &succeeded)); - EXPECT_TRUE(succeeded); + init_params, kRouteId, GetSharedHandle(), &result, + &capabilities)); + EXPECT_TRUE(result); GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId); ASSERT_TRUE(stub); @@ -101,17 +244,20 @@ TEST_F(GpuChannelTest, CreateViewCommandBufferDisallowed) { int32_t kRouteId = 1; GPUCreateCommandBufferConfig init_params; + init_params.surface_handle = surface_handle; + init_params.size = gfx::Size(); init_params.share_group_id = MSG_ROUTING_NONE; init_params.stream_id = 0; init_params.stream_priority = GpuStreamPriority::NORMAL; - init_params.attribs = std::vector<int>(); + init_params.attribs = gles2::ContextCreationAttribHelper(); init_params.active_url = GURL(); init_params.gpu_preference = gfx::PreferIntegratedGpu; - bool succeeded = false; + bool result = false; + gpu::Capabilities capabilities; HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer( - surface_handle, gfx::Size(), init_params, kRouteId, - &succeeded)); - EXPECT_FALSE(succeeded); + init_params, kRouteId, GetSharedHandle(), &result, + &capabilities)); + EXPECT_FALSE(result); GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId); EXPECT_FALSE(stub); @@ -124,17 +270,20 @@ TEST_F(GpuChannelTest, CreateOffscreenCommandBuffer) { int32_t kRouteId = 1; GPUCreateCommandBufferConfig init_params; + init_params.surface_handle = kNullSurfaceHandle; + init_params.size = gfx::Size(1, 1); init_params.share_group_id = MSG_ROUTING_NONE; init_params.stream_id = 0; init_params.stream_priority = GpuStreamPriority::NORMAL; - init_params.attribs = std::vector<int>(); + init_params.attribs = gles2::ContextCreationAttribHelper(); init_params.active_url = GURL(); init_params.gpu_preference = gfx::PreferIntegratedGpu; - bool succeeded = false; + bool result = false; + gpu::Capabilities capabilities; HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer( - kNullSurfaceHandle, gfx::Size(1, 1), - init_params, kRouteId, &succeeded)); - EXPECT_TRUE(succeeded); + init_params, kRouteId, GetSharedHandle(), &result, + &capabilities)); + EXPECT_TRUE(result); GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId); EXPECT_TRUE(stub); @@ -149,17 +298,20 @@ TEST_F(GpuChannelTest, IncompatibleStreamIds) { int32_t kRouteId1 = 1; int32_t kStreamId1 = 1; GPUCreateCommandBufferConfig init_params; + init_params.surface_handle = kNullSurfaceHandle; + init_params.size = gfx::Size(1, 1); init_params.share_group_id = MSG_ROUTING_NONE; init_params.stream_id = kStreamId1; init_params.stream_priority = GpuStreamPriority::NORMAL; - init_params.attribs = std::vector<int>(); + init_params.attribs = gles2::ContextCreationAttribHelper(); init_params.active_url = GURL(); init_params.gpu_preference = gfx::PreferIntegratedGpu; - bool succeeded = false; + bool result = false; + gpu::Capabilities capabilities; HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer( - kNullSurfaceHandle, gfx::Size(1, 1), - init_params, kRouteId1, &succeeded)); - EXPECT_TRUE(succeeded); + init_params, kRouteId1, GetSharedHandle(), &result, + &capabilities)); + EXPECT_TRUE(result); GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId1); EXPECT_TRUE(stub); @@ -171,14 +323,13 @@ TEST_F(GpuChannelTest, IncompatibleStreamIds) { init_params.share_group_id = kRouteId1; init_params.stream_id = kStreamId2; init_params.stream_priority = GpuStreamPriority::NORMAL; - init_params.attribs = std::vector<int>(); + init_params.attribs = gles2::ContextCreationAttribHelper(); init_params.active_url = GURL(); init_params.gpu_preference = gfx::PreferIntegratedGpu; - succeeded = false; HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer( - kNullSurfaceHandle, gfx::Size(1, 1), - init_params, kRouteId2, &succeeded)); - EXPECT_FALSE(succeeded); + init_params, kRouteId2, GetSharedHandle(), &result, + &capabilities)); + EXPECT_FALSE(result); stub = channel->LookupCommandBuffer(kRouteId2); EXPECT_FALSE(stub); @@ -194,17 +345,20 @@ TEST_F(GpuChannelTest, StreamLifetime) { int32_t kStreamId1 = 1; GpuStreamPriority kStreamPriority1 = GpuStreamPriority::NORMAL; GPUCreateCommandBufferConfig init_params; + init_params.surface_handle = kNullSurfaceHandle; + init_params.size = gfx::Size(1, 1); init_params.share_group_id = MSG_ROUTING_NONE; init_params.stream_id = kStreamId1; init_params.stream_priority = kStreamPriority1; - init_params.attribs = std::vector<int>(); + init_params.attribs = gles2::ContextCreationAttribHelper(); init_params.active_url = GURL(); init_params.gpu_preference = gfx::PreferIntegratedGpu; - bool succeeded = false; + bool result = false; + gpu::Capabilities capabilities; HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer( - kNullSurfaceHandle, gfx::Size(1, 1), - init_params, kRouteId1, &succeeded)); - EXPECT_TRUE(succeeded); + init_params, kRouteId1, GetSharedHandle(), &result, + &capabilities)); + EXPECT_TRUE(result); GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId1); EXPECT_TRUE(stub); @@ -221,14 +375,13 @@ TEST_F(GpuChannelTest, StreamLifetime) { init_params.share_group_id = MSG_ROUTING_NONE; init_params.stream_id = kStreamId2; init_params.stream_priority = kStreamPriority2; - init_params.attribs = std::vector<int>(); + init_params.attribs = gles2::ContextCreationAttribHelper(); init_params.active_url = GURL(); init_params.gpu_preference = gfx::PreferIntegratedGpu; - succeeded = false; HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer( - kNullSurfaceHandle, gfx::Size(1, 1), - init_params, kRouteId2, &succeeded)); - EXPECT_TRUE(succeeded); + init_params, kRouteId2, GetSharedHandle(), &result, + &capabilities)); + EXPECT_TRUE(result); stub = channel->LookupCommandBuffer(kRouteId2); EXPECT_TRUE(stub); @@ -245,17 +398,20 @@ TEST_F(GpuChannelTest, RealTimeStreamsDisallowed) { int32_t kStreamId = 1; GpuStreamPriority kStreamPriority = GpuStreamPriority::REAL_TIME; GPUCreateCommandBufferConfig init_params; + init_params.surface_handle = kNullSurfaceHandle; + init_params.size = gfx::Size(1, 1); init_params.share_group_id = MSG_ROUTING_NONE; init_params.stream_id = kStreamId; init_params.stream_priority = kStreamPriority; - init_params.attribs = std::vector<int>(); + init_params.attribs = gles2::ContextCreationAttribHelper(); init_params.active_url = GURL(); init_params.gpu_preference = gfx::PreferIntegratedGpu; - bool succeeded = false; + bool result = false; + gpu::Capabilities capabilities; HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer( - kNullSurfaceHandle, gfx::Size(1, 1), - init_params, kRouteId, &succeeded)); - EXPECT_FALSE(succeeded); + init_params, kRouteId, GetSharedHandle(), &result, + &capabilities)); + EXPECT_FALSE(result); GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId); EXPECT_FALSE(stub); @@ -272,20 +428,109 @@ TEST_F(GpuChannelTest, RealTimeStreamsAllowed) { int32_t kStreamId = 1; GpuStreamPriority kStreamPriority = GpuStreamPriority::REAL_TIME; GPUCreateCommandBufferConfig init_params; + init_params.surface_handle = kNullSurfaceHandle; + init_params.size = gfx::Size(1, 1); init_params.share_group_id = MSG_ROUTING_NONE; init_params.stream_id = kStreamId; init_params.stream_priority = kStreamPriority; - init_params.attribs = std::vector<int>(); + init_params.attribs = gles2::ContextCreationAttribHelper(); init_params.active_url = GURL(); init_params.gpu_preference = gfx::PreferIntegratedGpu; - bool succeeded = false; + bool result = false; + gpu::Capabilities capabilities; HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer( - kNullSurfaceHandle, gfx::Size(1, 1), - init_params, kRouteId, &succeeded)); - EXPECT_TRUE(succeeded); + init_params, kRouteId, GetSharedHandle(), &result, + &capabilities)); + EXPECT_TRUE(result); GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId); EXPECT_TRUE(stub); } +TEST_F(GpuChannelTest, CreateFailsIfSharedContextIsLost) { + int32_t kClientId = 1; + GpuChannel* channel = CreateChannel(kClientId, false, false); + ASSERT_TRUE(channel); + + // Create first context, we will share this one. + int32_t kSharedRouteId = 1; + { + SCOPED_TRACE("kSharedRouteId"); + GPUCreateCommandBufferConfig init_params; + init_params.surface_handle = kNullSurfaceHandle; + init_params.size = gfx::Size(1, 1); + init_params.share_group_id = MSG_ROUTING_NONE; + init_params.stream_id = 0; + init_params.stream_priority = GpuStreamPriority::NORMAL; + init_params.attribs = gles2::ContextCreationAttribHelper(); + init_params.active_url = GURL(); + init_params.gpu_preference = gfx::PreferIntegratedGpu; + bool result = false; + gpu::Capabilities capabilities; + HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer( + init_params, kSharedRouteId, GetSharedHandle(), + &result, &capabilities)); + EXPECT_TRUE(result); + } + EXPECT_TRUE(channel->LookupCommandBuffer(kSharedRouteId)); + + // This context shares with the first one, this should be possible. + int32_t kFriendlyRouteId = 2; + { + SCOPED_TRACE("kFriendlyRouteId"); + GPUCreateCommandBufferConfig init_params; + init_params.surface_handle = kNullSurfaceHandle; + init_params.size = gfx::Size(1, 1); + init_params.share_group_id = kSharedRouteId; + init_params.stream_id = 0; + init_params.stream_priority = GpuStreamPriority::NORMAL; + init_params.attribs = gles2::ContextCreationAttribHelper(); + init_params.active_url = GURL(); + init_params.gpu_preference = gfx::PreferIntegratedGpu; + bool result = false; + gpu::Capabilities capabilities; + HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer( + init_params, kFriendlyRouteId, GetSharedHandle(), + &result, &capabilities)); + EXPECT_TRUE(result); + } + EXPECT_TRUE(channel->LookupCommandBuffer(kFriendlyRouteId)); + + // The shared context is lost. + channel->LookupCommandBuffer(kSharedRouteId)->MarkContextLost(); + + // Meanwhile another context is being made pointing to the shared one. This + // should fail. + int32_t kAnotherRouteId = 3; + { + SCOPED_TRACE("kAnotherRouteId"); + GPUCreateCommandBufferConfig init_params; + init_params.surface_handle = kNullSurfaceHandle; + init_params.size = gfx::Size(1, 1); + init_params.share_group_id = kSharedRouteId; + init_params.stream_id = 0; + init_params.stream_priority = GpuStreamPriority::NORMAL; + init_params.attribs = gles2::ContextCreationAttribHelper(); + init_params.active_url = GURL(); + init_params.gpu_preference = gfx::PreferIntegratedGpu; + bool result = false; + gpu::Capabilities capabilities; + HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer( + init_params, kAnotherRouteId, GetSharedHandle(), + &result, &capabilities)); + EXPECT_FALSE(result); + } + EXPECT_FALSE(channel->LookupCommandBuffer(kAnotherRouteId)); + + // The lost context is still around though (to verify the failure happened due + // to the shared context being lost, not due to it being deleted). + EXPECT_TRUE(channel->LookupCommandBuffer(kSharedRouteId)); + + // Destroy the command buffers we initialized before destoying GL. + HandleMessage(channel, + new GpuChannelMsg_DestroyCommandBuffer(kFriendlyRouteId)); + HandleMessage(channel, + new GpuChannelMsg_DestroyCommandBuffer(kSharedRouteId)); +} + } // namespace gpu diff --git a/chromium/gpu/ipc/service/gpu_command_buffer_stub.cc b/chromium/gpu/ipc/service/gpu_command_buffer_stub.cc index f6f52ff8613..3c27b71f9eb 100644 --- a/chromium/gpu/ipc/service/gpu_command_buffer_stub.cc +++ b/chromium/gpu/ipc/service/gpu_command_buffer_stub.cc @@ -11,6 +11,7 @@ #include "base/hash.h" #include "base/json/json_writer.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/memory/shared_memory.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" @@ -28,7 +29,6 @@ #include "gpu/command_buffer/service/query_manager.h" #include "gpu/command_buffer/service/sync_point_manager.h" #include "gpu/command_buffer/service/transfer_buffer_manager.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" #include "gpu/ipc/common/gpu_messages.h" #include "gpu/ipc/service/gpu_channel.h" #include "gpu/ipc/service/gpu_channel_manager.h" @@ -38,8 +38,11 @@ #include "gpu/ipc/service/gpu_watchdog.h" #include "gpu/ipc/service/image_transport_surface.h" #include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_context.h" #include "ui/gl/gl_image.h" +#include "ui/gl/gl_implementation.h" #include "ui/gl/gl_switches.h" +#include "ui/gl/init/gl_factory.h" #if defined(OS_WIN) #include "base/win/win_util.h" @@ -56,7 +59,7 @@ struct WaitForCommandState { int32_t start; int32_t end; - scoped_ptr<IPC::Message> reply; + std::unique_ptr<IPC::Message> reply; }; namespace { @@ -93,7 +96,7 @@ class GpuCommandBufferMemoryTracker : public gles2::MemoryTracker { private: ~GpuCommandBufferMemoryTracker() override {} - scoped_ptr<GpuMemoryTrackingGroup> tracking_group_; + std::unique_ptr<GpuMemoryTrackingGroup> tracking_group_; const uint64_t client_tracing_id_; const int client_id_; const uint64_t share_group_tracing_guid_; @@ -130,7 +133,7 @@ const int64_t kMaxTimeSinceIdleMs = 10; class DevToolsChannelData : public base::trace_event::ConvertableToTraceFormat { public: - static scoped_ptr<base::trace_event::ConvertableToTraceFormat> + static std::unique_ptr<base::trace_event::ConvertableToTraceFormat> CreateForChannel(GpuChannel* channel); ~DevToolsChannelData() override {} @@ -142,16 +145,16 @@ class DevToolsChannelData : public base::trace_event::ConvertableToTraceFormat { private: explicit DevToolsChannelData(base::Value* value) : value_(value) {} - scoped_ptr<base::Value> value_; + std::unique_ptr<base::Value> value_; DISALLOW_COPY_AND_ASSIGN(DevToolsChannelData); }; -scoped_ptr<base::trace_event::ConvertableToTraceFormat> +std::unique_ptr<base::trace_event::ConvertableToTraceFormat> DevToolsChannelData::CreateForChannel(GpuChannel* channel) { - scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue); + std::unique_ptr<base::DictionaryValue> res(new base::DictionaryValue); res->SetInteger("renderer_pid", channel->GetClientPID()); res->SetDouble("used_bytes", channel->GetMemoryUsage()); - return make_scoped_ptr(new DevToolsChannelData(res.release())); + return base::WrapUnique(new DevToolsChannelData(res.release())); } CommandBufferId GetCommandBufferID(int channel_id, int32_t route_id) { @@ -161,100 +164,36 @@ CommandBufferId GetCommandBufferID(int channel_id, int32_t route_id) { } // namespace -GpuCommandBufferStub::GpuCommandBufferStub( +std::unique_ptr<GpuCommandBufferStub> GpuCommandBufferStub::Create( GpuChannel* channel, - SyncPointManager* sync_point_manager, - base::SingleThreadTaskRunner* task_runner, - GpuCommandBufferStub* share_group, - SurfaceHandle surface_handle, - gles2::MailboxManager* mailbox_manager, - PreemptionFlag* preempt_by_flag, - gles2::SubscriptionRefSet* subscription_ref_set, - ValueStateMap* pending_valuebuffer_state, - const gfx::Size& size, - const gles2::DisallowedFeatures& disallowed_features, - const std::vector<int32_t>& attribs, - gfx::GpuPreference gpu_preference, - int32_t stream_id, + GpuCommandBufferStub* share_command_buffer_stub, + const GPUCreateCommandBufferConfig& init_params, int32_t route_id, - GpuWatchdog* watchdog, - const GURL& active_url) + std::unique_ptr<base::SharedMemory> shared_state_shm) { + std::unique_ptr<GpuCommandBufferStub> stub( + new GpuCommandBufferStub(channel, init_params, route_id)); + if (!stub->Initialize(share_command_buffer_stub, init_params, + std::move(shared_state_shm))) + return nullptr; + return stub; +} + +GpuCommandBufferStub::GpuCommandBufferStub( + GpuChannel* channel, + const GPUCreateCommandBufferConfig& init_params, + int32_t route_id) : channel_(channel), - sync_point_manager_(sync_point_manager), - task_runner_(task_runner), initialized_(false), - surface_handle_(surface_handle), - initial_size_(size), - disallowed_features_(disallowed_features), - requested_attribs_(attribs), - gpu_preference_(gpu_preference), + surface_handle_(init_params.surface_handle), use_virtualized_gl_context_(false), command_buffer_id_(GetCommandBufferID(channel->client_id(), route_id)), - stream_id_(stream_id), + stream_id_(init_params.stream_id), route_id_(route_id), last_flush_count_(0), - surface_format_(gfx::GLSurface::SURFACE_DEFAULT), - watchdog_(watchdog), waiting_for_sync_point_(false), previous_processed_num_(0), - preemption_flag_(preempt_by_flag), - active_url_(active_url) { - active_url_hash_ = base::Hash(active_url.possibly_invalid_spec()); - FastSetActiveURL(active_url_, active_url_hash_, channel_); - - gles2::ContextCreationAttribHelper attrib_parser; - attrib_parser.Parse(requested_attribs_); - - if (share_group) { - context_group_ = share_group->context_group_; - DCHECK(context_group_->bind_generates_resource() == - attrib_parser.bind_generates_resource); - } else { - context_group_ = new gles2::ContextGroup( - channel_->gpu_channel_manager()->gpu_preferences(), mailbox_manager, - new GpuCommandBufferMemoryTracker(channel, - command_buffer_id_.GetUnsafeValue()), - channel_->gpu_channel_manager()->shader_translator_cache(), - channel_->gpu_channel_manager()->framebuffer_completeness_cache(), NULL, - subscription_ref_set, pending_valuebuffer_state, - attrib_parser.bind_generates_resource); - } - -// Virtualize PreferIntegratedGpu contexts by default on OS X to prevent -// performance regressions when enabling FCM. -// http://crbug.com/180463 -#if defined(OS_MACOSX) - if (gpu_preference_ == gfx::PreferIntegratedGpu) - use_virtualized_gl_context_ = true; -#endif - - use_virtualized_gl_context_ |= - context_group_->feature_info()->workarounds().use_virtualized_gl_contexts; - - // MailboxManagerSync synchronization correctness currently depends on having - // only a single context. See crbug.com/510243 for details. - use_virtualized_gl_context_ |= mailbox_manager->UsesSync(); - -#if defined(OS_ANDROID) - if (attrib_parser.red_size <= 5 && - attrib_parser.green_size <= 6 && - attrib_parser.blue_size <= 5 && - attrib_parser.alpha_size == 0) - surface_format_ = gfx::GLSurface::SURFACE_RGB565; - gfx::GLSurface* defaultOffscreenSurface = - channel_->gpu_channel_manager()->GetDefaultOffscreenSurface(); - bool is_onscreen = (surface_handle_ != kNullSurfaceHandle); - if (surface_format_ != defaultOffscreenSurface->GetFormat() && is_onscreen) - use_virtualized_gl_context_ = false; -#endif - - if ((surface_handle_ == kNullSurfaceHandle) && initial_size_.IsEmpty()) { - // If we're an offscreen surface with zero width and/or height, set to a - // non-zero size so that we have a complete framebuffer for operations like - // glClear. - initial_size_ = gfx::Size(1, 1); - } -} + active_url_(init_params.active_url), + active_url_hash_(base::Hash(active_url_.possibly_invalid_spec())) {} GpuCommandBufferStub::~GpuCommandBufferStub() { Destroy(); @@ -291,8 +230,6 @@ bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) { // here. This is so the reply can be delayed if the scheduler is unscheduled. bool handled = true; IPC_BEGIN_MESSAGE_MAP(GpuCommandBufferStub, message) - IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_Initialize, - OnInitialize); IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_SetGetBuffer, OnSetGetBuffer); IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ProduceFrontBuffer, @@ -344,7 +281,7 @@ void GpuCommandBufferStub::PollWork() { base::TimeTicks current_time = base::TimeTicks::Now(); DCHECK(!process_delayed_work_time_.is_null()); if (process_delayed_work_time_ > current_time) { - task_runner_->PostDelayedTask( + channel_->task_runner()->PostDelayedTask( FROM_HERE, base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()), process_delayed_work_time_ - current_time); return; @@ -433,7 +370,7 @@ void GpuCommandBufferStub::ScheduleDelayedWork(base::TimeDelta delay) { } process_delayed_work_time_ = current_time + delay; - task_runner_->PostDelayedTask( + channel_->task_runner()->PostDelayedTask( FROM_HERE, base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()), delay); } @@ -500,108 +437,143 @@ void GpuCommandBufferStub::Destroy() { surface_ = NULL; } -void GpuCommandBufferStub::OnInitializeFailed(IPC::Message* reply_message) { - Destroy(); - GpuCommandBufferMsg_Initialize::WriteReplyParams( - reply_message, false, Capabilities()); - Send(reply_message); -} +bool GpuCommandBufferStub::Initialize( + GpuCommandBufferStub* share_command_buffer_stub, + const GPUCreateCommandBufferConfig& init_params, + std::unique_ptr<base::SharedMemory> shared_state_shm) { + TRACE_EVENT0("gpu", "GpuCommandBufferStub::Initialize"); + FastSetActiveURL(active_url_, active_url_hash_, channel_); -scoped_refptr<gfx::GLSurface> GpuCommandBufferStub::CreateSurface() { GpuChannelManager* manager = channel_->gpu_channel_manager(); - scoped_refptr<gfx::GLSurface> surface; - if (surface_handle_ != kNullSurfaceHandle) { - surface = ImageTransportSurface::CreateNativeSurface( - manager, this, surface_handle_, surface_format_); - if (!surface || !surface->Initialize(surface_format_)) - return nullptr; + DCHECK(manager); + + if (share_command_buffer_stub) { + context_group_ = share_command_buffer_stub->context_group_; + DCHECK(context_group_->bind_generates_resource() == + init_params.attribs.bind_generates_resource); } else { - surface = manager->GetDefaultOffscreenSurface(); + scoped_refptr<gles2::FeatureInfo> feature_info = + new gles2::FeatureInfo(manager->gpu_driver_bug_workarounds()); + context_group_ = new gles2::ContextGroup( + manager->gpu_preferences(), channel_->mailbox_manager(), + new GpuCommandBufferMemoryTracker(channel_, + command_buffer_id_.GetUnsafeValue()), + manager->shader_translator_cache(), + manager->framebuffer_completeness_cache(), feature_info, + init_params.attribs.bind_generates_resource); } - return surface; -} -void GpuCommandBufferStub::OnInitialize( - base::SharedMemoryHandle shared_state_handle, - IPC::Message* reply_message) { - TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnInitialize"); - DCHECK(!command_buffer_.get()); +#if defined(OS_MACOSX) + // Virtualize PreferIntegratedGpu contexts by default on OS X to prevent + // performance regressions when enabling FCM. + // http://crbug.com/180463 + if (init_params.gpu_preference == gfx::PreferIntegratedGpu) + use_virtualized_gl_context_ = true; +#endif - scoped_ptr<base::SharedMemory> shared_state_shm( - new base::SharedMemory(shared_state_handle, false)); + use_virtualized_gl_context_ |= + context_group_->feature_info()->workarounds().use_virtualized_gl_contexts; - command_buffer_.reset(new CommandBufferService( - context_group_->transfer_buffer_manager())); + // MailboxManagerSync synchronization correctness currently depends on having + // only a single context. See crbug.com/510243 for details. + use_virtualized_gl_context_ |= channel_->mailbox_manager()->UsesSync(); + + gfx::GLSurface::Format surface_format = gfx::GLSurface::SURFACE_DEFAULT; + bool offscreen = (surface_handle_ == kNullSurfaceHandle); + gfx::GLSurface* default_surface = manager->GetDefaultOffscreenSurface(); + if (!default_surface) { + DLOG(ERROR) << "Failed to create default offscreen surface."; + return false; + } +#if defined(OS_ANDROID) + if (init_params.attribs.red_size <= 5 && + init_params.attribs.green_size <= 6 && + init_params.attribs.blue_size <= 5 && + init_params.attribs.alpha_size == 0) + surface_format = gfx::GLSurface::SURFACE_RGB565; + // We can only use virtualized contexts for onscreen command buffers if their + // config is compatible with the offscreen ones - otherwise MakeCurrent fails. + if (surface_format != default_surface->GetFormat() && !offscreen) + use_virtualized_gl_context_ = false; +#endif - bool result = command_buffer_->Initialize(); - DCHECK(result); + gfx::Size initial_size = init_params.size; + if (offscreen && initial_size.IsEmpty()) { + // If we're an offscreen surface with zero width and/or height, set to a + // non-zero size so that we have a complete framebuffer for operations like + // glClear. + initial_size = gfx::Size(1, 1); + } - GpuChannelManager* manager = channel_->gpu_channel_manager(); - DCHECK(manager); + command_buffer_.reset(new CommandBufferService( + context_group_->transfer_buffer_manager())); decoder_.reset(gles2::GLES2Decoder::Create(context_group_.get())); - executor_.reset(new CommandExecutor(command_buffer_.get(), - decoder_.get(), decoder_.get())); - sync_point_client_ = sync_point_manager_->CreateSyncPointClient( + executor_.reset(new CommandExecutor(command_buffer_.get(), decoder_.get(), + decoder_.get())); + sync_point_client_ = channel_->sync_point_manager()->CreateSyncPointClient( channel_->GetSyncPointOrderData(stream_id_), CommandBufferNamespace::GPU_IO, command_buffer_id_); - if (preemption_flag_.get()) - executor_->SetPreemptByFlag(preemption_flag_); + executor_->SetPreemptByFlag(channel_->preempted_flag()); decoder_->set_engine(executor_.get()); - surface_ = CreateSurface(); - if (!surface_.get()) { - DLOG(ERROR) << "Failed to create surface."; - OnInitializeFailed(reply_message); - return; + if (offscreen) { + surface_ = default_surface; + } else { + surface_ = ImageTransportSurface::CreateNativeSurface( + manager, this, surface_handle_, surface_format); + if (!surface_ || !surface_->Initialize(surface_format)) { + surface_ = nullptr; + DLOG(ERROR) << "Failed to create surface."; + return false; + } } scoped_refptr<gfx::GLContext> context; - gfx::GLShareGroup* share_group = channel_->share_group(); - if (use_virtualized_gl_context_ && share_group) { - context = share_group->GetSharedContext(); + gfx::GLShareGroup* gl_share_group = channel_->share_group(); + if (use_virtualized_gl_context_ && gl_share_group) { + context = gl_share_group->GetSharedContext(); if (!context.get()) { - context = gfx::GLContext::CreateGLContext( - channel_->share_group(), - channel_->gpu_channel_manager()->GetDefaultOffscreenSurface(), - gpu_preference_); + context = gl::init::CreateGLContext(gl_share_group, default_surface, + init_params.gpu_preference); if (!context.get()) { DLOG(ERROR) << "Failed to create shared context for virtualization."; - OnInitializeFailed(reply_message); - return; + return false; } - channel_->share_group()->SetSharedContext(context.get()); + // Ensure that context creation did not lose track of the intended + // gl_share_group. + DCHECK(context->share_group() == gl_share_group); + gl_share_group->SetSharedContext(context.get()); } - // This should be a non-virtual GL context. - DCHECK(context->GetHandle()); + // This should be either: + // (1) a non-virtual GL context, or + // (2) a mock context. + DCHECK(context->GetHandle() || + gfx::GetGLImplementation() == gfx::kGLImplementationMockGL); context = new GLContextVirtual( - share_group, context.get(), decoder_->AsWeakPtr()); - if (!context->Initialize(surface_.get(), gpu_preference_)) { + gl_share_group, context.get(), decoder_->AsWeakPtr()); + if (!context->Initialize(surface_.get(), init_params.gpu_preference)) { // The real context created above for the default offscreen surface // might not be compatible with this surface. context = NULL; - DLOG(ERROR) << "Failed to initialize virtual GL context."; - OnInitializeFailed(reply_message); - return; + return false; } } if (!context.get()) { - context = gfx::GLContext::CreateGLContext( - share_group, surface_.get(), gpu_preference_); + context = gl::init::CreateGLContext(gl_share_group, surface_.get(), + init_params.gpu_preference); } if (!context.get()) { DLOG(ERROR) << "Failed to create context."; - OnInitializeFailed(reply_message); - return; + return false; } if (!context->MakeCurrent(surface_.get())) { LOG(ERROR) << "Failed to make context current."; - OnInitializeFailed(reply_message); - return; + return false; } if (!context->GetGLStateRestorer()) { @@ -611,21 +583,18 @@ void GpuCommandBufferStub::OnInitialize( if (!context_group_->has_program_cache() && !context_group_->feature_info()->workarounds().disable_program_cache) { - context_group_->set_program_cache( - channel_->gpu_channel_manager()->program_cache()); + context_group_->set_program_cache(manager->program_cache()); } // Initialize the decoder with either the view or pbuffer GLContext. - bool offscreen = (surface_handle_ == kNullSurfaceHandle); - if (!decoder_->Initialize(surface_, context, offscreen, initial_size_, - disallowed_features_, requested_attribs_)) { + if (!decoder_->Initialize(surface_, context, offscreen, initial_size, + gpu::gles2::DisallowedFeatures(), + init_params.attribs)) { DLOG(ERROR) << "Failed to initialize decoder."; - OnInitializeFailed(reply_message); - return; + return false; } - if (channel_->gpu_channel_manager()-> - gpu_preferences().enable_gpu_service_logging) { + if (manager->gpu_preferences().enable_gpu_service_logging) { decoder_->set_log_commands(true); } @@ -646,10 +615,8 @@ void GpuCommandBufferStub::OnInitialize( &CommandExecutor::SetGetBuffer, base::Unretained(executor_.get()))); command_buffer_->SetParseErrorCallback( base::Bind(&GpuCommandBufferStub::OnParseError, base::Unretained(this))); - executor_->SetSchedulingChangedCallback(base::Bind( - &GpuCommandBufferStub::OnSchedulingChanged, base::Unretained(this))); - if (watchdog_) { + if (channel_->watchdog()) { executor_->SetCommandProcessedCallback(base::Bind( &GpuCommandBufferStub::OnCommandProcessed, base::Unretained(this))); } @@ -657,22 +624,16 @@ void GpuCommandBufferStub::OnInitialize( const size_t kSharedStateSize = sizeof(CommandBufferSharedState); if (!shared_state_shm->Map(kSharedStateSize)) { DLOG(ERROR) << "Failed to map shared state buffer."; - OnInitializeFailed(reply_message); - return; + return false; } command_buffer_->SetSharedStateBuffer(MakeBackingFromSharedMemory( std::move(shared_state_shm), kSharedStateSize)); - Capabilities capabilities = decoder_->GetCapabilities(); - - GpuCommandBufferMsg_Initialize::WriteReplyParams( - reply_message, true, capabilities); - Send(reply_message); - - if ((surface_handle_ == kNullSurfaceHandle) && !active_url_.is_empty()) + if (offscreen && !active_url_.is_empty()) manager->delegate()->DidCreateOffscreenContext(active_url_); initialized_ = true; + return true; } void GpuCommandBufferStub::OnCreateStreamTexture(uint32_t texture_id, @@ -690,18 +651,6 @@ void GpuCommandBufferStub::SetLatencyInfoCallback( latency_info_callback_ = callback; } -int32_t GpuCommandBufferStub::GetRequestedAttribute(int attr) const { - // The command buffer is pairs of enum, value - // search for the requested attribute, return the value. - for (std::vector<int32_t>::const_iterator it = requested_attribs_.begin(); - it != requested_attribs_.end(); ++it) { - if (*it++ == attr) { - return *it; - } - } - return -1; -} - void GpuCommandBufferStub::OnSetGetBuffer(int32_t shm_id, IPC::Message* reply_message) { TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSetGetBuffer"); @@ -740,12 +689,6 @@ void GpuCommandBufferStub::OnParseError() { CheckContextLost(); } -void GpuCommandBufferStub::OnSchedulingChanged(bool scheduled) { - TRACE_EVENT1("gpu", "GpuCommandBufferStub::OnSchedulingChanged", "scheduled", - scheduled); - channel_->OnStreamRescheduled(stream_id_, scheduled); -} - void GpuCommandBufferStub::OnWaitForTokenInRange(int32_t start, int32_t end, IPC::Message* reply_message) { @@ -755,7 +698,7 @@ void GpuCommandBufferStub::OnWaitForTokenInRange(int32_t start, if (wait_for_token_) LOG(ERROR) << "Got WaitForToken command while currently waiting for token."; wait_for_token_ = - make_scoped_ptr(new WaitForCommandState(start, end, reply_message)); + base::WrapUnique(new WaitForCommandState(start, end, reply_message)); CheckCompleteWaits(); } @@ -771,7 +714,7 @@ void GpuCommandBufferStub::OnWaitForGetOffsetInRange( << "Got WaitForGetOffset command while currently waiting for offset."; } wait_for_get_offset_ = - make_scoped_ptr(new WaitForCommandState(start, end, reply_message)); + base::WrapUnique(new WaitForCommandState(start, end, reply_message)); CheckCompleteWaits(); } @@ -844,7 +787,7 @@ void GpuCommandBufferStub::OnRegisterTransferBuffer( // Take ownership of the memory and map it into this process. // This validates the size. - scoped_ptr<base::SharedMemory> shared_memory( + std::unique_ptr<base::SharedMemory> shared_memory( new base::SharedMemory(transfer_buffer, false)); if (!shared_memory->Map(size)) { DVLOG(0) << "Failed to map shared memory."; @@ -865,8 +808,8 @@ void GpuCommandBufferStub::OnDestroyTransferBuffer(int32_t id) { } void GpuCommandBufferStub::OnCommandProcessed() { - if (watchdog_) - watchdog_->CheckArmed(); + DCHECK(channel_->watchdog()); + channel_->watchdog()->CheckArmed(); } void GpuCommandBufferStub::ReportState() { command_buffer_->UpdateState(); } @@ -891,7 +834,7 @@ void GpuCommandBufferStub::PullTextureUpdates( void GpuCommandBufferStub::OnSignalSyncToken(const SyncToken& sync_token, uint32_t id) { scoped_refptr<SyncPointClientState> release_state = - sync_point_manager_->GetSyncPointClientState( + channel_->sync_point_manager()->GetSyncPointClientState( sync_token.namespace_id(), sync_token.command_buffer_id()); if (release_state) { @@ -951,8 +894,8 @@ bool GpuCommandBufferStub::OnWaitFenceSync( DCHECK(executor_->scheduled()); scoped_refptr<SyncPointClientState> release_state = - sync_point_manager_->GetSyncPointClientState(namespace_id, - command_buffer_id); + channel_->sync_point_manager()->GetSyncPointClientState( + namespace_id, command_buffer_id); if (!release_state) return true; @@ -966,7 +909,7 @@ bool GpuCommandBufferStub::OnWaitFenceSync( this); waiting_for_sync_point_ = true; sync_point_client_->WaitNonThreadSafe( - release_state.get(), release, task_runner_, + release_state.get(), release, channel_->task_runner(), base::Bind(&GpuCommandBufferStub::OnWaitFenceSyncCompleted, this->AsWeakPtr(), namespace_id, command_buffer_id, release)); @@ -974,6 +917,7 @@ bool GpuCommandBufferStub::OnWaitFenceSync( return true; executor_->SetScheduled(false); + channel_->OnStreamRescheduled(stream_id_, false); return false; } @@ -987,6 +931,7 @@ void GpuCommandBufferStub::OnWaitFenceSyncCompleted( PullTextureUpdates(namespace_id, command_buffer_id, release); waiting_for_sync_point_ = false; executor_->SetScheduled(true); + channel_->OnStreamRescheduled(stream_id_, true); } void GpuCommandBufferStub::OnCreateImage( @@ -1033,6 +978,8 @@ void GpuCommandBufferStub::OnCreateImage( image_manager->AddImage(image.get(), id); if (image_release_count) { + DCHECK_EQ(image_release_count, + sync_point_client_->client_state()->fence_sync_release() + 1); sync_point_client_->ReleaseFenceSync(image_release_count); } } @@ -1127,10 +1074,8 @@ void GpuCommandBufferStub::MarkContextLost() { } void GpuCommandBufferStub::SendSwapBuffersCompleted( - const std::vector<ui::LatencyInfo>& latency_info, - gfx::SwapResult result) { - Send(new GpuCommandBufferMsg_SwapBuffersCompleted(route_id_, latency_info, - result)); + const GpuCommandBufferMsg_SwapBuffersCompleted_Params& params) { + Send(new GpuCommandBufferMsg_SwapBuffersCompleted(route_id_, params)); } void GpuCommandBufferStub::SendUpdateVSyncParameters(base::TimeTicks timebase, diff --git a/chromium/gpu/ipc/service/gpu_command_buffer_stub.h b/chromium/gpu/ipc/service/gpu_command_buffer_stub.h index 32175b2b7d6..79e86e6410e 100644 --- a/chromium/gpu/ipc/service/gpu_command_buffer_stub.h +++ b/chromium/gpu/ipc/service/gpu_command_buffer_stub.h @@ -9,6 +9,7 @@ #include <stdint.h> #include <deque> +#include <memory> #include <string> #include <vector> @@ -40,14 +41,14 @@ struct Mailbox; struct SyncToken; class SyncPointClient; class SyncPointManager; -class ValueStateMap; namespace gles2 { class MailboxManager; -class SubscriptionRefSet; } } +struct GPUCreateCommandBufferConfig; struct GpuCommandBufferMsg_CreateImage_Params; +struct GpuCommandBufferMsg_SwapBuffersCompleted_Params; namespace gpu { @@ -72,24 +73,12 @@ class GPU_EXPORT GpuCommandBufferStub typedef base::Callback<void(const std::vector<ui::LatencyInfo>&)> LatencyInfoCallback; - GpuCommandBufferStub( - GpuChannel* channel, - SyncPointManager* sync_point_manager, - base::SingleThreadTaskRunner* task_runner, - GpuCommandBufferStub* share_group, - SurfaceHandle surface_handle, - gles2::MailboxManager* mailbox_manager, - PreemptionFlag* preempt_by_flag, - gles2::SubscriptionRefSet* subscription_ref_set, - ValueStateMap* pending_valuebuffer_state, - const gfx::Size& size, - const gles2::DisallowedFeatures& disallowed_features, - const std::vector<int32_t>& attribs, - gfx::GpuPreference gpu_preference, - int32_t stream_id, - int32_t route_id, - GpuWatchdog* watchdog, - const GURL& active_url); + static std::unique_ptr<GpuCommandBufferStub> Create( + GpuChannel* channel, + GpuCommandBufferStub* share_group, + const GPUCreateCommandBufferConfig& init_params, + int32_t route_id, + std::unique_ptr<base::SharedMemory> shared_state_shm); ~GpuCommandBufferStub() override; @@ -121,10 +110,6 @@ class GPU_EXPORT GpuCommandBufferStub // Identifies the stream for this command buffer. int32_t stream_id() const { return stream_id_; } - gfx::GpuPreference gpu_preference() { return gpu_preference_; } - - int32_t GetRequestedAttribute(int attr) const; - // Sends a message to the console. void SendConsoleMessage(int32_t id, const std::string& message); @@ -142,26 +127,26 @@ class GPU_EXPORT GpuCommandBufferStub const gles2::FeatureInfo* GetFeatureInfo() const; void SendSwapBuffersCompleted( - const std::vector<ui::LatencyInfo>& latency_info, - gfx::SwapResult result); + const GpuCommandBufferMsg_SwapBuffersCompleted_Params& params); void SendUpdateVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval); private: + GpuCommandBufferStub(GpuChannel* channel, + const GPUCreateCommandBufferConfig& init_params, + int32_t route_id); + + bool Initialize(GpuCommandBufferStub* share_group, + const GPUCreateCommandBufferConfig& init_params, + std::unique_ptr<base::SharedMemory> shared_state_shm); + GpuMemoryManager* GetMemoryManager() const; void Destroy(); bool MakeCurrent(); - // Cleans up and sends reply if OnInitialize failed. - void OnInitializeFailed(IPC::Message* reply_message); - - scoped_refptr<gfx::GLSurface> CreateSurface(); - // Message handlers: - void OnInitialize(base::SharedMemoryHandle shared_state_shm, - IPC::Message* reply_message); void OnSetGetBuffer(int32_t shm_id, IPC::Message* reply_message); void OnProduceFrontBuffer(const Mailbox& mailbox); void OnGetState(IPC::Message* reply_message); @@ -199,10 +184,8 @@ class GPU_EXPORT GpuCommandBufferStub void OnCreateStreamTexture(uint32_t texture_id, int32_t stream_id, bool* succeeded); - void OnCommandProcessed(); void OnParseError(); - void OnSchedulingChanged(bool scheduled); void ReportState(); @@ -230,35 +213,22 @@ class GPU_EXPORT GpuCommandBufferStub // are destroyed. So a raw pointer is safe. GpuChannel* const channel_; - // Outlives the stub. - SyncPointManager* const sync_point_manager_; - - // Task runner for main thread. - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - // The group of contexts that share namespaces with this context. scoped_refptr<gles2::ContextGroup> context_group_; bool initialized_; const SurfaceHandle surface_handle_; - gfx::Size initial_size_; - gles2::DisallowedFeatures disallowed_features_; - std::vector<int32_t> requested_attribs_; - gfx::GpuPreference gpu_preference_; bool use_virtualized_gl_context_; const CommandBufferId command_buffer_id_; const int32_t stream_id_; const int32_t route_id_; uint32_t last_flush_count_; - scoped_ptr<CommandBufferService> command_buffer_; - scoped_ptr<gles2::GLES2Decoder> decoder_; - scoped_ptr<CommandExecutor> executor_; - scoped_ptr<SyncPointClient> sync_point_client_; + std::unique_ptr<CommandBufferService> command_buffer_; + std::unique_ptr<gles2::GLES2Decoder> decoder_; + std::unique_ptr<CommandExecutor> executor_; + std::unique_ptr<SyncPointClient> sync_point_client_; scoped_refptr<gfx::GLSurface> surface_; - gfx::GLSurface::Format surface_format_; - - GpuWatchdog* watchdog_; base::ObserverList<DestructionObserver> destruction_observers_; @@ -268,15 +238,13 @@ class GPU_EXPORT GpuCommandBufferStub uint32_t previous_processed_num_; base::TimeTicks last_idle_time_; - scoped_refptr<PreemptionFlag> preemption_flag_; - LatencyInfoCallback latency_info_callback_; GURL active_url_; size_t active_url_hash_; - scoped_ptr<WaitForCommandState> wait_for_token_; - scoped_ptr<WaitForCommandState> wait_for_get_offset_; + std::unique_ptr<WaitForCommandState> wait_for_token_; + std::unique_ptr<WaitForCommandState> wait_for_get_offset_; DISALLOW_COPY_AND_ASSIGN(GpuCommandBufferStub); }; diff --git a/chromium/gpu/ipc/service/gpu_memory_buffer_factory.cc b/chromium/gpu/ipc/service/gpu_memory_buffer_factory.cc index 01c62be8c96..bd8a79fee1b 100644 --- a/chromium/gpu/ipc/service/gpu_memory_buffer_factory.cc +++ b/chromium/gpu/ipc/service/gpu_memory_buffer_factory.cc @@ -5,6 +5,7 @@ #include "gpu/ipc/service/gpu_memory_buffer_factory.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "build/build_config.h" #if defined(OS_MACOSX) @@ -22,15 +23,16 @@ namespace gpu { // static -scoped_ptr<GpuMemoryBufferFactory> GpuMemoryBufferFactory::CreateNativeType() { +std::unique_ptr<GpuMemoryBufferFactory> +GpuMemoryBufferFactory::CreateNativeType() { #if defined(OS_MACOSX) - return make_scoped_ptr(new GpuMemoryBufferFactoryIOSurface); + return base::WrapUnique(new GpuMemoryBufferFactoryIOSurface); #endif #if defined(OS_ANDROID) - return make_scoped_ptr(new GpuMemoryBufferFactorySurfaceTexture); + return base::WrapUnique(new GpuMemoryBufferFactorySurfaceTexture); #endif #if defined(USE_OZONE) - return make_scoped_ptr(new GpuMemoryBufferFactoryOzoneNativePixmap); + return base::WrapUnique(new GpuMemoryBufferFactoryOzoneNativePixmap); #endif NOTREACHED(); return nullptr; diff --git a/chromium/gpu/ipc/service/gpu_memory_buffer_factory.h b/chromium/gpu/ipc/service/gpu_memory_buffer_factory.h index beb278cb372..0b2ba875ed0 100644 --- a/chromium/gpu/ipc/service/gpu_memory_buffer_factory.h +++ b/chromium/gpu/ipc/service/gpu_memory_buffer_factory.h @@ -5,11 +5,11 @@ #ifndef GPU_IPC_SERVICE_GPU_MEMORY_BUFFER_FACTORY_H_ #define GPU_IPC_SERVICE_GPU_MEMORY_BUFFER_FACTORY_H_ +#include <memory> #include <vector> #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "gpu/gpu_export.h" #include "gpu/ipc/common/surface_handle.h" #include "ui/gfx/geometry/size.h" @@ -24,7 +24,7 @@ class GPU_EXPORT GpuMemoryBufferFactory { virtual ~GpuMemoryBufferFactory() {} // Creates a new factory instance for native GPU memory buffers. - static scoped_ptr<GpuMemoryBufferFactory> CreateNativeType(); + static std::unique_ptr<GpuMemoryBufferFactory> CreateNativeType(); // Creates a new GPU memory buffer instance. A valid handle is returned on // success. It can be called on any thread. diff --git a/chromium/gpu/ipc/service/gpu_memory_buffer_factory_test_template.h b/chromium/gpu/ipc/service/gpu_memory_buffer_factory_test_template.h index 991df287822..7fa415e7859 100644 --- a/chromium/gpu/ipc/service/gpu_memory_buffer_factory_test_template.h +++ b/chromium/gpu/ipc/service/gpu_memory_buffer_factory_test_template.h @@ -8,8 +8,16 @@ #ifndef GPU_IPC_SERVICE_GPU_MEMORY_BUFFER_FACTORY_TEST_TEMPLATE_H_ #define GPU_IPC_SERVICE_GPU_MEMORY_BUFFER_FACTORY_TEST_TEMPLATE_H_ -#include "gpu/ipc/service/gpu_memory_buffer_factory.h" +#if defined(OS_ANDROID) +// TODO(markdittmer): Service code shouldn't depend on client code. +// See crbug.com/608800. +#include "gpu/ipc/client/android/in_process_surface_texture_manager.h" + +#include "gpu/ipc/common/android/surface_texture_manager.h" +#endif + #include "gpu/ipc/common/gpu_memory_buffer_support.h" +#include "gpu/ipc/service/gpu_memory_buffer_factory.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/buffer_format_util.h" @@ -24,6 +32,11 @@ class GpuMemoryBufferFactoryTest : public testing::Test { TYPED_TEST_CASE_P(GpuMemoryBufferFactoryTest); TYPED_TEST_P(GpuMemoryBufferFactoryTest, CreateGpuMemoryBuffer) { +#if defined(OS_ANDROID) + SurfaceTextureManager::SetInstance( + InProcessSurfaceTextureManager::GetInstance()); +#endif + const gfx::GpuMemoryBufferId kBufferId(1); const int kClientId = 1; @@ -41,7 +54,7 @@ TYPED_TEST_P(GpuMemoryBufferFactoryTest, CreateGpuMemoryBuffer) { gfx::GpuMemoryBufferHandle handle = TestFixture::factory_.CreateGpuMemoryBuffer(kBufferId, buffer_size, format, usage, kClientId, - gfx::kNullPluginWindow); + gpu::kNullSurfaceHandle); EXPECT_NE(handle.type, gfx::EMPTY_BUFFER); TestFixture::factory_.DestroyGpuMemoryBuffer(kBufferId, kClientId); } @@ -74,7 +87,7 @@ TYPED_TEST_P(GpuMemoryBufferFactoryImportTest, gfx::GpuMemoryBufferHandle handle1 = TestFixture::factory_.CreateGpuMemoryBuffer( kBufferId1, buffer_size, format, gfx::BufferUsage::GPU_READ, - kClientId, gfx::kNullPluginWindow); + kClientId, gpu::kNullSurfaceHandle); EXPECT_NE(handle1.type, gfx::EMPTY_BUFFER); // Create new buffer from |handle1|. diff --git a/chromium/gpu/ipc/service/image_transport_surface_android.cc b/chromium/gpu/ipc/service/image_transport_surface_android.cc index ce1ad886336..e73080cabcf 100644 --- a/chromium/gpu/ipc/service/image_transport_surface_android.cc +++ b/chromium/gpu/ipc/service/image_transport_surface_android.cc @@ -8,6 +8,7 @@ #include "gpu/ipc/common/gpu_surface_lookup.h" #include "gpu/ipc/service/pass_through_image_transport_surface.h" #include "ui/gl/gl_surface_egl.h" +#include "ui/gl/gl_surface_stub.h" namespace gpu { @@ -17,6 +18,8 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface( GpuCommandBufferStub* stub, SurfaceHandle surface_handle, gfx::GLSurface::Format format) { + if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) + return new gfx::GLSurfaceStub; DCHECK(GpuSurfaceLookup::GetInstance()); DCHECK_NE(surface_handle, kNullSurfaceHandle); // On Android, the surface_handle is the id of the surface in the diff --git a/chromium/gpu/ipc/service/image_transport_surface_linux.cc b/chromium/gpu/ipc/service/image_transport_surface_linux.cc index 9f60d45be01..24e21aeb88b 100644 --- a/chromium/gpu/ipc/service/image_transport_surface_linux.cc +++ b/chromium/gpu/ipc/service/image_transport_surface_linux.cc @@ -5,6 +5,7 @@ #include "gpu/ipc/service/image_transport_surface.h" #include "gpu/ipc/service/pass_through_image_transport_surface.h" +#include "ui/gl/init/gl_factory.h" namespace gpu { @@ -17,10 +18,10 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface( DCHECK_NE(surface_handle, kNullSurfaceHandle); scoped_refptr<gfx::GLSurface> surface; #if defined(USE_OZONE) - surface = gfx::GLSurface::CreateSurfacelessViewGLSurface(surface_handle); + surface = gl::init::CreateSurfacelessViewGLSurface(surface_handle); #endif if (!surface) - surface = gfx::GLSurface::CreateViewGLSurface(surface_handle); + surface = gl::init::CreateViewGLSurface(surface_handle); if (!surface) return surface; return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface( diff --git a/chromium/gpu/ipc/service/image_transport_surface_mac.mm b/chromium/gpu/ipc/service/image_transport_surface_mac.mm index 56da79fe2fa..0fc6589f818 100644 --- a/chromium/gpu/ipc/service/image_transport_surface_mac.mm +++ b/chromium/gpu/ipc/service/image_transport_surface_mac.mm @@ -8,6 +8,7 @@ #include "gpu/ipc/service/pass_through_image_transport_surface.h" #include "ui/gfx/native_widget_types.h" #include "ui/gl/gl_surface_osmesa.h" +#include "ui/gl/gl_surface_stub.h" namespace gpu { @@ -56,6 +57,8 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface( case gfx::kGLImplementationAppleGL: return ImageTransportSurfaceCreateNativeSurface(manager, stub, surface_handle); + case gfx::kGLImplementationMockGL: + return new gfx::GLSurfaceStub; default: // Content shell in DRT mode spins up a gpu process which needs an // image transport surface, but that surface isn't used to read pixel diff --git a/chromium/gpu/ipc/service/image_transport_surface_overlay_mac.h b/chromium/gpu/ipc/service/image_transport_surface_overlay_mac.h index dde6109abaf..0f3b2ec4193 100644 --- a/chromium/gpu/ipc/service/image_transport_surface_overlay_mac.h +++ b/chromium/gpu/ipc/service/image_transport_surface_overlay_mac.h @@ -6,6 +6,7 @@ #define GPU_IPC_SERVICE_IMAGE_TRANSPORT_SURFACE_OVERLAY_MAC_H_ #include <list> +#include <memory> #include <vector> #import "base/mac/scoped_nsobject.h" @@ -20,16 +21,20 @@ @class CAContext; @class CALayer; -namespace gpu { +namespace ui { +class CALayerTreeCoordinator; +} + +namespace gfx { +class GLFence; +} -class CALayerTree; -class CALayerPartialDamageTree; +namespace gpu { class ImageTransportSurfaceOverlayMac : public gfx::GLSurface, public ui::GpuSwitchingObserver { public: - ImageTransportSurfaceOverlayMac(GpuChannelManager* manager, - GpuCommandBufferStub* stub, + ImageTransportSurfaceOverlayMac(GpuCommandBufferStub* stub, SurfaceHandle handle); // GLSurface implementation @@ -45,7 +50,6 @@ class ImageTransportSurfaceOverlayMac : public gfx::GLSurface, gfx::Size GetSize() override; void* GetHandle() override; bool OnMakeCurrent(gfx::GLContext* context) override; - bool SetBackbufferAllocation(bool allocated) override; bool ScheduleOverlayPlane(int z_order, gfx::OverlayTransform transform, gl::GLImage* image, @@ -60,97 +64,49 @@ class ImageTransportSurfaceOverlayMac : public gfx::GLSurface, bool is_clipped, const gfx::RectF& clip_rect, const gfx::Transform& transform, - int sorting_context_id) override; + int sorting_context_id, + unsigned filter) override; bool IsSurfaceless() const override; // ui::GpuSwitchingObserver implementation. void OnGpuSwitched() override; private: - class PendingSwap; - class OverlayPlane; - ~ImageTransportSurfaceOverlayMac() override; void SetLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info); - void BufferPresented(int32_t surface_id, - const base::TimeTicks& vsync_timebase, - const base::TimeDelta& vsync_interval); void SendAcceleratedSurfaceBuffersSwapped( - int32_t surface_id, + gpu::SurfaceHandle surface_handle, CAContextID ca_context_id, + bool fullscreen_low_power_ca_context_valid, + CAContextID fullscreen_low_power_ca_context_id, const gfx::ScopedRefCountedIOSurfaceMachPort& io_surface, const gfx::Size& size, float scale_factor, std::vector<ui::LatencyInfo> latency_info); gfx::SwapResult SwapBuffersInternal(const gfx::Rect& pixel_damage_rect); - // Returns true if the front of |pending_swaps_| has completed, or has timed - // out by |now|. - bool IsFirstPendingSwapReadyToDisplay( - const base::TimeTicks& now); - // Sets the CALayer contents to the IOSurface for the front of - // |pending_swaps_|, and removes it from the queue. - void DisplayFirstPendingSwapImmediately(); - // Force that all of |pending_swaps_| displayed immediately, and the list be - // cleared. - void DisplayAndClearAllPendingSwaps(); - // Callback issued during the next vsync period ofter a SwapBuffers call, - // to check if the swap is completed, and display the frame. Note that if - // another SwapBuffers happens before this callback, the pending swap will - // be tested at that time, too. - void CheckPendingSwapsCallback(); - // Function to post the above callback. The argument |now| is passed as an - // argument to avoid redundant calls to base::TimeTicks::Now. - void PostCheckPendingSwapsCallbackIfNeeded(const base::TimeTicks& now); - - // Return the time of |interval_fraction| of the way through the next - // vsync period that starts after |from|. If the vsync parameters are not - // valid then return |from|. - base::TimeTicks GetNextVSyncTimeAfter( - const base::TimeTicks& from, double interval_fraction); - - GpuChannelManager* manager_; base::WeakPtr<GpuCommandBufferStub> stub_; SurfaceHandle handle_; std::vector<ui::LatencyInfo> latency_info_; bool use_remote_layer_api_; base::scoped_nsobject<CAContext> ca_context_; - base::scoped_nsobject<CALayer> ca_root_layer_; + base::scoped_nsobject<CAContext> fullscreen_low_power_ca_context_; + std::unique_ptr<ui::CALayerTreeCoordinator> ca_layer_tree_coordinator_; gfx::Size pixel_size_; float scale_factor_; + // A GLFence marking the end of the previous frame. Must only be accessed + // while in a ScopedSetGLToRealGLApi, and while the associated + // |previous_frame_context_| is bound. + std::unique_ptr<gfx::GLFence> previous_frame_fence_; + base::ScopedTypeRef<CGLContextObj> fence_context_obj_; + // The renderer ID that all contexts made current to this surface should be // targeting. GLint gl_renderer_id_; - - // Planes that have been scheduled, but have not had a subsequent SwapBuffers - // call made yet. - scoped_ptr<CALayerPartialDamageTree> pending_partial_damage_tree_; - scoped_ptr<CALayerTree> pending_ca_layer_tree_; - - // A queue of all frames that have been created by SwapBuffersInternal but - // have not yet been displayed. This queue is checked at the beginning of - // every swap and also by a callback. - std::deque<linked_ptr<PendingSwap>> pending_swaps_; - - // The planes that are currently being displayed on the screen. - scoped_ptr<CALayerPartialDamageTree> current_partial_damage_tree_; - scoped_ptr<CALayerTree> current_ca_layer_tree_; - - // The time of the last swap was issued. If this is more than two vsyncs, then - // use the simpler non-smooth animation path. - base::TimeTicks last_swap_time_; - - // The vsync information provided by the browser. - bool vsync_parameters_valid_; - base::TimeTicks vsync_timebase_; - base::TimeDelta vsync_interval_; - - base::Timer display_pending_swap_timer_; - base::WeakPtrFactory<ImageTransportSurfaceOverlayMac> weak_factory_; }; } // namespace gpu diff --git a/chromium/gpu/ipc/service/image_transport_surface_overlay_mac.mm b/chromium/gpu/ipc/service/image_transport_surface_overlay_mac.mm index 4eea4a1bf53..8a40b0efaec 100644 --- a/chromium/gpu/ipc/service/image_transport_surface_overlay_mac.mm +++ b/chromium/gpu/ipc/service/image_transport_surface_overlay_mac.mm @@ -24,14 +24,15 @@ typedef void* GLeglImageOES; #include "base/bind_helpers.h" #include "base/mac/scoped_cftyperef.h" #include "base/trace_event/trace_event.h" -#include "gpu/ipc/service/ca_layer_partial_damage_tree_mac.h" -#include "gpu/ipc/service/ca_layer_tree_mac.h" +#include "gpu/ipc/common/gpu_messages.h" #include "gpu/ipc/service/gpu_channel_manager.h" #include "gpu/ipc/service/gpu_channel_manager_delegate.h" +#include "ui/accelerated_widget_mac/ca_layer_tree_coordinator.h" #include "ui/accelerated_widget_mac/io_surface_context.h" #include "ui/base/cocoa/animation_utils.h" #include "ui/base/cocoa/remote_layer_api.h" #include "ui/gfx/geometry/rect_conversions.h" +#include "ui/gfx/swap_result.h" #include "ui/gfx/transform.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_fence.h" @@ -42,25 +43,6 @@ typedef void* GLeglImageOES; namespace { -// Don't let a frame draw until 5% of the way through the next vsync interval -// after the call to SwapBuffers. This slight offset is to ensure that skew -// doesn't result in the frame being presented to the previous vsync interval. -const double kVSyncIntervalFractionForEarliestDisplay = 0.05; - -// After doing a glFlush and putting in a fence in SwapBuffers, post a task to -// query the fence 50% of the way through the next vsync interval. If we are -// trying to animate smoothly, then want to query the fence at the next -// SwapBuffers. For this reason we schedule the callback for a long way into -// the next frame. -const double kVSyncIntervalFractionForDisplayCallback = 0.5; - -// If swaps arrive regularly and nearly at the vsync rate, then attempt to -// make animation smooth (each frame is shown for one vsync interval) by sending -// them to the window server only when their GL work completes. If frames are -// not coming in with each vsync, then just throw them at the window server as -// they come. -const double kMaximumVSyncsBetweenSwapsForSmoothAnimation = 1.5; - void CheckGLErrors(const char* msg) { GLenum gl_error; while ((gl_error = glGetError()) != GL_NO_ERROR) { @@ -73,63 +55,26 @@ void IOSurfaceContextNoOp(scoped_refptr<ui::IOSurfaceContext>) { } // namespace -@interface CALayer(Private) --(void)setContentsChanged; -@end - namespace gpu { scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface( GpuChannelManager* manager, GpuCommandBufferStub* stub, SurfaceHandle handle) { - return new ImageTransportSurfaceOverlayMac(manager, stub, handle); + return new ImageTransportSurfaceOverlayMac(stub, handle); } -class ImageTransportSurfaceOverlayMac::PendingSwap { - public: - PendingSwap() {} - ~PendingSwap() { DCHECK(!gl_fence); } - - gfx::Size pixel_size; - float scale_factor; - gfx::Rect pixel_damage_rect; - - scoped_ptr<CALayerPartialDamageTree> partial_damage_tree; - scoped_ptr<CALayerTree> ca_layer_tree; - std::vector<ui::LatencyInfo> latency_info; - - // A fence object, and the CGL context it was issued in. - base::ScopedTypeRef<CGLContextObj> cgl_context; - scoped_ptr<gfx::GLFence> gl_fence; - - // The earliest time that this frame may be drawn. A frame is not allowed - // to draw until a fraction of the way through the vsync interval after its - // This extra latency is to allow wiggle-room for smoothness. - base::TimeTicks earliest_display_time_allowed; - - // The time that this will wake up and draw, if a following swap does not - // cause it to draw earlier. - base::TimeTicks target_display_time; -}; - ImageTransportSurfaceOverlayMac::ImageTransportSurfaceOverlayMac( - GpuChannelManager* manager, GpuCommandBufferStub* stub, SurfaceHandle handle) - : manager_(manager), - stub_(stub->AsWeakPtr()), + : stub_(stub->AsWeakPtr()), handle_(handle), use_remote_layer_api_(ui::RemoteLayerAPISupported()), scale_factor_(1), - gl_renderer_id_(0), - vsync_parameters_valid_(false), - display_pending_swap_timer_(true, false), - weak_factory_(this) { - manager_->AddBufferPresentedCallback( - handle_, base::Bind(&ImageTransportSurfaceOverlayMac::BufferPresented, - base::Unretained(this))); + gl_renderer_id_(0) { ui::GpuSwitchingManager::GetInstance()->AddObserver(this); + ca_layer_tree_coordinator_.reset( + new ui::CALayerTreeCoordinator(use_remote_layer_api_)); } ImageTransportSurfaceOverlayMac::~ImageTransportSurfaceOverlayMac() { @@ -139,7 +84,6 @@ ImageTransportSurfaceOverlayMac::~ImageTransportSurfaceOverlayMac() { base::Callback<void(const std::vector<ui::LatencyInfo>&)>()); } Destroy(); - manager_->RemoveBufferPresentedCallback(handle_); } bool ImageTransportSurfaceOverlayMac::Initialize( @@ -157,19 +101,26 @@ bool ImageTransportSurfaceOverlayMac::Initialize( CGSConnectionID connection_id = CGSMainConnectionID(); ca_context_.reset([ [CAContext contextWithCGSConnection:connection_id options:@{}] retain]); - ca_root_layer_.reset([[CALayer alloc] init]); - [ca_root_layer_ setGeometryFlipped:YES]; - [ca_root_layer_ setOpaque:YES]; - [ca_context_ setLayer:ca_root_layer_]; + [ca_context_ setLayer:ca_layer_tree_coordinator_->GetCALayerForDisplay()]; + + fullscreen_low_power_ca_context_.reset([ + [CAContext contextWithCGSConnection:connection_id options:@{}] retain]); + [fullscreen_low_power_ca_context_ setLayer: + ca_layer_tree_coordinator_->GetFullscreenLowPowerLayerForDisplay()]; } return true; } void ImageTransportSurfaceOverlayMac::Destroy() { - DisplayAndClearAllPendingSwaps(); - - current_partial_damage_tree_.reset(); - current_ca_layer_tree_.reset(); + ca_layer_tree_coordinator_.reset(); + if (previous_frame_fence_) { + gfx::ScopedSetGLToRealGLApi scoped_set_gl_api; + // Ensure we are using the context with which the fence was created. + gfx::ScopedCGLSetCurrentContext scoped_set_current(fence_context_obj_); + CheckGLErrors("Before destroy fence"); + previous_frame_fence_.reset(); + CheckGLErrors("After destroy fence"); + } } bool ImageTransportSurfaceOverlayMac::IsOffscreen() { @@ -182,25 +133,11 @@ void ImageTransportSurfaceOverlayMac::SetLatencyInfo( latency_info.end()); } -void ImageTransportSurfaceOverlayMac::BufferPresented( - int32_t surface_id, - const base::TimeTicks& vsync_timebase, - const base::TimeDelta& vsync_interval) { - vsync_timebase_ = vsync_timebase; - vsync_interval_ = vsync_interval; - vsync_parameters_valid_ = (vsync_interval_ != base::TimeDelta()); - - // Compute |vsync_timebase_| to be the first vsync after time zero. - if (vsync_parameters_valid_) { - vsync_timebase_ -= - vsync_interval_ * - ((vsync_timebase_ - base::TimeTicks()) / vsync_interval_); - } -} - void ImageTransportSurfaceOverlayMac::SendAcceleratedSurfaceBuffersSwapped( - int32_t surface_id, + gpu::SurfaceHandle surface_handle, CAContextID ca_context_id, + bool fullscreen_low_power_ca_context_valid, + CAContextID fullscreen_low_power_ca_context_id, const gfx::ScopedRefCountedIOSurfaceMachPort& io_surface, const gfx::Size& size, float scale_factor, @@ -209,216 +146,117 @@ void ImageTransportSurfaceOverlayMac::SendAcceleratedSurfaceBuffersSwapped( TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers", TRACE_EVENT_SCOPE_THREAD, "GLImpl", static_cast<int>(gfx::GetGLImplementation()), "width", size.width()); - // On mac, handle_ is a surface id. See - // GpuProcessTransportFactory::CreatePerCompositorData - manager_->delegate()->SendAcceleratedSurfaceBuffersSwapped( - surface_id, ca_context_id, io_surface, size, scale_factor, - std::move(latency_info)); + + GpuCommandBufferMsg_SwapBuffersCompleted_Params params; + params.surface_handle = surface_handle; + params.ca_context_id = ca_context_id; + params.fullscreen_low_power_ca_context_valid = + fullscreen_low_power_ca_context_valid; + params.fullscreen_low_power_ca_context_id = + fullscreen_low_power_ca_context_id; + params.io_surface = io_surface; + params.pixel_size = size; + params.scale_factor = scale_factor; + params.latency_info = std::move(latency_info); + params.result = gfx::SwapResult::SWAP_ACK; + stub_->SendSwapBuffersCompleted(params); } gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffersInternal( const gfx::Rect& pixel_damage_rect) { TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::SwapBuffersInternal"); - // Use the same concept of 'now' for the entire function. The duration of - // this function only affect the result if this function lasts across a vsync - // boundary, in which case smooth animation is out the window anyway. - const base::TimeTicks now = base::TimeTicks::Now(); - - // Decide if the frame should be drawn immediately, or if we should wait until - // its work finishes before drawing immediately. - bool display_immediately = false; - if (vsync_parameters_valid_ && - now - last_swap_time_ > - kMaximumVSyncsBetweenSwapsForSmoothAnimation * vsync_interval_) { - display_immediately = true; - } - last_swap_time_ = now; - - // If the previous swap is ready to display, do it before flushing the - // new swap. It is desirable to always be hitting this path when trying to - // animate smoothly with vsync. - if (!pending_swaps_.empty()) { - if (IsFirstPendingSwapReadyToDisplay(now)) - DisplayFirstPendingSwapImmediately(); - } - - // The remainder of the function will populate the PendingSwap structure and - // then enqueue it. - linked_ptr<PendingSwap> new_swap(new PendingSwap); - new_swap->pixel_size = pixel_size_; - new_swap->scale_factor = scale_factor_; - new_swap->pixel_damage_rect = pixel_damage_rect; - new_swap->partial_damage_tree.swap(pending_partial_damage_tree_); - new_swap->ca_layer_tree.swap(pending_ca_layer_tree_); - new_swap->latency_info.swap(latency_info_); - - // A flush is required to ensure that all content appears in the layer. - { + // If supported, use GLFence to ensure that we haven't gotten more than one + // frame ahead of GL. + if (gfx::GLFence::IsSupported()) { gfx::ScopedSetGLToRealGLApi scoped_set_gl_api; - TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::glFlush"); - CheckGLErrors("before flushing frame"); - new_swap->cgl_context.reset(CGLGetCurrentContext(), - base::scoped_policy::RETAIN); - if (gfx::GLFence::IsSupported() && !display_immediately) - new_swap->gl_fence.reset(gfx::GLFence::Create()); - else - glFlush(); - CheckGLErrors("while flushing frame"); - } + CheckGLErrors("Before fence/flush"); - // Compute the deadlines for drawing this frame. - if (display_immediately) { - new_swap->earliest_display_time_allowed = now; - new_swap->target_display_time = now; - } else { - new_swap->earliest_display_time_allowed = - GetNextVSyncTimeAfter(now, kVSyncIntervalFractionForEarliestDisplay); - new_swap->target_display_time = - GetNextVSyncTimeAfter(now, kVSyncIntervalFractionForDisplayCallback); - } + // If we have gotten more than one frame ahead of GL, wait for the previous + // frame to complete. + if (previous_frame_fence_) { + TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::ClientWait"); - pending_swaps_.push_back(new_swap); - if (display_immediately) - DisplayFirstPendingSwapImmediately(); - else - PostCheckPendingSwapsCallbackIfNeeded(now); - return gfx::SwapResult::SWAP_ACK; -} + // Ensure we are using the context with which the fence was created. + gfx::ScopedCGLSetCurrentContext scoped_set_current(fence_context_obj_); + + // While we could call GLFence::ClientWait, this performs a busy wait on + // Mac, leading to high CPU usage. Instead we poll with a 1ms delay. This + // should have minimal impact, as we will only hit this path when we are + // more than one frame (16ms) behind. + // + // Note that on some platforms (10.9), fences appear to sometimes get + // lost and will never pass. Add a 32ms timout to prevent these + // situations from causing a GPU process hang. crbug.com/618075 + int timeout_msec = 32; + while (!previous_frame_fence_->HasCompleted() && timeout_msec > 0) { + --timeout_msec; + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); + } + if (!previous_frame_fence_->HasCompleted()) { + // We timed out waiting for the above fence, just issue a glFinish. + glFinish(); + } + } -bool ImageTransportSurfaceOverlayMac::IsFirstPendingSwapReadyToDisplay( - const base::TimeTicks& now) { - DCHECK(!pending_swaps_.empty()); - linked_ptr<PendingSwap> swap = pending_swaps_.front(); + // Create a fence for the current frame's work and save the context. + previous_frame_fence_.reset(gfx::GLFence::Create()); + fence_context_obj_.reset(CGLGetCurrentContext(), + base::scoped_policy::RETAIN); - // Frames are disallowed from drawing until the vsync interval after their - // swap is issued. - if (now < swap->earliest_display_time_allowed) - return false; + // A glFlush is necessary to ensure correct content appears. + glFlush(); - // If we've passed that marker, then wait for the work behind the fence to - // complete. - if (swap->gl_fence) { + CheckGLErrors("After fence/flush"); + } else { + // GLFence isn't supported - issue a glFinish on each frame to ensure + // there is backpressure from GL. gfx::ScopedSetGLToRealGLApi scoped_set_gl_api; - gfx::ScopedCGLSetCurrentContext scoped_set_current(swap->cgl_context); - - CheckGLErrors("before waiting on fence"); - if (!swap->gl_fence->HasCompleted()) { - TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::ClientWait"); - swap->gl_fence->ClientWait(); - } - swap->gl_fence.reset(); - CheckGLErrors("after waiting on fence"); + TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::glFinish"); + CheckGLErrors("Before finish"); + glFinish(); + CheckGLErrors("After finish"); } - return true; -} - -void ImageTransportSurfaceOverlayMac::DisplayFirstPendingSwapImmediately() { - TRACE_EVENT0("gpu", - "ImageTransportSurfaceOverlayMac::DisplayFirstPendingSwapImmediately"); - DCHECK(!pending_swaps_.empty()); - linked_ptr<PendingSwap> swap = pending_swaps_.front(); - - // If there is a fence for this object, delete it. - if (swap->gl_fence) { - gfx::ScopedSetGLToRealGLApi scoped_set_gl_api; - gfx::ScopedCGLSetCurrentContext scoped_set_current(swap->cgl_context); - CheckGLErrors("before deleting active fence"); - swap->gl_fence.reset(); - CheckGLErrors("while deleting active fence"); - } + base::TimeTicks finish_time = base::TimeTicks::Now(); - // Update the CALayer hierarchy. - { - gfx::RectF pixel_damage_rect = gfx::RectF(swap->pixel_damage_rect); - ScopedCAActionDisabler disabler; - if (swap->ca_layer_tree) { - swap->ca_layer_tree->CommitScheduledCALayers( - ca_root_layer_.get(), std::move(current_ca_layer_tree_), - swap->scale_factor); - current_ca_layer_tree_.swap(swap->ca_layer_tree); - current_partial_damage_tree_.reset(); - } else if (swap->partial_damage_tree) { - swap->partial_damage_tree->CommitCALayers( - ca_root_layer_.get(), std::move(current_partial_damage_tree_), - swap->scale_factor, swap->pixel_damage_rect); - current_partial_damage_tree_.swap(swap->partial_damage_tree); - current_ca_layer_tree_.reset(); - } else { - TRACE_EVENT0("gpu", "Blank frame: No overlays or CALayers"); - [ca_root_layer_ setSublayers:nil]; - current_partial_damage_tree_.reset(); - current_ca_layer_tree_.reset(); - } - swap->ca_layer_tree.reset(); - swap->partial_damage_tree.reset(); - } + bool fullscreen_low_power_layer_valid = false; + ca_layer_tree_coordinator_->CommitPendingTreesToCA( + pixel_damage_rect, &fullscreen_low_power_layer_valid); + // TODO(ccameron): Plumb the fullscreen low power layer through to the + // appropriate window. // Update the latency info to reflect the swap time. - base::TimeTicks swap_time = base::TimeTicks::Now(); - for (auto latency_info : swap->latency_info) { + for (auto latency_info : latency_info_) { latency_info.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1); + ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, finish_time, 1); latency_info.AddLatencyNumberWithTimestamp( ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0, - swap_time, 1); + finish_time, 1); } // Send acknowledgement to the browser. CAContextID ca_context_id = 0; - gfx::ScopedRefCountedIOSurfaceMachPort io_surface; + CAContextID fullscreen_low_power_ca_context_id = 0; + gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port; if (use_remote_layer_api_) { ca_context_id = [ca_context_ contextId]; - } else if (current_partial_damage_tree_) { - io_surface.reset(IOSurfaceCreateMachPort( - current_partial_damage_tree_->RootLayerIOSurface())); - } - gfx::Size size = swap->pixel_size; - float scale_factor = swap->scale_factor; - std::vector<ui::LatencyInfo> latency_info; - latency_info.swap(swap->latency_info); - SendAcceleratedSurfaceBuffersSwapped(handle_, ca_context_id, io_surface, size, - scale_factor, std::move(latency_info)); - - // Remove this from the queue, and reset any callback timers. - pending_swaps_.pop_front(); -} - -void ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps() { - TRACE_EVENT0("gpu", - "ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps"); - while (!pending_swaps_.empty()) - DisplayFirstPendingSwapImmediately(); -} - -void ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback() { - TRACE_EVENT0("gpu", - "ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback"); - - if (pending_swaps_.empty()) - return; - - const base::TimeTicks now = base::TimeTicks::Now(); - if (IsFirstPendingSwapReadyToDisplay(now)) - DisplayFirstPendingSwapImmediately(); - PostCheckPendingSwapsCallbackIfNeeded(now); -} - -void ImageTransportSurfaceOverlayMac::PostCheckPendingSwapsCallbackIfNeeded( - const base::TimeTicks& now) { - TRACE_EVENT0("gpu", - "ImageTransportSurfaceOverlayMac::PostCheckPendingSwapsCallbackIfNeeded"); - - if (pending_swaps_.empty()) { - display_pending_swap_timer_.Stop(); + fullscreen_low_power_ca_context_id = + [fullscreen_low_power_ca_context_ contextId]; } else { - display_pending_swap_timer_.Start( - FROM_HERE, - pending_swaps_.front()->target_display_time - now, - base::Bind(&ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback, - weak_factory_.GetWeakPtr())); + IOSurfaceRef io_surface = + ca_layer_tree_coordinator_->GetIOSurfaceForDisplay(); + if (io_surface) + io_surface_mach_port.reset(IOSurfaceCreateMachPort(io_surface)); } + SendAcceleratedSurfaceBuffersSwapped( + handle_, ca_context_id, fullscreen_low_power_layer_valid, + fullscreen_low_power_ca_context_id, io_surface_mach_port, pixel_size_, + scale_factor_, std::move(latency_info_)); + + // Reset all state for the next frame. + latency_info_.clear(); + return gfx::SwapResult::SWAP_ACK; } gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffers() { @@ -453,14 +291,6 @@ bool ImageTransportSurfaceOverlayMac::OnMakeCurrent(gfx::GLContext* context) { return true; } -bool ImageTransportSurfaceOverlayMac::SetBackbufferAllocation(bool allocated) { - if (!allocated) { - DisplayAndClearAllPendingSwaps(); - last_swap_time_ = base::TimeTicks(); - } - return true; -} - bool ImageTransportSurfaceOverlayMac::ScheduleOverlayPlane( int z_order, gfx::OverlayTransform transform, @@ -475,15 +305,8 @@ bool ImageTransportSurfaceOverlayMac::ScheduleOverlayPlane( DLOG(ERROR) << "Invalid non-zero Z order."; return false; } - if (pending_partial_damage_tree_) { - DLOG(ERROR) << "Only one overlay per swap is allowed."; - return false; - } - pending_partial_damage_tree_.reset(new CALayerPartialDamageTree( - use_remote_layer_api_, - static_cast<gl::GLImageIOSurface*>(image)->io_surface(), - pixel_frame_rect)); - return true; + return ca_layer_tree_coordinator_->SetPendingGLRendererBackbuffer( + static_cast<gl::GLImageIOSurface*>(image)->io_surface()); } bool ImageTransportSurfaceOverlayMac::ScheduleCALayer( @@ -496,18 +319,22 @@ bool ImageTransportSurfaceOverlayMac::ScheduleCALayer( bool is_clipped, const gfx::RectF& clip_rect, const gfx::Transform& transform, - int sorting_context_id) { + int sorting_context_id, + unsigned filter) { base::ScopedCFTypeRef<IOSurfaceRef> io_surface; + base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer; if (contents_image) { - io_surface = - static_cast<gl::GLImageIOSurface*>(contents_image)->io_surface(); + gl::GLImageIOSurface* io_surface_image = + static_cast<gl::GLImageIOSurface*>(contents_image); + io_surface = io_surface_image->io_surface(); + cv_pixel_buffer = io_surface_image->cv_pixel_buffer(); } - if (!pending_ca_layer_tree_) - pending_ca_layer_tree_.reset(new CALayerTree); - return pending_ca_layer_tree_->ScheduleCALayer( - is_clipped, gfx::ToEnclosingRect(clip_rect), sorting_context_id, - transform, io_surface, contents_rect, gfx::ToEnclosingRect(rect), - background_color, edge_aa_mask, opacity); + return ca_layer_tree_coordinator_->GetPendingCARendererLayerTree() + ->ScheduleCALayer(is_clipped, gfx::ToEnclosingRect(clip_rect), + sorting_context_id, transform, io_surface, + cv_pixel_buffer, contents_rect, + gfx::ToEnclosingRect(rect), background_color, + edge_aa_mask, opacity, filter); } bool ImageTransportSurfaceOverlayMac::IsSurfaceless() const { @@ -517,10 +344,9 @@ bool ImageTransportSurfaceOverlayMac::IsSurfaceless() const { bool ImageTransportSurfaceOverlayMac::Resize(const gfx::Size& pixel_size, float scale_factor, bool has_alpha) { - // Flush through any pending frames. - DisplayAndClearAllPendingSwaps(); pixel_size_ = pixel_size; scale_factor_ = scale_factor; + ca_layer_tree_coordinator_->Resize(pixel_size, scale_factor); return true; } @@ -546,18 +372,4 @@ void ImageTransportSurfaceOverlayMac::OnGpuSwitched() { FROM_HERE, base::Bind(&IOSurfaceContextNoOp, context_on_new_gpu)); } -base::TimeTicks ImageTransportSurfaceOverlayMac::GetNextVSyncTimeAfter( - const base::TimeTicks& from, double interval_fraction) { - if (!vsync_parameters_valid_) - return from; - - // Compute the previous vsync time. - base::TimeTicks previous_vsync = - vsync_interval_ * ((from - vsync_timebase_) / vsync_interval_) + - vsync_timebase_; - - // Return |interval_fraction| through the next vsync. - return previous_vsync + (1 + interval_fraction) * vsync_interval_; -} - } // namespace gpu diff --git a/chromium/gpu/ipc/service/image_transport_surface_win.cc b/chromium/gpu/ipc/service/image_transport_surface_win.cc index 818e7c81d3f..3bc4faed8d2 100644 --- a/chromium/gpu/ipc/service/image_transport_surface_win.cc +++ b/chromium/gpu/ipc/service/image_transport_surface_win.cc @@ -4,12 +4,15 @@ #include "gpu/ipc/service/image_transport_surface.h" +#include <memory> + #include "gpu/ipc/service/child_window_surface_win.h" #include "gpu/ipc/service/pass_through_image_transport_surface.h" #include "ui/gfx/native_widget_types.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_surface_egl.h" +#include "ui/gl/init/gl_factory.h" #include "ui/gl/vsync_provider_win.h" namespace gpu { @@ -30,12 +33,12 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface( surface = egl_surface; // TODO(jbauman): Get frame statistics from DirectComposition - scoped_ptr<gfx::VSyncProvider> vsync_provider( + std::unique_ptr<gfx::VSyncProvider> vsync_provider( new gfx::VSyncProviderWin(surface_handle)); if (!egl_surface->Initialize(std::move(vsync_provider))) return nullptr; } else { - surface = gfx::GLSurface::CreateViewGLSurface(surface_handle); + surface = gl::init::CreateViewGLSurface(surface_handle); if (!surface) return nullptr; } diff --git a/chromium/gpu/ipc/service/pass_through_image_transport_surface.cc b/chromium/gpu/ipc/service/pass_through_image_transport_surface.cc index 2fdfb6ca2f5..0c2643f6778 100644 --- a/chromium/gpu/ipc/service/pass_through_image_transport_surface.cc +++ b/chromium/gpu/ipc/service/pass_through_image_transport_surface.cc @@ -8,6 +8,7 @@ #include "base/bind_helpers.h" #include "base/command_line.h" #include "build/build_config.h" +#include "gpu/ipc/common/gpu_messages.h" #include "gpu/ipc/service/gpu_command_buffer_stub.h" #include "ui/gfx/vsync_provider.h" #include "ui/gl/gl_context.h" @@ -40,7 +41,8 @@ void PassThroughImageTransportSurface::Destroy() { } gfx::SwapResult PassThroughImageTransportSurface::SwapBuffers() { - scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers(); + std::unique_ptr<std::vector<ui::LatencyInfo>> latency_info = + StartSwapBuffers(); gfx::SwapResult result = gfx::GLSurfaceAdapter::SwapBuffers(); FinishSwapBuffers(std::move(latency_info), result); return result; @@ -48,7 +50,8 @@ gfx::SwapResult PassThroughImageTransportSurface::SwapBuffers() { void PassThroughImageTransportSurface::SwapBuffersAsync( const GLSurface::SwapCompletionCallback& callback) { - scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers(); + std::unique_ptr<std::vector<ui::LatencyInfo>> latency_info = + StartSwapBuffers(); // We use WeakPtr here to avoid manual management of life time of an instance // of this class. Callback will not be called once the instance of this class @@ -63,7 +66,8 @@ gfx::SwapResult PassThroughImageTransportSurface::PostSubBuffer(int x, int y, int width, int height) { - scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers(); + std::unique_ptr<std::vector<ui::LatencyInfo>> latency_info = + StartSwapBuffers(); gfx::SwapResult result = gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height); FinishSwapBuffers(std::move(latency_info), result); @@ -76,7 +80,8 @@ void PassThroughImageTransportSurface::PostSubBufferAsync( int width, int height, const GLSurface::SwapCompletionCallback& callback) { - scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers(); + std::unique_ptr<std::vector<ui::LatencyInfo>> latency_info = + StartSwapBuffers(); gfx::GLSurfaceAdapter::PostSubBufferAsync( x, y, width, height, base::Bind(&PassThroughImageTransportSurface::FinishSwapBuffersAsync, @@ -85,7 +90,8 @@ void PassThroughImageTransportSurface::PostSubBufferAsync( } gfx::SwapResult PassThroughImageTransportSurface::CommitOverlayPlanes() { - scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers(); + std::unique_ptr<std::vector<ui::LatencyInfo>> latency_info = + StartSwapBuffers(); gfx::SwapResult result = gfx::GLSurfaceAdapter::CommitOverlayPlanes(); FinishSwapBuffers(std::move(latency_info), result); return result; @@ -93,7 +99,8 @@ gfx::SwapResult PassThroughImageTransportSurface::CommitOverlayPlanes() { void PassThroughImageTransportSurface::CommitOverlayPlanesAsync( const GLSurface::SwapCompletionCallback& callback) { - scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers(); + std::unique_ptr<std::vector<ui::LatencyInfo>> latency_info = + StartSwapBuffers(); gfx::GLSurfaceAdapter::CommitOverlayPlanesAsync(base::Bind( &PassThroughImageTransportSurface::FinishSwapBuffersAsync, weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info), callback)); @@ -132,7 +139,7 @@ void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() { } } -scoped_ptr<std::vector<ui::LatencyInfo>> +std::unique_ptr<std::vector<ui::LatencyInfo>> PassThroughImageTransportSurface::StartSwapBuffers() { // GetVsyncValues before SwapBuffers to work around Mali driver bug: // crbug.com/223558. @@ -144,7 +151,7 @@ PassThroughImageTransportSurface::StartSwapBuffers() { ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1); } - scoped_ptr<std::vector<ui::LatencyInfo>> latency_info( + std::unique_ptr<std::vector<ui::LatencyInfo>> latency_info( new std::vector<ui::LatencyInfo>()); latency_info->swap(latency_info_); @@ -152,7 +159,7 @@ PassThroughImageTransportSurface::StartSwapBuffers() { } void PassThroughImageTransportSurface::FinishSwapBuffers( - scoped_ptr<std::vector<ui::LatencyInfo>> latency_info, + std::unique_ptr<std::vector<ui::LatencyInfo>> latency_info, gfx::SwapResult result) { base::TimeTicks swap_ack_time = base::TimeTicks::Now(); for (auto& latency : *latency_info) { @@ -161,11 +168,14 @@ void PassThroughImageTransportSurface::FinishSwapBuffers( swap_ack_time, 1); } - stub_->SendSwapBuffersCompleted(*latency_info, result); + GpuCommandBufferMsg_SwapBuffersCompleted_Params params; + params.latency_info = *latency_info; + params.result = result; + stub_->SendSwapBuffersCompleted(params); } void PassThroughImageTransportSurface::FinishSwapBuffersAsync( - scoped_ptr<std::vector<ui::LatencyInfo>> latency_info, + std::unique_ptr<std::vector<ui::LatencyInfo>> latency_info, GLSurface::SwapCompletionCallback callback, gfx::SwapResult result) { FinishSwapBuffers(std::move(latency_info), result); diff --git a/chromium/gpu/ipc/service/pass_through_image_transport_surface.h b/chromium/gpu/ipc/service/pass_through_image_transport_surface.h index b63194a7841..084b07c0b91 100644 --- a/chromium/gpu/ipc/service/pass_through_image_transport_surface.h +++ b/chromium/gpu/ipc/service/pass_through_image_transport_surface.h @@ -7,10 +7,10 @@ #include <stdint.h> +#include <memory> #include <vector> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "gpu/ipc/service/image_transport_surface.h" #include "ui/events/latency_info.h" @@ -52,11 +52,12 @@ class PassThroughImageTransportSurface : public gfx::GLSurfaceAdapter { void SendVSyncUpdateIfAvailable(); void SetLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info); - scoped_ptr<std::vector<ui::LatencyInfo>> StartSwapBuffers(); - void FinishSwapBuffers(scoped_ptr<std::vector<ui::LatencyInfo>> latency_info, - gfx::SwapResult result); + std::unique_ptr<std::vector<ui::LatencyInfo>> StartSwapBuffers(); + void FinishSwapBuffers( + std::unique_ptr<std::vector<ui::LatencyInfo>> latency_info, + gfx::SwapResult result); void FinishSwapBuffersAsync( - scoped_ptr<std::vector<ui::LatencyInfo>> latency_info, + std::unique_ptr<std::vector<ui::LatencyInfo>> latency_info, GLSurface::SwapCompletionCallback callback, gfx::SwapResult result); diff --git a/chromium/gpu/ipc/service/stream_texture_android.cc b/chromium/gpu/ipc/service/stream_texture_android.cc index fd4be171370..525cb4d1f9a 100644 --- a/chromium/gpu/ipc/service/stream_texture_android.cc +++ b/chromium/gpu/ipc/service/stream_texture_android.cc @@ -51,7 +51,7 @@ bool StreamTexture::Create(GpuCommandBufferStub* owner_stub, GL_UNSIGNED_BYTE, gfx::Rect(size)); texture_manager->SetLevelStreamTextureImage( texture, GL_TEXTURE_EXTERNAL_OES, 0, gl_image.get(), - gles2::Texture::UNBOUND); + gles2::Texture::UNBOUND, 0); return true; } @@ -91,8 +91,11 @@ StreamTexture::~StreamTexture() { // gpu::gles2::GLStreamTextureMatrix implementation void StreamTexture::GetTextureMatrix(float xform[16]) { - UpdateTexImage(); - surface_texture_->GetTransformMatrix(xform); + if (surface_texture_) { + UpdateTexImage(); + surface_texture_->GetTransformMatrix(current_matrix_); + } + memcpy(xform, current_matrix_, sizeof(current_matrix_)); } void StreamTexture::OnWillDestroyStub() { @@ -100,7 +103,8 @@ void StreamTexture::OnWillDestroyStub() { owner_stub_->channel()->RemoveRoute(route_id_); if (framebuffer_) { - scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current(MakeStubCurrent()); + std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current( + MakeStubCurrent()); glDeleteProgram(program_); glDeleteShader(vertex_shader_); @@ -126,8 +130,8 @@ void StreamTexture::Destroy(bool have_context) { NOTREACHED(); } -scoped_ptr<ui::ScopedMakeCurrent> StreamTexture::MakeStubCurrent() { - scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current; +std::unique_ptr<ui::ScopedMakeCurrent> StreamTexture::MakeStubCurrent() { + std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current; bool needs_make_current = !owner_stub_->decoder()->GetGLContext()->IsCurrent(NULL); if (needs_make_current) { @@ -143,7 +147,7 @@ void StreamTexture::UpdateTexImage() { if (!has_pending_frame_) return; - scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current(MakeStubCurrent()); + std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current(MakeStubCurrent()); surface_texture_->UpdateTexImage(); @@ -194,7 +198,7 @@ bool StreamTexture::CopyTexImage(unsigned target) { // CopyTexImage() is called each time the surface texture is used for // drawing. texture->SetLevelStreamTextureImage(GL_TEXTURE_EXTERNAL_OES, 0, this, - gles2::Texture::UNBOUND); + gles2::Texture::UNBOUND, 0); } return true; diff --git a/chromium/gpu/ipc/service/stream_texture_android.h b/chromium/gpu/ipc/service/stream_texture_android.h index 5cf9d14e28c..9f17ba760e1 100644 --- a/chromium/gpu/ipc/service/stream_texture_android.h +++ b/chromium/gpu/ipc/service/stream_texture_android.h @@ -7,6 +7,8 @@ #include <stdint.h> +#include <memory> + #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "gpu/command_buffer/service/gl_stream_texture_image.h" @@ -64,7 +66,7 @@ class StreamTexture : public gpu::gles2::GLStreamTextureImage, // GpuCommandBufferStub::DestructionObserver implementation. void OnWillDestroyStub() override; - scoped_ptr<ui::ScopedMakeCurrent> MakeStubCurrent(); + std::unique_ptr<ui::ScopedMakeCurrent> MakeStubCurrent(); void UpdateTexImage(); diff --git a/chromium/gpu/khronos_glcts_support/BUILD.gn b/chromium/gpu/khronos_glcts_support/BUILD.gn index dfd5253df8e..9df5736910c 100644 --- a/chromium/gpu/khronos_glcts_support/BUILD.gn +++ b/chromium/gpu/khronos_glcts_support/BUILD.gn @@ -540,27 +540,29 @@ if (internal_khronos_glcts_tests) { } } -# GYP version: gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test -test("khronos_glcts_test") { - sources = [ - "khronos_glcts_test.cc", - ] - - deps = [ - "//base", - "//gpu", - "//testing/gtest", - ] - - data = [ - "khronos_glcts_test_expectations.txt", - ] - - if (internal_khronos_glcts_tests) { - sources += [ "$target_gen_dir/khronos_glcts_test_autogen.cc" ] - deps += [ - ":generate_khronos_glcts_tests", - ":khronos_glcts_test_windowless", +if (!is_android) { + # GYP version: gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test + test("khronos_glcts_test") { + sources = [ + "khronos_glcts_test.cc", + ] + + deps = [ + "//base", + "//gpu", + "//testing/gtest", ] + + data = [ + "khronos_glcts_test_expectations.txt", + ] + + if (internal_khronos_glcts_tests) { + sources += [ "$target_gen_dir/khronos_glcts_test_autogen.cc" ] + deps += [ + ":generate_khronos_glcts_tests", + ":khronos_glcts_test_windowless", + ] + } } } diff --git a/chromium/gpu/khronos_glcts_support/native/egl_native_windowless.cc b/chromium/gpu/khronos_glcts_support/native/egl_native_windowless.cc index 0bed202b0a8..548f90b258b 100644 --- a/chromium/gpu/khronos_glcts_support/native/egl_native_windowless.cc +++ b/chromium/gpu/khronos_glcts_support/native/egl_native_windowless.cc @@ -6,7 +6,7 @@ // TODO: We may want to phase out the old gles2_conform support in preference // of this implementation. So eventually we'll need to move the egl_native // stuff here or to a shareable location/path. -#include "gpu/gles2_conform_support/egl/display.h" +#include "gpu/gles2_conform_support/egl/test_support.h" #include "third_party/khronos_glcts/framework/egl/tcuEglPlatform.hpp" @@ -74,9 +74,9 @@ class Platform : public tcu::EglPlatform { int height, qpVisibility visibility) override { tcu::egl::Display& eglDisplay = dpy.getEglDisplay(); - egl::Display* display = - static_cast<egl::Display*>(eglDisplay.getEGLDisplay()); - display->SetCreateOffscreen(width, height); + EGLDisplay display = eglDisplay.getEGLDisplay(); + CommandBufferGLESSetNextCreateWindowSurfaceCreatesPBuffer(display, width, + height); return new Window(eglDisplay, config, attribList, width, height); } }; diff --git a/chromium/gpu/perftests/measurements.h b/chromium/gpu/perftests/measurements.h index e0d9de36dc2..f92e7ad615b 100644 --- a/chromium/gpu/perftests/measurements.h +++ b/chromium/gpu/perftests/measurements.h @@ -5,9 +5,9 @@ #ifndef GPU_PERFTESTS_MEASUREMENTS_H_ #define GPU_PERFTESTS_MEASUREMENTS_H_ +#include <memory> #include <string> -#include "base/memory/scoped_ptr.h" #include "base/time/time.h" namespace gfx { @@ -49,7 +49,7 @@ class MeasurementTimers { private: base::TimeTicks wall_time_start_; base::ThreadTicks cpu_time_start_; - scoped_ptr<gfx::GPUTimer> gpu_timer_; + std::unique_ptr<gfx::GPUTimer> gpu_timer_; base::TimeDelta wall_time_; base::TimeDelta cpu_time_; diff --git a/chromium/gpu/perftests/texture_upload_perftest.cc b/chromium/gpu/perftests/texture_upload_perftest.cc index c3f3dfb3bf6..86eeb021d2f 100644 --- a/chromium/gpu/perftests/texture_upload_perftest.cc +++ b/chromium/gpu/perftests/texture_upload_perftest.cc @@ -6,12 +6,12 @@ #include <stdint.h> #include <algorithm> +#include <memory> #include <vector> #include "base/containers/small_map.h" #include "base/logging.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/strings/stringprintf.h" #include "gpu/perftests/measurements.h" #include "testing/gmock/include/gmock/gmock.h" @@ -25,6 +25,7 @@ #include "ui/gl/gl_surface.h" #include "ui/gl/gl_version_info.h" #include "ui/gl/gpu_timing.h" +#include "ui/gl/init/gl_factory.h" #include "ui/gl/scoped_make_current.h" #if defined(USE_OZONE) @@ -84,7 +85,7 @@ GLuint LoadShader(const GLenum type, const char* const src) { GLint len = 0; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); if (len > 1) { - scoped_ptr<char[]> error_log(new char[len]); + std::unique_ptr<char[]> error_log(new char[len]); glGetShaderInfoLog(shader, len, NULL, error_log.get()); LOG(ERROR) << "Error compiling shader: " << error_log.get(); } @@ -183,13 +184,13 @@ class TextureUploadPerfTest : public testing::Test { // thread. base::MessageLoopForUI main_loop; #endif - static bool gl_initialized = gfx::GLSurface::InitializeOneOff(); + static bool gl_initialized = gl::init::InitializeGLOneOff(); DCHECK(gl_initialized); // Initialize an offscreen surface and a gl context. - surface_ = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size()); - gl_context_ = gfx::GLContext::CreateGLContext(NULL, // share_group - surface_.get(), - gfx::PreferIntegratedGpu); + surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size()); + gl_context_ = + gl::init::CreateGLContext(nullptr, // share_group + surface_.get(), gfx::PreferIntegratedGpu); ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); glGenTextures(1, &color_texture_); glBindTexture(GL_TEXTURE_2D, color_texture_); diff --git a/chromium/gpu/skia_bindings/BUILD.gn b/chromium/gpu/skia_bindings/BUILD.gn index 3205a4a80f7..f9d96c38576 100644 --- a/chromium/gpu/skia_bindings/BUILD.gn +++ b/chromium/gpu/skia_bindings/BUILD.gn @@ -6,6 +6,8 @@ source_set("skia_bindings") { sources = [ "gl_bindings_skia_cmd_buffer.cc", "gl_bindings_skia_cmd_buffer.h", + "grcontext_for_gles2_interface.cc", + "grcontext_for_gles2_interface.h", ] deps = [ "//base", diff --git a/chromium/gpu/skia_bindings/grcontext_for_gles2_interface.cc b/chromium/gpu/skia_bindings/grcontext_for_gles2_interface.cc new file mode 100644 index 00000000000..57a68f97fe5 --- /dev/null +++ b/chromium/gpu/skia_bindings/grcontext_for_gles2_interface.cc @@ -0,0 +1,67 @@ +// Copyright (c) 2013 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_bindings/grcontext_for_gles2_interface.h" + +#include <stddef.h> +#include <string.h> +#include <utility> + +#include "base/lazy_instance.h" +#include "base/macros.h" +#include "base/trace_event/trace_event.h" +#include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h" +#include "third_party/skia/include/gpu/GrContext.h" +#include "third_party/skia/include/gpu/gl/GrGLInterface.h" + +namespace skia_bindings { + +GrContextForGLES2Interface::GrContextForGLES2Interface( + gpu::gles2::GLES2Interface* gl) { + sk_sp<GrGLInterface> interface( + skia_bindings::CreateGLES2InterfaceBindings(gl)); + gr_context_ = sk_sp<GrContext>( + GrContext::Create(kOpenGL_GrBackend, + // GrContext takes ownership of |interface|. + reinterpret_cast<GrBackendContext>(interface.get()))); + if (gr_context_) { + // The limit of the number of GPU resources we hold in the GrContext's + // GPU cache. + static const int kMaxGaneshResourceCacheCount = 2048; + // The limit of the bytes allocated toward GPU resources in the GrContext's + // GPU cache. + static const size_t kMaxGaneshResourceCacheBytes = 96 * 1024 * 1024; + + gr_context_->setResourceCacheLimits(kMaxGaneshResourceCacheCount, + kMaxGaneshResourceCacheBytes); + } +} + +GrContextForGLES2Interface::~GrContextForGLES2Interface() { + // At this point the GLES2Interface is going to be destroyed, so have + // the GrContext clean up and not try to use it anymore. + if (gr_context_) + gr_context_->releaseResourcesAndAbandonContext(); +} + +void GrContextForGLES2Interface::OnLostContext() { + if (gr_context_) + gr_context_->abandonContext(); +} + +void GrContextForGLES2Interface::ResetContext(uint32_t state) { + if (gr_context_) + gr_context_->resetContext(state); +} + +void GrContextForGLES2Interface::FreeGpuResources() { + if (gr_context_) { + TRACE_EVENT_INSTANT0("gpu", "GrContext::freeGpuResources", + TRACE_EVENT_SCOPE_THREAD); + gr_context_->freeGpuResources(); + } +} + +} // namespace skia_bindings diff --git a/chromium/gpu/skia_bindings/grcontext_for_gles2_interface.h b/chromium/gpu/skia_bindings/grcontext_for_gles2_interface.h new file mode 100644 index 00000000000..3813fb47bcd --- /dev/null +++ b/chromium/gpu/skia_bindings/grcontext_for_gles2_interface.h @@ -0,0 +1,43 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_SKIA_BINDINGS_GRCONTEXT_FOR_GLES2_INTERFACE_H_ +#define GPU_SKIA_BINDINGS_GRCONTEXT_FOR_GLES2_INTERFACE_H_ + +#include "base/macros.h" +#include "third_party/skia/include/core/SkRefCnt.h" + +class GrContext; + +namespace gpu { +namespace gles2 { +class GLES2Interface; +} +} + +namespace skia_bindings { + +// This class binds an offscreen GrContext to an offscreen context3d. The +// context3d is used by the GrContext so must be valid as long as this class +// is alive. +class GrContextForGLES2Interface { + public: + explicit GrContextForGLES2Interface(gpu::gles2::GLES2Interface* gl); + virtual ~GrContextForGLES2Interface(); + + GrContext* get() { return gr_context_.get(); } + + void OnLostContext(); + void ResetContext(uint32_t state); + void FreeGpuResources(); + + private: + sk_sp<class GrContext> gr_context_; + + DISALLOW_COPY_AND_ASSIGN(GrContextForGLES2Interface); +}; + +} // namespace skia_bindings + +#endif // GPU_SKIA_BINDINGS_GRCONTEXT_FOR_GLES2_INTERFACE_H_ diff --git a/chromium/gpu/skia_bindings/skia_bindings.gyp b/chromium/gpu/skia_bindings/skia_bindings.gyp index 7c3cf6a2511..322a3792c25 100644 --- a/chromium/gpu/skia_bindings/skia_bindings.gyp +++ b/chromium/gpu/skia_bindings/skia_bindings.gyp @@ -18,6 +18,8 @@ 'sources': [ 'gl_bindings_skia_cmd_buffer.cc', 'gl_bindings_skia_cmd_buffer.h', + 'grcontext_for_gles2_interface.cc', + 'grcontext_for_gles2_interface.h', ], } ] diff --git a/chromium/gpu/tools/compositor_model_bench/BUILD.gn b/chromium/gpu/tools/compositor_model_bench/BUILD.gn index b074ee772ea..fbef186806b 100644 --- a/chromium/gpu/tools/compositor_model_bench/BUILD.gn +++ b/chromium/gpu/tools/compositor_model_bench/BUILD.gn @@ -24,6 +24,7 @@ if (is_linux && !is_chromeos && target_cpu != "arm" && use_x11) { "//base", "//build/config/sanitizers:deps", "//ui/gl", + "//ui/gl/init", ] } } diff --git a/chromium/gpu/tools/compositor_model_bench/compositor_model_bench.cc b/chromium/gpu/tools/compositor_model_bench/compositor_model_bench.cc index 3d3d57f8886..dca35a7b3fa 100644 --- a/chromium/gpu/tools/compositor_model_bench/compositor_model_bench.cc +++ b/chromium/gpu/tools/compositor_model_bench/compositor_model_bench.cc @@ -28,15 +28,14 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/location.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/single_thread_task_runner.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "gpu/tools/compositor_model_bench/render_model_utils.h" #include "gpu/tools/compositor_model_bench/render_models.h" #include "gpu/tools/compositor_model_bench/render_tree.h" -#include "ui/gl/gl_surface.h" +#include "ui/gl/init/gl_factory.h" using base::TimeTicks; using base::DirectoryExists; @@ -187,8 +186,8 @@ class Simulator { // Initialize the OpenGL context. bool InitGLContext() { - if (!gfx::GLSurface::InitializeOneOff()) { - LOG(FATAL) << "gfx::GLSurface::InitializeOneOff failed"; + if (!gl::init::InitializeGLOneOff()) { + LOG(FATAL) << "gl::init::InitializeGLOneOff failed"; return false; } diff --git a/chromium/gpu/tools/compositor_model_bench/forward_render_model.h b/chromium/gpu/tools/compositor_model_bench/forward_render_model.h index ec34948f535..cceddd93a8d 100644 --- a/chromium/gpu/tools/compositor_model_bench/forward_render_model.h +++ b/chromium/gpu/tools/compositor_model_bench/forward_render_model.h @@ -7,8 +7,9 @@ #ifndef GPU_TOOLS_COMPOSITOR_MODEL_BENCH_FORWARD_RENDER_MODEL_H_ #define GPU_TOOLS_COMPOSITOR_MODEL_BENCH_FORWARD_RENDER_MODEL_H_ +#include <memory> + #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "gpu/tools/compositor_model_bench/render_model_utils.h" #include "gpu/tools/compositor_model_bench/render_models.h" @@ -24,8 +25,8 @@ class ForwardRenderSimulator : public RenderModelSimulator { void Resize(int width, int height) override; private: - scoped_ptr<ForwardRenderNodeVisitor> visitor_; - scoped_ptr<TextureGenerator> textures_; + std::unique_ptr<ForwardRenderNodeVisitor> visitor_; + std::unique_ptr<TextureGenerator> textures_; DISALLOW_IMPLICIT_CONSTRUCTORS(ForwardRenderSimulator); }; diff --git a/chromium/gpu/tools/compositor_model_bench/render_model_utils.h b/chromium/gpu/tools/compositor_model_bench/render_model_utils.h index 916276825c1..4c59f904b1d 100644 --- a/chromium/gpu/tools/compositor_model_bench/render_model_utils.h +++ b/chromium/gpu/tools/compositor_model_bench/render_model_utils.h @@ -10,11 +10,11 @@ #include <stdint.h> #include <map> +#include <memory> #include <set> #include <vector> #include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" #include "gpu/tools/compositor_model_bench/render_tree.h" // This is a visitor that runs over the tree structure that was built from the @@ -23,7 +23,7 @@ // texture ID's in the tree, replacing them with the matching new textures. class TextureGenerator : public RenderNodeVisitor { public: - typedef scoped_ptr<uint8_t[]> ImagePtr; + typedef std::unique_ptr<uint8_t[]> ImagePtr; typedef std::vector<Tile>::iterator tile_iter; explicit TextureGenerator(RenderNode* root); @@ -53,9 +53,9 @@ class TextureGenerator : public RenderNodeVisitor { TextureGenStage stage_; std::set<int> discovered_ids_; - scoped_ptr<GLuint[]> tex_ids_; + std::unique_ptr<GLuint[]> tex_ids_; std::map<int, int> remapped_ids_; - scoped_ptr<ImagePtr[]> image_data_; + std::unique_ptr<ImagePtr[]> image_data_; int images_generated_; std::set<int> ids_for_completed_textures_; }; diff --git a/chromium/gpu/tools/compositor_model_bench/render_models.h b/chromium/gpu/tools/compositor_model_bench/render_models.h index 5d04a3f25cd..cc17dcb3845 100644 --- a/chromium/gpu/tools/compositor_model_bench/render_models.h +++ b/chromium/gpu/tools/compositor_model_bench/render_models.h @@ -8,10 +8,10 @@ #ifndef GPU_TOOLS_COMPOSITOR_MODEL_BENCH_RENDER_MODELS_H_ #define GPU_TOOLS_COMPOSITOR_MODEL_BENCH_RENDER_MODELS_H_ -#include "gpu/tools/compositor_model_bench/render_tree.h" +#include <memory> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" +#include "gpu/tools/compositor_model_bench/render_tree.h" enum RenderModel { ForwardRenderModel @@ -27,7 +27,7 @@ class RenderModelSimulator { protected: explicit RenderModelSimulator(RenderNode* root); - scoped_ptr<RenderNode> root_; + std::unique_ptr<RenderNode> root_; private: DISALLOW_IMPLICIT_CONSTRUCTORS(RenderModelSimulator); diff --git a/chromium/gpu/tools/compositor_model_bench/render_tree.cc b/chromium/gpu/tools/compositor_model_bench/render_tree.cc index 143a1e30d2f..7c495e27e85 100644 --- a/chromium/gpu/tools/compositor_model_bench/render_tree.cc +++ b/chromium/gpu/tools/compositor_model_bench/render_tree.cc @@ -4,6 +4,7 @@ #include "gpu/tools/compositor_model_bench/render_tree.h" +#include <memory> #include <sstream> #include <vector> @@ -12,9 +13,7 @@ #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/values.h" - #include "gpu/tools/compositor_model_bench/shaders.h" using base::JSONReader; @@ -459,7 +458,7 @@ RenderNode* BuildRenderTreeFromFile(const base::FilePath& path) { int error_code = 0; string error_message; - scoped_ptr<base::Value> root = JSONReader::ReadAndReturnError( + std::unique_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() << diff --git a/chromium/gpu/tools/compositor_model_bench/render_tree.h b/chromium/gpu/tools/compositor_model_bench/render_tree.h index 591047421db..01f50ace5bb 100644 --- a/chromium/gpu/tools/compositor_model_bench/render_tree.h +++ b/chromium/gpu/tools/compositor_model_bench/render_tree.h @@ -10,11 +10,12 @@ #include <stddef.h> +#include <memory> #include <string> #include <vector> #include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" +#include "base/memory/ptr_util.h" #include "gpu/tools/compositor_model_bench/shaders.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_implementation.h" @@ -146,11 +147,11 @@ class ContentLayerNode : public RenderNode { } void add_child(RenderNode* child) { - children_.push_back(make_scoped_ptr(child)); + children_.push_back(base::WrapUnique(child)); } private: - std::vector<scoped_ptr<RenderNode>> children_; + std::vector<std::unique_ptr<RenderNode>> children_; bool skipsDraw_; }; diff --git a/chromium/gpu/tools/compositor_model_bench/shaders.cc b/chromium/gpu/tools/compositor_model_bench/shaders.cc index 0ea6275efe7..864f1e26669 100644 --- a/chromium/gpu/tools/compositor_model_bench/shaders.cc +++ b/chromium/gpu/tools/compositor_model_bench/shaders.cc @@ -7,6 +7,7 @@ #include <stdint.h> #include <algorithm> +#include <memory> #include "gpu/tools/compositor_model_bench/render_model_utils.h" #include "gpu/tools/compositor_model_bench/render_tree.h" @@ -237,7 +238,7 @@ static void ReportAnyShaderCompilationErrors(GLuint shader, ShaderID id) { // Get the length of the log string GLsizei length; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); - scoped_ptr<GLchar[]> log(new GLchar[length+1]); + std::unique_ptr<GLchar[]> log(new GLchar[length + 1]); glGetShaderInfoLog(shader, length, NULL, log.get()); LOG(ERROR) << log.get() << " in shader " << ShaderNameFromID(id); } diff --git a/chromium/gpu/tools/tools.gyp b/chromium/gpu/tools/tools.gyp index 342a7690882..c2109c13714 100644 --- a/chromium/gpu/tools/tools.gyp +++ b/chromium/gpu/tools/tools.gyp @@ -19,6 +19,7 @@ '../../base/base.gyp:base', '../../build/linux/system.gyp:x11', '../../ui/gl/gl.gyp:gl', + '../../ui/gl/init/gl_init.gyp:gl_init', ], 'libraries': [ '-lGL', diff --git a/chromium/gpu/vulkan/BUILD.gn b/chromium/gpu/vulkan/BUILD.gn index ff65fa4de36..e59be283e69 100644 --- a/chromium/gpu/vulkan/BUILD.gn +++ b/chromium/gpu/vulkan/BUILD.gn @@ -20,6 +20,12 @@ if (enable_vulkan) { "vulkan_command_buffer.h", "vulkan_command_pool.cc", "vulkan_command_pool.h", + "vulkan_descriptor_layout.cc", + "vulkan_descriptor_layout.h", + "vulkan_descriptor_pool.cc", + "vulkan_descriptor_pool.h", + "vulkan_descriptor_set.cc", + "vulkan_descriptor_set.h", "vulkan_device_queue.cc", "vulkan_device_queue.h", "vulkan_export.h", @@ -30,6 +36,10 @@ if (enable_vulkan) { "vulkan_platform.h", "vulkan_render_pass.cc", "vulkan_render_pass.h", + "vulkan_sampler.cc", + "vulkan_sampler.h", + "vulkan_shader_module.cc", + "vulkan_shader_module.h", "vulkan_surface.cc", "vulkan_surface.h", "vulkan_swap_chain.cc", @@ -53,6 +63,7 @@ if (enable_vulkan) { deps = [ "//base", + "//third_party/shaderc:libshaderc", "//ui/base", "//ui/gfx", ] @@ -66,7 +77,10 @@ if (enable_vulkan) { test("vulkan_tests") { sources = [ + "tests/basic_vulkan_test.cc", + "tests/basic_vulkan_test.h", "tests/native_window.h", + "tests/shader_module_unittest.cc", "tests/vulkan_test.cc", "tests/vulkan_tests_main.cc", ] diff --git a/chromium/gpu/vulkan/vulkan_command_buffer.cc b/chromium/gpu/vulkan/vulkan_command_buffer.cc index 5f345256e34..25190261fe3 100644 --- a/chromium/gpu/vulkan/vulkan_command_buffer.cc +++ b/chromium/gpu/vulkan/vulkan_command_buffer.cc @@ -148,14 +148,20 @@ void VulkanCommandBuffer::ResetIfDirty() { // using the asynchronous SubmissionFinished() function. VkDevice device = device_queue_->GetVulkanDevice(); vkWaitForFences(device, 1, &submission_fence_, true, UINT64_MAX); - - vkResetCommandBuffer(command_buffer_, 0); - record_type_ = RECORD_TYPE_EMPTY; + VkResult result = vkResetCommandBuffer(command_buffer_, 0); + if (VK_SUCCESS != result) { + DLOG(ERROR) << "vkResetCommandBuffer() failed: " << result; + } else { + record_type_ = RECORD_TYPE_EMPTY; + } } } CommandBufferRecorderBase::~CommandBufferRecorderBase() { - vkEndCommandBuffer(handle_); + VkResult result = vkEndCommandBuffer(handle_); + if (VK_SUCCESS != result) { + DLOG(ERROR) << "vkEndCommandBuffer() failed: " << result; + } }; ScopedMultiUseCommandBufferRecorder::ScopedMultiUseCommandBufferRecorder( @@ -164,7 +170,11 @@ ScopedMultiUseCommandBufferRecorder::ScopedMultiUseCommandBufferRecorder( ValidateMultiUse(command_buffer); VkCommandBufferBeginInfo begin_info = {}; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(handle_, &begin_info); + VkResult result = vkBeginCommandBuffer(handle_, &begin_info); + + if (VK_SUCCESS != result) { + DLOG(ERROR) << "vkBeginCommandBuffer() failed: " << result; + } } ScopedSingleUseCommandBufferRecorder::ScopedSingleUseCommandBufferRecorder( @@ -174,7 +184,11 @@ ScopedSingleUseCommandBufferRecorder::ScopedSingleUseCommandBufferRecorder( VkCommandBufferBeginInfo begin_info = {}; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - vkBeginCommandBuffer(handle_, &begin_info); + VkResult result = vkBeginCommandBuffer(handle_, &begin_info); + + if (VK_SUCCESS != result) { + DLOG(ERROR) << "vkBeginCommandBuffer() failed: " << result; + } } } // namespace gpu diff --git a/chromium/gpu/vulkan/vulkan_command_buffer.h b/chromium/gpu/vulkan/vulkan_command_buffer.h index 787488c1d7b..b55b02cb203 100644 --- a/chromium/gpu/vulkan/vulkan_command_buffer.h +++ b/chromium/gpu/vulkan/vulkan_command_buffer.h @@ -9,7 +9,6 @@ #include "base/logging.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "gpu/vulkan/vulkan_export.h" namespace gpu { diff --git a/chromium/gpu/vulkan/vulkan_command_pool.cc b/chromium/gpu/vulkan/vulkan_command_pool.cc index da781039720..9f741f3c57a 100644 --- a/chromium/gpu/vulkan/vulkan_command_pool.cc +++ b/chromium/gpu/vulkan/vulkan_command_pool.cc @@ -46,9 +46,9 @@ void VulkanCommandPool::Destroy() { } } -scoped_ptr<VulkanCommandBuffer> +std::unique_ptr<VulkanCommandBuffer> VulkanCommandPool::CreatePrimaryCommandBuffer() { - scoped_ptr<VulkanCommandBuffer> command_buffer( + std::unique_ptr<VulkanCommandBuffer> command_buffer( new VulkanCommandBuffer(device_queue_, this, true)); if (!command_buffer->Initialize()) return nullptr; @@ -56,9 +56,9 @@ VulkanCommandPool::CreatePrimaryCommandBuffer() { return command_buffer; } -scoped_ptr<VulkanCommandBuffer> +std::unique_ptr<VulkanCommandBuffer> VulkanCommandPool::CreateSecondaryCommandBuffer() { - scoped_ptr<VulkanCommandBuffer> command_buffer( + std::unique_ptr<VulkanCommandBuffer> command_buffer( new VulkanCommandBuffer(device_queue_, this, false)); if (!command_buffer->Initialize()) return nullptr; diff --git a/chromium/gpu/vulkan/vulkan_command_pool.h b/chromium/gpu/vulkan/vulkan_command_pool.h index 5b763ef5801..b54d5917c2e 100644 --- a/chromium/gpu/vulkan/vulkan_command_pool.h +++ b/chromium/gpu/vulkan/vulkan_command_pool.h @@ -7,8 +7,9 @@ #include <vulkan/vulkan.h> +#include <memory> + #include "base/macros.h" -#include "base/memory/scoped_ptr.h" namespace gpu { @@ -23,8 +24,8 @@ class VulkanCommandPool { bool Initialize(); void Destroy(); - scoped_ptr<VulkanCommandBuffer> CreatePrimaryCommandBuffer(); - scoped_ptr<VulkanCommandBuffer> CreateSecondaryCommandBuffer(); + std::unique_ptr<VulkanCommandBuffer> CreatePrimaryCommandBuffer(); + std::unique_ptr<VulkanCommandBuffer> CreateSecondaryCommandBuffer(); VkCommandPool handle() { return handle_; } diff --git a/chromium/gpu/vulkan/vulkan_descriptor_layout.cc b/chromium/gpu/vulkan/vulkan_descriptor_layout.cc new file mode 100644 index 00000000000..bc5772faf4a --- /dev/null +++ b/chromium/gpu/vulkan/vulkan_descriptor_layout.cc @@ -0,0 +1,49 @@ +// Copyright (c) 2016 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/vulkan/vulkan_descriptor_layout.h" + +#include "base/logging.h" +#include "gpu/vulkan/vulkan_descriptor_pool.h" +#include "gpu/vulkan/vulkan_device_queue.h" + +namespace gpu { + +VulkanDescriptorLayout::VulkanDescriptorLayout(VulkanDeviceQueue* device_queue) + : device_queue_(device_queue) {} + +VulkanDescriptorLayout::~VulkanDescriptorLayout() { + DCHECK_EQ(static_cast<VkDescriptorSetLayout>(VK_NULL_HANDLE), handle_); +} + +bool VulkanDescriptorLayout::Initialize( + const std::vector<VkDescriptorSetLayoutBinding>& layout) { + VkResult result = VK_SUCCESS; + VkDevice device = device_queue_->GetVulkanDevice(); + + VkDescriptorSetLayoutCreateInfo layout_create_info = {}; + layout_create_info.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layout_create_info.bindingCount = static_cast<uint32_t>(layout.size()); + layout_create_info.pBindings = layout.data(); + + result = vkCreateDescriptorSetLayout(device, &layout_create_info, nullptr, + &handle_); + if (VK_SUCCESS != result) { + DLOG(ERROR) << "vkCreateDescriptorSetLayout() failed: " << result; + return false; + } + + return true; +} + +void VulkanDescriptorLayout::Destroy() { + if (VK_NULL_HANDLE != handle_) { + vkDestroyDescriptorSetLayout( + device_queue_->GetVulkanDevice(), handle_, nullptr); + handle_ = VK_NULL_HANDLE; + } +} + +} // namespace gpu diff --git a/chromium/gpu/vulkan/vulkan_descriptor_layout.h b/chromium/gpu/vulkan/vulkan_descriptor_layout.h new file mode 100644 index 00000000000..80a3f435fd4 --- /dev/null +++ b/chromium/gpu/vulkan/vulkan_descriptor_layout.h @@ -0,0 +1,39 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_VULKAN_VULKAN_DESCRIPTOR_LAYOUT_H_ +#define GPU_VULKAN_VULKAN_DESCRIPTOR_LAYOUT_H_ + +#include <vulkan/vulkan.h> + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "gpu/vulkan/vulkan_export.h" + +namespace gpu { + +class VulkanDeviceQueue; + +class VULKAN_EXPORT VulkanDescriptorLayout { + public: + explicit VulkanDescriptorLayout(VulkanDeviceQueue* device_queue); + ~VulkanDescriptorLayout(); + + bool Initialize(const std::vector<VkDescriptorSetLayoutBinding>& layout); + void Destroy(); + + VkDescriptorSetLayout handle() const { return handle_; } + + private: + VulkanDeviceQueue* device_queue_ = nullptr; + VkDescriptorSetLayout handle_ = VK_NULL_HANDLE; + + DISALLOW_COPY_AND_ASSIGN(VulkanDescriptorLayout); +}; + +} // namespace gpu + +#endif // GPU_VULKAN_VULKAN_DESCRIPTOR_LAYOUT_H_ diff --git a/chromium/gpu/vulkan/vulkan_descriptor_pool.cc b/chromium/gpu/vulkan/vulkan_descriptor_pool.cc new file mode 100644 index 00000000000..99fd107c921 --- /dev/null +++ b/chromium/gpu/vulkan/vulkan_descriptor_pool.cc @@ -0,0 +1,79 @@ +// Copyright (c) 2016 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/vulkan/vulkan_descriptor_pool.h" + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "gpu/vulkan/vulkan_descriptor_set.h" +#include "gpu/vulkan/vulkan_device_queue.h" + +namespace gpu { + +VulkanDescriptorPool::VulkanDescriptorPool(VulkanDeviceQueue* device_queue) + : device_queue_(device_queue) {} + +VulkanDescriptorPool::~VulkanDescriptorPool() { + DCHECK_EQ(static_cast<VkDescriptorPool>(VK_NULL_HANDLE), handle_); + DCHECK_EQ(0u, descriptor_count_); +} + +bool VulkanDescriptorPool::Initialize( + uint32_t max_descriptor_sets, + const std::vector<VkDescriptorPoolSize>& pool_sizes) { + DCHECK_EQ(static_cast<VkDescriptorPool>(VK_NULL_HANDLE), handle_); + max_descriptor_sets_ = max_descriptor_sets; + + VkDescriptorPoolCreateInfo descriptor_pool_create_info = {}; + descriptor_pool_create_info.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descriptor_pool_create_info.flags = + VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; + descriptor_pool_create_info.maxSets = max_descriptor_sets; + descriptor_pool_create_info.poolSizeCount = + static_cast<uint32_t>(pool_sizes.size()); + descriptor_pool_create_info.pPoolSizes = pool_sizes.data(); + + VkResult result = + vkCreateDescriptorPool(device_queue_->GetVulkanDevice(), + &descriptor_pool_create_info, nullptr, &handle_); + if (VK_SUCCESS != result) { + DLOG(ERROR) << "vkCreateDescriptorPool() failed: " << result; + return false; + } + + return true; +} + +void VulkanDescriptorPool::Destroy() { + DCHECK_EQ(0u, descriptor_count_); + if (VK_NULL_HANDLE != handle_) { + vkDestroyDescriptorPool(device_queue_->GetVulkanDevice(), handle_, nullptr); + handle_ = VK_NULL_HANDLE; + } + + max_descriptor_sets_ = 0; +} + +std::unique_ptr<VulkanDescriptorSet> VulkanDescriptorPool::CreateDescriptorSet( + const VulkanDescriptorLayout* layout) { + std::unique_ptr<VulkanDescriptorSet> descriptor_set( + new VulkanDescriptorSet(device_queue_, this)); + if (!descriptor_set->Initialize(layout)) { + return nullptr; + } + return descriptor_set; +} + +void VulkanDescriptorPool::IncrementDescriptorSetCount() { + DCHECK_LT(descriptor_count_, max_descriptor_sets_); + descriptor_count_++; +} + +void VulkanDescriptorPool::DecrementDescriptorSetCount() { + DCHECK_LT(0u, descriptor_count_); + descriptor_count_--; +} + +} // namespace gpu diff --git a/chromium/gpu/vulkan/vulkan_descriptor_pool.h b/chromium/gpu/vulkan/vulkan_descriptor_pool.h new file mode 100644 index 00000000000..b27885d4412 --- /dev/null +++ b/chromium/gpu/vulkan/vulkan_descriptor_pool.h @@ -0,0 +1,50 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_VULKAN_VULKAN_DESCRIPTOR_POOL_H_ +#define GPU_VULKAN_VULKAN_DESCRIPTOR_POOL_H_ + +#include <vulkan/vulkan.h> + +#include <memory> +#include <vector> + +#include "base/macros.h" + +namespace gpu { + +class VulkanDescriptorLayout; +class VulkanDescriptorSet; +class VulkanDeviceQueue; + +class VulkanDescriptorPool { + public: + explicit VulkanDescriptorPool(VulkanDeviceQueue* device_queue); + ~VulkanDescriptorPool(); + + bool Initialize(uint32_t max_descriptor_sets, + const std::vector<VkDescriptorPoolSize>& pool_sizes); + void Destroy(); + + std::unique_ptr<VulkanDescriptorSet> CreateDescriptorSet( + const VulkanDescriptorLayout* layout); + VkDescriptorPool handle() { return handle_; } + + private: + friend class VulkanDescriptorSet; + + void IncrementDescriptorSetCount(); + void DecrementDescriptorSetCount(); + + VulkanDeviceQueue* device_queue_ = nullptr; + VkDescriptorPool handle_ = VK_NULL_HANDLE; + uint32_t max_descriptor_sets_ = 0; + uint32_t descriptor_count_ = 0; + + DISALLOW_COPY_AND_ASSIGN(VulkanDescriptorPool); +}; + +} // namespace gpu + +#endif // GPU_VULKAN_VULKAN_DESCRIPTOR_POOL_H_ diff --git a/chromium/gpu/vulkan/vulkan_descriptor_set.cc b/chromium/gpu/vulkan/vulkan_descriptor_set.cc new file mode 100644 index 00000000000..d8f775b8d6a --- /dev/null +++ b/chromium/gpu/vulkan/vulkan_descriptor_set.cc @@ -0,0 +1,98 @@ +// Copyright (c) 2016 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/vulkan/vulkan_descriptor_set.h" + +#include "base/logging.h" +#include "gpu/vulkan/vulkan_descriptor_layout.h" +#include "gpu/vulkan/vulkan_descriptor_pool.h" +#include "gpu/vulkan/vulkan_device_queue.h" + +namespace gpu { + +VulkanDescriptorSet::~VulkanDescriptorSet() { + DCHECK_EQ(static_cast<VkDescriptorSet>(VK_NULL_HANDLE), handle_); + descriptor_pool_->DecrementDescriptorSetCount(); +} + +bool VulkanDescriptorSet::Initialize(const VulkanDescriptorLayout* layout) { + VkResult result = VK_SUCCESS; + VkDevice device = device_queue_->GetVulkanDevice(); + + VkDescriptorSetLayout layout_handle = layout->handle(); + + VkDescriptorSetAllocateInfo set_allocate_info = {}; + set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + set_allocate_info.descriptorPool = descriptor_pool_->handle(); + set_allocate_info.descriptorSetCount = 1; + set_allocate_info.pSetLayouts = &layout_handle; + + result = vkAllocateDescriptorSets(device, &set_allocate_info, &handle_); + if (VK_SUCCESS != result) { + DLOG(ERROR) << "vkAllocateDescriptorSets() failed: " << result; + return false; + } + + return true; +} + +void VulkanDescriptorSet::Destroy() { + VkDevice device = device_queue_->GetVulkanDevice(); + if (VK_NULL_HANDLE != handle_) { + vkFreeDescriptorSets(device, descriptor_pool_->handle(), 1, &handle_); + handle_ = VK_NULL_HANDLE; + } +} + +void VulkanDescriptorSet::WriteToDescriptorSet( + uint32_t dst_binding, + uint32_t dst_array_element, + uint32_t descriptor_count, + VkDescriptorType descriptor_type, + const VkDescriptorImageInfo* image_info, + const VkDescriptorBufferInfo* buffer_info, + const VkBufferView* texel_buffer_view) { + VkWriteDescriptorSet write_descriptor_set = {}; + write_descriptor_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptor_set.dstSet = handle_; + write_descriptor_set.dstBinding = dst_binding; + write_descriptor_set.dstArrayElement = dst_array_element; + write_descriptor_set.descriptorCount = descriptor_count; + write_descriptor_set.descriptorType = descriptor_type; + write_descriptor_set.pImageInfo = image_info; + write_descriptor_set.pBufferInfo = buffer_info; + write_descriptor_set.pTexelBufferView = texel_buffer_view; + + vkUpdateDescriptorSets(device_queue_->GetVulkanDevice(), 1, + &write_descriptor_set, 0, nullptr); +} + +void VulkanDescriptorSet::CopyFromDescriptorSet( + const VulkanDescriptorSet* source_set, + uint32_t src_binding, + uint32_t src_array_element, + uint32_t dst_binding, + uint32_t dst_array_element, + uint32_t descriptor_count) { + VkCopyDescriptorSet copy_descriptor_set = {}; + copy_descriptor_set.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; + copy_descriptor_set.srcSet = source_set->handle(); + copy_descriptor_set.srcBinding = src_binding; + copy_descriptor_set.srcArrayElement = src_array_element; + copy_descriptor_set.dstSet = handle_; + copy_descriptor_set.dstBinding = dst_binding; + copy_descriptor_set.dstArrayElement = dst_array_element; + copy_descriptor_set.descriptorCount = descriptor_count; + + vkUpdateDescriptorSets(device_queue_->GetVulkanDevice(), 0, nullptr, 1, + ©_descriptor_set); +} + +VulkanDescriptorSet::VulkanDescriptorSet(VulkanDeviceQueue* device_queue, + VulkanDescriptorPool* descriptor_pool) + : device_queue_(device_queue), descriptor_pool_(descriptor_pool) { + descriptor_pool_->IncrementDescriptorSetCount(); +} + +} // namespace gpu diff --git a/chromium/gpu/vulkan/vulkan_descriptor_set.h b/chromium/gpu/vulkan/vulkan_descriptor_set.h new file mode 100644 index 00000000000..71ba285460c --- /dev/null +++ b/chromium/gpu/vulkan/vulkan_descriptor_set.h @@ -0,0 +1,60 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_VULKAN_VULKAN_DESCRIPTOR_SET_H_ +#define GPU_VULKAN_VULKAN_DESCRIPTOR_SET_H_ + +#include <vulkan/vulkan.h> + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "gpu/vulkan/vulkan_export.h" + +namespace gpu { + +class VulkanDescriptorPool; +class VulkanDescriptorLayout; +class VulkanDeviceQueue; + +class VULKAN_EXPORT VulkanDescriptorSet { + public: + ~VulkanDescriptorSet(); + + bool Initialize(const VulkanDescriptorLayout* layout); + void Destroy(); + + void WriteToDescriptorSet(uint32_t dst_binding, + uint32_t dst_array_element, + uint32_t descriptor_count, + VkDescriptorType descriptor_type, + const VkDescriptorImageInfo* image_info, + const VkDescriptorBufferInfo* buffer_info, + const VkBufferView* texel_buffer_view); + + void CopyFromDescriptorSet(const VulkanDescriptorSet* source_set, + uint32_t src_binding, + uint32_t src_array_element, + uint32_t dst_binding, + uint32_t dst_array_element, + uint32_t descriptor_count); + + VkDescriptorSet handle() const { return handle_; } + + private: + friend class VulkanDescriptorPool; + VulkanDescriptorSet(VulkanDeviceQueue* device_queue, + VulkanDescriptorPool* descriptor_pool); + + VulkanDeviceQueue* device_queue_ = nullptr; + VulkanDescriptorPool* descriptor_pool_ = nullptr; + VkDescriptorSet handle_ = VK_NULL_HANDLE; + + DISALLOW_COPY_AND_ASSIGN(VulkanDescriptorSet); +}; + +} // namespace gpu + +#endif // GPU_VULKAN_VULKAN_DESCRIPTOR_SET_H_ diff --git a/chromium/gpu/vulkan/vulkan_device_queue.cc b/chromium/gpu/vulkan/vulkan_device_queue.cc index 17fc1a39e2c..28000d5e47e 100644 --- a/chromium/gpu/vulkan/vulkan_device_queue.cc +++ b/chromium/gpu/vulkan/vulkan_device_queue.cc @@ -75,6 +75,10 @@ bool VulkanDeviceQueue::Initialize(uint32_t options) { visual_id)) { continue; } +#elif defined(VK_USE_PLATFORM_ANDROID_KHR) +// On Android, all physical devices and queue families must be capable of +// presentation with any native window. +// As a result there is no Android-specific query for these capabilities. #else #error Non-Supported Vulkan implementation. #endif @@ -166,8 +170,8 @@ void VulkanDeviceQueue::Destroy() { vk_physical_device_ = VK_NULL_HANDLE; } -scoped_ptr<VulkanCommandPool> VulkanDeviceQueue::CreateCommandPool() { - scoped_ptr<VulkanCommandPool> command_pool(new VulkanCommandPool(this)); +std::unique_ptr<VulkanCommandPool> VulkanDeviceQueue::CreateCommandPool() { + std::unique_ptr<VulkanCommandPool> command_pool(new VulkanCommandPool(this)); if (!command_pool->Initialize()) return nullptr; diff --git a/chromium/gpu/vulkan/vulkan_device_queue.h b/chromium/gpu/vulkan/vulkan_device_queue.h index 59d3e96039f..ecb1724b4dd 100644 --- a/chromium/gpu/vulkan/vulkan_device_queue.h +++ b/chromium/gpu/vulkan/vulkan_device_queue.h @@ -7,9 +7,10 @@ #include <vulkan/vulkan.h> +#include <memory> + #include "base/logging.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "gpu/vulkan/vulkan_export.h" namespace gpu { @@ -47,7 +48,7 @@ class VULKAN_EXPORT VulkanDeviceQueue { uint32_t GetVulkanQueueIndex() const { return vk_queue_index_; } - scoped_ptr<gpu::VulkanCommandPool> CreateCommandPool(); + std::unique_ptr<gpu::VulkanCommandPool> CreateCommandPool(); private: VkPhysicalDevice vk_physical_device_ = VK_NULL_HANDLE; diff --git a/chromium/gpu/vulkan/vulkan_implementation.cc b/chromium/gpu/vulkan/vulkan_implementation.cc index db6a3d52de8..731842bb4ed 100644 --- a/chromium/gpu/vulkan/vulkan_implementation.cc +++ b/chromium/gpu/vulkan/vulkan_implementation.cc @@ -60,6 +60,8 @@ struct VulkanInstance { #if defined(VK_USE_PLATFORM_XLIB_KHR) enabled_ext_names.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); +#elif defined(VK_USE_PLATFORM_ANDROID_KHR) + enabled_ext_names.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); #endif uint32_t num_instance_exts = 0; @@ -131,6 +133,7 @@ struct VulkanInstance { return false; } +#if DCHECK_IS_ON() // Register our error logging function. if (debug_report_enabled) { PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = @@ -163,6 +166,7 @@ struct VulkanInstance { return false; } } +#endif return true; } @@ -184,6 +188,11 @@ bool InitializeVulkan() { return vulkan_instance->valid; } +bool VulkanSupported() { + DCHECK(vulkan_instance); + return vulkan_instance->valid; +} + VkInstance GetVulkanInstance() { DCHECK(vulkan_instance); DCHECK(vulkan_instance->valid); diff --git a/chromium/gpu/vulkan/vulkan_implementation.h b/chromium/gpu/vulkan/vulkan_implementation.h index fa8639d6d84..b669316e255 100644 --- a/chromium/gpu/vulkan/vulkan_implementation.h +++ b/chromium/gpu/vulkan/vulkan_implementation.h @@ -7,13 +7,13 @@ #include <vulkan/vulkan.h> -#include "base/memory/scoped_ptr.h" - +#include "gpu/vulkan/vulkan_export.h" namespace gpu { class VulkanCommandPool; -bool InitializeVulkan(); +VULKAN_EXPORT bool InitializeVulkan(); +VULKAN_EXPORT bool VulkanSupported(); VkInstance GetVulkanInstance(); diff --git a/chromium/gpu/vulkan/vulkan_platform.h b/chromium/gpu/vulkan/vulkan_platform.h index 471b65ed1ff..674b4a9b777 100644 --- a/chromium/gpu/vulkan/vulkan_platform.h +++ b/chromium/gpu/vulkan/vulkan_platform.h @@ -17,6 +17,10 @@ extern "C" { #define VK_USE_PLATFORM_XLIB_KHR #endif +#if defined(OS_ANDROID) +#define VK_USE_PLATFORM_ANDROID_KHR +#endif + // This section below is taken from <vulkan/vulkan.h> #ifdef VK_USE_PLATFORM_XLIB_KHR #define VK_KHR_xlib_surface 1 @@ -61,6 +65,37 @@ vkGetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice, #endif #endif /* VK_USE_PLATFORM_XLIB_KHR */ +#ifdef VK_USE_PLATFORM_ANDROID_KHR +#define VK_KHR_android_surface 1 +#include <android/native_window.h> + +#define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6 +#define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface" + +typedef VkFlags VkAndroidSurfaceCreateFlagsKHR; + +typedef struct VkAndroidSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkAndroidSurfaceCreateFlagsKHR flags; + ANativeWindow* window; +} VkAndroidSurfaceCreateInfoKHR; + +typedef VkResult(VKAPI_PTR* PFN_vkCreateAndroidSurfaceKHR)( + VkInstance instance, + const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL +vkCreateAndroidSurfaceKHR(VkInstance instance, + const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif +#endif /* VK_USE_PLATFORM_ANDROID_KHR */ + #ifdef __cplusplus } // extern "C" #endif diff --git a/chromium/gpu/vulkan/vulkan_render_pass.cc b/chromium/gpu/vulkan/vulkan_render_pass.cc index a142fc1b3ee..a3aeda246f2 100644 --- a/chromium/gpu/vulkan/vulkan_render_pass.cc +++ b/chromium/gpu/vulkan/vulkan_render_pass.cc @@ -99,6 +99,10 @@ bool VulkanRenderPass::AttachmentData::ValidateData( VulkanRenderPass::SubpassData::SubpassData() {} +VulkanRenderPass::SubpassData::SubpassData(const SubpassData& data) = default; + +VulkanRenderPass::SubpassData::SubpassData(SubpassData&& data) = default; + VulkanRenderPass::SubpassData::~SubpassData() {} bool VulkanRenderPass::SubpassData::ValidateData( @@ -126,6 +130,12 @@ bool VulkanRenderPass::SubpassData::ValidateData( VulkanRenderPass::RenderPassData::RenderPassData() {} +VulkanRenderPass::RenderPassData::RenderPassData(const RenderPassData& data) = + default; + +VulkanRenderPass::RenderPassData::RenderPassData(RenderPassData&& data) = + default; + VulkanRenderPass::RenderPassData::~RenderPassData() {} VulkanRenderPass::VulkanRenderPass(VulkanDeviceQueue* device_queue) diff --git a/chromium/gpu/vulkan/vulkan_render_pass.h b/chromium/gpu/vulkan/vulkan_render_pass.h index 326e99b235c..0c283dc21db 100644 --- a/chromium/gpu/vulkan/vulkan_render_pass.h +++ b/chromium/gpu/vulkan/vulkan_render_pass.h @@ -63,6 +63,8 @@ class VULKAN_EXPORT VulkanRenderPass { struct SubpassData { SubpassData(); + SubpassData(const SubpassData& data); + SubpassData(SubpassData&& data); ~SubpassData(); std::vector<SubpassAttachment> subpass_attachments; @@ -72,6 +74,8 @@ class VULKAN_EXPORT VulkanRenderPass { struct RenderPassData { RenderPassData(); + RenderPassData(const RenderPassData& data); + RenderPassData(RenderPassData&& data); ~RenderPassData(); std::vector<AttachmentData> attachments; diff --git a/chromium/gpu/vulkan/vulkan_sampler.cc b/chromium/gpu/vulkan/vulkan_sampler.cc new file mode 100644 index 00000000000..fbd0d7ee9fd --- /dev/null +++ b/chromium/gpu/vulkan/vulkan_sampler.cc @@ -0,0 +1,60 @@ +// Copyright (c) 2016 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/vulkan/vulkan_sampler.h" + +#include "base/logging.h" +#include "gpu/vulkan/vulkan_device_queue.h" + +namespace gpu { + +VulkanSampler::SamplerOptions::SamplerOptions() = default; +VulkanSampler::SamplerOptions::~SamplerOptions() = default; + +VulkanSampler::VulkanSampler(VulkanDeviceQueue* device_queue) + : device_queue_(device_queue) {} + +VulkanSampler::~VulkanSampler() { + DCHECK_EQ(static_cast<VkSampler>(VK_NULL_HANDLE), handle_); +} + +bool VulkanSampler::Initialize(const SamplerOptions& options) { + DCHECK_EQ(static_cast<VkSampler>(VK_NULL_HANDLE), handle_); + + VkSamplerCreateInfo sampler_create_info = {}; + sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + sampler_create_info.magFilter = options.mag_filter; + sampler_create_info.minFilter = options.min_filter; + sampler_create_info.mipmapMode = options.mipmap_mode; + sampler_create_info.addressModeU = options.address_mode_u; + sampler_create_info.addressModeV = options.address_mode_v; + sampler_create_info.addressModeW = options.address_mode_w; + sampler_create_info.mipLodBias = options.mip_lod_bias; + sampler_create_info.anisotropyEnable = options.anisotropy_enable; + sampler_create_info.maxAnisotropy = options.max_anisotropy; + sampler_create_info.compareOp = options.compare_op; + sampler_create_info.minLod = options.min_lod; + sampler_create_info.maxLod = options.max_lod; + sampler_create_info.borderColor = options.border_color; + sampler_create_info.unnormalizedCoordinates = + options.unnormalized_coordinates; + + VkResult result = vkCreateSampler(device_queue_->GetVulkanDevice(), + &sampler_create_info, nullptr, &handle_); + if (VK_SUCCESS != result) { + DLOG(ERROR) << "vkCreateSampler() failed: " << result; + return false; + } + + return true; +} + +void VulkanSampler::Destroy() { + if (VK_NULL_HANDLE != handle_) { + vkDestroySampler(device_queue_->GetVulkanDevice(), handle_, nullptr); + handle_ = VK_NULL_HANDLE; + } +} + +} // namespace gpu diff --git a/chromium/gpu/vulkan/vulkan_sampler.h b/chromium/gpu/vulkan/vulkan_sampler.h new file mode 100644 index 00000000000..87889fe6c03 --- /dev/null +++ b/chromium/gpu/vulkan/vulkan_sampler.h @@ -0,0 +1,58 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_VULKAN_VULKAN_SAMPLER_H_ +#define GPU_VULKAN_VULKAN_SAMPLER_H_ + +#include <float.h> +#include <vulkan/vulkan.h> + +#include "base/macros.h" +#include "gpu/vulkan/vulkan_export.h" + +namespace gpu { + +class VulkanDeviceQueue; + +class VULKAN_EXPORT VulkanSampler { + public: + struct SamplerOptions { + SamplerOptions(); + ~SamplerOptions(); + + VkFilter mag_filter = VK_FILTER_NEAREST; + VkFilter min_filter = VK_FILTER_NEAREST; + VkSamplerMipmapMode mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + VkSamplerAddressMode address_mode_u = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + VkSamplerAddressMode address_mode_v = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + VkSamplerAddressMode address_mode_w = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + float mip_lod_bias = 0.0f; + bool anisotropy_enable = false; + float max_anisotropy = 1.0f; + bool compare_enable = false; + VkCompareOp compare_op = VK_COMPARE_OP_NEVER; + float min_lod = 0.0f; + float max_lod = FLT_MAX; + VkBorderColor border_color = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + bool unnormalized_coordinates = false; + }; + + explicit VulkanSampler(VulkanDeviceQueue* device_queue); + ~VulkanSampler(); + + bool Initialize(const SamplerOptions& options); + void Destroy(); + + VkSampler handle() const { return handle_; } + + private: + VulkanDeviceQueue* device_queue_ = nullptr; + VkSampler handle_ = VK_NULL_HANDLE; + + DISALLOW_COPY_AND_ASSIGN(VulkanSampler); +}; + +} // namespace gpu + +#endif // GPU_VULKAN_VULKAN_SAMPLER_H_ diff --git a/chromium/gpu/vulkan/vulkan_shader_module.cc b/chromium/gpu/vulkan/vulkan_shader_module.cc new file mode 100644 index 00000000000..4b13667e959 --- /dev/null +++ b/chromium/gpu/vulkan/vulkan_shader_module.cc @@ -0,0 +1,154 @@ +// Copyright (c) 2016 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/vulkan/vulkan_shader_module.h" + +#include <memory> +#include <shaderc/shaderc.h> +#include <sstream> + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "gpu/vulkan/vulkan_device_queue.h" + +namespace { + +class ShaderCCompiler { + public: + class CompilationResult { + public: + explicit CompilationResult(shaderc_compilation_result_t compilation_result) + : compilation_result_(compilation_result) {} + + ~CompilationResult() { shaderc_result_release(compilation_result_); } + + bool IsValid() const { + return shaderc_compilation_status_success == + shaderc_result_get_compilation_status(compilation_result_); + } + + std::string GetErrors() const { + return shaderc_result_get_error_message(compilation_result_); + } + + std::string GetResult() const { + return std::string(shaderc_result_get_bytes(compilation_result_), + shaderc_result_get_length(compilation_result_)); + } + + private: + shaderc_compilation_result_t compilation_result_; + }; + + ShaderCCompiler() + : compiler_(shaderc_compiler_initialize()), + compiler_options_(shaderc_compile_options_initialize()) {} + + ~ShaderCCompiler() { shaderc_compiler_release(compiler_); } + + void AddMacroDef(const std::string& name, const std::string& value) { + shaderc_compile_options_add_macro_definition(compiler_options_, + name.c_str(), name.length(), + value.c_str(), value.length()); + } + + std::unique_ptr<ShaderCCompiler::CompilationResult> CompileShaderModule( + gpu::VulkanShaderModule::ShaderType shader_type, + const std::string& name, + const std::string& entry_point, + const std::string& source) { + return base::MakeUnique<ShaderCCompiler::CompilationResult>( + shaderc_compile_into_spv( + compiler_, source.c_str(), source.length(), + (shader_type == gpu::VulkanShaderModule::ShaderType::VERTEX + ? shaderc_glsl_vertex_shader + : shaderc_glsl_fragment_shader), + name.c_str(), entry_point.c_str(), compiler_options_)); + } + + private: + shaderc_compiler_t compiler_; + shaderc_compile_options_t compiler_options_; +}; + +} // namespace + +namespace gpu { + +VulkanShaderModule::VulkanShaderModule(VulkanDeviceQueue* device_queue) + : device_queue_(device_queue) { + DCHECK(device_queue_); +} + +VulkanShaderModule::~VulkanShaderModule() { + DCHECK_EQ(static_cast<VkShaderModule>(VK_NULL_HANDLE), handle_); +} + +bool VulkanShaderModule::InitializeGLSL(ShaderType type, + std::string name, + std::string entry_point, + std::string source) { + ShaderCCompiler shaderc_compiler; + std::unique_ptr<ShaderCCompiler::CompilationResult> compilation_result( + shaderc_compiler.CompileShaderModule(type, name, entry_point, source)); + + if (!compilation_result->IsValid()) { + error_messages_ = compilation_result->GetErrors(); + return false; + } + + return InitializeSPIRV(type, std::move(name), std::move(entry_point), + compilation_result->GetResult()); +} + +bool VulkanShaderModule::InitializeSPIRV(ShaderType type, + std::string name, + std::string entry_point, + std::string source) { + DCHECK_EQ(static_cast<VkShaderModule>(VK_NULL_HANDLE), handle_); + shader_type_ = type; + name_ = std::move(name); + entry_point_ = std::move(entry_point); + + // Make sure source is a multiple of 4. + const int padding = 4 - (source.length() % 4); + if (padding < 4) { + for (int i = 0; i < padding; ++i) { + source += ' '; + } + } + + VkShaderModuleCreateInfo shader_module_create_info = {}; + shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_module_create_info.pCode = + reinterpret_cast<const uint32_t*>(source.c_str()); + shader_module_create_info.codeSize = source.length() / 4; + + VkShaderModule shader_module = VK_NULL_HANDLE; + VkResult result = + vkCreateShaderModule(device_queue_->GetVulkanDevice(), + &shader_module_create_info, nullptr, &shader_module); + if (VK_SUCCESS != result) { + std::stringstream ss; + ss << "vkCreateShaderModule() failed: " << result; + error_messages_ = ss.str(); + DLOG(ERROR) << error_messages_; + return false; + } + + handle_ = shader_module; + return true; +} + +void VulkanShaderModule::Destroy() { + if (handle_ != VK_NULL_HANDLE) { + vkDestroyShaderModule(device_queue_->GetVulkanDevice(), handle_, nullptr); + handle_ = VK_NULL_HANDLE; + } + + entry_point_.clear(); + error_messages_.clear(); +} + +} // namespace gpu diff --git a/chromium/gpu/vulkan/vulkan_shader_module.h b/chromium/gpu/vulkan/vulkan_shader_module.h new file mode 100644 index 00000000000..89c80f7853b --- /dev/null +++ b/chromium/gpu/vulkan/vulkan_shader_module.h @@ -0,0 +1,59 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_VULKAN_VULKAN_SHADER_MODULE_H_ +#define GPU_VULKAN_VULKAN_SHADER_MODULE_H_ + +#include <string> +#include <vulkan/vulkan.h> + +#include "base/macros.h" +#include "gpu/vulkan/vulkan_export.h" + +namespace gpu { + +class VulkanDeviceQueue; + +class VULKAN_EXPORT VulkanShaderModule { + public: + enum class ShaderType { + VERTEX, + FRAGMENT, + }; + + VulkanShaderModule(VulkanDeviceQueue* device_queue); + ~VulkanShaderModule(); + + bool InitializeGLSL(ShaderType type, + std::string name, + std::string entry_point, + std::string source); + bool InitializeSPIRV(ShaderType type, + std::string name, + std::string entry_point, + std::string source); + void Destroy(); + + bool IsValid() const { return handle_ != VK_NULL_HANDLE; } + std::string GetErrorMessages() const { return error_messages_; } + + ShaderType shader_type() const { return shader_type_; } + const std::string& name() const { return name_; } + VkShaderModule handle() const { return handle_; } + const std::string& entry_point() const { return entry_point_; } + + private: + VulkanDeviceQueue* device_queue_ = nullptr; + ShaderType shader_type_ = ShaderType::VERTEX; + VkShaderModule handle_ = VK_NULL_HANDLE; + std::string name_; + std::string entry_point_; + std::string error_messages_; + + DISALLOW_COPY_AND_ASSIGN(VulkanShaderModule); +}; + +} // namespace gpu + +#endif // GPU_VULKAN_VULKAN_SHADER_MODULE_H_ diff --git a/chromium/gpu/vulkan/vulkan_surface.cc b/chromium/gpu/vulkan/vulkan_surface.cc index 8d1bbab9c46..4344362ed9f 100644 --- a/chromium/gpu/vulkan/vulkan_surface.cc +++ b/chromium/gpu/vulkan/vulkan_surface.cc @@ -20,12 +20,14 @@ namespace gpu { namespace { -const VkFormat kNativeVkFormat[] = { - VK_FORMAT_B8G8R8A8_UNORM, // FORMAT_BGRA8888, +const VkFormat kPreferredVkFormats32[] = { + VK_FORMAT_B8G8R8A8_UNORM, // FORMAT_BGRA8888, + VK_FORMAT_R8G8B8A8_UNORM, // FORMAT_RGBA8888, +}; + +const VkFormat kPreferredVkFormats16[] = { VK_FORMAT_R5G6B5_UNORM_PACK16, // FORMAT_RGB565, }; -static_assert(arraysize(kNativeVkFormat) == VulkanSurface::NUM_SURFACE_FORMATS, - "Array size for kNativeVkFormat must match surface formats."); } // namespace @@ -54,6 +56,17 @@ class VulkanWSISurface : public VulkanSurface { DLOG(ERROR) << "vkCreateXlibSurfaceKHR() failed: " << result; return false; } +#elif defined(VK_USE_PLATFORM_ANDROID_KHR) + VkAndroidSurfaceCreateInfoKHR surface_create_info = {}; + surface_create_info.sType = + VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + surface_create_info.window = window_; + result = vkCreateAndroidSurfaceKHR( + GetVulkanInstance(), &surface_create_info, nullptr, &surface_); + if (VK_SUCCESS != result) { + DLOG(ERROR) << "vkCreateAndroidSurfaceKHR() failed: " << result; + return false; + } #else #error Unsupported Vulkan Platform. #endif @@ -83,19 +96,30 @@ class VulkanWSISurface : public VulkanSurface { return false; } - const VkFormat preferred_format = kNativeVkFormat[format]; + const VkFormat* preferred_formats = (format == FORMAT_RGBA_32) + ? kPreferredVkFormats32 + : kPreferredVkFormats16; + unsigned int size = (format == FORMAT_RGBA_32) + ? arraysize(kPreferredVkFormats32) + : arraysize(kPreferredVkFormats16); + if (formats.size() == 1 && VK_FORMAT_UNDEFINED == formats[0].format) { - surface_format_.format = preferred_format; + surface_format_.format = preferred_formats[0]; surface_format_.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; } else { bool format_set = false; for (VkSurfaceFormatKHR supported_format : formats) { - if (supported_format.format == preferred_format) { - surface_format_ = supported_format; - surface_format_.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - format_set = true; - break; + unsigned int counter = 0; + while (counter < size && format_set == false) { + if (supported_format.format == preferred_formats[counter]) { + surface_format_ = supported_format; + surface_format_.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; + format_set = true; + } + counter++; } + if (format_set) + break; } if (!format_set) { DLOG(ERROR) << "Format not supported."; @@ -147,20 +171,12 @@ class VulkanWSISurface : public VulkanSurface { VulkanSwapChain swap_chain_; }; -// static -bool VulkanSurface::InitializeOneOff() { - if (!InitializeVulkan()) - return false; - - return true; -} - VulkanSurface::~VulkanSurface() {} // static -scoped_ptr<VulkanSurface> VulkanSurface::CreateViewSurface( +std::unique_ptr<VulkanSurface> VulkanSurface::CreateViewSurface( gfx::AcceleratedWidget window) { - return scoped_ptr<VulkanSurface>(new VulkanWSISurface(window)); + return std::unique_ptr<VulkanSurface>(new VulkanWSISurface(window)); } VulkanSurface::VulkanSurface() {} diff --git a/chromium/gpu/vulkan/vulkan_surface.h b/chromium/gpu/vulkan/vulkan_surface.h index c1cd166e99a..2d39812f311 100644 --- a/chromium/gpu/vulkan/vulkan_surface.h +++ b/chromium/gpu/vulkan/vulkan_surface.h @@ -5,7 +5,8 @@ #ifndef GPU_VULKAN_VULKAN_SURFACE_H_ #define GPU_VULKAN_VULKAN_SURFACE_H_ -#include "base/memory/scoped_ptr.h" +#include <memory> + #include "gpu/vulkan/vulkan_export.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h" @@ -18,15 +19,13 @@ class VulkanSwapChain; class VULKAN_EXPORT VulkanSurface { public: - static bool InitializeOneOff(); - // Minimum bit depth of surface. enum Format { - FORMAT_BGRA8888, - FORMAT_RGB565, + FORMAT_RGBA_32, + FORMAT_RGB_16, NUM_SURFACE_FORMATS, - DEFAULT_SURFACE_FORMAT = FORMAT_BGRA8888 + DEFAULT_SURFACE_FORMAT = FORMAT_RGBA_32 }; virtual ~VulkanSurface() = 0; @@ -42,7 +41,7 @@ class VULKAN_EXPORT VulkanSurface { virtual void Finish() = 0; // Create a surface that render directlys into a surface. - static scoped_ptr<VulkanSurface> CreateViewSurface( + static std::unique_ptr<VulkanSurface> CreateViewSurface( gfx::AcceleratedWidget window); protected: diff --git a/chromium/gpu/vulkan/vulkan_swap_chain.cc b/chromium/gpu/vulkan/vulkan_swap_chain.cc index c4e62295521..a42e26ed9d8 100644 --- a/chromium/gpu/vulkan/vulkan_swap_chain.cc +++ b/chromium/gpu/vulkan/vulkan_swap_chain.cc @@ -41,15 +41,7 @@ gfx::SwapResult VulkanSwapChain::SwapBuffers() { VkDevice device = device_queue_->GetVulkanDevice(); VkQueue queue = device_queue_->GetVulkanQueue(); - scoped_ptr<ImageData>& current_image_data = images_[current_image_]; - - // Default image subresource range. - VkImageSubresourceRange image_subresource_range = {}; - image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - image_subresource_range.baseMipLevel = 0; - image_subresource_range.levelCount = 1; - image_subresource_range.baseArrayLayer = 0; - image_subresource_range.layerCount = 1; + std::unique_ptr<ImageData>& current_image_data = images_[current_image_]; // Submit our command buffer for the current buffer. if (!current_image_data->command_buffer->Submit( @@ -190,7 +182,7 @@ bool VulkanSwapChain::InitializeSwapImages( images_.resize(image_count); for (uint32_t i = 0; i < image_count; ++i) { images_[i].reset(new ImageData); - scoped_ptr<ImageData>& image_data = images_[i]; + std::unique_ptr<ImageData>& image_data = images_[i]; image_data->image = images[i]; // Setup semaphores. @@ -258,7 +250,7 @@ void VulkanSwapChain::DestroySwapImages() { next_present_semaphore_ = VK_NULL_HANDLE; } - for (const scoped_ptr<ImageData>& image_data : images_) { + for (const std::unique_ptr<ImageData>& image_data : images_) { if (image_data->command_buffer) { // Make sure command buffer is done processing. image_data->command_buffer->Wait(UINT64_MAX); diff --git a/chromium/gpu/vulkan/vulkan_swap_chain.h b/chromium/gpu/vulkan/vulkan_swap_chain.h index e084716f5f7..08f39028dbc 100644 --- a/chromium/gpu/vulkan/vulkan_swap_chain.h +++ b/chromium/gpu/vulkan/vulkan_swap_chain.h @@ -5,10 +5,10 @@ #ifndef GPU_VULKAN_VULKAN_SWAP_CHAIN_H_ #define GPU_VULKAN_VULKAN_SWAP_CHAIN_H_ +#include <memory> #include <vector> #include <vulkan/vulkan.h> -#include "base/memory/scoped_ptr.h" #include "gpu/vulkan/vulkan_export.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/swap_result.h" @@ -64,7 +64,7 @@ class VulkanSwapChain { VulkanDeviceQueue* device_queue_; VkSwapchainKHR swap_chain_ = VK_NULL_HANDLE; - scoped_ptr<VulkanCommandPool> command_pool_; + std::unique_ptr<VulkanCommandPool> command_pool_; gfx::Size size_; @@ -73,13 +73,13 @@ class VulkanSwapChain { ~ImageData(); VkImage image = VK_NULL_HANDLE; - scoped_ptr<VulkanImageView> image_view; - scoped_ptr<VulkanCommandBuffer> command_buffer; + std::unique_ptr<VulkanImageView> image_view; + std::unique_ptr<VulkanCommandBuffer> command_buffer; VkSemaphore render_semaphore = VK_NULL_HANDLE; VkSemaphore present_semaphore = VK_NULL_HANDLE; }; - std::vector<scoped_ptr<ImageData>> images_; + std::vector<std::unique_ptr<ImageData>> images_; uint32_t current_image_ = 0; VkSemaphore next_present_semaphore_ = VK_NULL_HANDLE; |