From daa093eea7c773db06799a13bd7e4e2e2a9f8f14 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 20 Nov 2017 15:06:40 +0100 Subject: BASELINE: Update Chromium to 63.0.3239.58 Change-Id: Ia93b322a00ba4dd4004f3bcf1254063ba90e1605 Reviewed-by: Alexandru Croitor --- chromium/gpu/command_buffer/OWNERS | 1 - .../gpu/command_buffer/build_gles2_cmd_buffer.py | 1 + .../client/client_discardable_manager.h | 4 +- .../gpu/command_buffer/client/client_test_helper.h | 3 +- .../command_buffer/client/gles2_implementation.h | 6 +- .../client/gles2_implementation_unittest.cc | 52 +- chromium/gpu/command_buffer/client/gpu_control.h | 2 +- .../gpu/command_buffer/client/query_tracker.cc | 5 +- chromium/gpu/command_buffer/client/query_tracker.h | 4 +- chromium/gpu/command_buffer/client/ring_buffer.h | 7 +- chromium/gpu/command_buffer/client/share_group.cc | 5 +- .../command_buffer/client/shared_memory_limits.h | 2 +- chromium/gpu/command_buffer/common/capabilities.h | 12 +- .../command_buffer/common/debug_marker_manager.h | 5 +- .../gles2_cmd_utils_implementation_autogen.h | 1 + .../command_buffer/common/scheduling_priority.cc | 4 - .../command_buffer/common/scheduling_priority.h | 15 +- .../command_buffer/service/client_service_map.h | 23 +- .../gpu/command_buffer/service/context_group.cc | 32 +- .../service/context_group_unittest.cc | 7 +- .../service/create_gr_gl_interface.cc | 20 +- .../gpu/command_buffer/service/feature_info.cc | 88 +- chromium/gpu/command_buffer/service/feature_info.h | 3 + .../command_buffer/service/framebuffer_manager.cc | 17 +- .../command_buffer/service/framebuffer_manager.h | 6 +- .../service/framebuffer_manager_unittest.cc | 4 +- .../service/gl_context_virtual_unittest.cc | 4 +- .../command_buffer/service/gles2_cmd_decoder.cc | 61 +- .../gpu/command_buffer/service/gles2_cmd_decoder.h | 15 +- .../service/gles2_cmd_decoder_mock.cc | 5 +- .../service/gles2_cmd_decoder_mock.h | 3 +- .../service/gles2_cmd_decoder_passthrough.cc | 711 +++++++++++++- .../service/gles2_cmd_decoder_passthrough.h | 157 ++- ...gles2_cmd_decoder_passthrough_doer_prototypes.h | 14 + .../service/gles2_cmd_decoder_passthrough_doers.cc | 357 ++++++- .../gles2_cmd_decoder_passthrough_handlers.cc | 1020 +++++++++----------- ...es2_cmd_decoder_passthrough_unittest_drawing.cc | 41 + ...md_decoder_passthrough_unittest_framebuffers.cc | 420 ++++++++ .../service/gles2_cmd_decoder_unittest_base.cc | 108 ++- .../service/gles2_cmd_decoder_unittest_base.h | 64 ++ .../service/gles2_cmd_decoder_unittest_textures.cc | 6 +- .../gles2_cmd_validation_implementation_autogen.h | 1 + .../gpu/command_buffer/service/gpu_preferences.h | 3 - .../gpu/command_buffer/service/gpu_switches.cc | 4 + chromium/gpu/command_buffer/service/gpu_switches.h | 1 + chromium/gpu/command_buffer/service/gpu_tracer.cc | 47 +- chromium/gpu/command_buffer/service/gpu_tracer.h | 52 +- .../command_buffer/service/gpu_tracer_unittest.cc | 111 +-- .../command_buffer/service/mailbox_manager_sync.cc | 6 +- .../gpu/command_buffer/service/query_manager.h | 10 +- .../service/query_manager_unittest.cc | 5 +- .../gpu/command_buffer/service/sampler_manager.cc | 2 +- chromium/gpu/command_buffer/service/scheduler.cc | 52 +- chromium/gpu/command_buffer/service/scheduler.h | 12 +- .../command_buffer/service/scheduler_unittest.cc | 78 +- .../service_discardable_manager_unittest.cc | 4 +- .../gpu/command_buffer/service/service_utils.cc | 7 + .../gpu/command_buffer/service/service_utils.h | 5 + .../command_buffer/service/shader_translator.cc | 8 +- .../service/shader_translator_unittest.cc | 14 +- .../service/sync_point_manager_unittest.cc | 4 +- chromium/gpu/command_buffer/service/test_helper.cc | 24 +- .../gpu/command_buffer/service/texture_manager.cc | 5 + .../service/texture_manager_unittest.cc | 10 +- 64 files changed, 2798 insertions(+), 982 deletions(-) create mode 100644 chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_drawing.cc create mode 100644 chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_framebuffers.cc (limited to 'chromium/gpu/command_buffer') diff --git a/chromium/gpu/command_buffer/OWNERS b/chromium/gpu/command_buffer/OWNERS index 49a178a25da..95fbe52bc30 100644 --- a/chromium/gpu/command_buffer/OWNERS +++ b/chromium/gpu/command_buffer/OWNERS @@ -1,5 +1,4 @@ piman@chromium.org -jbauman@chromium.org bajones@chromium.org zmo@chromium.org vmiura@chromium.org diff --git a/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py b/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py index c11416239e4..6c90e56f5b3 100755 --- a/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -2057,6 +2057,7 @@ _NAMED_TYPE_INFO = { 'GL_RGB_YCRCB_420_CHROMIUM', 'GL_RGB_YCBCR_422_CHROMIUM', 'GL_RGB_YCBCR_420V_CHROMIUM', + 'GL_R16_EXT', ], }, 'TextureInternalFormatStorage': { diff --git a/chromium/gpu/command_buffer/client/client_discardable_manager.h b/chromium/gpu/command_buffer/client/client_discardable_manager.h index 780b80dcf17..25418eb40d4 100644 --- a/chromium/gpu/command_buffer/client/client_discardable_manager.h +++ b/chromium/gpu/command_buffer/client/client_discardable_manager.h @@ -6,9 +6,9 @@ #define GPU_COMMAND_BUFFER_CLIENT_CLIENT_DISCARDABLE_MANAGER_H_ #include -#include #include +#include "base/containers/queue.h" #include "gpu/command_buffer/common/command_buffer.h" #include "gpu/command_buffer/common/discardable_handle.h" #include "gpu/gpu_export.h" @@ -62,7 +62,7 @@ class GPU_EXPORT ClientDiscardableManager { // Handles that are pending service deletion, and can be re-used once // ClientDiscardableHandle::CanBeReUsed returns true. - std::queue pending_handles_; + base::queue pending_handles_; DISALLOW_COPY_AND_ASSIGN(ClientDiscardableManager); }; diff --git a/chromium/gpu/command_buffer/client/client_test_helper.h b/chromium/gpu/command_buffer/client/client_test_helper.h index 25a05ada70c..71bd3c26bf9 100644 --- a/chromium/gpu/command_buffer/client/client_test_helper.h +++ b/chromium/gpu/command_buffer/client/client_test_helper.h @@ -103,7 +103,7 @@ class MockClientGpuControl : public GpuControl { virtual ~MockClientGpuControl(); MOCK_METHOD1(SetGpuControlClient, void(GpuControlClient*)); - MOCK_METHOD0(GetCapabilities, Capabilities()); + MOCK_CONST_METHOD0(GetCapabilities, const Capabilities&()); MOCK_METHOD4(CreateImage, int32_t(ClientBuffer buffer, size_t width, @@ -136,4 +136,3 @@ class MockClientGpuControl : public GpuControl { } // namespace gpu #endif // GPU_COMMAND_BUFFER_CLIENT_CLIENT_TEST_HELPER_H_ - diff --git a/chromium/gpu/command_buffer/client/gles2_implementation.h b/chromium/gpu/command_buffer/client/gles2_implementation.h index 17f77992128..8ce0179fbef 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation.h +++ b/chromium/gpu/command_buffer/client/gles2_implementation.h @@ -11,13 +11,13 @@ #include #include #include -#include #include #include #include #include #include "base/compiler_specific.h" +#include "base/containers/queue.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/trace_event/memory_dump_provider.h" @@ -693,8 +693,8 @@ class GLES2_IMPL_EXPORT GLES2Implementation DebugMarkerManager debug_marker_manager_; std::string this_in_hex_; - std::queue swap_buffers_tokens_; - std::queue rate_limit_tokens_; + base::queue swap_buffers_tokens_; + base::queue rate_limit_tokens_; ExtensionStatus chromium_framebuffer_multisample_; diff --git a/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc b/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc index 386ff6afb4f..d724023c4e5 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -46,6 +46,7 @@ using testing::Sequence; using testing::StrictMock; using testing::Truly; using testing::Return; +using testing::ReturnRef; namespace gpu { namespace gles2 { @@ -445,42 +446,42 @@ class GLES2ImplementationTest : public testing::Test { helper_->Initialize(limits.command_buffer_size); gpu_control_.reset(new StrictMock()); - Capabilities capabilities; - capabilities.VisitPrecisions( + capabilities_.VisitPrecisions( [](GLenum shader, GLenum type, Capabilities::ShaderPrecision* precision) { precision->min_range = 3; precision->max_range = 5; precision->precision = 7; }); - capabilities.max_combined_texture_image_units = + capabilities_.max_combined_texture_image_units = kMaxCombinedTextureImageUnits; - capabilities.max_cube_map_texture_size = kMaxCubeMapTextureSize; - capabilities.max_fragment_uniform_vectors = kMaxFragmentUniformVectors; - capabilities.max_renderbuffer_size = kMaxRenderbufferSize; - capabilities.max_texture_image_units = kMaxTextureImageUnits; - capabilities.max_texture_size = kMaxTextureSize; - capabilities.max_varying_vectors = kMaxVaryingVectors; - capabilities.max_vertex_attribs = kMaxVertexAttribs; - capabilities.max_vertex_texture_image_units = kMaxVertexTextureImageUnits; - capabilities.max_vertex_uniform_vectors = kMaxVertexUniformVectors; - capabilities.max_viewport_width = kMaxViewportWidth; - capabilities.max_viewport_height = kMaxViewportHeight; - capabilities.num_compressed_texture_formats = + capabilities_.max_cube_map_texture_size = kMaxCubeMapTextureSize; + capabilities_.max_fragment_uniform_vectors = kMaxFragmentUniformVectors; + capabilities_.max_renderbuffer_size = kMaxRenderbufferSize; + capabilities_.max_texture_image_units = kMaxTextureImageUnits; + capabilities_.max_texture_size = kMaxTextureSize; + capabilities_.max_varying_vectors = kMaxVaryingVectors; + capabilities_.max_vertex_attribs = kMaxVertexAttribs; + capabilities_.max_vertex_texture_image_units = + kMaxVertexTextureImageUnits; + capabilities_.max_vertex_uniform_vectors = kMaxVertexUniformVectors; + capabilities_.max_viewport_width = kMaxViewportWidth; + capabilities_.max_viewport_height = kMaxViewportHeight; + capabilities_.num_compressed_texture_formats = kNumCompressedTextureFormats; - capabilities.num_shader_binary_formats = kNumShaderBinaryFormats; - capabilities.max_transform_feedback_separate_attribs = + capabilities_.num_shader_binary_formats = kNumShaderBinaryFormats; + capabilities_.max_transform_feedback_separate_attribs = kMaxTransformFeedbackSeparateAttribs; - capabilities.max_uniform_buffer_bindings = kMaxUniformBufferBindings; - capabilities.bind_generates_resource_chromium = + capabilities_.max_uniform_buffer_bindings = kMaxUniformBufferBindings; + capabilities_.bind_generates_resource_chromium = bind_generates_resource_service ? 1 : 0; - capabilities.sync_query = sync_query; - capabilities.occlusion_query_boolean = occlusion_query_boolean; - capabilities.timer_queries = timer_queries; - capabilities.major_version = major_version; - capabilities.minor_version = minor_version; + capabilities_.sync_query = sync_query; + capabilities_.occlusion_query_boolean = occlusion_query_boolean; + capabilities_.timer_queries = timer_queries; + capabilities_.major_version = major_version; + capabilities_.minor_version = minor_version; EXPECT_CALL(*gpu_control_, GetCapabilities()) - .WillOnce(Return(capabilities)); + .WillOnce(ReturnRef(capabilities_)); { InSequence sequence; @@ -543,6 +544,7 @@ class GLES2ImplementationTest : public testing::Test { std::unique_ptr gl_; CommandBufferEntry* commands_; int token_; + Capabilities capabilities_; }; GLES2ImplementationTest() : commands_(NULL) {} diff --git a/chromium/gpu/command_buffer/client/gpu_control.h b/chromium/gpu/command_buffer/client/gpu_control.h index 7c6384bd4ea..948788485bf 100644 --- a/chromium/gpu/command_buffer/client/gpu_control.h +++ b/chromium/gpu/command_buffer/client/gpu_control.h @@ -40,7 +40,7 @@ class GPU_EXPORT GpuControl { virtual void SetGpuControlClient(GpuControlClient* gpu_control_client) = 0; - virtual Capabilities GetCapabilities() = 0; + virtual const Capabilities& GetCapabilities() const = 0; // Create an image for a client buffer with the given dimensions and // format. Returns its ID or -1 on error. diff --git a/chromium/gpu/command_buffer/client/query_tracker.cc b/chromium/gpu/command_buffer/client/query_tracker.cc index a4b76f5f0b3..0def9cda03b 100644 --- a/chromium/gpu/command_buffer/client/query_tracker.cc +++ b/chromium/gpu/command_buffer/client/query_tracker.cc @@ -13,6 +13,7 @@ #include #include "base/atomicops.h" +#include "base/containers/circular_deque.h" #include "base/memory/ptr_util.h" #include "base/numerics/safe_conversions.h" #include "gpu/command_buffer/client/gles2_cmd_helper.h" @@ -111,8 +112,7 @@ void QuerySyncManager::Free(const QuerySyncManager::QueryInfo& info) { } void QuerySyncManager::Shrink(CommandBufferHelper* helper) { - std::deque> new_buckets; - bool has_token = false; + base::circular_deque> new_buckets; uint32_t token = 0; while (!buckets_.empty()) { std::unique_ptr& bucket = buckets_.front(); @@ -124,7 +124,6 @@ void QuerySyncManager::Shrink(CommandBufferHelper* helper) { // access the shared memory after current commands, so we can // free-pending-token. token = helper->InsertToken(); - has_token = true; mapped_memory_->FreePendingToken(bucket->syncs, token); } else { new_buckets.push_back(std::move(bucket)); diff --git a/chromium/gpu/command_buffer/client/query_tracker.h b/chromium/gpu/command_buffer/client/query_tracker.h index a52910055d2..7d104ac0228 100644 --- a/chromium/gpu/command_buffer/client/query_tracker.h +++ b/chromium/gpu/command_buffer/client/query_tracker.h @@ -11,11 +11,11 @@ #include #include -#include #include #include #include "base/atomicops.h" +#include "base/containers/circular_deque.h" #include "base/containers/flat_map.h" #include "base/containers/hash_tables.h" #include "base/gtest_prod_util.h" @@ -78,7 +78,7 @@ class GLES2_IMPL_EXPORT QuerySyncManager { FRIEND_TEST_ALL_PREFIXES(QuerySyncManagerTest, Shrink); MappedMemoryManager* mapped_memory_; - std::deque> buckets_; + base::circular_deque> buckets_; DISALLOW_COPY_AND_ASSIGN(QuerySyncManager); }; diff --git a/chromium/gpu/command_buffer/client/ring_buffer.h b/chromium/gpu/command_buffer/client/ring_buffer.h index 48ba789ec9d..f2278229ad2 100644 --- a/chromium/gpu/command_buffer/client/ring_buffer.h +++ b/chromium/gpu/command_buffer/client/ring_buffer.h @@ -9,8 +9,7 @@ #include -#include - +#include "base/containers/circular_deque.h" #include "base/logging.h" #include "base/macros.h" #include "gpu/gpu_export.h" @@ -114,8 +113,8 @@ class GPU_EXPORT RingBuffer { State state; }; - typedef std::deque Container; - typedef unsigned int BlockIndex; + using Container = base::circular_deque; + using BlockIndex = unsigned int; void FreeOldestBlock(); diff --git a/chromium/gpu/command_buffer/client/share_group.cc b/chromium/gpu/command_buffer/client/share_group.cc index 126332cc865..5c4e4da21e0 100644 --- a/chromium/gpu/command_buffer/client/share_group.cc +++ b/chromium/gpu/command_buffer/client/share_group.cc @@ -6,8 +6,9 @@ #include -#include #include + +#include "base/containers/stack.h" #include "base/logging.h" #include "base/synchronization/lock.h" #include "gpu/command_buffer/client/gles2_cmd_helper.h" @@ -255,7 +256,7 @@ class StrictIdHandler : public IdHandlerInterface { base::Lock lock_; std::vector id_states_; - std::stack free_ids_; + base::stack free_ids_; }; // An id handler for ids that are never reused. diff --git a/chromium/gpu/command_buffer/client/shared_memory_limits.h b/chromium/gpu/command_buffer/client/shared_memory_limits.h index ed62e956cfb..16da712c7e4 100644 --- a/chromium/gpu/command_buffer/client/shared_memory_limits.h +++ b/chromium/gpu/command_buffer/client/shared_memory_limits.h @@ -26,7 +26,7 @@ struct SharedMemoryLimits { : 0; // On memory constrained devices, switch to lower limits. - if (base::SysInfo::AmountOfPhysicalMemoryMB() < 512) { + if (base::SysInfo::AmountOfPhysicalMemoryMB() <= 512) { command_buffer_size = 512 * 1024; start_transfer_buffer_size = 256 * 1024; min_transfer_buffer_size = 128 * 1024; diff --git a/chromium/gpu/command_buffer/common/capabilities.h b/chromium/gpu/command_buffer/common/capabilities.h index e49f3004ac1..46b02e5d88d 100644 --- a/chromium/gpu/command_buffer/common/capabilities.h +++ b/chromium/gpu/command_buffer/common/capabilities.h @@ -152,8 +152,6 @@ struct GPU_EXPORT Capabilities { bool flips_vertically = false; bool msaa_is_slow = false; bool disable_one_component_textures = false; - bool disable_multisampling_color_mask_usage = false; - bool disable_webgl_rgb_multisampling_usage = false; bool gpu_rasterization = false; bool avoid_stencil_buffers = false; bool multisample_compatibility = false; @@ -168,19 +166,13 @@ struct GPU_EXPORT Capabilities { // details. bool chromium_image_rgb_emulation = false; - // When true, RGB framebuffer formats are unsupported. Emulate with RGBA to - // work around this. See https://crbug.com/449150 for an example. - bool emulate_rgb_buffer_with_rgba = false; - - // When true, is safe to convert a canvas from software to accelerated. - // See https://crbug.com/710029. - bool software_to_accelerated_canvas_upgrade = true; - // When true, non-empty post sub buffer calls are unsupported. bool disable_non_empty_post_sub_buffers = false; bool disable_2d_canvas_copy_on_write = false; + bool texture_npot = false; + int major_version = 2; int minor_version = 0; }; diff --git a/chromium/gpu/command_buffer/common/debug_marker_manager.h b/chromium/gpu/command_buffer/common/debug_marker_manager.h index 65e0cd011d6..810352cd0c5 100644 --- a/chromium/gpu/command_buffer/common/debug_marker_manager.h +++ b/chromium/gpu/command_buffer/common/debug_marker_manager.h @@ -5,8 +5,9 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_DEBUG_MARKER_MANAGER_H_ #define GPU_COMMAND_BUFFER_SERVICE_DEBUG_MARKER_MANAGER_H_ -#include #include + +#include "base/containers/stack.h" #include "gpu/gpu_export.h" namespace gpu { @@ -49,7 +50,7 @@ class GPU_EXPORT DebugMarkerManager { std::string marker_; }; - typedef std::stack GroupStack; + using GroupStack = base::stack; GroupStack group_stack_; std::string empty_; 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 b6a91d84d79..1e8f611f43a 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 @@ -5622,6 +5622,7 @@ std::string GLES2Util::GetStringTextureSizedTextureFilterableInternalFormat( {GL_RGB_YCRCB_420_CHROMIUM, "GL_RGB_YCRCB_420_CHROMIUM"}, {GL_RGB_YCBCR_422_CHROMIUM, "GL_RGB_YCBCR_422_CHROMIUM"}, {GL_RGB_YCBCR_420V_CHROMIUM, "GL_RGB_YCBCR_420V_CHROMIUM"}, + {GL_R16_EXT, "GL_R16_EXT"}, }; return GLES2Util::GetQualifiedEnumString(string_table, arraysize(string_table), value); diff --git a/chromium/gpu/command_buffer/common/scheduling_priority.cc b/chromium/gpu/command_buffer/common/scheduling_priority.cc index 62b6456c921..351a65182da 100644 --- a/chromium/gpu/command_buffer/common/scheduling_priority.cc +++ b/chromium/gpu/command_buffer/common/scheduling_priority.cc @@ -10,16 +10,12 @@ namespace gpu { const char* SchedulingPriorityToString(SchedulingPriority priority) { switch (priority) { - case SchedulingPriority::kHighest: - return "Highest"; case SchedulingPriority::kHigh: return "High"; case SchedulingPriority::kNormal: return "Normal"; case SchedulingPriority::kLow: return "Low"; - case SchedulingPriority::kLowest: - return "Lowest"; } NOTREACHED(); return ""; diff --git a/chromium/gpu/command_buffer/common/scheduling_priority.h b/chromium/gpu/command_buffer/common/scheduling_priority.h index ca93809f608..b4bdfb0c601 100644 --- a/chromium/gpu/command_buffer/common/scheduling_priority.h +++ b/chromium/gpu/command_buffer/common/scheduling_priority.h @@ -10,19 +10,16 @@ namespace gpu { enum class SchedulingPriority { - // The Highest and High priorities can be used by priveleged clients only. - // This priority should be used for UI contexts. - kHighest, - // This priority is used by the scheduler for prioritizing contexts which have - // outstanding sync token waits. + // The High priority can be used by priveleged clients only. This priority is + // used for UI contexts and by the scheduler for prioritizing contexts which + // have outstanding sync token waits or client side waits. kHigh, // The following priorities can be used on unprivileged clients. - // This priority should be used as the default priority for all contexts. + // This priority is used as the default priority for all contexts. kNormal, + // This priority is used for worker contexts. kLow, - // This priority should be used for worker contexts. - kLowest, - kLast = kLowest + kLast = kLow }; GPU_EXPORT const char* SchedulingPriorityToString(SchedulingPriority priority); diff --git a/chromium/gpu/command_buffer/service/client_service_map.h b/chromium/gpu/command_buffer/service/client_service_map.h index 904a0951716..5d83573525a 100644 --- a/chromium/gpu/command_buffer/service/client_service_map.h +++ b/chromium/gpu/command_buffer/service/client_service_map.h @@ -30,18 +30,17 @@ class ClientServiceMap { void Clear() { client_to_service_.clear(); } bool GetServiceID(ClientType client_id, ServiceType* service_id) const { - if (client_id == 0) { - if (service_id) { - *service_id = 0; - } - return true; - } auto iter = client_to_service_.find(client_id); if (iter != client_to_service_.end()) { if (service_id) { *service_id = iter->second; } return true; + } else if (client_id == 0) { + if (service_id) { + *service_id = 0; + } + return true; } return false; } @@ -55,12 +54,6 @@ class ClientServiceMap { } bool GetClientID(ServiceType service_id, ClientType* client_id) const { - if (service_id == 0) { - if (client_id) { - *client_id = 0; - } - return true; - } for (auto mapping : client_to_service_) { if (mapping.second == service_id) { if (client_id) { @@ -69,6 +62,12 @@ class ClientServiceMap { return true; } } + if (service_id == 0) { + if (client_id) { + *client_id = 0; + } + return true; + } return false; } diff --git a/chromium/gpu/command_buffer/service/context_group.cc b/chromium/gpu/command_buffer/service/context_group.cc index 11a8eb90e8d..146958140b6 100644 --- a/chromium/gpu/command_buffer/service/context_group.cc +++ b/chromium/gpu/command_buffer/service/context_group.cc @@ -46,15 +46,15 @@ DisallowedFeatures AdjustDisallowedFeatures( DisallowedFeatures adjusted_disallowed_features = disallowed_features; if (context_type == CONTEXT_TYPE_WEBGL1) { adjusted_disallowed_features.npot_support = true; - adjusted_disallowed_features.oes_texture_half_float_linear = true; } if (context_type == CONTEXT_TYPE_WEBGL1 || context_type == CONTEXT_TYPE_WEBGL2) { adjusted_disallowed_features.chromium_color_buffer_float_rgba = true; adjusted_disallowed_features.chromium_color_buffer_float_rgb = true; adjusted_disallowed_features.ext_color_buffer_float = true; - adjusted_disallowed_features.ext_color_buffer_half_float = true; adjusted_disallowed_features.oes_texture_float_linear = true; + adjusted_disallowed_features.ext_color_buffer_half_float = true; + adjusted_disallowed_features.oes_texture_half_float_linear = true; } return adjusted_disallowed_features; } @@ -128,12 +128,24 @@ ContextGroup::ContextGroup( bool ContextGroup::Initialize(GLES2Decoder* decoder, ContextType context_type, const DisallowedFeatures& disallowed_features) { - bool enable_es3 = context_type == CONTEXT_TYPE_OPENGLES3 || - context_type == CONTEXT_TYPE_WEBGL2; - if (!gpu_preferences_.enable_es3_apis && enable_es3) { - DLOG(ERROR) << "ContextGroup::Initialize failed because ES3 APIs are " - << "not available."; - return false; + switch (context_type) { + case CONTEXT_TYPE_WEBGL1: + if (kGpuFeatureStatusBlacklisted == + gpu_feature_info_.status_values[GPU_FEATURE_TYPE_ACCELERATED_WEBGL]) { + DLOG(ERROR) << "ContextGroup::Initialize failed: WebGL1 baclklisted"; + return false; + } + break; + case CONTEXT_TYPE_WEBGL2: + if (kGpuFeatureStatusBlacklisted == + gpu_feature_info_ + .status_values[GPU_FEATURE_TYPE_ACCELERATED_WEBGL2]) { + DLOG(ERROR) << "ContextGroup::Initialize failed: WebGL2 blacklisted"; + return false; + } + break; + default: + break; } if (HaveContexts()) { if (context_type != feature_info_->context_type()) { @@ -176,7 +188,9 @@ bool ContextGroup::Initialize(GLES2Decoder* decoder, } } - if (enable_es3 || feature_info_->feature_flags().ext_draw_buffers) { + if (context_type == CONTEXT_TYPE_OPENGLES3 || + context_type == CONTEXT_TYPE_WEBGL2 || + feature_info_->feature_flags().ext_draw_buffers) { GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_color_attachments_); if (max_color_attachments_ < 1) max_color_attachments_ = 1; diff --git a/chromium/gpu/command_buffer/service/context_group_unittest.cc b/chromium/gpu/command_buffer/service/context_group_unittest.cc index 28fb63a9d35..0cb509858f7 100644 --- a/chromium/gpu/command_buffer/service/context_group_unittest.cc +++ b/chromium/gpu/command_buffer/service/context_group_unittest.cc @@ -11,6 +11,7 @@ #include "gpu/command_buffer/client/client_test_helper.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/gpu_service_test.h" +#include "gpu/command_buffer/service/gpu_tracer.h" #include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager_impl.h" #include "gpu/command_buffer/service/service_discardable_manager.h" @@ -43,7 +44,7 @@ class ContextGroupTest : public GpuServiceTest { protected: void SetUp() override { GpuServiceTest::SetUp(); - decoder_.reset(new MockGLES2Decoder(&command_buffer_service_)); + decoder_.reset(new MockGLES2Decoder(&command_buffer_service_, &outputter_)); scoped_refptr feature_info = new FeatureInfo; group_ = scoped_refptr(new ContextGroup( gpu_preferences_, false, &mailbox_manager_, @@ -59,6 +60,7 @@ class ContextGroupTest : public GpuServiceTest { ServiceDiscardableManager discardable_manager_; FakeCommandBufferServiceBase command_buffer_service_; MailboxManagerImpl mailbox_manager_; + TraceOutputter outputter_; std::unique_ptr decoder_; scoped_refptr group_; }; @@ -116,8 +118,9 @@ TEST_F(ContextGroupTest, InitializeNoExtensions) { TEST_F(ContextGroupTest, MultipleContexts) { FakeCommandBufferServiceBase command_buffer_service2; + TraceOutputter outputter; std::unique_ptr decoder2_( - new MockGLES2Decoder(&command_buffer_service2)); + new MockGLES2Decoder(&command_buffer_service2, &outputter)); TestHelper::SetupContextGroupInitExpectations( gl_.get(), DisallowedFeatures(), "", "", CONTEXT_TYPE_OPENGLES2, kBindGeneratesResource); diff --git a/chromium/gpu/command_buffer/service/create_gr_gl_interface.cc b/chromium/gpu/command_buffer/service/create_gr_gl_interface.cc index 08c3c64a6c2..691dbc84e8a 100644 --- a/chromium/gpu/command_buffer/service/create_gr_gl_interface.cc +++ b/chromium/gpu/command_buffer/service/create_gr_gl_interface.cc @@ -11,6 +11,12 @@ namespace gles2 { namespace { +template +GrGLFunction bind(R (gl::GLApi::*func)(Args...), + gl::GLApi* api) { + return [func, api](Args... args) { return (api->*func)(args...); }; +} + const GLubyte* GetStringHook(const char* version_string, GLenum name) { switch (name) { case GL_VERSION: @@ -43,6 +49,7 @@ const char* kBlacklistExtensions[] = { sk_sp CreateGrGLInterface( const gl::GLVersionInfo& version_info) { gl::ProcsGL* gl = &gl::g_current_gl_driver->fn; + gl::GLApi* api = gl::g_current_gl_context; GrGLStandard standard = version_info.is_es ? kGLES_GrGLStandard : kGL_GrGLStandard; @@ -60,12 +67,14 @@ sk_sp CreateGrGLInterface( return GetStringHook(fake_version, name); }; } else { - get_string = gl->glGetStringFn; + get_string = bind(&gl::GLApi::glGetStringFn, api); } + auto get_stringi = bind(&gl::GLApi::glGetStringiFn, api); + auto get_integerv = bind(&gl::GLApi::glGetIntegervFn, api); + GrGLExtensions extensions; - if (!extensions.init(standard, get_string, gl->glGetStringiFn, - gl->glGetIntegervFn)) { + if (!extensions.init(standard, get_string, get_stringi, get_integerv)) { LOG(ERROR) << "Failed to initialize extensions"; return nullptr; } @@ -113,6 +122,7 @@ sk_sp CreateGrGLInterface( functions->fDepthMask = gl->glDepthMaskFn; functions->fDisable = gl->glDisableFn; functions->fDisableVertexAttribArray = gl->glDisableVertexAttribArrayFn; + functions->fDiscardFramebuffer = gl->glDiscardFramebufferEXTFn; functions->fDrawArrays = gl->glDrawArraysFn; functions->fDrawBuffer = gl->glDrawBufferFn; functions->fDrawBuffers = gl->glDrawBuffersARBFn; @@ -249,6 +259,10 @@ sk_sp CreateGrGLInterface( functions->fBindRenderbuffer = gl->glBindRenderbufferEXTFn; functions->fRenderbufferStorageMultisample = gl->glRenderbufferStorageMultisampleEXTFn; + functions->fFramebufferTexture2DMultisample = + gl->glFramebufferTexture2DMultisampleEXTFn; + functions->fRenderbufferStorageMultisampleES2EXT = + gl->glRenderbufferStorageMultisampleEXTFn; functions->fBlitFramebuffer = gl->glBlitFramebufferFn; functions->fMatrixLoadf = gl->glMatrixLoadfEXTFn; diff --git a/chromium/gpu/command_buffer/service/feature_info.cc b/chromium/gpu/command_buffer/service/feature_info.cc index f038996b228..b8851b35169 100644 --- a/chromium/gpu/command_buffer/service/feature_info.cc +++ b/chromium/gpu/command_buffer/service/feature_info.cc @@ -177,6 +177,35 @@ bool IsWebGLDrawBuffersSupported(bool webglCompatibilityContext, } // anonymous namespace. +namespace { + +enum GpuTextureResultR16_L16 { + // Values synced with 'GpuTextureResultR16_L16' in + // src/tools/metrics/histograms/histograms.xml + kHaveNone = 0, + kHaveR16 = 1, + kHaveL16 = 2, + kHaveR16AndL16 = 3, + kMax = kHaveR16AndL16 +}; + +// TODO(riju): For UMA, remove after crbug.com/759456 is resolved. +bool g_r16_is_present; +bool g_l16_is_present; + +GpuTextureResultR16_L16 GpuTextureUMAHelper() { + if (g_r16_is_present && g_l16_is_present) { + return GpuTextureResultR16_L16::kHaveR16AndL16; + } else if (g_r16_is_present) { + return GpuTextureResultR16_L16::kHaveR16; + } else if (g_l16_is_present) { + return GpuTextureResultR16_L16::kHaveL16; + } + return GpuTextureResultR16_L16::kHaveNone; +} + +} // anonymous namespace. + FeatureInfo::FeatureFlags::FeatureFlags() {} FeatureInfo::FeatureInfo() { @@ -1296,8 +1325,11 @@ void FeatureInfo::InitializeFeatures() { UMA_HISTOGRAM_BOOLEAN("GPU.TextureRG", feature_flags_.ext_texture_rg); if (gl_version_info_->is_desktop_core_profile || + (gl_version_info_->IsAtLeastGL(2, 1) && + gl::HasExtension(extensions, "GL_ARB_texture_rg")) || gl::HasExtension(extensions, "GL_EXT_texture_norm16")) { feature_flags_.ext_texture_norm16 = true; + g_r16_is_present = true; AddExtensionString("GL_EXT_texture_norm16"); // Note: EXT_texture_norm16 is not exposed through WebGL API so we validate @@ -1308,6 +1340,10 @@ void FeatureInfo::InitializeFeatures() { validators_.texture_unsized_internal_format.AddValue(GL_RED_EXT); } + UMA_HISTOGRAM_ENUMERATION( + "GPU.TextureR16Ext_LuminanceF16", GpuTextureUMAHelper(), + static_cast(GpuTextureResultR16_L16::kMax) + 1); + bool has_opengl_dual_source_blending = gl_version_info_->IsAtLeastGL(3, 3) || (gl_version_info_->IsAtLeastGL(3, 2) && @@ -1385,6 +1421,11 @@ void FeatureInfo::InitializeFeatures() { gl::HasExtension(extensions, "GL_CHROMIUM_texture_filtering_hint"); feature_flags_.ext_pixel_buffer_object = gl::HasExtension(extensions, "GL_NV_pixel_buffer_object"); + feature_flags_.oes_rgb8_rgba8 = + gl::HasExtension(extensions, "GL_OES_rgb8_rgba8"); + feature_flags_.angle_robust_resource_initialization = + gl::HasExtension(extensions, "GL_ANGLE_robust_resource_initialization"); + feature_flags_.nv_fence = gl::HasExtension(extensions, "GL_NV_fence"); } void FeatureInfo::InitializeFloatAndHalfFloatFeatures( @@ -1406,8 +1447,14 @@ void FeatureInfo::InitializeFloatAndHalfFloatFeatures( // rendered to via framebuffer objects. if (gl::HasExtension(extensions, "GL_EXT_color_buffer_float")) enable_ext_color_buffer_float = true; - if (gl::HasExtension(extensions, "GL_EXT_color_buffer_half_float")) + if (gl::HasExtension(extensions, "GL_EXT_color_buffer_half_float")) { + // TODO(zmo): even if the underlying driver reports the extension, WebGL + // version of the extension requires RGBA16F to be color-renderable, + // whereas the OpenGL ES extension only requires one of the format to be + // color-renderable. So we still need to do some verification before + // exposing the extension. enable_ext_color_buffer_half_float = true; + } if (gl::HasExtension(extensions, "GL_ARB_texture_float") || gl_version_info_->is_desktop_core_profile) { @@ -1541,28 +1588,20 @@ void FeatureInfo::InitializeFloatAndHalfFloatFeatures( // Likewise for EXT_color_buffer_half_float on ES2 contexts. On desktop, // require at least GL 3.0, to ensure that all formats are defined. if (IsWebGL1OrES2Context() && !enable_ext_color_buffer_half_float && - (gl_version_info_->is_es || gl_version_info_->IsAtLeastGL(3, 0))) { - bool full_half_float_support = true; - GLenum internal_formats[] = { - GL_R16F, GL_RG16F, GL_RGBA16F, - }; - GLenum formats[] = { - GL_RED, GL_RG, GL_RGBA, - }; - GLenum data_type = GL_FLOAT; - if (gl_version_info_->is_es2) - data_type = GL_HALF_FLOAT_OES; - if (gl_version_info_->is_es3) - data_type = GL_HALF_FLOAT; - DCHECK_EQ(arraysize(internal_formats), arraysize(formats)); - for (size_t i = 0; i < arraysize(formats); ++i) { - glTexImage2D(GL_TEXTURE_2D, 0, internal_formats[i], width, width, 0, - formats[i], data_type, NULL); - full_half_float_support &= - glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) == - GL_FRAMEBUFFER_COMPLETE; - } - enable_ext_color_buffer_half_float = full_half_float_support; + (gl_version_info_->IsAtLeastGLES(3, 0) || + gl_version_info_->IsAtLeastGL(3, 0))) { + // EXT_color_buffer_half_float requires at least one of the formats is + // supported to be color-renderable. WebGL's extension requires RGBA16F + // to be the supported effective format. Here we only expose the extension + // if RGBA16F is color-renderable. + GLenum internal_format = GL_RGBA16F; + GLenum format = GL_RGBA; + GLenum data_type = GL_HALF_FLOAT; + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, width, 0, format, + data_type, nullptr); + enable_ext_color_buffer_half_float = + (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) == + GL_FRAMEBUFFER_COMPLETE); } glDeleteFramebuffersEXT(1, &fb_id); @@ -1616,6 +1655,9 @@ void FeatureInfo::InitializeFloatAndHalfFloatFeatures( GL_LUMINANCE_ALPHA16F_EXT); } } + + g_l16_is_present = + enable_texture_half_float && feature_flags_.ext_texture_storage; } bool FeatureInfo::IsES3Capable() const { diff --git a/chromium/gpu/command_buffer/service/feature_info.h b/chromium/gpu/command_buffer/service/feature_info.h index 6fe9fbe527e..bb5daf39d41 100644 --- a/chromium/gpu/command_buffer/service/feature_info.h +++ b/chromium/gpu/command_buffer/service/feature_info.h @@ -119,6 +119,9 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted { bool khr_robustness = false; bool ext_robustness = false; bool ext_pixel_buffer_object = false; + bool oes_rgb8_rgba8 = false; + bool angle_robust_resource_initialization = false; + bool nv_fence = false; }; FeatureInfo(); diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager.cc b/chromium/gpu/command_buffer/service/framebuffer_manager.cc index 366c5085c87..86ef51edec1 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager.cc +++ b/chromium/gpu/command_buffer/service/framebuffer_manager.cc @@ -722,6 +722,7 @@ GLenum Framebuffer::IsPossiblyComplete(const FeatureInfo* feature_info) const { // Since DirectX doesn't allow attachments to be of different sizes, // even though ES3 allows it, it is still forbidden to ensure consistent // behaviors across platforms. + // Note: Framebuffer::GetFramebufferValidSize relies on this behavior. return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT; } @@ -1050,6 +1051,19 @@ const Framebuffer::Attachment* Framebuffer::GetReadBufferAttachment() const { return GetAttachment(read_buffer_); } +gfx::Size Framebuffer::GetFramebufferValidSize() const { + // This DCHECK ensures the framebuffer was already checked to be complete. + DCHECK(manager_->IsComplete(this)); + + // IsPossiblyComplete ensures that there is at least one attachment, and that + // all of the attachments have the same dimensions. So it's okay to just pick + // any arbitrary attachment and return it as the min size. + auto it = attachments_.begin(); + DCHECK(it != attachments_.end()); + const auto& attachment = it->second; + return gfx::Size(attachment->width(), attachment->height()); +} + bool FramebufferManager::GetClientId( GLuint service_id, GLuint* client_id) const { // This doesn't need to be fast. It's only used during slow queries. @@ -1080,8 +1094,7 @@ void FramebufferManager::MarkAsComplete( framebuffer->MarkAsComplete(framebuffer_state_change_count_); } -bool FramebufferManager::IsComplete( - Framebuffer* framebuffer) { +bool FramebufferManager::IsComplete(const Framebuffer* framebuffer) { DCHECK(framebuffer); return framebuffer->framebuffer_complete_state_count_id() == framebuffer_state_change_count_; diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager.h b/chromium/gpu/command_buffer/service/framebuffer_manager.h index 09ab0923206..c29dc649b11 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager.h +++ b/chromium/gpu/command_buffer/service/framebuffer_manager.h @@ -133,6 +133,10 @@ class GPU_EXPORT Framebuffer : public base::RefCounted { const Attachment* GetReadBufferAttachment() const; + // Returns the max dimensions which fit inside all of the attachments. + // Can only be called after the framebuffer has been checked to be complete. + gfx::Size GetFramebufferValidSize() const; + GLsizei GetSamples() const; bool IsDeleted() const { @@ -345,7 +349,7 @@ class GPU_EXPORT FramebufferManager { void MarkAsComplete(Framebuffer* framebuffer); - bool IsComplete(Framebuffer* framebuffer); + bool IsComplete(const Framebuffer* framebuffer); void IncFramebufferStateChangeCount() { // make sure this is never 0. diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc index ebe5fc8cafa..6a96d4c1e87 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc @@ -11,6 +11,7 @@ #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/gpu_service_test.h" +#include "gpu/command_buffer/service/gpu_tracer.h" #include "gpu/command_buffer/service/renderbuffer_manager.h" #include "gpu/command_buffer/service/service_discardable_manager.h" #include "gpu/command_buffer/service/test_helper.h" @@ -150,7 +151,7 @@ class FramebufferInfoTestBase : public GpuServiceTest { TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(gl_.get(), extensions, "", gl_version, context_type_); feature_info_->InitializeForTesting(context_type_); - decoder_.reset(new MockGLES2Decoder(&command_buffer_service_)); + decoder_.reset(new MockGLES2Decoder(&command_buffer_service_, &outputter_)); manager_.CreateFramebuffer(kClient1Id, kService1Id); error_state_.reset(new ::testing::StrictMock()); framebuffer_ = manager_.GetFramebuffer(kClient1Id); @@ -167,6 +168,7 @@ class FramebufferInfoTestBase : public GpuServiceTest { std::unique_ptr renderbuffer_manager_; std::unique_ptr error_state_; FakeCommandBufferServiceBase command_buffer_service_; + TraceOutputter outputter_; std::unique_ptr decoder_; }; diff --git a/chromium/gpu/command_buffer/service/gl_context_virtual_unittest.cc b/chromium/gpu/command_buffer/service/gl_context_virtual_unittest.cc index cdac976c64e..e2566c9ec51 100644 --- a/chromium/gpu/command_buffer/service/gl_context_virtual_unittest.cc +++ b/chromium/gpu/command_buffer/service/gl_context_virtual_unittest.cc @@ -7,6 +7,7 @@ #include "gpu/command_buffer/client/client_test_helper.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/gpu_service_test.h" +#include "gpu/command_buffer/service/gpu_tracer.h" #include "ui/gl/gl_context_stub.h" #include "ui/gl/gl_share_group.h" #include "ui/gl/gl_surface.h" @@ -21,11 +22,12 @@ using testing::Return; class GLContextVirtualTest : public GpuServiceTest { public: GLContextVirtualTest() - : decoder_(new gles2::MockGLES2Decoder(&command_buffer_service_)) {} + : decoder_(new MockGLES2Decoder(&command_buffer_service_, &outputter_)) {} ~GLContextVirtualTest() override {} protected: FakeCommandBufferServiceBase command_buffer_service_; + TraceOutputter outputter_; std::unique_ptr decoder_; }; diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc index 2da74f06c8a..a5446a0059a 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -14,10 +14,10 @@ #include #include #include -#include #include "base/callback.h" #include "base/callback_helpers.h" +#include "base/containers/queue.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" @@ -496,11 +496,11 @@ uint32_t GLES2Decoder::GetAndClearBackbufferClearBitsForTest() { return 0; } -GLES2Decoder::GLES2Decoder(CommandBufferServiceBase* command_buffer_service) - : CommonDecoder(command_buffer_service), - initialized_(false), - debug_(false), - log_commands_(false) {} +GLES2Decoder::GLES2Decoder(CommandBufferServiceBase* command_buffer_service, + Outputter* outputter) + : CommonDecoder(command_buffer_service), outputter_(outputter) { + DCHECK(outputter_); +} GLES2Decoder::~GLES2Decoder() { } @@ -519,6 +519,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { public: GLES2DecoderImpl(GLES2DecoderClient* client, CommandBufferServiceBase* command_buffer_service, + Outputter* outputter, ContextGroup* group); ~GLES2DecoderImpl() override; @@ -2470,7 +2471,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { bool gpu_trace_commands_; bool gpu_debug_commands_; - std::queue pending_readpixel_fences_; + base::queue pending_readpixel_fences_; // After a second fence is inserted, both the GpuChannelMessageQueue and // CommandExecutor are descheduled. Once the first fence has completed, both @@ -2521,7 +2522,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl); }; -const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = { +constexpr GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = { #define GLES2_CMD_OP(name) \ { \ &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \ @@ -3096,19 +3097,21 @@ GLenum BackFramebuffer::CheckStatus() { GLES2Decoder* GLES2Decoder::Create( GLES2DecoderClient* client, CommandBufferServiceBase* command_buffer_service, + Outputter* outputter, ContextGroup* group) { if (group->use_passthrough_cmd_decoder()) { return new GLES2DecoderPassthroughImpl(client, command_buffer_service, - group); + outputter, group); } - return new GLES2DecoderImpl(client, command_buffer_service, group); + return new GLES2DecoderImpl(client, command_buffer_service, outputter, group); } GLES2DecoderImpl::GLES2DecoderImpl( GLES2DecoderClient* client, CommandBufferServiceBase* command_buffer_service, + Outputter* outputter, ContextGroup* group) - : GLES2Decoder(command_buffer_service), + : GLES2Decoder(command_buffer_service, outputter), client_(client), group_(group), logger_(&debug_marker_manager_, client_), @@ -3399,7 +3402,7 @@ bool GLES2DecoderImpl::Initialize( offscreen_single_buffer_ = attrib_helper.single_buffer; if (gl_version_info().is_es) { - const bool rgb8_supported = context_->HasExtension("GL_OES_rgb8_rgba8"); + const bool rgb8_supported = features().oes_rgb8_rgba8; // The only available default render buffer formats in GLES2 have very // little precision. Don't enable multisampling unless 8-bit render // buffer formats are available--instead fall back to 8-bit textures. @@ -3920,20 +3923,11 @@ Capabilities GLES2DecoderImpl::GetCapabilities() { caps.occlusion_query = feature_info_->feature_flags().occlusion_query; caps.occlusion_query_boolean = feature_info_->feature_flags().occlusion_query_boolean; - caps.timer_queries = - query_manager_->GPUTimingAvailable(); - caps.disable_multisampling_color_mask_usage = - workarounds().disable_multisampling_color_mask_usage; + caps.timer_queries = query_manager_->GPUTimingAvailable(); caps.gpu_rasterization = group_->gpu_feature_info() .status_values[GPU_FEATURE_TYPE_GPU_RASTERIZATION] == kGpuFeatureStatusEnabled; - caps.disable_webgl_rgb_multisampling_usage = - workarounds().disable_webgl_rgb_multisampling_usage; - caps.software_to_accelerated_canvas_upgrade = - !workarounds().disable_software_to_accelerated_canvas_upgrade; - caps.emulate_rgb_buffer_with_rgba = - workarounds().disable_gl_rgb_format; if (workarounds().disable_non_empty_post_sub_buffers_for_onscreen_surfaces && !surface_->IsOffscreen()) { caps.disable_non_empty_post_sub_buffers = true; @@ -3942,6 +3936,7 @@ Capabilities GLES2DecoderImpl::GetCapabilities() { group_->gpu_preferences().enable_threaded_texture_mailboxes) { caps.disable_2d_canvas_copy_on_write = true; } + caps.texture_npot = feature_info_->feature_flags().npot_ok; return caps; } @@ -4081,6 +4076,10 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { if (workarounds().rewrite_float_unary_minus_operator) driver_bug_workarounds |= SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR; + // Initialize uninitialized locals by default + if (!workarounds().dont_initialize_uninitialized_locals) + driver_bug_workarounds |= SH_INITIALIZE_UNINITIALIZED_LOCALS; + resources.WEBGL_debug_shader_precision = group_->gpu_preferences().emulate_shader_precision; @@ -4589,12 +4588,7 @@ bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop( gfx::Size GLES2DecoderImpl::GetBoundReadFramebufferSize() { Framebuffer* framebuffer = GetBoundReadFramebuffer(); if (framebuffer) { - const Framebuffer::Attachment* attachment = - framebuffer->GetReadBufferAttachment(); - if (attachment) { - return gfx::Size(attachment->width(), attachment->height()); - } - return gfx::Size(0, 0); + return framebuffer->GetFramebufferValidSize(); } else if (offscreen_target_frame_buffer_.get()) { return offscreen_size_; } else { @@ -4974,7 +4968,7 @@ void GLES2DecoderImpl::Destroy(bool have_context) { // Release all fences now, because some fence types need the context to be // current on destruction. - pending_readpixel_fences_ = std::queue(); + pending_readpixel_fences_ = base::queue(); // Need to release these before releasing |group_| which may own the // ShaderTranslatorCache. @@ -10424,10 +10418,8 @@ error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE( if (!features().angle_instanced_arrays) return error::kUnknownCommand; - return DoDrawArrays("glDrawArraysIntancedANGLE", - true, - static_cast(c.mode), - static_cast(c.first), + return DoDrawArrays("glDrawArraysInstancedANGLE", true, + static_cast(c.mode), static_cast(c.first), static_cast(c.count), static_cast(c.primcount)); } @@ -11814,9 +11806,6 @@ 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 && !gl_version_info().is_es) { - type = GL_HALF_FLOAT; - } if (width == 0 || height == 0) { return error::kNoError; } diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h index 688537a3ba3..b7a07e3f478 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -48,6 +48,7 @@ class FramebufferManager; class GLES2Util; class ImageManager; class Logger; +class Outputter; class QueryManager; class ShaderTranslatorInterface; class Texture; @@ -127,6 +128,7 @@ class GPU_EXPORT GLES2Decoder : public CommonDecoder, public AsyncAPIInterface { // Creates a decoder. static GLES2Decoder* Create(GLES2DecoderClient* client, CommandBufferServiceBase* command_buffer_service, + Outputter* outputter, ContextGroup* group); ~GLES2Decoder() override; @@ -157,6 +159,8 @@ class GPU_EXPORT GLES2Decoder : public CommonDecoder, public AsyncAPIInterface { log_commands_ = log_commands; } + Outputter* outputter() const { return outputter_; } + virtual base::WeakPtr AsWeakPtr() = 0; // Initializes the graphics context. Can create an offscreen @@ -342,14 +346,17 @@ class GPU_EXPORT GLES2Decoder : public CommonDecoder, public AsyncAPIInterface { bool can_bind_to_sampler) = 0; protected: - explicit GLES2Decoder(CommandBufferServiceBase* command_buffer_service); + GLES2Decoder(CommandBufferServiceBase* command_buffer_service, + Outputter* outputter); base::StringPiece GetLogPrefix() override; private: - bool initialized_; - bool debug_; - bool log_commands_; + bool initialized_ = false; + bool debug_ = false; + bool log_commands_ = false; + Outputter* outputter_ = nullptr; + DISALLOW_COPY_AND_ASSIGN(GLES2Decoder); }; 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 5df3d06eb0c..50511a581dc 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc @@ -10,8 +10,9 @@ namespace gpu { namespace gles2 { MockGLES2Decoder::MockGLES2Decoder( - CommandBufferServiceBase* command_buffer_service) - : GLES2Decoder(command_buffer_service), weak_ptr_factory_(this) { + CommandBufferServiceBase* command_buffer_service, + Outputter* outputter) + : GLES2Decoder(command_buffer_service, outputter), weak_ptr_factory_(this) { ON_CALL(*this, MakeCurrent()) .WillByDefault(testing::Return(true)); } 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 a694ba2e8e2..5a85501e7d1 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -36,7 +36,8 @@ struct ContextState; class MockGLES2Decoder : public GLES2Decoder { public: - explicit MockGLES2Decoder(CommandBufferServiceBase* command_buffer_service); + MockGLES2Decoder(CommandBufferServiceBase* command_buffer_service, + Outputter* outputter); virtual ~MockGLES2Decoder(); base::WeakPtr AsWeakPtr() override; diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index f033ced36c0..4d427bec788 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc @@ -46,6 +46,31 @@ bool GetClientID(const ClientServiceMap* map, return true; }; +void ResizeRenderbuffer(GLuint renderbuffer, + const gfx::Size& size, + GLsizei samples, + GLenum internal_format, + const FeatureInfo* feature_info) { + ScopedRenderbufferBindingReset scoped_renderbuffer_reset; + + glBindRenderbufferEXT(GL_RENDERBUFFER, renderbuffer); + if (samples > 0) { + if (feature_info->feature_flags().angle_framebuffer_multisample) { + glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, samples, + internal_format, size.width(), + size.height()); + } else { + DCHECK(feature_info->gl_version_info().is_es3); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, + internal_format, size.width(), + size.height()); + } + } else { + glRenderbufferStorageEXT(GL_RENDERBUFFER, internal_format, size.width(), + size.height()); + } +} + } // anonymous namespace PassthroughResources::PassthroughResources() {} @@ -90,6 +115,34 @@ void PassthroughResources::Destroy(bool have_context) { texture_object_map.clear(); } +ScopedFramebufferBindingReset::ScopedFramebufferBindingReset() + : draw_framebuffer_(0), read_framebuffer_(0) { + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer_); + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer_); +} + +ScopedFramebufferBindingReset::~ScopedFramebufferBindingReset() { + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer_); + glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer_); +} + +ScopedRenderbufferBindingReset::ScopedRenderbufferBindingReset() + : renderbuffer_(0) { + glGetIntegerv(GL_RENDERBUFFER_BINDING, &renderbuffer_); +} + +ScopedRenderbufferBindingReset::~ScopedRenderbufferBindingReset() { + glBindRenderbufferEXT(GL_RENDERBUFFER, renderbuffer_); +} + +ScopedTexture2DBindingReset::ScopedTexture2DBindingReset() : texture_(0) { + glGetIntegerv(GL_TEXTURE_2D_BINDING_EXT, &texture_); +} + +ScopedTexture2DBindingReset::~ScopedTexture2DBindingReset() { + glBindTexture(GL_TEXTURE_2D, texture_); +} + GLES2DecoderPassthroughImpl::PendingQuery::PendingQuery() = default; GLES2DecoderPassthroughImpl::PendingQuery::~PendingQuery() = default; GLES2DecoderPassthroughImpl::PendingQuery::PendingQuery(const PendingQuery&) = @@ -125,11 +178,237 @@ GLES2DecoderPassthroughImpl::BoundTexture::operator=(const BoundTexture&) = GLES2DecoderPassthroughImpl::BoundTexture& GLES2DecoderPassthroughImpl::BoundTexture::operator=(BoundTexture&&) = default; +GLES2DecoderPassthroughImpl::PendingReadPixels::PendingReadPixels() = default; +GLES2DecoderPassthroughImpl::PendingReadPixels::~PendingReadPixels() = default; +GLES2DecoderPassthroughImpl::PendingReadPixels::PendingReadPixels( + PendingReadPixels&&) = default; +GLES2DecoderPassthroughImpl::PendingReadPixels& +GLES2DecoderPassthroughImpl::PendingReadPixels::operator=(PendingReadPixels&&) = + default; + +GLES2DecoderPassthroughImpl::EmulatedColorBuffer::EmulatedColorBuffer( + const EmulatedDefaultFramebufferFormat& format_in) + : format(format_in) { + ScopedTexture2DBindingReset scoped_texture_reset; + + GLuint color_buffer_texture = 0; + glGenTextures(1, &color_buffer_texture); + glBindTexture(GL_TEXTURE_2D, color_buffer_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture = new TexturePassthrough(color_buffer_texture, GL_TEXTURE_2D); +} + +GLES2DecoderPassthroughImpl::EmulatedColorBuffer::~EmulatedColorBuffer() = + default; + +bool GLES2DecoderPassthroughImpl::EmulatedColorBuffer::Resize( + const gfx::Size& new_size) { + if (size == new_size) { + return true; + } + size = new_size; + + ScopedTexture2DBindingReset scoped_texture_reset; + + DCHECK(texture); + DCHECK(texture->target() == GL_TEXTURE_2D); + + glBindTexture(texture->target(), texture->service_id()); + glTexImage2D(texture->target(), 0, format.color_texture_internal_format, + size.width(), size.height(), 0, format.color_texture_format, + format.color_texture_type, nullptr); + + return true; +} + +void GLES2DecoderPassthroughImpl::EmulatedColorBuffer::Destroy( + bool have_context) { + if (!have_context) { + texture->MarkContextLost(); + } + texture = nullptr; +} + +GLES2DecoderPassthroughImpl::EmulatedDefaultFramebuffer:: + EmulatedDefaultFramebuffer( + const EmulatedDefaultFramebufferFormat& format_in, + const FeatureInfo* feature_info) + : format(format_in) { + ScopedFramebufferBindingReset scoped_fbo_reset; + ScopedRenderbufferBindingReset scoped_renderbuffer_reset; + + glGenFramebuffersEXT(1, &framebuffer_service_id); + glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_service_id); + + if (format.samples > 0) { + glGenRenderbuffersEXT(1, &color_buffer_service_id); + glBindRenderbufferEXT(GL_RENDERBUFFER, color_buffer_service_id); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, color_buffer_service_id); + } else { + color_texture.reset(new EmulatedColorBuffer(format)); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + color_texture->texture->service_id(), 0); + } + + if (format.depth_stencil_internal_format != GL_NONE) { + DCHECK(format.depth_internal_format == GL_NONE && + format.stencil_internal_format == GL_NONE); + glGenRenderbuffersEXT(1, &depth_stencil_buffer_service_id); + glBindRenderbufferEXT(GL_RENDERBUFFER, depth_stencil_buffer_service_id); + if (feature_info->gl_version_info().IsAtLeastGLES(3, 0) || + feature_info->feature_flags().angle_webgl_compatibility) { + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, + depth_stencil_buffer_service_id); + } else { + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, + depth_stencil_buffer_service_id); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, + depth_stencil_buffer_service_id); + } + } else { + if (format.depth_internal_format != GL_NONE) { + glGenRenderbuffersEXT(1, &depth_buffer_service_id); + glBindRenderbufferEXT(GL_RENDERBUFFER, depth_buffer_service_id); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, depth_buffer_service_id); + } + + if (format.stencil_internal_format != GL_NONE) { + glGenRenderbuffersEXT(1, &stencil_buffer_service_id); + glBindRenderbufferEXT(GL_RENDERBUFFER, stencil_buffer_service_id); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, stencil_buffer_service_id); + } + } +} + +GLES2DecoderPassthroughImpl::EmulatedDefaultFramebuffer:: + ~EmulatedDefaultFramebuffer() = default; + +std::unique_ptr +GLES2DecoderPassthroughImpl::EmulatedDefaultFramebuffer::SetColorBuffer( + std::unique_ptr new_color_buffer) { + DCHECK(color_texture != nullptr && new_color_buffer != nullptr); + DCHECK(color_texture->size == new_color_buffer->size); + std::unique_ptr old_buffer(std::move(color_texture)); + color_texture = std::move(new_color_buffer); + + // Bind the new texture to this FBO + ScopedFramebufferBindingReset scoped_fbo_reset; + glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_service_id); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + color_texture->texture->service_id(), 0); + + return old_buffer; +} + +void GLES2DecoderPassthroughImpl::EmulatedDefaultFramebuffer::Blit( + EmulatedColorBuffer* target) { + DCHECK(target != nullptr); + DCHECK(target->size == size); + + ScopedFramebufferBindingReset scoped_fbo_reset; + + glBindFramebufferEXT(GL_READ_FRAMEBUFFER, framebuffer_service_id); + + GLuint temp_fbo; + glGenFramebuffersEXT(1, &temp_fbo); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, temp_fbo); + glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, target->texture->service_id(), 0); + + glBlitFramebufferANGLE(0, 0, size.width(), size.height(), 0, 0, + target->size.width(), target->size.height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + + glDeleteFramebuffersEXT(1, &temp_fbo); +} + +bool GLES2DecoderPassthroughImpl::EmulatedDefaultFramebuffer::Resize( + const gfx::Size& new_size, + const FeatureInfo* feature_info) { + if (size == new_size) { + return true; + } + size = new_size; + + if (color_buffer_service_id != 0) { + ResizeRenderbuffer(color_buffer_service_id, size, format.samples, + format.color_renderbuffer_internal_format, feature_info); + } + if (color_texture) { + if (!color_texture->Resize(size)) { + return false; + } + } + if (depth_stencil_buffer_service_id != 0) { + ResizeRenderbuffer(depth_stencil_buffer_service_id, size, format.samples, + format.depth_stencil_internal_format, feature_info); + } + if (depth_buffer_service_id != 0) { + ResizeRenderbuffer(depth_buffer_service_id, size, format.samples, + format.depth_internal_format, feature_info); + } + if (stencil_buffer_service_id != 0) { + ResizeRenderbuffer(stencil_buffer_service_id, size, format.samples, + format.stencil_internal_format, feature_info); + } + + // Check that the framebuffer is complete + { + ScopedFramebufferBindingReset scoped_fbo_reset; + glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_service_id); + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != + GL_FRAMEBUFFER_COMPLETE) { + LOG(ERROR) + << "GLES2DecoderPassthroughImpl::ResizeOffscreenFramebuffer failed " + << "because the resulting framebuffer was not complete."; + return false; + } + } + + DCHECK(color_texture == nullptr || color_texture->size == size); + + return true; +} + +void GLES2DecoderPassthroughImpl::EmulatedDefaultFramebuffer::Destroy( + bool have_context) { + if (have_context) { + glDeleteFramebuffersEXT(1, &framebuffer_service_id); + framebuffer_service_id = 0; + + glDeleteRenderbuffersEXT(1, &color_buffer_service_id); + color_buffer_service_id = 0; + + glDeleteRenderbuffersEXT(1, &depth_stencil_buffer_service_id); + color_buffer_service_id = 0; + + glDeleteRenderbuffersEXT(1, &depth_buffer_service_id); + depth_buffer_service_id = 0; + + glDeleteRenderbuffersEXT(1, &stencil_buffer_service_id); + stencil_buffer_service_id = 0; + } + if (color_texture) { + color_texture->Destroy(have_context); + } +} + GLES2DecoderPassthroughImpl::GLES2DecoderPassthroughImpl( GLES2DecoderClient* client, CommandBufferServiceBase* command_buffer_service, + Outputter* outputter, ContextGroup* group) - : GLES2Decoder(command_buffer_service), + : GLES2Decoder(command_buffer_service, outputter), client_(client), commands_to_process_(0), debug_marker_manager_(), @@ -139,6 +418,13 @@ GLES2DecoderPassthroughImpl::GLES2DecoderPassthroughImpl( offscreen_(false), group_(group), feature_info_(new FeatureInfo(group->feature_info()->workarounds())), + emulated_back_buffer_(nullptr), + offscreen_single_buffer_(false), + offscreen_target_buffer_preserved_(false), + create_color_buffer_count_for_test_(0), + max_2d_texture_size_(0), + bound_draw_framebuffer_(0), + bound_read_framebuffer_(0), gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))), gpu_trace_level_(2), @@ -147,6 +433,7 @@ GLES2DecoderPassthroughImpl::GLES2DecoderPassthroughImpl( has_robustness_extension_(false), context_lost_(false), reset_by_robustness_extension_(false), + lose_context_when_out_of_memory_(false), weak_ptr_factory_(this) { DCHECK(client); DCHECK(group); @@ -282,6 +569,61 @@ bool GLES2DecoderPassthroughImpl::Initialize( return false; } + // Extensions that are enabled via emulation on the client side or needed for + // basic command buffer functionality. Make sure they are always enabled. + if (IsWebGLContextType(attrib_helper.context_type)) { + static constexpr const char* kEnableByDefaultExtensions[] = { + "GL_ANGLE_depth_texture", + "GL_ANGLE_framebuffer_blit", + "GL_ANGLE_framebuffer_multisample", + "GL_ANGLE_instanced_arrays", + "GL_ANGLE_pack_reverse_row_order", + "GL_ANGLE_texture_compression_dxt3", + "GL_ANGLE_texture_compression_dxt5", + "GL_ANGLE_texture_usage", + "GL_ANGLE_translated_shader_source", + "GL_CHROMIUM_bind_uniform_location", + "GL_CHROMIUM_framebuffer_mixed_samples", + "GL_CHROMIUM_path_rendering", + "GL_CHROMIUM_sync_query", + "GL_EXT_blend_minmax", + "GL_EXT_debug_marker", + "GL_EXT_discard_framebuffer", + "GL_EXT_disjoint_timer_query", + "GL_EXT_occlusion_query_boolean", + "GL_EXT_sRGB", + "GL_EXT_sRGB_write_control", + "GL_EXT_texture_compression_dxt1", + "GL_EXT_texture_compression_s3tc_srgb", + "GL_EXT_texture_norm16", + "GL_EXT_texture_rg", + "GL_EXT_texture_sRGB_decode", + "GL_EXT_texture_storage", + "GL_EXT_unpack_subimage", + "GL_KHR_texture_compression_astc_hdr", + "GL_KHR_texture_compression_astc_ldr", + "GL_NV_fence", + "GL_NV_pack_subimage", + "GL_OES_compressed_ETC1_RGB8_texture", + "GL_OES_depth32", + "GL_OES_fbo_render_mipmap", + "GL_OES_packed_depth_stencil", + "GL_OES_rgb8_rgba8", + "GL_OES_vertex_array_object", + }; + + // Grab the extensions that are requestable + gl::ExtensionSet requestable_extensions( + gl::GetRequestableGLExtensionsFromCurrentContext()); + for (const char* default_extension : kEnableByDefaultExtensions) { + if (gl::HasExtension(requestable_extensions, default_extension)) { + // Request the intersection of the two sets + glRequestExtensionANGLE(default_extension); + } + } + context->ReinitializeDynamicBindings(); + } + // Each context initializes its own feature info because some extensions may // be enabled dynamically. Don't disallow any features, leave it up to ANGLE // to dynamically enable extensions. @@ -292,6 +634,9 @@ bool GLES2DecoderPassthroughImpl::Initialize( } // Check for required extensions + // TODO(geofflang): verify + // feature_info_->feature_flags().angle_robust_resource_initialization and + // glIsEnabled(GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE) if (!feature_info_->feature_flags().angle_robust_client_memory || !feature_info_->feature_flags().chromium_bind_generates_resource || !feature_info_->feature_flags().chromium_copy_texture || @@ -333,6 +678,9 @@ bool GLES2DecoderPassthroughImpl::Initialize( feature_info_->feature_flags().nv_egl_stream_consumer_external) { bound_textures_[GL_TEXTURE_EXTERNAL_OES].resize(num_texture_units); } + if (feature_info_->feature_flags().arb_texture_rectangle) { + bound_textures_[GL_TEXTURE_RECTANGLE_ARB].resize(num_texture_units); + } // Initialize the tracked buffer bindings bound_buffers_[GL_ARRAY_BUFFER] = 0; @@ -367,6 +715,87 @@ bool GLES2DecoderPassthroughImpl::Initialize( has_robustness_extension_ = feature_info_->feature_flags().khr_robustness || feature_info_->feature_flags().ext_robustness; + lose_context_when_out_of_memory_ = + attrib_helper.lose_context_when_out_of_memory; + + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_2d_texture_size_); + + if (offscreen_) { + offscreen_single_buffer_ = attrib_helper.single_buffer; + offscreen_target_buffer_preserved_ = attrib_helper.buffer_preserved; + const bool multisampled_framebuffers_supported = + feature_info_->gl_version_info().IsAtLeastGLES(3, 0) || + feature_info_->feature_flags().angle_framebuffer_multisample; + if (attrib_helper.samples > 0 && attrib_helper.sample_buffers > 0 && + multisampled_framebuffers_supported && !offscreen_single_buffer_) { + GLint max_sample_count = 0; + glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count); + emulated_default_framebuffer_format_.samples = + std::min(attrib_helper.samples, max_sample_count); + } + + const bool rgb8_supported = feature_info_->feature_flags().oes_rgb8_rgba8; + const bool alpha_channel_requested = attrib_helper.alpha_size > 0; + // The only available default render buffer formats in GLES2 have very + // little precision. Don't enable multisampling unless 8-bit render + // buffer formats are available--instead fall back to 8-bit textures. + if (rgb8_supported && emulated_default_framebuffer_format_.samples > 0) { + emulated_default_framebuffer_format_.color_renderbuffer_internal_format = + alpha_channel_requested ? GL_RGBA8 : GL_RGB8; + } else { + emulated_default_framebuffer_format_.samples = 0; + } + + emulated_default_framebuffer_format_.color_texture_internal_format = + alpha_channel_requested ? GL_RGBA : GL_RGB; + emulated_default_framebuffer_format_.color_texture_format = + emulated_default_framebuffer_format_.color_texture_internal_format; + emulated_default_framebuffer_format_.color_texture_type = GL_UNSIGNED_BYTE; + + const bool depth24_stencil8_supported = + feature_info_->feature_flags().packed_depth24_stencil8; + if ((attrib_helper.depth_size > 0 || attrib_helper.stencil_size > 0) && + depth24_stencil8_supported) { + emulated_default_framebuffer_format_.depth_stencil_internal_format = + GL_DEPTH24_STENCIL8; + } else { + // It may be the case that this depth/stencil combination is not + // supported, but this will be checked later by CheckFramebufferStatus. + if (attrib_helper.depth_size > 0) { + emulated_default_framebuffer_format_.depth_internal_format = + GL_DEPTH_COMPONENT16; + } + if (attrib_helper.stencil_size > 0) { + emulated_default_framebuffer_format_.stencil_internal_format = + GL_STENCIL_INDEX8; + } + } + + FlushErrors(); + emulated_back_buffer_.reset(new EmulatedDefaultFramebuffer( + emulated_default_framebuffer_format_, feature_info_.get())); + if (!emulated_back_buffer_->Resize(attrib_helper.offscreen_framebuffer_size, + feature_info_.get())) { + Destroy(true); + return false; + } + + if (FlushErrors()) { + LOG(ERROR) << "Creation of the offscreen framebuffer failed because " + "errors were generated."; + Destroy(true); + return false; + } + + framebuffer_id_map_.SetIDMapping( + 0, emulated_back_buffer_->framebuffer_service_id); + + // Bind the emulated default framebuffer and initialize the viewport + glBindFramebufferEXT(GL_FRAMEBUFFER, + emulated_back_buffer_->framebuffer_service_id); + glViewport(0, 0, attrib_helper.offscreen_framebuffer_size.width(), + attrib_helper.offscreen_framebuffer_size.height()); + } set_initialized(); return true; @@ -375,6 +804,12 @@ bool GLES2DecoderPassthroughImpl::Initialize( void GLES2DecoderPassthroughImpl::Destroy(bool have_context) { if (have_context) { FlushErrors(); + + // Destroy all pending read pixels operations + for (const PendingReadPixels& pending_read_pixels : pending_read_pixels_) { + glDeleteBuffersARB(1, &pending_read_pixels.buffer_service_id); + } + pending_read_pixels_.clear(); } if (!have_context) { @@ -402,6 +837,27 @@ void GLES2DecoderPassthroughImpl::Destroy(bool have_context) { glDeleteVertexArraysOES(1, &vertex_array); }); + // Destroy the emulated backbuffer + if (emulated_back_buffer_) { + emulated_back_buffer_->Destroy(have_context); + emulated_back_buffer_.reset(); + } + + if (emulated_front_buffer_) { + emulated_front_buffer_->Destroy(have_context); + emulated_front_buffer_.reset(); + } + + for (auto& in_use_color_texture : in_use_color_textures_) { + in_use_color_texture->Destroy(have_context); + } + in_use_color_textures_.clear(); + + for (auto& available_color_texture : available_color_textures_) { + available_color_texture->Destroy(have_context); + } + available_color_textures_.clear(); + // Destroy the GPU Tracer which may own some in process GPU Timings. if (gpu_tracer_) { gpu_tracer_->Destroy(have_context); @@ -448,13 +904,116 @@ void GLES2DecoderPassthroughImpl::ReleaseSurface() { surface_ = nullptr; } -void GLES2DecoderPassthroughImpl::TakeFrontBuffer(const Mailbox& mailbox) {} +void GLES2DecoderPassthroughImpl::TakeFrontBuffer(const Mailbox& mailbox) { + if (offscreen_single_buffer_) { + DCHECK(emulated_back_buffer_->color_texture != nullptr); + mailbox_manager_->ProduceTexture( + mailbox, emulated_back_buffer_->color_texture->texture.get()); + return; + } + + if (!emulated_front_buffer_.get()) { + DLOG(ERROR) << "Called TakeFrontBuffer on a non-offscreen context"; + return; + } + + mailbox_manager_->ProduceTexture(mailbox, + emulated_front_buffer_->texture.get()); + in_use_color_textures_.push_back(std::move(emulated_front_buffer_)); + emulated_front_buffer_ = nullptr; + + if (available_color_textures_.empty()) { + // Create a new color texture to use as the front buffer + emulated_front_buffer_.reset( + new EmulatedColorBuffer(emulated_default_framebuffer_format_)); + if (!emulated_front_buffer_->Resize(emulated_back_buffer_->size)) { + DLOG(ERROR) << "Failed to create a new emulated front buffer texture."; + return; + } + create_color_buffer_count_for_test_++; + } else { + emulated_front_buffer_ = std::move(available_color_textures_.back()); + available_color_textures_.pop_back(); + } +} void GLES2DecoderPassthroughImpl::ReturnFrontBuffer(const Mailbox& mailbox, - bool is_lost) {} + bool is_lost) { + TexturePassthrough* texture = static_cast( + mailbox_manager_->ConsumeTexture(mailbox)); + + if (offscreen_single_buffer_) { + return; + } + + auto it = in_use_color_textures_.begin(); + while (it != in_use_color_textures_.end()) { + if ((*it)->texture == texture) { + break; + } + it++; + } + if (it == in_use_color_textures_.end()) { + DLOG(ERROR) << "Attempting to return a frontbuffer that was not saved."; + return; + } + + if (is_lost) { + (*it)->texture->MarkContextLost(); + (*it)->Destroy(false); + } else if ((*it)->size != emulated_back_buffer_->size) { + (*it)->Destroy(true); + } else { + available_color_textures_.push_back(std::move(*it)); + } + in_use_color_textures_.erase(it); +} bool GLES2DecoderPassthroughImpl::ResizeOffscreenFramebuffer( const gfx::Size& size) { + DCHECK(offscreen_); + if (!emulated_back_buffer_) { + LOG(ERROR) + << "GLES2DecoderPassthroughImpl::ResizeOffscreenFramebuffer called " + << " with an onscreen framebuffer."; + return false; + } + + if (emulated_back_buffer_->size == size) { + return true; + } + + if (size.width() < 0 || size.height() < 0 || + size.width() > max_2d_texture_size_ || + size.height() > max_2d_texture_size_) { + LOG(ERROR) << "GLES2DecoderPassthroughImpl::ResizeOffscreenFramebuffer " + "failed to allocate storage due to excessive dimensions."; + return false; + } + + FlushErrors(); + + if (!emulated_back_buffer_->Resize(size, feature_info_.get())) { + LOG(ERROR) << "GLES2DecoderPassthroughImpl::ResizeOffscreenFramebuffer " + "failed to resize the emulated framebuffer."; + return false; + } + + if (FlushErrors()) { + LOG(ERROR) << "GLES2DecoderPassthroughImpl::ResizeOffscreenFramebuffer " + "failed to resize the emulated framebuffer because errors " + "were generated."; + return false; + } + + // Destroy all the available color textures, they should not be the same size + // as the back buffer + for (auto& available_color_texture : available_color_textures_) { + DCHECK(available_color_texture->size != size); + available_color_texture->Destroy(true); + } + available_color_textures_.clear(); + return true; } @@ -573,6 +1132,7 @@ gpu::Capabilities GLES2DecoderPassthroughImpl::GetCapabilities() { caps.multisample_compatibility = feature_info_->feature_flags().ext_multisample_compatibility; caps.dc_layers = !offscreen_ && surface_->SupportsDCLayers(); + caps.texture_npot = feature_info_->feature_flags().npot_ok; // TODO: // caps.commit_overlay_planes @@ -626,11 +1186,11 @@ void GLES2DecoderPassthroughImpl::SetForceShaderNameHashingForTest(bool force) { } size_t GLES2DecoderPassthroughImpl::GetSavedBackTextureCountForTest() { - return 0; + return in_use_color_textures_.size() + available_color_textures_.size(); } size_t GLES2DecoderPassthroughImpl::GetCreatedBackTextureCountForTest() { - return 0; + return create_color_buffer_count_for_test_; } gpu::gles2::QueryManager* GLES2DecoderPassthroughImpl::GetQueryManager() { @@ -667,11 +1227,14 @@ void GLES2DecoderPassthroughImpl::ProcessPendingQueries(bool did_finish) { } bool GLES2DecoderPassthroughImpl::HasMoreIdleWork() const { - return gpu_tracer_->HasTracesToProcess(); + return gpu_tracer_->HasTracesToProcess() || !pending_read_pixels_.empty() || + !pending_queries_.empty(); } void GLES2DecoderPassthroughImpl::PerformIdleWork() { gpu_tracer_->ProcessTraces(); + ProcessReadPixels(false); + ProcessQueries(false); } bool GLES2DecoderPassthroughImpl::HasPollingWork() const { @@ -1015,6 +1578,14 @@ GLES2DecoderPassthroughImpl::PatchGetFramebufferAttachmentParameter( } } break; + // If the framebuffer is an emulated default framebuffer, all attachment + // object types are GL_FRAMEBUFFER_DEFAULT + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + if (IsEmulatedFramebufferBound(target)) { + *params = GL_FRAMEBUFFER_DEFAULT; + } + break; + default: break; } @@ -1038,24 +1609,46 @@ GLenum GLES2DecoderPassthroughImpl::PopError() { } bool GLES2DecoderPassthroughImpl::FlushErrors() { + auto get_next_error = [this]() { + // Always read a real GL error so that it can be replaced by the injected + // error + GLenum error = glGetError(); + if (!injected_driver_errors_.empty()) { + error = injected_driver_errors_.front(); + injected_driver_errors_.pop_front(); + } + return error; + }; + bool had_error = false; - GLenum error = glGetError(); + GLenum error = get_next_error(); while (error != GL_NO_ERROR) { errors_.insert(error); had_error = true; // Check for context loss on out-of-memory errors - if (error == GL_OUT_OF_MEMORY && !WasContextLost() && CheckResetStatus()) { - MarkContextLost(error::kOutOfMemory); - group_->LoseContexts(error::kUnknown); + if (error == GL_OUT_OF_MEMORY && !WasContextLost() && + lose_context_when_out_of_memory_) { + error::ContextLostReason other = error::kOutOfMemory; + if (CheckResetStatus()) { + other = error::kUnknown; + } else { + // Need to lose current context before broadcasting! + MarkContextLost(error::kOutOfMemory); + } + group_->LoseContexts(other); break; } - error = glGetError(); + error = get_next_error(); } return had_error; } +void GLES2DecoderPassthroughImpl::InjectDriverError(GLenum error) { + injected_driver_errors_.push_back(error); +} + bool GLES2DecoderPassthroughImpl::CheckResetStatus() { DCHECK(!WasContextLost()); DCHECK(context_->IsCurrent(nullptr)); @@ -1125,9 +1718,20 @@ error::Error GLES2DecoderPassthroughImpl::ProcessQueries(bool did_finish) { break; case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM: - // TODO: Use a fence and do a real async readback + // Initialize the result to being available. Will be marked as + // unavailable if any pending read pixels operations reference this + // query. result_available = GL_TRUE; result = GL_TRUE; + for (const PendingReadPixels& pending_read_pixels : + pending_read_pixels_) { + if (pending_read_pixels.waiting_async_pack_queries.count( + query.service_id) > 0) { + result_available = GL_FALSE; + result = GL_FALSE; + break; + } + } break; case GL_GET_ERROR_QUERY_CHROMIUM: @@ -1188,6 +1792,69 @@ void GLES2DecoderPassthroughImpl::RemovePendingQuery(GLuint service_id) { } } +error::Error GLES2DecoderPassthroughImpl::ProcessReadPixels(bool did_finish) { + while (!pending_read_pixels_.empty()) { + const PendingReadPixels& pending_read_pixels = pending_read_pixels_.front(); + if (did_finish || pending_read_pixels.fence->HasCompleted()) { + using Result = cmds::ReadPixels::Result; + Result* result = nullptr; + if (pending_read_pixels.result_shm_id != 0) { + result = GetSharedMemoryAs( + pending_read_pixels.result_shm_id, + pending_read_pixels.result_shm_offset, sizeof(*result)); + if (!result) { + glDeleteBuffersARB(1, &pending_read_pixels.buffer_service_id); + pending_read_pixels_.pop_front(); + break; + } + } + + void* pixels = + GetSharedMemoryAs(pending_read_pixels.pixels_shm_id, + pending_read_pixels.pixels_shm_offset, + pending_read_pixels.pixels_size); + if (!pixels) { + glDeleteBuffersARB(1, &pending_read_pixels.buffer_service_id); + pending_read_pixels_.pop_front(); + break; + } + + glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, + pending_read_pixels.buffer_service_id); + void* data = nullptr; + if (feature_info_->feature_flags().map_buffer_range) { + data = + glMapBufferRange(GL_PIXEL_PACK_BUFFER_ARB, 0, + pending_read_pixels.pixels_size, GL_MAP_READ_BIT); + } else { + data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); + } + if (!data) { + InsertError(GL_OUT_OF_MEMORY, "Failed to map pixel pack buffer."); + pending_read_pixels_.pop_front(); + break; + } + + memcpy(pixels, data, pending_read_pixels.pixels_size); + glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB); + glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, + resources_->buffer_id_map.GetServiceIDOrInvalid( + bound_buffers_[GL_PIXEL_PACK_BUFFER_ARB])); + glDeleteBuffersARB(1, &pending_read_pixels.buffer_service_id); + + if (result != nullptr) { + result->success = 1; + } + + pending_read_pixels_.pop_front(); + } + } + + // If glFinish() has been called, all of our fences should be completed. + DCHECK(!did_finish || pending_read_pixels_.empty()); + return error::kNoError; +} + void GLES2DecoderPassthroughImpl::UpdateTextureBinding( GLenum target, GLuint client_id, @@ -1270,6 +1937,24 @@ error::Error GLES2DecoderPassthroughImpl::HandleRasterCHROMIUM( return error::kNoError; } +bool GLES2DecoderPassthroughImpl::IsEmulatedFramebufferBound( + GLenum target) const { + if (!emulated_back_buffer_) { + return false; + } + + if ((target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER) && + bound_draw_framebuffer_ == 0) { + return true; + } + + if (target == GL_READ_FRAMEBUFFER && bound_read_framebuffer_ == 0) { + return true; + } + + return false; +} + #define GLES2_CMD_OP(name) \ { \ &GLES2DecoderPassthroughImpl::Handle##name, cmds::name::kArgFlags, \ @@ -1277,7 +1962,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleRasterCHROMIUM( sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \ }, /* NOLINT */ -const GLES2DecoderPassthroughImpl::CommandInfo +constexpr GLES2DecoderPassthroughImpl::CommandInfo GLES2DecoderPassthroughImpl::command_info[] = { GLES2_COMMAND_LIST(GLES2_CMD_OP)}; diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h index 2d85fa65cc3..8b209280a1e 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h @@ -7,6 +7,7 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_PASSTHROUGH_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_PASSTHROUGH_H_ +#include "base/containers/circular_deque.h" #include "base/memory/ref_counted.h" #include "gpu/command_buffer/common/debug_marker_manager.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" @@ -22,9 +23,14 @@ #include "gpu/command_buffer/service/texture_manager.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" +#include "ui/gl/gl_fence.h" #include "ui/gl/gl_image.h" #include "ui/gl/gl_surface.h" +namespace gl { +class GLFence; +} + namespace gpu { namespace gles2 { @@ -69,10 +75,39 @@ struct PassthroughResources { std::unordered_map mapped_buffer_map; }; +class ScopedFramebufferBindingReset { + public: + ScopedFramebufferBindingReset(); + ~ScopedFramebufferBindingReset(); + + private: + GLint draw_framebuffer_; + GLint read_framebuffer_; +}; + +class ScopedRenderbufferBindingReset { + public: + ScopedRenderbufferBindingReset(); + ~ScopedRenderbufferBindingReset(); + + private: + GLint renderbuffer_; +}; + +class ScopedTexture2DBindingReset { + public: + ScopedTexture2DBindingReset(); + ~ScopedTexture2DBindingReset(); + + private: + GLint texture_; +}; + class GPU_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { public: GLES2DecoderPassthroughImpl(GLES2DecoderClient* client, CommandBufferServiceBase* command_buffer_service, + Outputter* outputter, ContextGroup* group); ~GLES2DecoderPassthroughImpl() override; @@ -254,6 +289,9 @@ class GPU_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { bool can_bind_to_sampler) override; private: + // Allow unittests to inspect internal state tracking + friend class GLES2DecoderPassthroughTestBase; + const char* GetCommandName(unsigned int command_id) const; void* GetScratchMemory(size_t size); @@ -306,6 +344,10 @@ class GPU_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { GLenum PopError(); bool FlushErrors(); + // Inject a driver-level GL error that will replace the result of the next + // call to glGetError + void InjectDriverError(GLenum error); + bool CheckResetStatus(); bool IsRobustnessSupported(); @@ -313,6 +355,8 @@ class GPU_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { error::Error ProcessQueries(bool did_finish); void RemovePendingQuery(GLuint service_id); + error::Error ProcessReadPixels(bool did_finish); + void UpdateTextureBinding(GLenum target, GLuint client_id, TexturePassthrough* texture); @@ -323,6 +367,8 @@ class GPU_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { void VerifyServiceTextureObjectsExist(); + bool IsEmulatedFramebufferBound(GLenum target) const; + GLES2DecoderClient* client_; int commands_to_process_; @@ -418,7 +464,7 @@ class GPU_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { QuerySync* sync = nullptr; base::subtle::Atomic32 submit_count = 0; }; - std::deque pending_queries_; + base::circular_deque pending_queries_; // Currently active queries struct ActiveQuery { @@ -435,8 +481,116 @@ class GPU_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { }; std::unordered_map active_queries_; + // Pending async ReadPixels calls + struct PendingReadPixels { + PendingReadPixels(); + ~PendingReadPixels(); + PendingReadPixels(PendingReadPixels&&); + PendingReadPixels& operator=(PendingReadPixels&&); + + std::unique_ptr fence = nullptr; + GLuint buffer_service_id = 0; + uint32_t pixels_size = 0; + uint32_t pixels_shm_id = 0; + uint32_t pixels_shm_offset = 0; + uint32_t result_shm_id = 0; + uint32_t result_shm_offset = 0; + + // Service IDs of GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM queries waiting for + // this read pixels operation to complete + base::flat_set waiting_async_pack_queries; + + DISALLOW_COPY_AND_ASSIGN(PendingReadPixels); + }; + base::circular_deque pending_read_pixels_; + + // Error state + base::circular_deque injected_driver_errors_; std::set errors_; + // Default framebuffer emulation + struct EmulatedDefaultFramebufferFormat { + GLenum color_renderbuffer_internal_format = GL_NONE; + GLenum color_texture_internal_format = GL_NONE; + GLenum color_texture_format = GL_NONE; + GLenum color_texture_type = GL_NONE; + GLenum depth_stencil_internal_format = GL_NONE; + GLenum depth_internal_format = GL_NONE; + GLenum stencil_internal_format = GL_NONE; + GLint samples = 0; + }; + + struct EmulatedColorBuffer { + explicit EmulatedColorBuffer( + const EmulatedDefaultFramebufferFormat& format_in); + ~EmulatedColorBuffer(); + + bool Resize(const gfx::Size& new_size); + void Destroy(bool have_context); + + scoped_refptr texture; + + gfx::Size size; + EmulatedDefaultFramebufferFormat format; + + DISALLOW_COPY_AND_ASSIGN(EmulatedColorBuffer); + }; + + struct EmulatedDefaultFramebuffer { + EmulatedDefaultFramebuffer( + const EmulatedDefaultFramebufferFormat& format_in, + const FeatureInfo* feature_info); + ~EmulatedDefaultFramebuffer(); + + // Set a new color buffer, return the old one + std::unique_ptr SetColorBuffer( + std::unique_ptr new_color_buffer); + + // Blit this framebuffer into another same-sized color buffer + void Blit(EmulatedColorBuffer* target); + + bool Resize(const gfx::Size& new_size, const FeatureInfo* feature_info); + void Destroy(bool have_context); + + // Service ID of the framebuffer + GLuint framebuffer_service_id = 0; + + // Service ID of the color renderbuffer (if multisampled) + GLuint color_buffer_service_id = 0; + + // Color buffer texture (if not multisampled) + std::unique_ptr color_texture; + + // Service ID of the depth stencil renderbuffer + GLuint depth_stencil_buffer_service_id = 0; + + // Service ID of the depth renderbuffer + GLuint depth_buffer_service_id = 0; + + // Service ID of the stencil renderbuffer ( + GLuint stencil_buffer_service_id = 0; + + gfx::Size size; + EmulatedDefaultFramebufferFormat format; + + DISALLOW_COPY_AND_ASSIGN(EmulatedDefaultFramebuffer); + }; + EmulatedDefaultFramebufferFormat emulated_default_framebuffer_format_; + std::unique_ptr emulated_back_buffer_; + std::unique_ptr emulated_front_buffer_; + bool offscreen_single_buffer_; + bool offscreen_target_buffer_preserved_; + std::vector> in_use_color_textures_; + std::vector> available_color_textures_; + size_t create_color_buffer_count_for_test_; + + // Maximum 2D texture size for limiting offscreen framebuffer sizes + GLint max_2d_texture_size_; + + // State tracking of currently bound draw and read framebuffers (client IDs) + GLuint bound_draw_framebuffer_; + GLuint bound_read_framebuffer_; + // Tracing std::unique_ptr gpu_tracer_; const unsigned char* gpu_decoder_category_; @@ -448,6 +602,7 @@ class GPU_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { bool has_robustness_extension_; bool context_lost_; bool reset_by_robustness_extension_; + bool lose_context_when_out_of_memory_; // Cache of scratch memory std::vector scratch_memory_; diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h index a598f9027de..55c292e2073 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h @@ -428,6 +428,20 @@ error::Error DoReadPixels(GLint x, GLsizei* rows, void* pixels, int32_t* success); +error::Error DoReadPixelsAsync(GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLsizei bufsize, + GLsizei* length, + GLsizei* columns, + GLsizei* rows, + uint32_t pixels_shm_id, + uint32_t pixels_shm_offset, + uint32_t result_shm_id, + uint32_t result_shm_offset); error::Error DoReleaseShaderCompiler(); error::Error DoRenderbufferStorage(GLenum target, GLenum internalformat, diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index e08bc9719c5..8b6433b39e9 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc @@ -61,8 +61,13 @@ error::Error DeleteHelper(GLsizei n, std::vector service_ids(n, 0); for (GLsizei ii = 0; ii < n; ++ii) { ClientType client_id = client_ids[ii]; - service_ids[ii] = id_map->GetServiceIDOrInvalid(client_id); - id_map->RemoveClientID(client_id); + + // Don't pass service IDs of objects with a client ID of 0. They are + // emulated and should not be deleteable + if (client_id != 0) { + service_ids[ii] = id_map->GetServiceIDOrInvalid(client_id); + id_map->RemoveClientID(client_id); + } } delete_function(n, service_ids.data()); @@ -273,6 +278,35 @@ class ScopedPackStateRowLengthReset { GLint row_length_ = 0; }; +bool ModifyAttachmentForEmulatedFramebuffer(GLenum* attachment) { + switch (*attachment) { + case GL_BACK: + *attachment = GL_COLOR_ATTACHMENT0; + return true; + + case GL_DEPTH: + *attachment = GL_DEPTH_ATTACHMENT; + return true; + + case GL_STENCIL: + *attachment = GL_STENCIL_ATTACHMENT; + return true; + + default: + return false; + } +} + +bool ModifyAttachmentsForEmulatedFramebuffer(std::vector* attachments) { + for (GLenum& attachment : *attachments) { + if (!ModifyAttachmentForEmulatedFramebuffer(&attachment)) { + return false; + } + } + + return true; +} + } // anonymous namespace // Implementations of commands @@ -357,9 +391,34 @@ error::Error GLES2DecoderPassthroughImpl::DoBindBufferRange(GLenum target, error::Error GLES2DecoderPassthroughImpl::DoBindFramebuffer( GLenum target, GLuint framebuffer) { + FlushErrors(); glBindFramebufferEXT( target, GetFramebufferServiceID(framebuffer, &framebuffer_id_map_, bind_generates_resource_)); + if (FlushErrors()) { + return error::kNoError; + } + + // Update tracking of the bound framebuffer + switch (target) { + case GL_FRAMEBUFFER_EXT: + bound_draw_framebuffer_ = framebuffer; + bound_read_framebuffer_ = framebuffer; + break; + + case GL_DRAW_FRAMEBUFFER: + bound_draw_framebuffer_ = framebuffer; + break; + + case GL_READ_FRAMEBUFFER: + bound_read_framebuffer_ = framebuffer; + break; + + default: + NOTREACHED(); + break; + } + return error::kNoError; } @@ -746,7 +805,29 @@ error::Error GLES2DecoderPassthroughImpl::DoDeleteFramebuffers( InsertError(GL_INVALID_VALUE, "n cannot be negative."); return error::kNoError; } - return DeleteHelper(n, framebuffers, &framebuffer_id_map_, + + std::vector framebuffers_copy(framebuffers, framebuffers + n); + + // If a bound framebuffer is deleted, it's binding is reset to 0. In the case + // of an emulated default framebuffer, bind the emulated one. + for (GLuint framebuffer : framebuffers_copy) { + if (framebuffer == bound_draw_framebuffer_) { + bound_draw_framebuffer_ = 0; + if (emulated_back_buffer_) { + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, + emulated_back_buffer_->framebuffer_service_id); + } + } + if (framebuffer == bound_read_framebuffer_) { + bound_read_framebuffer_ = 0; + if (emulated_back_buffer_) { + glBindFramebufferEXT(GL_READ_FRAMEBUFFER, + emulated_back_buffer_->framebuffer_service_id); + } + } + } + + return DeleteHelper(n, framebuffers_copy.data(), &framebuffer_id_map_, [](GLsizei n, GLuint* framebuffers) { glDeleteFramebuffersEXT(n, framebuffers); }); @@ -927,11 +1008,21 @@ error::Error GLES2DecoderPassthroughImpl::DoFenceSync(GLenum condition, error::Error GLES2DecoderPassthroughImpl::DoFinish() { glFinish(); + + error::Error error = ProcessReadPixels(true); + if (error != error::kNoError) { + return error; + } return ProcessQueries(true); } error::Error GLES2DecoderPassthroughImpl::DoFlush() { glFlush(); + + error::Error error = ProcessReadPixels(false); + if (error != error::kNoError) { + return error; + } return ProcessQueries(false); } @@ -991,6 +1082,11 @@ error::Error GLES2DecoderPassthroughImpl::DoFramebufferRenderbuffer( GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { + if (IsEmulatedFramebufferBound(target)) { + InsertError(GL_INVALID_OPERATION, + "Cannot change the attachments of the default framebuffer."); + return error::kNoError; + } glFramebufferRenderbufferEXT( target, attachment, renderbuffertarget, GetRenderbufferServiceID(renderbuffer, resources_, false)); @@ -1003,6 +1099,11 @@ error::Error GLES2DecoderPassthroughImpl::DoFramebufferTexture2D( GLenum textarget, GLuint texture, GLint level) { + if (IsEmulatedFramebufferBound(target)) { + InsertError(GL_INVALID_OPERATION, + "Cannot change the attachments of the default framebuffer."); + return error::kNoError; + } glFramebufferTexture2DEXT(target, attachment, textarget, GetTextureServiceID(texture, resources_, false), level); @@ -1015,6 +1116,11 @@ error::Error GLES2DecoderPassthroughImpl::DoFramebufferTextureLayer( GLuint texture, GLint level, GLint layer) { + if (IsEmulatedFramebufferBound(target)) { + InsertError(GL_INVALID_OPERATION, + "Cannot change the attachments of the default framebuffer."); + return error::kNoError; + } glFramebufferTextureLayer(target, attachment, GetTextureServiceID(texture, resources_, false), level, layer); @@ -1290,14 +1396,43 @@ error::Error GLES2DecoderPassthroughImpl::DoGetFramebufferAttachmentParameteriv( GLsizei bufsize, GLsizei* length, GLint* params) { + GLenum updated_attachment = attachment; + if (IsEmulatedFramebufferBound(target)) { + // Update the attachment do the equivalent one in the emulated framebuffer + if (!ModifyAttachmentForEmulatedFramebuffer(&updated_attachment)) { + InsertError(GL_INVALID_OPERATION, "Invalid attachment."); + *length = 0; + return error::kNoError; + } + + // Generate errors for parameter names that are only valid for non-default + // framebuffers + switch (pname) { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + InsertError(GL_INVALID_ENUM, "Invalid parameter name."); + *length = 0; + return error::kNoError; + } + } + + FlushErrors(); + // Get a scratch buffer to hold the result of the query GLint* scratch_params = GetTypedScratchMemory(bufsize); glGetFramebufferAttachmentParameterivRobustANGLE( - target, attachment, pname, bufsize, length, scratch_params); + target, updated_attachment, pname, bufsize, length, scratch_params); + + if (FlushErrors()) { + DCHECK(*length == 0); + return error::kNoError; + } // Update the results of the query, if needed error::Error error = PatchGetFramebufferAttachmentParameter( - target, attachment, pname, *length, scratch_params); + target, updated_attachment, pname, *length, scratch_params); if (error != error::kNoError) { *length = 0; return error; @@ -1702,7 +1837,15 @@ error::Error GLES2DecoderPassthroughImpl::DoInvalidateFramebuffer( InsertError(GL_INVALID_VALUE, "count cannot be negative."); return error::kNoError; } + std::vector attachments_copy(attachments, attachments + count); + if (IsEmulatedFramebufferBound(target)) { + // Update the attachment do the equivalent one in the emulated framebuffer + if (!ModifyAttachmentsForEmulatedFramebuffer(&attachments_copy)) { + InsertError(GL_INVALID_OPERATION, "Invalid attachment."); + return error::kNoError; + } + } glInvalidateFramebuffer(target, count, attachments_copy.data()); return error::kNoError; } @@ -1720,7 +1863,15 @@ error::Error GLES2DecoderPassthroughImpl::DoInvalidateSubFramebuffer( InsertError(GL_INVALID_VALUE, "count cannot be negative."); return error::kNoError; } + std::vector attachments_copy(attachments, attachments + count); + if (IsEmulatedFramebufferBound(target)) { + // Update the attachment do the equivalent one in the emulated framebuffer + if (!ModifyAttachmentsForEmulatedFramebuffer(&attachments_copy)) { + InsertError(GL_INVALID_OPERATION, "Invalid attachment."); + return error::kNoError; + } + } glInvalidateSubFramebuffer(target, count, attachments_copy.data(), x, y, width, height); return error::kNoError; @@ -1843,6 +1994,84 @@ error::Error GLES2DecoderPassthroughImpl::DoReadPixels(GLint x, return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::DoReadPixelsAsync( + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLsizei bufsize, + GLsizei* length, + GLsizei* columns, + GLsizei* rows, + uint32_t pixels_shm_id, + uint32_t pixels_shm_offset, + uint32_t result_shm_id, + uint32_t result_shm_offset) { + DCHECK(feature_info_->feature_flags().use_async_readpixels && + bound_buffers_[GL_PIXEL_PACK_BUFFER] == 0); + + FlushErrors(); + ScopedPackStateRowLengthReset reset_row_length( + bufsize != 0 && feature_info_->gl_version_info().is_es3); + + PendingReadPixels pending_read_pixels; + pending_read_pixels.pixels_shm_id = pixels_shm_id; + pending_read_pixels.pixels_shm_offset = pixels_shm_offset; + pending_read_pixels.result_shm_id = result_shm_id; + pending_read_pixels.result_shm_offset = result_shm_offset; + + glGenBuffersARB(1, &pending_read_pixels.buffer_service_id); + glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pending_read_pixels.buffer_service_id); + + // GL_STREAM_READ is not available until ES3. + const GLenum usage_hint = feature_info_->gl_version_info().IsAtLeastGLES(3, 0) + ? GL_STREAM_READ + : GL_STATIC_DRAW; + + const uint32_t bytes_per_pixel = + GLES2Util::ComputeImageGroupSize(format, type); + if (bytes_per_pixel == 0) { + InsertError(GL_INVALID_ENUM, "Invalid ReadPixels format or type."); + return error::kNoError; + } + + if (width < 0 || height < 0) { + InsertError(GL_INVALID_VALUE, "Width and height cannot be negative."); + return error::kNoError; + } + + if (!base::CheckMul(bytes_per_pixel, width, height) + .AssignIfValid(&pending_read_pixels.pixels_size)) { + return error::kOutOfBounds; + } + + glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pending_read_pixels.pixels_size, + nullptr, usage_hint); + + // No need to worry about ES3 pixel pack parameters, because no + // PIXEL_PACK_BUFFER is bound, and all these settings haven't been + // sent to GL. + glReadPixels(x, y, width, height, format, type, nullptr); + + glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); + + // Test for errors now before creating a fence + if (FlushErrors()) { + return error::kNoError; + } + + pending_read_pixels.fence.reset(gl::GLFence::Create()); + + if (FlushErrors()) { + return error::kNoError; + } + + pending_read_pixels_.push_back(std::move(pending_read_pixels)); + return error::kNoError; +} + error::Error GLES2DecoderPassthroughImpl::DoReleaseShaderCompiler() { glReleaseShaderCompiler(); return error::kNoError; @@ -2591,6 +2820,11 @@ error::Error GLES2DecoderPassthroughImpl::DoFramebufferTexture2DMultisampleEXT( return error::kUnknownCommand; } + if (IsEmulatedFramebufferBound(target)) { + InsertError(GL_INVALID_OPERATION, + "Cannot change the attachments of the default framebuffer."); + return error::kNoError; + } glFramebufferTexture2DMultisampleEXT( target, attachment, textarget, GetTextureServiceID(texture, resources_, false), level, samples); @@ -2769,10 +3003,17 @@ error::Error GLES2DecoderPassthroughImpl::DoBeginTransformFeedback( error::Error GLES2DecoderPassthroughImpl::DoEndQueryEXT(GLenum target, uint32_t submit_count) { if (IsEmulatedQueryTarget(target)) { - if (active_queries_.find(target) == active_queries_.end()) { + auto active_query_iter = active_queries_.find(target); + if (active_query_iter == active_queries_.end()) { InsertError(GL_INVALID_OPERATION, "No active query on target."); return error::kNoError; } + if (target == GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM && + !pending_read_pixels_.empty()) { + GLuint query_service_id = active_query_iter->second.service_id; + pending_read_pixels_.back().waiting_async_pack_queries.insert( + query_service_id); + } } else { // Flush all previous errors FlushErrors(); @@ -2872,7 +3113,55 @@ error::Error GLES2DecoderPassthroughImpl::DoBindVertexArrayOES(GLuint array) { error::Error GLES2DecoderPassthroughImpl::DoSwapBuffers() { if (offscreen_) { - NOTIMPLEMENTED(); + if (offscreen_single_buffer_) { + return error::kNoError; + } + + DCHECK(emulated_back_buffer_); + + // Make sure the emulated front buffer is allocated and the correct size + if (emulated_front_buffer_ && + emulated_front_buffer_->size != emulated_back_buffer_->size) { + emulated_front_buffer_->Destroy(true); + emulated_front_buffer_ = nullptr; + } + + if (emulated_front_buffer_ == nullptr) { + if (!available_color_textures_.empty()) { + emulated_front_buffer_ = std::move(available_color_textures_.back()); + available_color_textures_.pop_back(); + } else { + emulated_front_buffer_.reset( + new EmulatedColorBuffer(emulated_default_framebuffer_format_)); + if (!emulated_front_buffer_->Resize(emulated_back_buffer_->size)) { + DLOG(ERROR) + << "Failed to create a new emulated front buffer texture."; + return error::kLostContext; + } + } + } + + DCHECK(emulated_front_buffer_->size == emulated_back_buffer_->size); + + if (emulated_default_framebuffer_format_.samples > 0) { + // Resolve the multisampled renderbuffer into the emulated_front_buffer_ + emulated_back_buffer_->Blit(emulated_front_buffer_.get()); + } else { + DCHECK(emulated_back_buffer_->color_texture != nullptr); + // If the offscreen buffer should be preserved, copy the old backbuffer + // into the new one + if (offscreen_target_buffer_preserved_) { + emulated_back_buffer_->Blit(emulated_front_buffer_.get()); + } + + // Swap the front and back buffer textures and update the framebuffer + // attachment. + std::unique_ptr old_front_buffer = + std::move(emulated_front_buffer_); + emulated_front_buffer_ = + emulated_back_buffer_->SetColorBuffer(std::move(old_front_buffer)); + } + return error::kNoError; } @@ -3012,30 +3301,33 @@ error::Error GLES2DecoderPassthroughImpl::DoResizeCHROMIUM(GLuint width, GLfloat scale_factor, GLenum color_space, GLboolean alpha) { - gl::GLSurface::ColorSpace surface_color_space = - gl::GLSurface::ColorSpace::UNSPECIFIED; - switch (color_space) { - case GL_COLOR_SPACE_UNSPECIFIED_CHROMIUM: - surface_color_space = gl::GLSurface::ColorSpace::UNSPECIFIED; - break; - case GL_COLOR_SPACE_SCRGB_LINEAR_CHROMIUM: - surface_color_space = gl::GLSurface::ColorSpace::SCRGB_LINEAR; - break; - case GL_COLOR_SPACE_SRGB_CHROMIUM: - surface_color_space = gl::GLSurface::ColorSpace::SRGB; - break; - case GL_COLOR_SPACE_DISPLAY_P3_CHROMIUM: - surface_color_space = gl::GLSurface::ColorSpace::DISPLAY_P3; - break; - default: + if (offscreen_) { + if (!ResizeOffscreenFramebuffer(gfx::Size(width, height))) { LOG(ERROR) << "GLES2DecoderPassthroughImpl: Context lost because " - "specified color space was invalid."; + << "ResizeOffscreenFramebuffer failed."; return error::kLostContext; - } - if (offscreen_) { - // TODO: crbug.com/665521 - NOTIMPLEMENTED(); + } } else { + gl::GLSurface::ColorSpace surface_color_space = + gl::GLSurface::ColorSpace::UNSPECIFIED; + switch (color_space) { + case GL_COLOR_SPACE_UNSPECIFIED_CHROMIUM: + surface_color_space = gl::GLSurface::ColorSpace::UNSPECIFIED; + break; + case GL_COLOR_SPACE_SCRGB_LINEAR_CHROMIUM: + surface_color_space = gl::GLSurface::ColorSpace::SCRGB_LINEAR; + break; + case GL_COLOR_SPACE_SRGB_CHROMIUM: + surface_color_space = gl::GLSurface::ColorSpace::SRGB; + break; + case GL_COLOR_SPACE_DISPLAY_P3_CHROMIUM: + surface_color_space = gl::GLSurface::ColorSpace::DISPLAY_P3; + break; + default: + LOG(ERROR) << "GLES2DecoderPassthroughImpl: Context lost because " + "specified color space was invalid."; + return error::kLostContext; + } if (!surface_->Resize(gfx::Size(width, height), scale_factor, surface_color_space, !!alpha)) { LOG(ERROR) @@ -3542,6 +3834,9 @@ error::Error GLES2DecoderPassthroughImpl::DoDrawArraysInstancedANGLE( GLint first, GLsizei count, GLsizei primcount) { + if (!feature_info_->feature_flags().angle_instanced_arrays) { + return error::kUnknownCommand; + } glDrawArraysInstancedANGLE(mode, first, count, primcount); return error::kNoError; } @@ -3552,6 +3847,9 @@ error::Error GLES2DecoderPassthroughImpl::DoDrawElementsInstancedANGLE( GLenum type, const void* indices, GLsizei primcount) { + if (!feature_info_->feature_flags().angle_instanced_arrays) { + return error::kUnknownCommand; + } glDrawElementsInstancedANGLE(mode, count, type, indices, primcount); return error::kNoError; } @@ -3559,6 +3857,9 @@ error::Error GLES2DecoderPassthroughImpl::DoDrawElementsInstancedANGLE( error::Error GLES2DecoderPassthroughImpl::DoVertexAttribDivisorANGLE( GLuint index, GLuint divisor) { + if (!feature_info_->feature_flags().angle_instanced_arrays) { + return error::kUnknownCommand; + } glVertexAttribDivisorANGLE(index, divisor); return error::kNoError; } diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc index 75e33d2b5d4..20b117d3b48 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc @@ -16,7 +16,9 @@ error::Error GLES2DecoderPassthroughImpl::HandleBindAttribLocationBucket( cmd_data); GLuint program = static_cast(c.program); GLuint index = static_cast(c.index); - Bucket* bucket = GetBucket(c.name_bucket_id); + uint32_t name_bucket_id = c.name_bucket_id; + + Bucket* bucket = GetBucket(name_bucket_id); if (!bucket || bucket->size() == 0) { return error::kInvalidArguments; } @@ -24,11 +26,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleBindAttribLocationBucket( if (!bucket->GetAsString(&name_str)) { return error::kInvalidArguments; } - error::Error error = DoBindAttribLocation(program, index, name_str.c_str()); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoBindAttribLocation(program, index, name_str.c_str()); } error::Error GLES2DecoderPassthroughImpl::HandleBufferData( @@ -38,21 +36,18 @@ error::Error GLES2DecoderPassthroughImpl::HandleBufferData( *static_cast(cmd_data); GLenum target = static_cast(c.target); GLsizeiptr size = static_cast(c.size); - uint32_t data_shm_id = static_cast(c.data_shm_id); - uint32_t data_shm_offset = static_cast(c.data_shm_offset); + uint32_t data_shm_id = c.data_shm_id; + uint32_t data_shm_offset = c.data_shm_offset; GLenum usage = static_cast(c.usage); - const void* data = NULL; + + const void* data = nullptr; if (data_shm_id != 0 || data_shm_offset != 0) { data = GetSharedMemoryAs(data_shm_id, data_shm_offset, size); if (!data) { return error::kOutOfBounds; } } - error::Error error = DoBufferData(target, size, data, usage); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoBufferData(target, size, data, usage); } error::Error GLES2DecoderPassthroughImpl::HandleClientWaitSync( @@ -63,17 +58,16 @@ error::Error GLES2DecoderPassthroughImpl::HandleClientWaitSync( const GLuint sync = static_cast(c.sync); const GLbitfield flags = static_cast(c.flags); const GLuint64 timeout = c.timeout(); + uint32_t result_shm_id = c.result_shm_id; + uint32_t result_shm_offset = c.result_shm_offset; + typedef cmds::ClientWaitSync::Result Result; Result* result_dst = GetSharedMemoryAs( - c.result_shm_id, c.result_shm_offset, sizeof(*result_dst)); + result_shm_id, result_shm_offset, sizeof(*result_dst)); if (!result_dst) { return error::kOutOfBounds; } - error::Error error = DoClientWaitSync(sync, flags, timeout, result_dst); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoClientWaitSync(sync, flags, timeout, result_dst); } error::Error GLES2DecoderPassthroughImpl::HandleCreateProgram( @@ -82,11 +76,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleCreateProgram( const volatile gles2::cmds::CreateProgram& c = *static_cast(cmd_data); GLuint client_id = static_cast(c.client_id); - error::Error error = DoCreateProgram(client_id); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoCreateProgram(client_id); } error::Error GLES2DecoderPassthroughImpl::HandleCreateShader( @@ -96,11 +87,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleCreateShader( *static_cast(cmd_data); GLenum type = static_cast(c.type); GLuint client_id = static_cast(c.client_id); - error::Error error = DoCreateShader(type, client_id); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoCreateShader(type, client_id); } error::Error GLES2DecoderPassthroughImpl::HandleFenceSync( @@ -111,11 +99,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleFenceSync( GLenum condition = static_cast(c.condition); GLbitfield flags = static_cast(c.flags); GLuint client_id = static_cast(c.client_id); - error::Error error = DoFenceSync(condition, flags, client_id); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoFenceSync(condition, flags, client_id); } error::Error GLES2DecoderPassthroughImpl::HandleDrawArrays( @@ -126,11 +111,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleDrawArrays( GLenum mode = static_cast(c.mode); GLint first = static_cast(c.first); GLsizei count = static_cast(c.count); - error::Error error = DoDrawArrays(mode, first, count); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoDrawArrays(mode, first, count); } error::Error GLES2DecoderPassthroughImpl::HandleDrawElements( @@ -143,11 +125,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleDrawElements( GLenum type = static_cast(c.type); const GLvoid* indices = reinterpret_cast(static_cast(c.index_offset)); - error::Error error = DoDrawElements(mode, count, type, indices); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoDrawElements(mode, count, type, indices); } error::Error GLES2DecoderPassthroughImpl::HandleGetActiveAttrib( @@ -158,9 +137,12 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetActiveAttrib( GLuint program = static_cast(c.program); GLuint index = static_cast(c.index); uint32_t name_bucket_id = c.name_bucket_id; + uint32_t result_shm_id = c.result_shm_id; + uint32_t result_shm_offset = c.result_shm_offset; + typedef cmds::GetActiveAttrib::Result Result; - Result* result = GetSharedMemoryAs( - c.result_shm_id, c.result_shm_offset, sizeof(*result)); + Result* result = GetSharedMemoryAs(result_shm_id, result_shm_offset, + sizeof(*result)); if (!result) { return error::kOutOfBounds; } @@ -190,9 +172,12 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetActiveUniform( GLuint program = static_cast(c.program); GLuint index = static_cast(c.index); uint32_t name_bucket_id = c.name_bucket_id; + uint32_t result_shm_id = c.result_shm_id; + uint32_t result_shm_offset = c.result_shm_offset; + typedef cmds::GetActiveUniform::Result Result; - Result* result = GetSharedMemoryAs( - c.result_shm_id, c.result_shm_offset, sizeof(*result)); + Result* result = GetSharedMemoryAs(result_shm_id, result_shm_offset, + sizeof(*result)); if (!result) { return error::kOutOfBounds; } @@ -223,12 +208,15 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetActiveUniformBlockiv( GLuint program = static_cast(c.program); GLuint uniformBlockIndex = static_cast(c.index); GLenum pname = static_cast(c.pname); + uint32_t params_shm_id = c.params_shm_id; + uint32_t params_shm_offset = c.params_shm_offset; + unsigned int buffer_size = 0; typedef cmds::GetActiveUniformBlockiv::Result Result; Result* result = GetSharedMemoryAndSizeAs( - c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size); - GLint* params = result ? result->GetData() : NULL; - if (params == NULL) { + params_shm_id, params_shm_offset, sizeof(Result), &buffer_size); + GLint* params = result ? result->GetData() : nullptr; + if (params == nullptr) { return error::kOutOfBounds; } GLsizei bufsize = Result::ComputeMaxResults(buffer_size); @@ -254,9 +242,12 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetActiveUniformBlockName( GLuint program = static_cast(c.program); GLuint uniformBlockIndex = static_cast(c.index); uint32_t name_bucket_id = c.name_bucket_id; + uint32_t result_shm_id = c.result_shm_id; + uint32_t result_shm_offset = c.result_shm_offset; + typedef cmds::GetActiveUniformBlockName::Result Result; - Result* result = GetSharedMemoryAs( - c.result_shm_id, c.result_shm_offset, sizeof(*result)); + Result* result = GetSharedMemoryAs(result_shm_id, result_shm_offset, + sizeof(*result)); if (!result) { return error::kOutOfBounds; } @@ -285,7 +276,11 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetActiveUniformsiv( *static_cast(cmd_data); GLuint program = static_cast(c.program); GLenum pname = static_cast(c.pname); - Bucket* bucket = GetBucket(c.indices_bucket_id); + uint32_t params_shm_id = c.params_shm_id; + uint32_t params_shm_offset = c.params_shm_offset; + uint32_t indices_bucket_id = c.indices_bucket_id; + + Bucket* bucket = GetBucket(indices_bucket_id); if (!bucket) { return error::kInvalidArguments; } @@ -293,9 +288,9 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetActiveUniformsiv( const GLuint* indices = bucket->GetDataAs(0, bucket->size()); typedef cmds::GetActiveUniformsiv::Result Result; Result* result = GetSharedMemoryAs( - c.params_shm_id, c.params_shm_offset, Result::ComputeSize(uniformCount)); - GLint* params = result ? result->GetData() : NULL; - if (params == NULL) { + params_shm_id, params_shm_offset, Result::ComputeSize(uniformCount)); + GLint* params = result ? result->GetData() : nullptr; + if (params == nullptr) { return error::kOutOfBounds; } // Check that the client initialized the result. @@ -319,10 +314,14 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetAttachedShaders( const volatile gles2::cmds::GetAttachedShaders& c = *static_cast(cmd_data); GLuint program = static_cast(c.program); + uint32_t result_size = c.result_size; + uint32_t result_shm_id = c.result_shm_id; + uint32_t result_shm_offset = c.result_shm_offset; + typedef cmds::GetAttachedShaders::Result Result; - uint32_t maxCount = Result::ComputeMaxResults(c.result_size); - Result* result = GetSharedMemoryAs( - c.result_shm_id, c.result_shm_offset, Result::ComputeSize(maxCount)); + uint32_t maxCount = Result::ComputeMaxResults(result_size); + Result* result = GetSharedMemoryAs(result_shm_id, result_shm_offset, + Result::ComputeSize(maxCount)); if (!result) { return error::kOutOfBounds; } @@ -347,7 +346,11 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetAttribLocation( const volatile gles2::cmds::GetAttribLocation& c = *static_cast(cmd_data); GLuint program = static_cast(c.program); - Bucket* bucket = GetBucket(c.name_bucket_id); + uint32_t name_bucket_id = c.name_bucket_id; + uint32_t location_shm_id = c.location_shm_id; + uint32_t location_shm_offset = c.location_shm_offset; + + Bucket* bucket = GetBucket(name_bucket_id); if (!bucket) { return error::kInvalidArguments; } @@ -356,18 +359,14 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetAttribLocation( return error::kInvalidArguments; } GLint* location = GetSharedMemoryAs( - c.location_shm_id, c.location_shm_offset, sizeof(GLint)); + location_shm_id, location_shm_offset, sizeof(GLint)); if (!location) { return error::kOutOfBounds; } if (*location != -1) { return error::kInvalidArguments; } - error::Error error = DoGetAttribLocation(program, name_str.c_str(), location); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoGetAttribLocation(program, name_str.c_str(), location); } error::Error GLES2DecoderPassthroughImpl::HandleGetBufferSubDataAsyncCHROMIUM( @@ -379,21 +378,16 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetBufferSubDataAsyncCHROMIUM( GLenum target = static_cast(c.target); GLintptr offset = static_cast(c.offset); GLsizeiptr size = static_cast(c.size); - uint32_t data_shm_id = static_cast(c.data_shm_id); + uint32_t data_shm_id = c.data_shm_id; + uint32_t data_shm_offset = c.data_shm_offset; uint8_t* mem = - GetSharedMemoryAs(data_shm_id, c.data_shm_offset, size); + GetSharedMemoryAs(data_shm_id, data_shm_offset, size); if (!mem) { return error::kOutOfBounds; } - error::Error error = - DoGetBufferSubDataAsyncCHROMIUM(target, offset, size, mem); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; + return DoGetBufferSubDataAsyncCHROMIUM(target, offset, size, mem); } @@ -403,7 +397,11 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetFragDataLocation( const volatile gles2::cmds::GetFragDataLocation& c = *static_cast(cmd_data); GLuint program = static_cast(c.program); - Bucket* bucket = GetBucket(c.name_bucket_id); + uint32_t location_shm_id = c.location_shm_id; + uint32_t location_shm_offset = c.location_shm_offset; + uint32_t name_bucket_id = c.name_bucket_id; + + Bucket* bucket = GetBucket(name_bucket_id); if (!bucket) { return error::kInvalidArguments; } @@ -412,19 +410,14 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetFragDataLocation( return error::kInvalidArguments; } GLint* location = GetSharedMemoryAs( - c.location_shm_id, c.location_shm_offset, sizeof(GLint)); + location_shm_id, location_shm_offset, sizeof(GLint)); if (!location) { return error::kOutOfBounds; } if (*location != -1) { return error::kInvalidArguments; } - error::Error error = - DoGetFragDataLocation(program, name_str.c_str(), location); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoGetFragDataLocation(program, name_str.c_str(), location); } error::Error GLES2DecoderPassthroughImpl::HandleGetInternalformativ( @@ -435,12 +428,15 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetInternalformativ( GLenum target = static_cast(c.target); GLenum internalformat = static_cast(c.format); GLenum pname = static_cast(c.pname); + uint32_t params_shm_id = c.params_shm_id; + uint32_t params_shm_offset = c.params_shm_offset; + unsigned int buffer_size = 0; typedef cmds::GetInternalformativ::Result Result; Result* result = GetSharedMemoryAndSizeAs( - c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size); - GLint* params = result ? result->GetData() : NULL; - if (params == NULL) { + params_shm_id, params_shm_offset, sizeof(Result), &buffer_size); + GLint* params = result ? result->GetData() : nullptr; + if (params == nullptr) { return error::kOutOfBounds; } GLsizei bufsize = Result::ComputeMaxResults(buffer_size); @@ -463,7 +459,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetProgramInfoLog( const volatile gles2::cmds::GetProgramInfoLog& c = *static_cast(cmd_data); GLuint program = static_cast(c.program); - uint32_t bucket_id = static_cast(c.bucket_id); + uint32_t bucket_id = c.bucket_id; std::string infolog; error::Error error = DoGetProgramInfoLog(program, &infolog); @@ -482,7 +478,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetShaderInfoLog( const volatile gles2::cmds::GetShaderInfoLog& c = *static_cast(cmd_data); GLuint shader = static_cast(c.shader); - uint32_t bucket_id = static_cast(c.bucket_id); + uint32_t bucket_id = c.bucket_id; std::string infolog; error::Error error = DoGetShaderInfoLog(shader, &infolog); @@ -503,9 +499,12 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetShaderPrecisionFormat( cmd_data); GLenum shader_type = static_cast(c.shadertype); GLenum precision_type = static_cast(c.precisiontype); + uint32_t result_shm_id = c.result_shm_id; + uint32_t result_shm_offset = c.result_shm_offset; + typedef cmds::GetShaderPrecisionFormat::Result Result; - Result* result = GetSharedMemoryAs( - c.result_shm_id, c.result_shm_offset, sizeof(*result)); + Result* result = GetSharedMemoryAs(result_shm_id, result_shm_offset, + sizeof(*result)); if (!result) { return error::kOutOfBounds; } @@ -536,7 +535,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetShaderSource( const volatile gles2::cmds::GetShaderSource& c = *static_cast(cmd_data); GLuint shader = static_cast(c.shader); - uint32_t bucket_id = static_cast(c.bucket_id); + uint32_t bucket_id = c.bucket_id; std::string source; error::Error error = DoGetShaderSource(shader, &source); @@ -556,6 +555,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetString( const volatile gles2::cmds::GetString& c = *static_cast(cmd_data); GLenum name = static_cast(c.name); + uint32_t bucket_id = c.bucket_id; const char* str = nullptr; error::Error error = DoGetString(name, &str); @@ -565,7 +565,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetString( if (!str) { return error::kOutOfBounds; } - Bucket* bucket = CreateBucket(c.bucket_id); + Bucket* bucket = CreateBucket(bucket_id); bucket->SetFromString(str); return error::kNoError; @@ -580,9 +580,12 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetTransformFeedbackVarying( GLuint program = static_cast(c.program); GLuint index = static_cast(c.index); uint32_t name_bucket_id = c.name_bucket_id; + uint32_t result_shm_id = c.result_shm_id; + uint32_t result_shm_offset = c.result_shm_offset; + typedef cmds::GetTransformFeedbackVarying::Result Result; - Result* result = GetSharedMemoryAs( - c.result_shm_id, c.result_shm_offset, sizeof(*result)); + Result* result = GetSharedMemoryAs(result_shm_id, result_shm_offset, + sizeof(*result)); if (!result) { return error::kOutOfBounds; } @@ -614,7 +617,11 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetUniformBlockIndex( const volatile gles2::cmds::GetUniformBlockIndex& c = *static_cast(cmd_data); GLuint program = static_cast(c.program); - Bucket* bucket = GetBucket(c.name_bucket_id); + uint32_t name_bucket_id = c.name_bucket_id; + uint32_t index_shm_id = c.index_shm_id; + uint32_t index_shm_offset = c.index_shm_offset; + + Bucket* bucket = GetBucket(name_bucket_id); if (!bucket) { return error::kInvalidArguments; } @@ -622,19 +629,15 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetUniformBlockIndex( if (!bucket->GetAsString(&name_str)) { return error::kInvalidArguments; } - GLint* index = GetSharedMemoryAs(c.index_shm_id, c.index_shm_offset, - sizeof(GLint)); + GLint* index = + GetSharedMemoryAs(index_shm_id, index_shm_offset, sizeof(GLint)); if (!index) { return error::kOutOfBounds; } if (*index != -1) { return error::kInvalidArguments; } - error::Error error = DoGetUniformBlockIndex(program, name_str.c_str(), index); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoGetUniformBlockIndex(program, name_str.c_str(), index); } error::Error GLES2DecoderPassthroughImpl::HandleGetUniformfv( @@ -644,12 +647,15 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetUniformfv( *static_cast(cmd_data); GLuint program = static_cast(c.program); GLint location = static_cast(c.location); + uint32_t params_shm_id = c.params_shm_id; + uint32_t params_shm_offset = c.params_shm_offset; + unsigned int buffer_size = 0; typedef cmds::GetUniformfv::Result Result; Result* result = GetSharedMemoryAndSizeAs( - c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size); - GLfloat* params = result ? result->GetData() : NULL; - if (params == NULL) { + params_shm_id, params_shm_offset, sizeof(Result), &buffer_size); + GLfloat* params = result ? result->GetData() : nullptr; + if (params == nullptr) { return error::kOutOfBounds; } GLsizei bufsize = Result::ComputeMaxResults(buffer_size); @@ -673,12 +679,15 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetUniformiv( *static_cast(cmd_data); GLuint program = static_cast(c.program); GLint location = static_cast(c.location); + uint32_t params_shm_id = c.params_shm_id; + uint32_t params_shm_offset = c.params_shm_offset; + unsigned int buffer_size = 0; typedef cmds::GetUniformiv::Result Result; Result* result = GetSharedMemoryAndSizeAs( - c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size); - GLint* params = result ? result->GetData() : NULL; - if (params == NULL) { + params_shm_id, params_shm_offset, sizeof(Result), &buffer_size); + GLint* params = result ? result->GetData() : nullptr; + if (params == nullptr) { return error::kOutOfBounds; } GLsizei bufsize = Result::ComputeMaxResults(buffer_size); @@ -702,12 +711,15 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetUniformuiv( *static_cast(cmd_data); GLuint program = static_cast(c.program); GLint location = static_cast(c.location); + uint32_t params_shm_id = c.params_shm_id; + uint32_t params_shm_offset = c.params_shm_offset; + unsigned int buffer_size = 0; typedef cmds::GetUniformuiv::Result Result; Result* result = GetSharedMemoryAndSizeAs( - c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size); - GLuint* params = result ? result->GetData() : NULL; - if (params == NULL) { + params_shm_id, params_shm_offset, sizeof(Result), &buffer_size); + GLuint* params = result ? result->GetData() : nullptr; + if (params == nullptr) { return error::kOutOfBounds; } GLsizei bufsize = Result::ComputeMaxResults(buffer_size); @@ -730,7 +742,11 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetUniformIndices( const volatile gles2::cmds::GetUniformIndices& c = *static_cast(cmd_data); GLuint program = static_cast(c.program); - Bucket* bucket = GetBucket(c.names_bucket_id); + uint32_t names_bucket_id = c.names_bucket_id; + uint32_t indices_shm_id = c.indices_shm_id; + uint32_t indices_shm_offset = c.indices_shm_offset; + + Bucket* bucket = GetBucket(names_bucket_id); if (!bucket) { return error::kInvalidArguments; } @@ -742,10 +758,10 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetUniformIndices( } typedef cmds::GetUniformIndices::Result Result; Result* result = GetSharedMemoryAs( - c.indices_shm_id, c.indices_shm_offset, + indices_shm_id, indices_shm_offset, Result::ComputeSize(static_cast(count))); - GLuint* indices = result ? result->GetData() : NULL; - if (indices == NULL) { + GLuint* indices = result ? result->GetData() : nullptr; + if (indices == nullptr) { return error::kOutOfBounds; } // Check that the client initialized the result. @@ -767,7 +783,11 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetUniformLocation( const volatile gles2::cmds::GetUniformLocation& c = *static_cast(cmd_data); GLuint program = static_cast(c.program); - Bucket* bucket = GetBucket(c.name_bucket_id); + uint32_t name_bucket_id = c.name_bucket_id; + uint32_t location_shm_id = c.location_shm_id; + uint32_t location_shm_offset = c.location_shm_offset; + + Bucket* bucket = GetBucket(name_bucket_id); if (!bucket) { return error::kInvalidArguments; } @@ -776,19 +796,14 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetUniformLocation( return error::kInvalidArguments; } GLint* location = GetSharedMemoryAs( - c.location_shm_id, c.location_shm_offset, sizeof(GLint)); + location_shm_id, location_shm_offset, sizeof(GLint)); if (!location) { return error::kOutOfBounds; } if (*location != -1) { return error::kInvalidArguments; } - error::Error error = - DoGetUniformLocation(program, name_str.c_str(), location); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoGetUniformLocation(program, name_str.c_str(), location); } error::Error GLES2DecoderPassthroughImpl::HandleGetVertexAttribPointerv( @@ -799,12 +814,15 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetVertexAttribPointerv( cmd_data); GLuint index = static_cast(c.index); GLenum pname = static_cast(c.pname); + uint32_t pointer_shm_id = c.pointer_shm_id; + uint32_t pointer_shm_offset = c.pointer_shm_offset; + unsigned int buffer_size = 0; typedef cmds::GetVertexAttribPointerv::Result Result; Result* result = GetSharedMemoryAndSizeAs( - c.pointer_shm_id, c.pointer_shm_offset, sizeof(Result), &buffer_size); - GLuint* params = result ? result->GetData() : NULL; - if (params == NULL) { + pointer_shm_id, pointer_shm_offset, sizeof(Result), &buffer_size); + GLuint* params = result ? result->GetData() : nullptr; + if (params == nullptr) { return error::kOutOfBounds; } GLsizei bufsize = Result::ComputeMaxResults(buffer_size); @@ -828,11 +846,8 @@ error::Error GLES2DecoderPassthroughImpl::HandlePixelStorei( *static_cast(cmd_data); GLenum pname = static_cast(c.pname); GLint param = static_cast(c.param); - error::Error error = DoPixelStorei(pname, param); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoPixelStorei(pname, param); } error::Error GLES2DecoderPassthroughImpl::HandleReadPixels( @@ -848,16 +863,27 @@ error::Error GLES2DecoderPassthroughImpl::HandleReadPixels( GLenum type = static_cast(c.type); uint32_t pixels_shm_id = c.pixels_shm_id; uint32_t pixels_shm_offset = c.pixels_shm_offset; + uint32_t result_shm_id = c.result_shm_id; + uint32_t result_shm_offset = c.result_shm_offset; + GLboolean async = static_cast(c.async); + + bool pack_buffer_bound = bound_buffers_[GL_PIXEL_PACK_BUFFER] != 0; uint8_t* pixels = nullptr; unsigned int buffer_size = 0; - if (c.pixels_shm_id != 0) { + if (pixels_shm_id != 0) { + if (pack_buffer_bound) { + return error::kInvalidArguments; + } pixels = GetSharedMemoryAndSizeAs( pixels_shm_id, pixels_shm_offset, 0, &buffer_size); if (!pixels) { return error::kOutOfBounds; } } else { + if (!pack_buffer_bound) { + return error::kInvalidArguments; + } pixels = reinterpret_cast(static_cast(pixels_shm_offset)); } @@ -867,8 +893,16 @@ error::Error GLES2DecoderPassthroughImpl::HandleReadPixels( GLsizei columns = 0; GLsizei rows = 0; int32_t success = 0; - error::Error error = DoReadPixels(x, y, width, height, format, type, bufsize, - &length, &columns, &rows, pixels, &success); + error::Error error = error::kNoError; + if (async && feature_info_->feature_flags().use_async_readpixels && + !pack_buffer_bound) { + error = DoReadPixelsAsync( + x, y, width, height, format, type, bufsize, &length, &columns, &rows, + pixels_shm_id, pixels_shm_offset, result_shm_id, result_shm_offset); + } else { + error = DoReadPixels(x, y, width, height, format, type, bufsize, &length, + &columns, &rows, pixels, &success); + } if (error != error::kNoError) { return error; } @@ -876,20 +910,17 @@ error::Error GLES2DecoderPassthroughImpl::HandleReadPixels( return error::kOutOfBounds; } - typedef cmds::ReadPixels::Result Result; - Result* result = nullptr; - if (c.result_shm_id != 0) { - result = GetSharedMemoryAs(c.result_shm_id, c.result_shm_offset, - sizeof(*result)); + if (result_shm_id != 0) { + typedef cmds::ReadPixels::Result Result; + Result* result = GetSharedMemoryAs( + result_shm_id, result_shm_offset, sizeof(*result)); if (!result) { return error::kOutOfBounds; } if (result->success != 0) { return error::kInvalidArguments; } - } - if (result) { result->success = success; result->row_length = static_cast(columns); result->num_rows = static_cast(rows); @@ -905,25 +936,25 @@ error::Error GLES2DecoderPassthroughImpl::HandleShaderBinary( *static_cast(cmd_data); GLsizei n = static_cast(c.n); GLsizei length = static_cast(c.length); + GLenum binaryformat = static_cast(c.binaryformat); + uint32_t shaders_shm_id = c.shaders_shm_id; + uint32_t shaders_shm_offset = c.shaders_shm_offset; + uint32_t binary_shm_id = c.binary_shm_id; + uint32_t binary_shm_offset = c.binary_shm_offset; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } const GLuint* shaders = GetSharedMemoryAs( - c.shaders_shm_id, c.shaders_shm_offset, data_size); - GLenum binaryformat = static_cast(c.binaryformat); - const void* binary = GetSharedMemoryAs( - c.binary_shm_id, c.binary_shm_offset, length); - if (shaders == NULL || binary == NULL) { + shaders_shm_id, shaders_shm_offset, data_size); + const void* binary = + GetSharedMemoryAs(binary_shm_id, binary_shm_offset, length); + if (shaders == nullptr || binary == nullptr) { return error::kOutOfBounds; } - error::Error error = DoShaderBinary(n, shaders, binaryformat, binary, length); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; + return DoShaderBinary(n, shaders, binaryformat, binary, length); } error::Error GLES2DecoderPassthroughImpl::HandleTexImage2D( @@ -1074,12 +1105,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleUniformBlockBinding( GLuint index = static_cast(c.index); GLuint binding = static_cast(c.binding); - error::Error error = DoUniformBlockBinding(program, index, binding); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; + return DoUniformBlockBinding(program, index, binding); } error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribIPointer( @@ -1094,12 +1120,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribIPointer( GLsizei offset = static_cast(c.offset); const void* ptr = reinterpret_cast(offset); - error::Error error = DoVertexAttribIPointer(index, size, type, stride, ptr); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; + return DoVertexAttribIPointer(index, size, type, stride, ptr); } error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribPointer( @@ -1115,13 +1136,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribPointer( GLsizei offset = static_cast(c.offset); const void* ptr = reinterpret_cast(offset); - error::Error error = - DoVertexAttribPointer(index, size, type, normalized, stride, ptr); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; + return DoVertexAttribPointer(index, size, type, normalized, stride, ptr); } error::Error GLES2DecoderPassthroughImpl::HandleWaitSync( @@ -1133,12 +1148,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleWaitSync( const GLbitfield flags = static_cast(c.flags); const GLuint64 timeout = c.timeout(); - error::Error error = DoWaitSync(sync, flags, timeout); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; + return DoWaitSync(sync, flags, timeout); } error::Error GLES2DecoderPassthroughImpl::HandleQueryCounterEXT( @@ -1148,17 +1158,12 @@ error::Error GLES2DecoderPassthroughImpl::HandleQueryCounterEXT( *static_cast(cmd_data); GLuint id = static_cast(c.id); GLenum target = static_cast(c.target); - int32_t sync_shm_id = static_cast(c.sync_data_shm_id); - uint32_t sync_shm_offset = static_cast(c.sync_data_shm_offset); + uint32_t sync_shm_id = c.sync_data_shm_id; + uint32_t sync_shm_offset = c.sync_data_shm_offset; uint32_t submit_count = static_cast(c.submit_count); - error::Error error = - DoQueryCounterEXT(id, target, sync_shm_id, sync_shm_offset, submit_count); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; + return DoQueryCounterEXT(id, target, sync_shm_id, sync_shm_offset, + submit_count); } error::Error GLES2DecoderPassthroughImpl::HandleBeginQueryEXT( @@ -1168,16 +1173,10 @@ error::Error GLES2DecoderPassthroughImpl::HandleBeginQueryEXT( *static_cast(cmd_data); GLenum target = static_cast(c.target); GLuint id = static_cast(c.id); - int32_t sync_shm_id = static_cast(c.sync_data_shm_id); - uint32_t sync_shm_offset = static_cast(c.sync_data_shm_offset); + uint32_t sync_shm_id = c.sync_data_shm_id; + uint32_t sync_shm_offset = c.sync_data_shm_offset; - error::Error error = - DoBeginQueryEXT(target, id, sync_shm_id, sync_shm_offset); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; + return DoBeginQueryEXT(target, id, sync_shm_id, sync_shm_offset); } error::Error GLES2DecoderPassthroughImpl::HandleEndQueryEXT( @@ -1188,12 +1187,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleEndQueryEXT( GLenum target = static_cast(c.target); uint32_t submit_count = static_cast(c.submit_count); - error::Error error = DoEndQueryEXT(target, submit_count); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; + return DoEndQueryEXT(target, submit_count); } error::Error GLES2DecoderPassthroughImpl::HandleSetDisjointValueSyncCHROMIUM( @@ -1202,16 +1196,15 @@ error::Error GLES2DecoderPassthroughImpl::HandleSetDisjointValueSyncCHROMIUM( const volatile gles2::cmds::SetDisjointValueSyncCHROMIUM& c = *static_cast( cmd_data); + uint32_t sync_data_shm_id = c.sync_data_shm_id; + uint32_t sync_data_shm_offset = c.sync_data_shm_offset; + DisjointValueSync* sync = GetSharedMemoryAs( - c.sync_data_shm_id, c.sync_data_shm_offset, sizeof(*sync)); + sync_data_shm_id, sync_data_shm_offset, sizeof(*sync)); if (!sync) { return error::kOutOfBounds; } - error::Error error = DoSetDisjointValueSyncCHROMIUM(sync); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoSetDisjointValueSyncCHROMIUM(sync); } error::Error GLES2DecoderPassthroughImpl::HandleInsertEventMarkerEXT( @@ -1219,7 +1212,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleInsertEventMarkerEXT( const volatile void* cmd_data) { const volatile gles2::cmds::InsertEventMarkerEXT& c = *static_cast(cmd_data); - GLuint bucket_id = static_cast(c.bucket_id); + uint32_t bucket_id = c.bucket_id; + Bucket* bucket = GetBucket(bucket_id); if (!bucket || bucket->size() == 0) { return error::kInvalidArguments; @@ -1228,11 +1222,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleInsertEventMarkerEXT( if (!bucket->GetAsString(&str)) { return error::kInvalidArguments; } - error::Error error = DoInsertEventMarkerEXT(0, str.c_str()); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoInsertEventMarkerEXT(0, str.c_str()); } error::Error GLES2DecoderPassthroughImpl::HandlePushGroupMarkerEXT( @@ -1240,7 +1230,8 @@ error::Error GLES2DecoderPassthroughImpl::HandlePushGroupMarkerEXT( const volatile void* cmd_data) { const volatile gles2::cmds::PushGroupMarkerEXT& c = *static_cast(cmd_data); - GLuint bucket_id = static_cast(c.bucket_id); + uint32_t bucket_id = c.bucket_id; + Bucket* bucket = GetBucket(bucket_id); if (!bucket || bucket->size() == 0) { return error::kInvalidArguments; @@ -1249,11 +1240,7 @@ error::Error GLES2DecoderPassthroughImpl::HandlePushGroupMarkerEXT( if (!bucket->GetAsString(&str)) { return error::kInvalidArguments; } - error::Error error = DoPushGroupMarkerEXT(0, str.c_str()); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoPushGroupMarkerEXT(0, str.c_str()); } error::Error GLES2DecoderPassthroughImpl::HandleEnableFeatureCHROMIUM( @@ -1262,13 +1249,17 @@ error::Error GLES2DecoderPassthroughImpl::HandleEnableFeatureCHROMIUM( const volatile gles2::cmds::EnableFeatureCHROMIUM& c = *static_cast( cmd_data); - Bucket* bucket = GetBucket(c.bucket_id); + uint32_t bucket_id = c.bucket_id; + uint32_t result_shm_id = c.result_shm_id; + uint32_t result_shm_offset = c.result_shm_offset; + + Bucket* bucket = GetBucket(bucket_id); if (!bucket || bucket->size() == 0) { return error::kInvalidArguments; } typedef cmds::EnableFeatureCHROMIUM::Result Result; - Result* result = GetSharedMemoryAs( - c.result_shm_id, c.result_shm_offset, sizeof(*result)); + Result* result = GetSharedMemoryAs(result_shm_id, result_shm_offset, + sizeof(*result)); if (!result) { return error::kOutOfBounds; } @@ -1298,10 +1289,14 @@ error::Error GLES2DecoderPassthroughImpl::HandleMapBufferRange( GLbitfield access = static_cast(c.access); GLintptr offset = static_cast(c.offset); GLsizeiptr size = static_cast(c.size); + uint32_t result_shm_id = c.result_shm_id; + uint32_t result_shm_offset = c.result_shm_offset; + uint32_t data_shm_id = c.data_shm_id; + uint32_t data_shm_offset = c.data_shm_offset; typedef cmds::MapBufferRange::Result Result; - Result* result = GetSharedMemoryAs( - c.result_shm_id, c.result_shm_offset, sizeof(*result)); + Result* result = GetSharedMemoryAs(result_shm_id, result_shm_offset, + sizeof(*result)); if (!result) { return error::kOutOfBounds; } @@ -1310,20 +1305,15 @@ error::Error GLES2DecoderPassthroughImpl::HandleMapBufferRange( return error::kInvalidArguments; } uint8_t* mem = - GetSharedMemoryAs(c.data_shm_id, c.data_shm_offset, size); + GetSharedMemoryAs(data_shm_id, data_shm_offset, size); if (!mem) { return error::kOutOfBounds; } - error::Error error = - DoMapBufferRange(target, offset, size, access, mem, c.data_shm_id, - c.data_shm_offset, result); - if (error != error::kNoError) { - DCHECK(*result == 0); - return error; - } - - return error::kNoError; + error::Error error = DoMapBufferRange(target, offset, size, access, mem, + data_shm_id, data_shm_offset, result); + DCHECK(error == error::kNoError || *result == 0); + return error; } error::Error GLES2DecoderPassthroughImpl::HandleUnmapBuffer( @@ -1332,11 +1322,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleUnmapBuffer( const volatile gles2::cmds::UnmapBuffer& c = *static_cast(cmd_data); GLenum target = static_cast(c.target); - error::Error error = DoUnmapBuffer(target); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoUnmapBuffer(target); } error::Error GLES2DecoderPassthroughImpl::HandleResizeCHROMIUM( @@ -1349,12 +1336,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleResizeCHROMIUM( GLfloat scale_factor = static_cast(c.scale_factor); GLenum color_space = static_cast(c.color_space); GLboolean has_alpha = static_cast(c.alpha); - error::Error error = - DoResizeCHROMIUM(width, height, scale_factor, color_space, has_alpha); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoResizeCHROMIUM(width, height, scale_factor, color_space, has_alpha); } error::Error @@ -1365,6 +1348,8 @@ GLES2DecoderPassthroughImpl::HandleGetRequestableExtensionsCHROMIUM( *static_cast< const volatile gles2::cmds::GetRequestableExtensionsCHROMIUM*>( cmd_data); + uint32_t bucket_id = c.bucket_id; + const char* str = nullptr; error::Error error = DoGetRequestableExtensionsCHROMIUM(&str); if (error != error::kNoError) { @@ -1373,7 +1358,7 @@ GLES2DecoderPassthroughImpl::HandleGetRequestableExtensionsCHROMIUM( if (!str) { return error::kOutOfBounds; } - Bucket* bucket = CreateBucket(c.bucket_id); + Bucket* bucket = CreateBucket(bucket_id); bucket->SetFromString(str); return error::kNoError; @@ -1385,7 +1370,9 @@ error::Error GLES2DecoderPassthroughImpl::HandleRequestExtensionCHROMIUM( const volatile gles2::cmds::RequestExtensionCHROMIUM& c = *static_cast( cmd_data); - Bucket* bucket = GetBucket(c.bucket_id); + uint32_t bucket_id = c.bucket_id; + + Bucket* bucket = GetBucket(bucket_id); if (!bucket || bucket->size() == 0) { return error::kInvalidArguments; } @@ -1393,11 +1380,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleRequestExtensionCHROMIUM( if (!bucket->GetAsString(&feature_str)) { return error::kInvalidArguments; } - error::Error error = DoRequestExtensionCHROMIUM(feature_str.c_str()); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoRequestExtensionCHROMIUM(feature_str.c_str()); } error::Error GLES2DecoderPassthroughImpl::HandleGetProgramInfoCHROMIUM( @@ -1407,8 +1390,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetProgramInfoCHROMIUM( *static_cast( cmd_data); GLuint program = static_cast(c.program); - uint32_t bucket_id = c.bucket_id; + Bucket* bucket = CreateBucket(bucket_id); bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail. @@ -1431,8 +1414,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetUniformBlocksCHROMIUM( *static_cast( cmd_data); GLuint program = static_cast(c.program); - uint32_t bucket_id = c.bucket_id; + Bucket* bucket = CreateBucket(bucket_id); bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail. @@ -1457,8 +1440,8 @@ GLES2DecoderPassthroughImpl::HandleGetTransformFeedbackVaryingsCHROMIUM( const volatile gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>( cmd_data); GLuint program = static_cast(c.program); - uint32_t bucket_id = c.bucket_id; + Bucket* bucket = CreateBucket(bucket_id); bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail. @@ -1481,8 +1464,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetUniformsES3CHROMIUM( *static_cast( cmd_data); GLuint program = static_cast(c.program); - uint32_t bucket_id = c.bucket_id; + Bucket* bucket = CreateBucket(bucket_id); bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail. @@ -1505,6 +1488,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetTranslatedShaderSourceANGLE( *static_cast( cmd_data); GLuint shader = static_cast(c.shader); + uint32_t bucket_id = c.bucket_id; std::string source; error::Error error = DoGetTranslatedShaderSourceANGLE(shader, &source); @@ -1512,7 +1496,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetTranslatedShaderSourceANGLE( return error; } - Bucket* bucket = CreateBucket(c.bucket_id); + Bucket* bucket = CreateBucket(bucket_id); bucket->SetFromString(source.c_str()); return error::kNoError; @@ -1528,11 +1512,8 @@ error::Error GLES2DecoderPassthroughImpl::HandlePostSubBufferCHROMIUM( GLint y = static_cast(c.y); GLint width = static_cast(c.width); GLint height = static_cast(c.height); - error::Error error = DoPostSubBufferCHROMIUM(x, y, width, height); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoPostSubBufferCHROMIUM(x, y, width, height); } error::Error GLES2DecoderPassthroughImpl::HandleDrawArraysInstancedANGLE( @@ -1545,12 +1526,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleDrawArraysInstancedANGLE( GLint first = static_cast(c.first); GLsizei count = static_cast(c.count); GLsizei primcount = static_cast(c.primcount); - error::Error error = - DoDrawArraysInstancedANGLE(mode, first, count, primcount); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoDrawArraysInstancedANGLE(mode, first, count, primcount); } error::Error GLES2DecoderPassthroughImpl::HandleDrawElementsInstancedANGLE( @@ -1565,12 +1542,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleDrawElementsInstancedANGLE( const GLvoid* indices = reinterpret_cast(static_cast(c.index_offset)); GLsizei primcount = static_cast(c.primcount); - error::Error error = - DoDrawElementsInstancedANGLE(mode, count, type, indices, primcount); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoDrawElementsInstancedANGLE(mode, count, type, indices, primcount); } error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribDivisorANGLE( @@ -1581,11 +1554,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribDivisorANGLE( cmd_data); GLuint index = static_cast(c.index); GLuint divisor = static_cast(c.divisor); - error::Error error = DoVertexAttribDivisorANGLE(index, divisor); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoVertexAttribDivisorANGLE(index, divisor); } error::Error @@ -1598,7 +1568,9 @@ GLES2DecoderPassthroughImpl::HandleBindUniformLocationCHROMIUMBucket( cmd_data); GLuint program = static_cast(c.program); GLint location = static_cast(c.location); - Bucket* bucket = GetBucket(c.name_bucket_id); + uint32_t name_bucket_id = c.name_bucket_id; + + Bucket* bucket = GetBucket(name_bucket_id); if (!bucket || bucket->size() == 0) { return error::kInvalidArguments; } @@ -1606,12 +1578,7 @@ GLES2DecoderPassthroughImpl::HandleBindUniformLocationCHROMIUMBucket( if (!bucket->GetAsString(&name_str)) { return error::kInvalidArguments; } - error::Error error = - DoBindUniformLocationCHROMIUM(program, location, name_str.c_str()); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoBindUniformLocationCHROMIUM(program, location, name_str.c_str()); } error::Error GLES2DecoderPassthroughImpl::HandleTraceBeginCHROMIUM( @@ -1619,8 +1586,11 @@ error::Error GLES2DecoderPassthroughImpl::HandleTraceBeginCHROMIUM( const volatile void* cmd_data) { const volatile gles2::cmds::TraceBeginCHROMIUM& c = *static_cast(cmd_data); - Bucket* category_bucket = GetBucket(c.category_bucket_id); - Bucket* name_bucket = GetBucket(c.name_bucket_id); + uint32_t name_bucket_id = c.name_bucket_id; + uint32_t category_bucket_id = c.category_bucket_id; + + Bucket* category_bucket = GetBucket(category_bucket_id); + Bucket* name_bucket = GetBucket(name_bucket_id); if (!category_bucket || category_bucket->size() == 0 || !name_bucket || name_bucket->size() == 0) { return error::kInvalidArguments; @@ -1633,22 +1603,13 @@ error::Error GLES2DecoderPassthroughImpl::HandleTraceBeginCHROMIUM( return error::kInvalidArguments; } - error::Error error = - DoTraceBeginCHROMIUM(category_name.c_str(), trace_name.c_str()); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoTraceBeginCHROMIUM(category_name.c_str(), trace_name.c_str()); } error::Error GLES2DecoderPassthroughImpl::HandleDescheduleUntilFinishedCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { - error::Error error = DoDescheduleUntilFinishedCHROMIUM(); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoDescheduleUntilFinishedCHROMIUM(); } error::Error GLES2DecoderPassthroughImpl::HandleInsertFenceSyncCHROMIUM( @@ -1658,11 +1619,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleInsertFenceSyncCHROMIUM( *static_cast( cmd_data); GLuint64 release_count = c.release_count(); - error::Error error = DoInsertFenceSyncCHROMIUM(release_count); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoInsertFenceSyncCHROMIUM(release_count); } error::Error GLES2DecoderPassthroughImpl::HandleWaitSyncTokenCHROMIUM( @@ -1673,9 +1631,9 @@ error::Error GLES2DecoderPassthroughImpl::HandleWaitSyncTokenCHROMIUM( cmd_data); CommandBufferNamespace namespace_id = static_cast(c.namespace_id); + const uint64_t release_count = c.release_count(); CommandBufferId command_buffer_id = CommandBufferId::FromUnsafeValue(c.command_buffer_id()); - const uint64_t release_count = c.release_count(); const CommandBufferNamespace kMinNamespaceId = CommandBufferNamespace::INVALID; @@ -1686,22 +1644,14 @@ error::Error GLES2DecoderPassthroughImpl::HandleWaitSyncTokenCHROMIUM( namespace_id = gpu::CommandBufferNamespace::INVALID; } - error::Error error = - DoWaitSyncTokenCHROMIUM(namespace_id, command_buffer_id, release_count); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoWaitSyncTokenCHROMIUM(namespace_id, command_buffer_id, + release_count); } error::Error GLES2DecoderPassthroughImpl::HandleDiscardBackbufferCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { - error::Error error = DoDiscardBackbufferCHROMIUM(); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoDiscardBackbufferCHROMIUM(); } error::Error GLES2DecoderPassthroughImpl::HandleScheduleOverlayPlaneCHROMIUM( @@ -1721,13 +1671,10 @@ error::Error GLES2DecoderPassthroughImpl::HandleScheduleOverlayPlaneCHROMIUM( GLfloat uv_y = static_cast(c.uv_x); GLfloat uv_width = static_cast(c.uv_x); GLfloat uv_height = static_cast(c.uv_x); - error::Error error = DoScheduleOverlayPlaneCHROMIUM( + + return DoScheduleOverlayPlaneCHROMIUM( plane_z_order, plane_transform, overlay_texture_id, bounds_x, bounds_y, bounds_width, bounds_height, uv_x, uv_y, uv_width, uv_height); - if (error != error::kNoError) { - return error; - } - return error::kNoError; } error::Error @@ -1738,22 +1685,21 @@ GLES2DecoderPassthroughImpl::HandleScheduleCALayerSharedStateCHROMIUM( *static_cast< const volatile gles2::cmds::ScheduleCALayerSharedStateCHROMIUM*>( cmd_data); - const GLfloat* mem = GetSharedMemoryAs(c.shm_id, c.shm_offset, + GLfloat opacity = static_cast(c.opacity); + GLboolean is_clipped = static_cast(c.is_clipped); + GLint sorting_context_id = static_cast(c.sorting_context_id); + uint32_t shm_id = c.shm_id; + uint32_t shm_offset = c.shm_offset; + + const GLfloat* mem = GetSharedMemoryAs(shm_id, shm_offset, 20 * sizeof(GLfloat)); if (!mem) { return error::kOutOfBounds; } - GLfloat opacity = static_cast(c.opacity); - GLboolean is_clipped = static_cast(c.is_clipped); const GLfloat* clip_rect = mem + 0; - GLint sorting_context_id = static_cast(c.sorting_context_id); const GLfloat* transform = mem + 4; - error::Error error = DoScheduleCALayerSharedStateCHROMIUM( - opacity, is_clipped, clip_rect, sorting_context_id, transform); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoScheduleCALayerSharedStateCHROMIUM(opacity, is_clipped, clip_rect, + sorting_context_id, transform); } error::Error GLES2DecoderPassthroughImpl::HandleScheduleCALayerCHROMIUM( @@ -1762,23 +1708,21 @@ error::Error GLES2DecoderPassthroughImpl::HandleScheduleCALayerCHROMIUM( const volatile gles2::cmds::ScheduleCALayerCHROMIUM& c = *static_cast( cmd_data); - const GLfloat* mem = GetSharedMemoryAs(c.shm_id, c.shm_offset, + GLuint contents_texture_id = static_cast(c.contents_texture_id); + GLuint background_color = static_cast(c.background_color); + GLuint edge_aa_mask = static_cast(c.edge_aa_mask); + uint32_t shm_id = c.shm_id; + uint32_t shm_offset = c.shm_offset; + + const GLfloat* mem = GetSharedMemoryAs(shm_id, shm_offset, 8 * sizeof(GLfloat)); if (!mem) { return error::kOutOfBounds; } - GLuint contents_texture_id = static_cast(c.contents_texture_id); const GLfloat* contents_rect = mem; - GLuint background_color = static_cast(c.background_color); - GLuint edge_aa_mask = static_cast(c.edge_aa_mask); const GLfloat* bounds_rect = mem + 4; - error::Error error = - DoScheduleCALayerCHROMIUM(contents_texture_id, contents_rect, - background_color, edge_aa_mask, bounds_rect); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoScheduleCALayerCHROMIUM(contents_texture_id, contents_rect, + background_color, edge_aa_mask, bounds_rect); } error::Error @@ -1789,22 +1733,21 @@ GLES2DecoderPassthroughImpl::HandleScheduleDCLayerSharedStateCHROMIUM( *static_cast< const volatile gles2::cmds::ScheduleDCLayerSharedStateCHROMIUM*>( cmd_data); - const GLfloat* mem = GetSharedMemoryAs(c.shm_id, c.shm_offset, + GLfloat opacity = static_cast(c.opacity); + GLboolean is_clipped = static_cast(c.is_clipped); + GLint z_order = static_cast(c.z_order); + uint32_t shm_id = c.shm_id; + uint32_t shm_offset = c.shm_offset; + + const GLfloat* mem = GetSharedMemoryAs(shm_id, shm_offset, 20 * sizeof(GLfloat)); if (!mem) { return error::kOutOfBounds; } - GLfloat opacity = static_cast(c.opacity); - GLboolean is_clipped = static_cast(c.is_clipped); const GLfloat* clip_rect = mem + 0; - GLint z_order = static_cast(c.z_order); const GLfloat* transform = mem + 4; - error::Error error = DoScheduleDCLayerSharedStateCHROMIUM( - opacity, is_clipped, clip_rect, z_order, transform); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoScheduleDCLayerSharedStateCHROMIUM(opacity, is_clipped, clip_rect, + z_order, transform); } error::Error GLES2DecoderPassthroughImpl::HandleScheduleDCLayerCHROMIUM( @@ -1813,13 +1756,19 @@ error::Error GLES2DecoderPassthroughImpl::HandleScheduleDCLayerCHROMIUM( const volatile gles2::cmds::ScheduleDCLayerCHROMIUM& c = *static_cast( cmd_data); + GLuint background_color = static_cast(c.background_color); + GLuint edge_aa_mask = static_cast(c.edge_aa_mask); + GLenum filter = static_cast(c.filter); + const GLsizei num_textures = c.num_textures; + uint32_t shm_id = c.shm_id; + uint32_t shm_offset = c.shm_offset; + unsigned int size; const GLfloat* mem = GetSharedMemoryAndSizeAs( - c.shm_id, c.shm_offset, 8 * sizeof(GLfloat), &size); + shm_id, shm_offset, 8 * sizeof(GLfloat), &size); if (!mem) { return error::kOutOfBounds; } - const GLsizei num_textures = c.num_textures; if (num_textures < 0 || (size - 8 * sizeof(GLfloat)) / sizeof(GLuint) < static_cast(num_textures)) { return error::kOutOfBounds; @@ -1827,17 +1776,10 @@ error::Error GLES2DecoderPassthroughImpl::HandleScheduleDCLayerCHROMIUM( const volatile GLuint* contents_texture_ids = reinterpret_cast(mem + 8); const GLfloat* contents_rect = mem; - GLuint background_color = static_cast(c.background_color); - GLuint edge_aa_mask = static_cast(c.edge_aa_mask); - GLenum filter = static_cast(c.filter); const GLfloat* bounds_rect = mem + 4; - error::Error error = DoScheduleDCLayerCHROMIUM( - num_textures, contents_texture_ids, contents_rect, background_color, - edge_aa_mask, filter, bounds_rect); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoScheduleDCLayerCHROMIUM(num_textures, contents_texture_ids, + contents_rect, background_color, + edge_aa_mask, filter, bounds_rect); } error::Error GLES2DecoderPassthroughImpl::HandleSetColorSpaceForScanoutCHROMIUM( @@ -1854,11 +1796,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleGenPathsCHROMIUM( *static_cast(cmd_data); GLuint path = static_cast(c.first_client_id); GLsizei range = static_cast(c.range); - error::Error error = DoGenPathsCHROMIUM(path, range); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoGenPathsCHROMIUM(path, range); } error::Error GLES2DecoderPassthroughImpl::HandleDeletePathsCHROMIUM( @@ -1868,11 +1807,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleDeletePathsCHROMIUM( *static_cast(cmd_data); GLuint path = static_cast(c.first_client_id); GLsizei range = static_cast(c.range); - error::Error error = DoDeletePathsCHROMIUM(path, range); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoDeletePathsCHROMIUM(path, range); } error::Error GLES2DecoderPassthroughImpl::HandlePathCommandsCHROMIUM( @@ -1882,10 +1818,15 @@ error::Error GLES2DecoderPassthroughImpl::HandlePathCommandsCHROMIUM( *static_cast(cmd_data); GLuint path = static_cast(c.path); GLsizei num_commands = static_cast(c.numCommands); + GLsizei num_coords = static_cast(c.numCoords); + GLenum coord_type = static_cast(c.coordType); + uint32_t commands_shm_id = c.commands_shm_id; + uint32_t commands_shm_offset = c.commands_shm_offset; + uint32_t coords_shm_id = c.coords_shm_id; + uint32_t coords_shm_offset = c.coords_shm_offset; + const GLubyte* commands = nullptr; if (num_commands > 0) { - uint32_t commands_shm_id = static_cast(c.commands_shm_id); - uint32_t commands_shm_offset = static_cast(c.commands_shm_offset); if (commands_shm_id != 0 || commands_shm_offset != 0) { commands = GetSharedMemoryAs( commands_shm_id, commands_shm_offset, num_commands); @@ -1894,13 +1835,9 @@ error::Error GLES2DecoderPassthroughImpl::HandlePathCommandsCHROMIUM( return error::kOutOfBounds; } } - GLsizei num_coords = static_cast(c.numCoords); - GLenum coord_type = static_cast(c.coordType); const GLvoid* coords = nullptr; GLsizei coords_bufsize = 0; if (num_coords > 0) { - uint32_t coords_shm_id = static_cast(c.coords_shm_id); - uint32_t coords_shm_offset = static_cast(c.coords_shm_offset); if (coords_shm_id != 0 || coords_shm_offset != 0) { unsigned int memory_size = 0; coords = GetSharedMemoryAndSizeAs( @@ -1913,14 +1850,8 @@ error::Error GLES2DecoderPassthroughImpl::HandlePathCommandsCHROMIUM( } } - error::Error error = - DoPathCommandsCHROMIUM(path, num_commands, commands, num_coords, - coord_type, coords, coords_bufsize); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; + return DoPathCommandsCHROMIUM(path, num_commands, commands, num_coords, + coord_type, coords, coords_bufsize); } error::Error GLES2DecoderPassthroughImpl::HandlePathParameterfCHROMIUM( @@ -1932,11 +1863,8 @@ error::Error GLES2DecoderPassthroughImpl::HandlePathParameterfCHROMIUM( GLuint path = static_cast(c.path); GLenum pname = static_cast(c.pname); GLfloat value = static_cast(c.value); - error::Error error = DoPathParameterfCHROMIUM(path, pname, value); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoPathParameterfCHROMIUM(path, pname, value); } error::Error GLES2DecoderPassthroughImpl::HandlePathParameteriCHROMIUM( @@ -1948,11 +1876,8 @@ error::Error GLES2DecoderPassthroughImpl::HandlePathParameteriCHROMIUM( GLuint path = static_cast(c.path); GLenum pname = static_cast(c.pname); GLint value = static_cast(c.value); - error::Error error = DoPathParameteriCHROMIUM(path, pname, value); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoPathParameteriCHROMIUM(path, pname, value); } error::Error GLES2DecoderPassthroughImpl::HandleStencilFillPathCHROMIUM( @@ -1964,11 +1889,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleStencilFillPathCHROMIUM( GLuint path = static_cast(c.path); GLenum fill_mode = static_cast(c.fillMode); GLuint mask = static_cast(c.mask); - error::Error error = DoStencilFillPathCHROMIUM(path, fill_mode, mask); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoStencilFillPathCHROMIUM(path, fill_mode, mask); } error::Error GLES2DecoderPassthroughImpl::HandleStencilStrokePathCHROMIUM( @@ -1980,11 +1902,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleStencilStrokePathCHROMIUM( GLuint path = static_cast(c.path); GLint reference = static_cast(c.reference); GLuint mask = static_cast(c.mask); - error::Error error = DoStencilStrokePathCHROMIUM(path, reference, mask); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoStencilStrokePathCHROMIUM(path, reference, mask); } error::Error GLES2DecoderPassthroughImpl::HandleCoverFillPathCHROMIUM( @@ -1995,11 +1914,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleCoverFillPathCHROMIUM( cmd_data); GLuint path = static_cast(c.path); GLenum cover_mode = static_cast(c.coverMode); - error::Error error = DoCoverFillPathCHROMIUM(path, cover_mode); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoCoverFillPathCHROMIUM(path, cover_mode); } error::Error GLES2DecoderPassthroughImpl::HandleCoverStrokePathCHROMIUM( @@ -2010,11 +1926,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleCoverStrokePathCHROMIUM( cmd_data); GLuint path = static_cast(c.path); GLenum cover_mode = static_cast(c.coverMode); - error::Error error = DoCoverStrokePathCHROMIUM(path, cover_mode); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoCoverStrokePathCHROMIUM(path, cover_mode); } error::Error @@ -2029,12 +1942,8 @@ GLES2DecoderPassthroughImpl::HandleStencilThenCoverFillPathCHROMIUM( GLenum fill_mode = static_cast(c.fillMode); GLuint mask = static_cast(c.mask); GLenum cover_mode = static_cast(c.coverMode); - error::Error error = - DoStencilThenCoverFillPathCHROMIUM(path, fill_mode, mask, cover_mode); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoStencilThenCoverFillPathCHROMIUM(path, fill_mode, mask, cover_mode); } error::Error @@ -2049,12 +1958,9 @@ GLES2DecoderPassthroughImpl::HandleStencilThenCoverStrokePathCHROMIUM( GLint reference = static_cast(c.reference); GLuint mask = static_cast(c.mask); GLenum cover_mode = static_cast(c.coverMode); - error::Error error = - DoStencilThenCoverStrokePathCHROMIUM(path, reference, mask, cover_mode); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + + return DoStencilThenCoverStrokePathCHROMIUM(path, reference, mask, + cover_mode); } error::Error @@ -2067,11 +1973,18 @@ GLES2DecoderPassthroughImpl::HandleStencilFillPathInstancedCHROMIUM( cmd_data); GLsizei num_paths = static_cast(c.numPaths); GLenum path_name_type = static_cast(c.pathNameType); + GLuint path_base = static_cast(c.pathBase); + GLenum fill_mode = static_cast(c.fillMode); + GLuint mask = static_cast(c.mask); + GLenum transform_type = static_cast(c.transformType); + uint32_t paths_shm_id = c.paths_shm_id; + uint32_t paths_shm_offset = c.paths_shm_offset; + uint32_t transform_values_shm_id = c.transformValues_shm_id; + uint32_t transform_values_shm_offset = c.transformValues_shm_offset; + const GLvoid* paths = nullptr; GLsizei paths_bufsize = 0; if (num_paths > 0) { - uint32_t paths_shm_id = static_cast(c.paths_shm_id); - uint32_t paths_shm_offset = static_cast(c.paths_shm_offset); if (paths_shm_id != 0 || paths_shm_offset != 0) { unsigned int memory_size = 0; paths = GetSharedMemoryAndSizeAs( @@ -2083,31 +1996,21 @@ GLES2DecoderPassthroughImpl::HandleStencilFillPathInstancedCHROMIUM( return error::kOutOfBounds; } } - GLuint path_base = static_cast(c.pathBase); - GLenum fill_mode = static_cast(c.fillMode); - GLuint mask = static_cast(c.mask); - GLenum transform_type = static_cast(c.transformType); const GLfloat* transform_values = nullptr; GLsizei transform_values_bufsize = 0; - if (c.transformValues_shm_id != 0 || c.transformValues_shm_offset != 0) { + if (transform_values_shm_id != 0 || transform_values_shm_offset != 0) { unsigned int memory_size = 0; transform_values = GetSharedMemoryAndSizeAs( - c.transformValues_shm_id, c.transformValues_shm_offset, 0, - &memory_size); + transform_values_shm_id, transform_values_shm_offset, 0, &memory_size); transform_values_bufsize = static_cast(memory_size); } if (!transform_values) { return error::kOutOfBounds; } - error::Error error = DoStencilFillPathInstancedCHROMIUM( + return DoStencilFillPathInstancedCHROMIUM( num_paths, path_name_type, paths, paths_bufsize, path_base, fill_mode, mask, transform_type, transform_values, transform_values_bufsize); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; } error::Error @@ -2120,11 +2023,18 @@ GLES2DecoderPassthroughImpl::HandleStencilStrokePathInstancedCHROMIUM( cmd_data); GLsizei num_paths = static_cast(c.numPaths); GLenum path_name_type = static_cast(c.pathNameType); + GLuint path_base = static_cast(c.pathBase); + GLint reference = static_cast(c.reference); + GLuint mask = static_cast(c.mask); + GLenum transform_type = static_cast(c.transformType); + uint32_t paths_shm_id = c.paths_shm_id; + uint32_t paths_shm_offset = c.paths_shm_offset; + uint32_t transform_values_shm_id = c.transformValues_shm_id; + uint32_t transform_values_shm_offset = c.transformValues_shm_offset; + const GLvoid* paths = nullptr; GLsizei paths_bufsize = 0; if (num_paths > 0) { - uint32_t paths_shm_id = static_cast(c.paths_shm_id); - uint32_t paths_shm_offset = static_cast(c.paths_shm_offset); if (paths_shm_id != 0 || paths_shm_offset != 0) { unsigned int memory_size = 0; paths = GetSharedMemoryAndSizeAs( @@ -2136,31 +2046,21 @@ GLES2DecoderPassthroughImpl::HandleStencilStrokePathInstancedCHROMIUM( return error::kOutOfBounds; } } - GLuint path_base = static_cast(c.pathBase); - GLint reference = static_cast(c.reference); - GLuint mask = static_cast(c.mask); - GLenum transform_type = static_cast(c.transformType); const GLfloat* transform_values = nullptr; GLsizei transform_values_bufsize = 0; - if (c.transformValues_shm_id != 0 || c.transformValues_shm_offset != 0) { + if (transform_values_shm_id != 0 || transform_values_shm_offset != 0) { unsigned int memory_size = 0; transform_values = GetSharedMemoryAndSizeAs( - c.transformValues_shm_id, c.transformValues_shm_offset, 0, - &memory_size); + transform_values_shm_id, transform_values_shm_offset, 0, &memory_size); transform_values_bufsize = static_cast(memory_size); } if (!transform_values) { return error::kOutOfBounds; } - error::Error error = DoStencilStrokePathInstancedCHROMIUM( + return DoStencilStrokePathInstancedCHROMIUM( num_paths, path_name_type, paths, paths_bufsize, path_base, reference, mask, transform_type, transform_values, transform_values_bufsize); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; } error::Error GLES2DecoderPassthroughImpl::HandleCoverFillPathInstancedCHROMIUM( @@ -2171,11 +2071,17 @@ error::Error GLES2DecoderPassthroughImpl::HandleCoverFillPathInstancedCHROMIUM( cmd_data); GLsizei num_paths = static_cast(c.numPaths); GLenum path_name_type = static_cast(c.pathNameType); + GLuint path_base = static_cast(c.pathBase); + GLenum cover_mode = static_cast(c.coverMode); + GLenum transform_type = static_cast(c.transformType); + uint32_t paths_shm_id = c.paths_shm_id; + uint32_t paths_shm_offset = c.paths_shm_offset; + uint32_t transform_values_shm_id = c.transformValues_shm_id; + uint32_t transform_values_shm_offset = c.transformValues_shm_offset; + const GLvoid* paths = nullptr; GLsizei paths_bufsize = 0; if (num_paths > 0) { - uint32_t paths_shm_id = static_cast(c.paths_shm_id); - uint32_t paths_shm_offset = static_cast(c.paths_shm_offset); if (paths_shm_id != 0 || paths_shm_offset != 0) { unsigned int memory_size = 0; paths = GetSharedMemoryAndSizeAs( @@ -2187,30 +2093,21 @@ error::Error GLES2DecoderPassthroughImpl::HandleCoverFillPathInstancedCHROMIUM( return error::kOutOfBounds; } } - GLuint path_base = static_cast(c.pathBase); - GLenum cover_mode = static_cast(c.coverMode); - GLenum transform_type = static_cast(c.transformType); const GLfloat* transform_values = nullptr; GLsizei transform_values_bufsize = 0; - if (c.transformValues_shm_id != 0 || c.transformValues_shm_offset != 0) { + if (transform_values_shm_id != 0 || transform_values_shm_offset != 0) { unsigned int memory_size = 0; transform_values = GetSharedMemoryAndSizeAs( - c.transformValues_shm_id, c.transformValues_shm_offset, 0, - &memory_size); + transform_values_shm_id, transform_values_shm_offset, 0, &memory_size); transform_values_bufsize = static_cast(memory_size); } if (!transform_values) { return error::kOutOfBounds; } - error::Error error = DoCoverFillPathInstancedCHROMIUM( + return DoCoverFillPathInstancedCHROMIUM( num_paths, path_name_type, paths, paths_bufsize, path_base, cover_mode, transform_type, transform_values, transform_values_bufsize); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; } error::Error @@ -2223,11 +2120,17 @@ GLES2DecoderPassthroughImpl::HandleCoverStrokePathInstancedCHROMIUM( cmd_data); GLsizei num_paths = static_cast(c.numPaths); GLenum path_name_type = static_cast(c.pathNameType); + GLuint path_base = static_cast(c.pathBase); + GLenum cover_mode = static_cast(c.coverMode); + GLenum transform_type = static_cast(c.transformType); + uint32_t paths_shm_id = c.paths_shm_id; + uint32_t paths_shm_offset = c.paths_shm_offset; + uint32_t transform_values_shm_id = c.transformValues_shm_id; + uint32_t transform_values_shm_offset = c.transformValues_shm_offset; + const GLvoid* paths = nullptr; GLsizei paths_bufsize = 0; if (num_paths > 0) { - uint32_t paths_shm_id = static_cast(c.paths_shm_id); - uint32_t paths_shm_offset = static_cast(c.paths_shm_offset); if (paths_shm_id != 0 || paths_shm_offset != 0) { unsigned int memory_size = 0; paths = GetSharedMemoryAndSizeAs( @@ -2239,30 +2142,21 @@ GLES2DecoderPassthroughImpl::HandleCoverStrokePathInstancedCHROMIUM( return error::kOutOfBounds; } } - GLuint path_base = static_cast(c.pathBase); - GLenum cover_mode = static_cast(c.coverMode); - GLenum transform_type = static_cast(c.transformType); const GLfloat* transform_values = nullptr; GLsizei transform_values_bufsize = 0; - if (c.transformValues_shm_id != 0 || c.transformValues_shm_offset != 0) { + if (transform_values_shm_id != 0 || transform_values_shm_offset != 0) { unsigned int memory_size = 0; transform_values = GetSharedMemoryAndSizeAs( - c.transformValues_shm_id, c.transformValues_shm_offset, 0, - &memory_size); + transform_values_shm_id, transform_values_shm_offset, 0, &memory_size); transform_values_bufsize = static_cast(memory_size); } if (!transform_values) { return error::kOutOfBounds; } - error::Error error = DoCoverStrokePathInstancedCHROMIUM( + return DoCoverStrokePathInstancedCHROMIUM( num_paths, path_name_type, paths, paths_bufsize, path_base, cover_mode, transform_type, transform_values, transform_values_bufsize); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; } error::Error @@ -2274,11 +2168,19 @@ GLES2DecoderPassthroughImpl::HandleStencilThenCoverFillPathInstancedCHROMIUM( StencilThenCoverFillPathInstancedCHROMIUM*>(cmd_data); GLsizei num_paths = static_cast(c.numPaths); GLenum path_name_type = static_cast(c.pathNameType); + GLuint path_base = static_cast(c.pathBase); + GLenum cover_mode = static_cast(c.coverMode); + GLenum fill_mode = static_cast(c.fillMode); + GLuint mask = static_cast(c.mask); + GLenum transform_type = static_cast(c.transformType); + uint32_t paths_shm_id = c.paths_shm_id; + uint32_t paths_shm_offset = c.paths_shm_offset; + uint32_t transform_values_shm_id = c.transformValues_shm_id; + uint32_t transform_values_shm_offset = c.transformValues_shm_offset; + const GLvoid* paths = nullptr; GLsizei paths_bufsize = 0; if (num_paths > 0) { - uint32_t paths_shm_id = static_cast(c.paths_shm_id); - uint32_t paths_shm_offset = static_cast(c.paths_shm_offset); if (paths_shm_id != 0 || paths_shm_offset != 0) { unsigned int memory_size = 0; paths = GetSharedMemoryAndSizeAs( @@ -2290,33 +2192,22 @@ GLES2DecoderPassthroughImpl::HandleStencilThenCoverFillPathInstancedCHROMIUM( return error::kOutOfBounds; } } - GLuint path_base = static_cast(c.pathBase); - GLenum cover_mode = static_cast(c.coverMode); - GLenum fill_mode = static_cast(c.fillMode); - GLuint mask = static_cast(c.mask); - GLenum transform_type = static_cast(c.transformType); const GLfloat* transform_values = nullptr; GLsizei transform_values_bufsize = 0; - if (c.transformValues_shm_id != 0 || c.transformValues_shm_offset != 0) { + if (transform_values_shm_id != 0 || transform_values_shm_offset != 0) { unsigned int memory_size = 0; transform_values = GetSharedMemoryAndSizeAs( - c.transformValues_shm_id, c.transformValues_shm_offset, 0, - &memory_size); + transform_values_shm_id, transform_values_shm_offset, 0, &memory_size); transform_values_bufsize = static_cast(memory_size); } if (!transform_values) { return error::kOutOfBounds; } - error::Error error = DoStencilThenCoverFillPathInstancedCHROMIUM( + return DoStencilThenCoverFillPathInstancedCHROMIUM( num_paths, path_name_type, paths, paths_bufsize, path_base, cover_mode, fill_mode, mask, transform_type, transform_values, transform_values_bufsize); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; } error::Error @@ -2328,11 +2219,19 @@ GLES2DecoderPassthroughImpl::HandleStencilThenCoverStrokePathInstancedCHROMIUM( StencilThenCoverStrokePathInstancedCHROMIUM*>(cmd_data); GLsizei num_paths = static_cast(c.numPaths); GLenum path_name_type = static_cast(c.pathNameType); + GLuint path_base = static_cast(c.pathBase); + GLenum cover_mode = static_cast(c.coverMode); + GLint reference = static_cast(c.reference); + GLuint mask = static_cast(c.mask); + GLenum transform_type = static_cast(c.transformType); + uint32_t paths_shm_id = c.paths_shm_id; + uint32_t paths_shm_offset = c.paths_shm_offset; + uint32_t transform_values_shm_id = c.transformValues_shm_id; + uint32_t transform_values_shm_offset = c.transformValues_shm_offset; + const GLvoid* paths = nullptr; GLsizei paths_bufsize = 0; if (num_paths > 0) { - uint32_t paths_shm_id = static_cast(c.paths_shm_id); - uint32_t paths_shm_offset = static_cast(c.paths_shm_offset); if (paths_shm_id != 0 || paths_shm_offset != 0) { unsigned int memory_size = 0; paths = GetSharedMemoryAndSizeAs( @@ -2344,33 +2243,22 @@ GLES2DecoderPassthroughImpl::HandleStencilThenCoverStrokePathInstancedCHROMIUM( return error::kOutOfBounds; } } - GLuint path_base = static_cast(c.pathBase); - GLenum cover_mode = static_cast(c.coverMode); - GLint reference = static_cast(c.reference); - GLuint mask = static_cast(c.mask); - GLenum transform_type = static_cast(c.transformType); const GLfloat* transform_values = nullptr; GLsizei transform_values_bufsize = 0; - if (c.transformValues_shm_id != 0 || c.transformValues_shm_offset != 0) { + if (transform_values_shm_id != 0 || transform_values_shm_offset != 0) { unsigned int memory_size = 0; transform_values = GetSharedMemoryAndSizeAs( - c.transformValues_shm_id, c.transformValues_shm_offset, 0, - &memory_size); + transform_values_shm_id, transform_values_shm_offset, 0, &memory_size); transform_values_bufsize = static_cast(memory_size); } if (!transform_values) { return error::kOutOfBounds; } - error::Error error = DoStencilThenCoverStrokePathInstancedCHROMIUM( + return DoStencilThenCoverStrokePathInstancedCHROMIUM( num_paths, path_name_type, paths, paths_bufsize, path_base, cover_mode, reference, mask, transform_type, transform_values, transform_values_bufsize); - if (error != error::kNoError) { - return error; - } - - return error::kNoError; } error::Error @@ -2383,7 +2271,9 @@ GLES2DecoderPassthroughImpl::HandleBindFragmentInputLocationCHROMIUMBucket( cmd_data); GLuint program = static_cast(c.program); GLint location = static_cast(c.location); - Bucket* bucket = GetBucket(c.name_bucket_id); + uint32_t name_bucket_id = c.name_bucket_id; + + Bucket* bucket = GetBucket(name_bucket_id); if (!bucket || bucket->size() == 0) { return error::kInvalidArguments; } @@ -2391,12 +2281,8 @@ GLES2DecoderPassthroughImpl::HandleBindFragmentInputLocationCHROMIUMBucket( if (!bucket->GetAsString(&name_str)) { return error::kInvalidArguments; } - error::Error error = - DoBindFragmentInputLocationCHROMIUM(program, location, name_str.c_str()); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoBindFragmentInputLocationCHROMIUM(program, location, + name_str.c_str()); } error::Error @@ -2411,23 +2297,22 @@ GLES2DecoderPassthroughImpl::HandleProgramPathFragmentInputGenCHROMIUM( GLint location = static_cast(c.location); GLenum gen_mode = static_cast(c.genMode); GLint components = static_cast(c.components); + uint32_t coeffs_shm_id = c.coeffs_shm_id; + uint32_t coeffs_shm_offset = c.coeffs_shm_offset; + const GLfloat* coeffs = nullptr; GLsizei coeffs_bufsize = 0; - if (c.coeffs_shm_id != 0 || c.coeffs_shm_offset != 0) { + if (coeffs_shm_id != 0 || coeffs_shm_offset != 0) { unsigned int memory_size = 0; coeffs = GetSharedMemoryAndSizeAs( - c.coeffs_shm_id, c.coeffs_shm_offset, 0, &memory_size); + coeffs_shm_id, coeffs_shm_offset, 0, &memory_size); coeffs_bufsize = static_cast(memory_size); } if (!coeffs) { return error::kOutOfBounds; } - error::Error error = DoProgramPathFragmentInputGenCHROMIUM( + return DoProgramPathFragmentInputGenCHROMIUM( program, location, gen_mode, components, coeffs, coeffs_bufsize); - if (error != error::kNoError) { - return error; - } - return error::kNoError; } error::Error @@ -2441,7 +2326,9 @@ GLES2DecoderPassthroughImpl::HandleBindFragDataLocationIndexedEXTBucket( GLuint program = static_cast(c.program); GLuint colorNumber = static_cast(c.colorNumber); GLuint index = static_cast(c.index); - Bucket* bucket = GetBucket(c.name_bucket_id); + uint32_t name_bucket_id = c.name_bucket_id; + + Bucket* bucket = GetBucket(name_bucket_id); if (!bucket || bucket->size() == 0) { return error::kInvalidArguments; } @@ -2449,12 +2336,8 @@ GLES2DecoderPassthroughImpl::HandleBindFragDataLocationIndexedEXTBucket( if (!bucket->GetAsString(&name_str)) { return error::kInvalidArguments; } - error::Error error = DoBindFragDataLocationIndexedEXT( - program, colorNumber, index, name_str.c_str()); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoBindFragDataLocationIndexedEXT(program, colorNumber, index, + name_str.c_str()); } error::Error GLES2DecoderPassthroughImpl::HandleBindFragDataLocationEXTBucket( @@ -2465,7 +2348,9 @@ error::Error GLES2DecoderPassthroughImpl::HandleBindFragDataLocationEXTBucket( cmd_data); GLuint program = static_cast(c.program); GLuint colorNumber = static_cast(c.colorNumber); - Bucket* bucket = GetBucket(c.name_bucket_id); + uint32_t name_bucket_id = c.name_bucket_id; + + Bucket* bucket = GetBucket(name_bucket_id); if (!bucket || bucket->size() == 0) { return error::kInvalidArguments; } @@ -2473,12 +2358,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleBindFragDataLocationEXTBucket( if (!bucket->GetAsString(&name_str)) { return error::kInvalidArguments; } - error::Error error = - DoBindFragDataLocationEXT(program, colorNumber, name_str.c_str()); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoBindFragDataLocationEXT(program, colorNumber, name_str.c_str()); } error::Error GLES2DecoderPassthroughImpl::HandleGetFragDataIndexEXT( @@ -2487,7 +2367,11 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetFragDataIndexEXT( const volatile gles2::cmds::GetFragDataIndexEXT& c = *static_cast(cmd_data); GLuint program = static_cast(c.program); - Bucket* bucket = GetBucket(c.name_bucket_id); + uint32_t index_shm_id = c.index_shm_id; + uint32_t index_shm_offset = c.index_shm_offset; + uint32_t name_bucket_id = c.name_bucket_id; + + Bucket* bucket = GetBucket(name_bucket_id); if (!bucket) { return error::kInvalidArguments; } @@ -2495,8 +2379,8 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetFragDataIndexEXT( if (!bucket->GetAsString(&name_str)) { return error::kInvalidArguments; } - GLint* index = GetSharedMemoryAs(c.index_shm_id, c.index_shm_offset, - sizeof(GLint)); + GLint* index = + GetSharedMemoryAs(index_shm_id, index_shm_offset, sizeof(GLint)); if (!index) { return error::kOutOfBounds; } @@ -2504,11 +2388,7 @@ error::Error GLES2DecoderPassthroughImpl::HandleGetFragDataIndexEXT( if (*index != -1) { return error::kInvalidArguments; } - error::Error error = DoGetFragDataIndexEXT(program, name_str.c_str(), index); - if (error != error::kNoError) { - return error; - } - return error::kNoError; + return DoGetFragDataIndexEXT(program, name_str.c_str(), index); } error::Error GLES2DecoderPassthroughImpl::HandleCompressedTexImage2DBucket( @@ -2521,11 +2401,13 @@ error::Error GLES2DecoderPassthroughImpl::HandleCompressedTexImage2DBucket( GLenum internal_format = static_cast(c.internalformat); GLsizei width = static_cast(c.width); GLsizei height = static_cast(c.height); - GLuint bucket_id = static_cast(c.bucket_id); + uint32_t bucket_id = c.bucket_id; GLint border = static_cast(c.border); + Bucket* bucket = GetBucket(bucket_id); - if (!bucket) + if (!bucket) { return error::kInvalidArguments; + } uint32_t image_size = bucket->size(); const void* data = bucket->GetData(0, image_size); DCHECK(data || !image_size); @@ -2576,10 +2458,12 @@ error::Error GLES2DecoderPassthroughImpl::HandleCompressedTexSubImage2DBucket( GLsizei width = static_cast(c.width); GLsizei height = static_cast(c.height); GLenum format = static_cast(c.format); - GLuint bucket_id = static_cast(c.bucket_id); + uint32_t bucket_id = c.bucket_id; + Bucket* bucket = GetBucket(bucket_id); - if (!bucket) + if (!bucket) { return error::kInvalidArguments; + } uint32_t image_size = bucket->size(); const void* data = bucket->GetData(0, image_size); DCHECK(data || !image_size); @@ -2632,11 +2516,13 @@ error::Error GLES2DecoderPassthroughImpl::HandleCompressedTexImage3DBucket( GLsizei width = static_cast(c.width); GLsizei height = static_cast(c.height); GLsizei depth = static_cast(c.depth); - GLuint bucket_id = static_cast(c.bucket_id); + uint32_t bucket_id = c.bucket_id; GLint border = static_cast(c.border); + Bucket* bucket = GetBucket(bucket_id); - if (!bucket) + if (!bucket) { return error::kInvalidArguments; + } GLsizei image_size = bucket->size(); const void* data = bucket->GetData(0, image_size); DCHECK(data || !image_size); @@ -2690,10 +2576,12 @@ error::Error GLES2DecoderPassthroughImpl::HandleCompressedTexSubImage3DBucket( GLsizei height = static_cast(c.height); GLsizei depth = static_cast(c.depth); GLenum format = static_cast(c.format); - GLuint bucket_id = static_cast(c.bucket_id); + uint32_t bucket_id = c.bucket_id; + Bucket* bucket = GetBucket(bucket_id); - if (!bucket) + if (!bucket) { return error::kInvalidArguments; + } uint32_t image_size = bucket->size(); const void* data = bucket->GetData(0, image_size); DCHECK(data || !image_size); diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_drawing.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_drawing.cc new file mode 100644 index 00000000000..20f03399deb --- /dev/null +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_drawing.cc @@ -0,0 +1,41 @@ +// Copyright 2017 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 "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" + +namespace gpu { +namespace gles2 { + +using namespace cmds; + +TEST_F(GLES2DecoderPassthroughTest, DrawArraysInstancedANGLEEnablement) { + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, 3, 1); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); + + DoRequestExtension("GL_ANGLE_instanced_arrays"); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_F(GLES2DecoderPassthroughTest, VertexAttribDivisorANGLEEnablement) { + VertexAttribDivisorANGLE cmd; + cmd.Init(0, 1); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); + + DoRequestExtension("GL_ANGLE_instanced_arrays"); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_F(GLES2DecoderPassthroughTest, DrawElementsInstancedANGLEEnablement) { + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0, 1); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); + + DoRequestExtension("GL_ANGLE_instanced_arrays"); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_framebuffers.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_framebuffers.cc new file mode 100644 index 00000000000..c8fd6c14956 --- /dev/null +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_framebuffers.cc @@ -0,0 +1,420 @@ +// Copyright 2017 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 + +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" + +namespace gpu { +namespace gles2 { + +using namespace cmds; + +TEST_F(GLES3DecoderPassthroughTest, ReadPixelsBufferBound) { + const GLsizei kWidth = 5; + const GLsizei kHeight = 3; + const GLint kBytesPerPixel = 4; + GLint size = kWidth * kHeight * kBytesPerPixel; + typedef ReadPixels::Result Result; + Result* result = GetSharedMemoryAs(); + uint32_t result_shm_id = shared_memory_id_; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t pixels_shm_id = shared_memory_id_; + uint32_t pixels_shm_offset = kSharedMemoryOffset + sizeof(Result); + + DoBindBuffer(GL_PIXEL_PACK_BUFFER, kClientBufferId); + DoBufferData(GL_PIXEL_PACK_BUFFER, size, nullptr, GL_STATIC_DRAW); + + ReadPixels cmd; + cmd.Init(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels_shm_id, + pixels_shm_offset, result_shm_id, result_shm_offset, false); + result->success = 0; + EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_F(GLES3DecoderPassthroughTest, ReadPixels2PixelPackBufferNoBufferBound) { + const GLsizei kWidth = 5; + const GLsizei kHeight = 3; + + ReadPixels cmd; + cmd.Init(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 0, 0, false); + EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_F(GLES3DecoderPassthroughTest, ReadPixels2PixelPackBuffer) { + const GLsizei kWidth = 5; + const GLsizei kHeight = 3; + const GLint kBytesPerPixel = 4; + GLint size = kWidth * kHeight * kBytesPerPixel; + + DoBindBuffer(GL_PIXEL_PACK_BUFFER, kClientBufferId); + DoBufferData(GL_PIXEL_PACK_BUFFER, size, nullptr, GL_STATIC_DRAW); + + ReadPixels cmd; + cmd.Init(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 0, 0, false); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_F(GLES2DecoderPassthroughTest, DiscardFramebufferEXTUnsupported) { + const GLenum target = GL_FRAMEBUFFER; + const GLsizei count = 1; + const GLenum attachments[] = {GL_COLOR_EXT}; + DiscardFramebufferEXTImmediate& cmd = + *GetImmediateAs(); + cmd.Init(target, count, attachments); + EXPECT_EQ(error::kUnknownCommand, + ExecuteImmediateCmd(cmd, sizeof(attachments))); +} + +TEST_F(GLES2DecoderPassthroughTest, ReadPixelsOutOfRange) { + const GLint kWidth = 5; + const GLint kHeight = 3; + const GLenum kFormat = GL_RGBA; + + // Set up GL objects for the read pixels with a known framebuffer size + DoBindTexture(GL_TEXTURE_2D, kClientTextureId); + DoTexImage2D(GL_TEXTURE_2D, 0, kFormat, kWidth, kHeight, 0, kFormat, + GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer(GL_FRAMEBUFFER, kClientFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + kClientTextureId, 0); + + // Put the resulting pixels and the result in shared memory + typedef ReadPixels::Result Result; + Result* result = GetSharedMemoryAs(); + uint32_t result_shm_id = shared_memory_id_; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t pixels_shm_id = shared_memory_id_; + uint32_t pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); + + uint8_t* dest = reinterpret_cast(&result[1]); + + // The test cases + static struct { + GLint x, y, w, h; + } tests[] = { + { + -2, -1, 9, 5, + }, // out of range on all sides + { + 2, 1, 9, 5, + }, // out of range on right, bottom + { + -7, -4, 9, 5, + }, // out of range on left, top + { + 0, -5, 9, 5, + }, // completely off top + { + 0, 3, 9, 5, + }, // completely off bottom + { + -9, 0, 9, 5, + }, // completely off left + { + 5, 0, 9, 5, + }, // completely off right + }; + + for (auto test : tests) { + // Clear the readpixels buffer so that we can see which pixels have been + // written + memset(dest, 0, 4 * test.w * test.h); + + ReadPixels cmd; + cmd.Init(test.x, test.y, test.w, test.h, kFormat, GL_UNSIGNED_BYTE, + pixels_shm_id, pixels_shm_offset, result_shm_id, result_shm_offset, + false); + result->success = 0; + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + + EXPECT_TRUE(result->success); + + // Check the Result has the correct metadata for what was read. + GLint startx = std::max(test.x, 0); + GLint endx = std::min(test.x + test.w, kWidth); + EXPECT_EQ(result->row_length, endx - startx); + + GLint starty = std::max(test.y, 0); + GLint endy = std::min(test.y + test.h, kHeight); + EXPECT_EQ(result->num_rows, endy - starty); + + // Check each pixel and expect them to be non-zero if they were written. The + // non-zero values are written by ANGLE's NULL backend to simulate the + // memory that would be modified by the call. + for (GLint dx = 0; dx < test.w; ++dx) { + GLint x = test.x + dx; + for (GLint dy = 0; dy < test.h; ++dy) { + GLint y = test.y + dy; + + bool expect_written = 0 <= x && x < kWidth && 0 <= y && y < kHeight; + for (GLint component = 0; component < 4; ++component) { + uint8_t value = dest[4 * (dy * test.w + dx) + component]; + EXPECT_EQ(expect_written, value != 0) + << x << " " << y << " " << value; + } + } + } + } +} + +TEST_F(GLES2DecoderPassthroughTest, ReadPixelsAsync) { + typedef ReadPixels::Result Result; + Result* result = GetSharedMemoryAs(); + const GLsizei kWidth = 4; + const GLsizei kHeight = 4; + uint32_t result_shm_id = shared_memory_id_; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t pixels_shm_id = shared_memory_id_; + uint32_t pixels_shm_offset = kSharedMemoryOffset + sizeof(Result); + + ReadPixels read_pixels_cmd; + read_pixels_cmd.Init(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + pixels_shm_id, pixels_shm_offset, result_shm_id, + result_shm_offset, true); + result->success = 0; + + EXPECT_EQ(error::kNoError, ExecuteCmd(read_pixels_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(GetDecoder()->HasMoreIdleWork()); + + { + // Verify internals of pending read pixels + const auto& all_pending_read_pixels = GetPendingReadPixels(); + EXPECT_EQ(1u, all_pending_read_pixels.size()); + + const auto& pending_read_pixels = all_pending_read_pixels.front(); + EXPECT_NE(nullptr, pending_read_pixels.fence); + EXPECT_EQ(pixels_shm_id, pending_read_pixels.pixels_shm_id); + EXPECT_EQ(pixels_shm_offset, pending_read_pixels.pixels_shm_offset); + EXPECT_EQ(result_shm_offset, pending_read_pixels.result_shm_offset); + EXPECT_EQ(result_shm_id, pending_read_pixels.result_shm_id); + EXPECT_NE(0u, pending_read_pixels.buffer_service_id); + EXPECT_TRUE(pending_read_pixels.waiting_async_pack_queries.empty()); + } + + Finish finish_cmd; + finish_cmd.Init(); + EXPECT_EQ(error::kNoError, ExecuteCmd(finish_cmd)); + EXPECT_FALSE(GetDecoder()->HasMoreIdleWork()); + EXPECT_TRUE(GetPendingReadPixels().empty()); +} + +TEST_F(GLES3DecoderPassthroughTest, ReadPixelsAsyncSkippedIfPBOBound) { + typedef ReadPixels::Result Result; + Result* result = GetSharedMemoryAs(); + const GLsizei kWidth = 4; + const GLsizei kHeight = 4; + uint32_t result_shm_id = shared_memory_id_; + uint32_t result_shm_offset = kSharedMemoryOffset; + + cmds::BindBuffer bind_cmd; + bind_cmd.Init(GL_PIXEL_PACK_BUFFER, kClientBufferId); + EXPECT_EQ(error::kNoError, ExecuteCmd(bind_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + cmds::BufferData buffer_data_cmd; + size_t read_pixels_result_size = kWidth * kHeight * 4; + buffer_data_cmd.Init(GL_PIXEL_PACK_BUFFER, read_pixels_result_size, 0, 0, + GL_STREAM_DRAW); + EXPECT_EQ(error::kNoError, ExecuteCmd(buffer_data_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Check that there is no idle work to do when a PBO is already bound and that + // the ReadPixel succeeded + ReadPixels read_pixels_cmd; + read_pixels_cmd.Init(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, + result_shm_id, result_shm_offset, true); + result->success = 0; + EXPECT_EQ(error::kNoError, ExecuteCmd(read_pixels_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_FALSE(GetDecoder()->HasMoreIdleWork()); +} + +TEST_F(GLES2DecoderPassthroughTest, ReadPixelsAsyncModifyCommand) { + typedef ReadPixels::Result Result; + size_t shm_size = 0; + Result* result = GetSharedMemoryAsWithSize(&shm_size); + const GLsizei kWidth = 4; + const GLsizei kHeight = 4; + uint32_t result_shm_id = shared_memory_id_; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t pixels_shm_id = shared_memory_id_; + uint32_t pixels_shm_offset = kSharedMemoryOffset + sizeof(Result); + + size_t pixels_memory_size = shm_size - 1; + char* pixels = reinterpret_cast(result + 1); + + constexpr char kDummyValue = 11; + size_t read_pixels_result_size = kWidth * kHeight * 4; + EXPECT_GT(pixels_memory_size, read_pixels_result_size); + memset(pixels, kDummyValue, pixels_memory_size); + + ReadPixels read_pixels_cmd; + read_pixels_cmd.Init(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + pixels_shm_id, pixels_shm_offset, result_shm_id, + result_shm_offset, true); + result->success = 0; + + EXPECT_EQ(error::kNoError, ExecuteCmd(read_pixels_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(GetDecoder()->HasMoreIdleWork()); + + // Change command after ReadPixels issued, but before we finish the read, + // should have no impact. + read_pixels_cmd.Init(1, 2, 6, 7, GL_RGB, GL_UNSIGNED_SHORT, pixels_shm_id, + pixels_shm_offset, result_shm_id, result_shm_offset, + false); + + Finish finish_cmd; + finish_cmd.Init(); + EXPECT_EQ(error::kNoError, ExecuteCmd(finish_cmd)); + EXPECT_FALSE(GetDecoder()->HasMoreIdleWork()); + EXPECT_TRUE(GetPendingReadPixels().empty()); + + // Validate that only the correct bytes of pixels have been written to. + for (size_t i = 0; i < pixels_memory_size; i++) { + // ANGLE's null context always returns 42 for all pixel bytes for ReadPixels + // calls. + constexpr char kReadPixelsValue = 42; + char expected_value = + i < read_pixels_result_size ? kReadPixelsValue : kDummyValue; + EXPECT_EQ(expected_value, pixels[i]); + } +} + +TEST_F(GLES2DecoderPassthroughTest, ReadPixelsAsyncChangePackAlignment) { + typedef ReadPixels::Result Result; + size_t shm_size = 0; + Result* result = GetSharedMemoryAsWithSize(&shm_size); + const GLsizei kWidth = 4; + const GLsizei kHeight = 4; + uint32_t result_shm_id = shared_memory_id_; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t pixels_shm_id = shared_memory_id_; + uint32_t pixels_shm_offset = kSharedMemoryOffset + sizeof(Result); + + size_t pixels_memory_size = shm_size - 1; + char* pixels = reinterpret_cast(result + 1); + + constexpr char kDummyValue = 11; + size_t read_pixels_result_size = kWidth * kHeight * 4; + EXPECT_GT(pixels_memory_size, read_pixels_result_size); + memset(pixels, kDummyValue, pixels_memory_size); + + ReadPixels read_pixels_cmd; + read_pixels_cmd.Init(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + pixels_shm_id, pixels_shm_offset, result_shm_id, + result_shm_offset, true); + result->success = 0; + + EXPECT_EQ(error::kNoError, ExecuteCmd(read_pixels_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(GetDecoder()->HasMoreIdleWork()); + + PixelStorei pixel_store_i_cmd; + pixel_store_i_cmd.Init(GL_PACK_ALIGNMENT, 8); + EXPECT_EQ(error::kNoError, ExecuteCmd(pixel_store_i_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + Finish finish_cmd; + finish_cmd.Init(); + EXPECT_EQ(error::kNoError, ExecuteCmd(finish_cmd)); + EXPECT_FALSE(GetDecoder()->HasMoreIdleWork()); + EXPECT_TRUE(GetPendingReadPixels().empty()); + + // Validate that only the correct bytes of pixels have been written to. + for (size_t i = 0; i < pixels_memory_size; i++) { + // ANGLE's null context always returns 42 for all pixel bytes for ReadPixels + // calls. + constexpr char kReadPixelsValue = 42; + char expected_value = + i < read_pixels_result_size ? kReadPixelsValue : kDummyValue; + EXPECT_EQ(expected_value, pixels[i]); + } +} + +TEST_F(GLES2DecoderPassthroughTest, ReadPixelsAsyncError) { + typedef ReadPixels::Result Result; + Result* result = GetSharedMemoryAs(); + const GLsizei kWidth = 4; + const GLsizei kHeight = 4; + uint32_t result_shm_id = shared_memory_id_; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t pixels_shm_id = shared_memory_id_; + uint32_t pixels_shm_offset = kSharedMemoryOffset + sizeof(Result); + + // Inject an INVALID_OPERATION error on the call to ReadPixels + InjectGLError(GL_NO_ERROR); + InjectGLError(GL_INVALID_OPERATION); + + ReadPixels cmd; + cmd.Init(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels_shm_id, + pixels_shm_offset, result_shm_id, result_shm_offset, true); + result->success = 0; + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_FALSE(GetDecoder()->HasMoreIdleWork()); + EXPECT_TRUE(GetPendingReadPixels().empty()); +} + +TEST_F(GLES2DecoderPassthroughTest, + RenderbufferStorageMultisampleEXTNotSupported) { + DoBindRenderbuffer(GL_RENDERBUFFER, kClientRenderbufferId); + // GL_EXT_framebuffer_multisample uses RenderbufferStorageMultisampleCHROMIUM. + RenderbufferStorageMultisampleEXT cmd; + cmd.Init(GL_RENDERBUFFER, 1, GL_RGBA4, 1, 1); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); +} + +TEST_F(GLES2DecoderPassthroughTest, + GetFramebufferAttachmentParameterivWithRenderbuffer) { + DoBindFramebuffer(GL_FRAMEBUFFER, kClientFramebufferId); + DoBindRenderbuffer(GL_RENDERBUFFER, kClientRenderbufferId); + DoFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, kClientRenderbufferId); + + GetFramebufferAttachmentParameteriv::Result* result = + static_cast( + shared_memory_address_); + result->size = 0; + const GLint* result_value = result->GetData(); + + GetFramebufferAttachmentParameteriv cmd; + cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(kClientRenderbufferId, static_cast(*result_value)); +} + +TEST_F(GLES2DecoderPassthroughTest, + GetFramebufferAttachmentParameterivWithTexture) { + DoBindFramebuffer(GL_FRAMEBUFFER, kClientFramebufferId); + DoBindTexture(GL_TEXTURE_2D, kClientTextureId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + kClientTextureId, 0); + + GetFramebufferAttachmentParameteriv::Result* result = + static_cast( + shared_memory_address_); + result->size = 0; + const GLint* result_value = result->GetData(); + + GetFramebufferAttachmentParameteriv cmd; + cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(kClientTextureId, static_cast(*result_value)); +} + +} // namespace gles2 +} // namespace gpu 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 0c39b3be25b..5fdc10d2d44 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 @@ -18,6 +18,7 @@ #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/program_manager.h" @@ -242,7 +243,8 @@ void GLES2DecoderTestBase::InitDecoderWithWorkarounds( // we can use the ContextGroup to figure out how the real GLES2Decoder // will initialize itself. command_buffer_service_.reset(new FakeCommandBufferServiceBase()); - mock_decoder_.reset(new MockGLES2Decoder(command_buffer_service_.get())); + mock_decoder_.reset( + new MockGLES2Decoder(command_buffer_service_.get(), &outputter_)); EXPECT_TRUE(group_->Initialize(mock_decoder_.get(), init.context_type, DisallowedFeatures())); @@ -484,8 +486,8 @@ void GLES2DecoderTestBase::InitDecoderWithWorkarounds( normalized_init.lose_context_when_out_of_memory; attribs.context_type = init.context_type; - decoder_.reset( - GLES2Decoder::Create(this, command_buffer_service_.get(), group_.get())); + decoder_.reset(GLES2Decoder::Create(this, command_buffer_service_.get(), + &outputter_, group_.get())); decoder_->SetIgnoreCachedStateForTest(ignore_cached_state_for_test_); decoder_->GetLogger()->set_log_synthesized_gl_errors(false); ASSERT_TRUE(decoder_->Initialize(surface_, context_, false, @@ -2270,7 +2272,7 @@ void GLES2DecoderPassthroughTestBase::SetUp() { command_buffer_service_.reset(new FakeCommandBufferServiceBase()); decoder_.reset(new GLES2DecoderPassthroughImpl( - this, command_buffer_service_.get(), group_.get())); + this, command_buffer_service_.get(), &outputter_, group_.get())); ASSERT_TRUE(group_->Initialize(decoder_.get(), context_creation_attribs_.context_type, DisallowedFeatures())); @@ -2285,6 +2287,7 @@ void GLES2DecoderPassthroughTestBase::SetUp() { shared_memory_address_ = reinterpret_cast(buffer->memory()) + shared_memory_offset_; shared_memory_base_ = buffer->memory(); + shared_memory_size_ = kSharedBufferSize - shared_memory_offset_; decoder_->MakeCurrent(); decoder_->BeginDecoding(); @@ -2302,6 +2305,25 @@ void GLES2DecoderPassthroughTestBase::TearDown() { gl::init::ShutdownGL(); } +void GLES2DecoderPassthroughTestBase::SetBucketData(uint32_t bucket_id, + const void* data, + size_t data_size) { + DCHECK(data || data_size == 0); + { + cmd::SetBucketSize cmd; + cmd.Init(bucket_id, static_cast(data_size)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + if (data) { + memcpy(shared_memory_address_, data, data_size); + cmd::SetBucketData cmd; + cmd.Init(bucket_id, 0, static_cast(data_size), shared_memory_id_, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + memset(shared_memory_address_, 0, data_size); + } +} + GLint GLES2DecoderPassthroughTestBase::GetGLError() { cmds::GetError cmd; cmd.Init(shared_memory_id_, shared_memory_offset_); @@ -2309,6 +2331,22 @@ GLint GLES2DecoderPassthroughTestBase::GetGLError() { return static_cast(*GetSharedMemoryAs()); } +void GLES2DecoderPassthroughTestBase::InjectGLError(GLenum error) { + decoder_->InjectDriverError(error); +} + +void GLES2DecoderPassthroughTestBase::DoRequestExtension( + const char* extension) { + DCHECK(extension != nullptr); + + uint32_t bucket_id = 0; + SetBucketData(bucket_id, extension, strlen(extension) + 1); + + cmds::RequestExtensionCHROMIUM cmd; + cmd.Init(bucket_id); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + void GLES2DecoderPassthroughTestBase::DoBindBuffer(GLenum target, GLuint client_id) { cmds::BindBuffer cmd; @@ -2347,6 +2385,65 @@ void GLES2DecoderPassthroughTestBase::DoBufferSubData(GLenum target, EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); } +void GLES2DecoderPassthroughTestBase::DoBindTexture(GLenum target, + GLuint client_id) { + cmds::BindTexture cmd; + cmd.Init(target, client_id); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +void GLES2DecoderPassthroughTestBase::DoTexImage2D( + GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLint border, + GLenum format, + GLenum type, + uint32_t shared_memory_id, + uint32_t shared_memory_offset) { + cmds::TexImage2D cmd; + cmd.Init(target, level, internal_format, width, height, format, type, + shared_memory_id, shared_memory_offset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +void GLES2DecoderPassthroughTestBase::DoBindFramebuffer(GLenum target, + GLuint client_id) { + cmds::BindFramebuffer cmd; + cmd.Init(target, client_id); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +void GLES2DecoderPassthroughTestBase::DoFramebufferTexture2D( + GLenum target, + GLenum attachment, + GLenum textarget, + GLuint texture_client_id, + GLint level) { + cmds::FramebufferTexture2D cmd; + cmd.Init(target, attachment, textarget, texture_client_id, level); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +void GLES2DecoderPassthroughTestBase::DoFramebufferRenderbuffer( + GLenum target, + GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer) { + cmds::FramebufferRenderbuffer cmd; + cmd.Init(target, attachment, renderbuffertarget, renderbuffer); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +void GLES2DecoderPassthroughTestBase::DoBindRenderbuffer(GLenum target, + GLuint client_id) { + cmds::BindRenderbuffer cmd; + cmd.Init(target, client_id); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + // GCC requires these declarations, but MSVC requires they not be present #ifndef COMPILER_MSVC const size_t GLES2DecoderPassthroughTestBase::kSharedBufferSize; @@ -2356,6 +2453,9 @@ const int32_t GLES2DecoderPassthroughTestBase::kInvalidSharedMemoryId; const uint32_t GLES2DecoderPassthroughTestBase::kNewClientId; const GLuint GLES2DecoderPassthroughTestBase::kClientBufferId; +const GLuint GLES2DecoderPassthroughTestBase::kClientTextureId; +const GLuint GLES2DecoderPassthroughTestBase::kClientFramebufferId; +const GLuint GLES2DecoderPassthroughTestBase::kClientRenderbufferId; #endif } // namespace gles2 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 adcef8523f6..ff7f6cf6092 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 @@ -23,6 +23,7 @@ #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h" #include "gpu/command_buffer/service/gpu_preferences.h" +#include "gpu/command_buffer/service/gpu_tracer.h" #include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager_impl.h" #include "gpu/command_buffer/service/program_manager.h" @@ -668,6 +669,7 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam, scoped_refptr surface_; scoped_refptr context_; std::unique_ptr command_buffer_service_; + TraceOutputter outputter_; std::unique_ptr mock_decoder_; std::unique_ptr decoder_; MemoryTracker* memory_tracker_; @@ -859,24 +861,54 @@ class GLES2DecoderPassthroughTestBase : public testing::Test, &entries_processed); } + void SetBucketData(uint32_t bucket_id, const void* data, size_t data_size); + template T GetSharedMemoryAs() { return reinterpret_cast(shared_memory_address_); } + template + T GetSharedMemoryAsWithSize(size_t* out_shmem_size) { + *out_shmem_size = shared_memory_size_; + return reinterpret_cast(shared_memory_address_); + } + template T GetSharedMemoryAsWithOffset(uint32_t offset) { void* ptr = reinterpret_cast(shared_memory_address_) + offset; return reinterpret_cast(ptr); } + template + T GetSharedMemoryAsWithOffsetAndSize(uint32_t offset, + size_t* out_shmem_size) { + EXPECT_LT(offset, shared_memory_size_); + *out_shmem_size = shared_memory_size_ - offset; + void* ptr = reinterpret_cast(shared_memory_address_) + offset; + return reinterpret_cast(ptr); + } + + template + T* GetImmediateAs() { + return reinterpret_cast(immediate_buffer_); + } + + GLES2DecoderPassthroughImpl* GetDecoder() const { return decoder_.get(); } PassthroughResources* GetPassthroughResources() const { return group_->passthrough_resources(); } + const base::circular_deque& + GetPendingReadPixels() const { + return decoder_->pending_read_pixels_; + } GLint GetGLError(); + void InjectGLError(GLenum error); protected: + void DoRequestExtension(const char* extension); + void DoBindBuffer(GLenum target, GLuint client_id); void DoDeleteBuffer(GLuint client_id); void DoBufferData(GLenum target, @@ -888,6 +920,31 @@ class GLES2DecoderPassthroughTestBase : public testing::Test, GLsizeiptr size, const void* data); + void DoBindTexture(GLenum target, GLuint client_id); + void DoTexImage2D(GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLint border, + GLenum format, + GLenum type, + uint32_t shared_memory_id, + uint32_t shared_memory_offset); + + void DoBindFramebuffer(GLenum target, GLuint client_id); + void DoFramebufferTexture2D(GLenum target, + GLenum attachment, + GLenum textarget, + GLuint texture_client_id, + GLint level); + void DoFramebufferRenderbuffer(GLenum target, + GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer); + + void DoBindRenderbuffer(GLenum target, GLuint client_id); + static const size_t kSharedBufferSize = 2048; static const uint32_t kSharedMemoryOffset = 132; static const uint32_t kInvalidSharedMemoryOffset = kSharedBufferSize + 1; @@ -896,11 +953,17 @@ class GLES2DecoderPassthroughTestBase : public testing::Test, static const uint32_t kNewClientId = 501; static const GLuint kClientBufferId = 100; + static const GLuint kClientTextureId = 101; + static const GLuint kClientFramebufferId = 102; + static const GLuint kClientRenderbufferId = 103; int32_t shared_memory_id_; uint32_t shared_memory_offset_; void* shared_memory_address_; void* shared_memory_base_; + size_t shared_memory_size_; + + uint32_t immediate_buffer_[64]; private: ContextCreationAttribHelper context_creation_attribs_; @@ -914,6 +977,7 @@ class GLES2DecoderPassthroughTestBase : public testing::Test, scoped_refptr surface_; scoped_refptr context_; std::unique_ptr command_buffer_service_; + TraceOutputter outputter_; std::unique_ptr decoder_; scoped_refptr group_; }; 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 7524122ad36..99289d7a411 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 @@ -4041,8 +4041,10 @@ TEST_P(GLES2DecoderManualInitTest, TexImage2DFloatOnGLES3) { init.gl_version = "opengl es 3.0"; InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 17, 0, GL_RGBA, GL_FLOAT, 0, 0); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 17, 0, GL_RGB, GL_FLOAT, 0, 0); + DoTexImage2DConvertInternalFormat(GL_TEXTURE_2D, 0, GL_RGBA, 16, 17, 0, + GL_RGBA, GL_FLOAT, 0, 0, GL_RGBA32F); + DoTexImage2DConvertInternalFormat(GL_TEXTURE_2D, 0, GL_RGB, 16, 17, 0, GL_RGB, + GL_FLOAT, 0, 0, GL_RGB32F); DoTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 17, 0, GL_RGBA, GL_FLOAT, 0, 0); DoTexImage2D( 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 c5b581a826a..94e56da1f65 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 @@ -1211,6 +1211,7 @@ static const GLenum GL_RGB_YCRCB_420_CHROMIUM, GL_RGB_YCBCR_422_CHROMIUM, GL_RGB_YCBCR_420V_CHROMIUM, + GL_R16_EXT, }; bool Validators::TextureSrgbDecodeExtValidator::IsValid( diff --git a/chromium/gpu/command_buffer/service/gpu_preferences.h b/chromium/gpu/command_buffer/service/gpu_preferences.h index 8dd0ff114ea..b37c2cc70ec 100644 --- a/chromium/gpu/command_buffer/service/gpu_preferences.h +++ b/chromium/gpu/command_buffer/service/gpu_preferences.h @@ -141,9 +141,6 @@ struct GPU_EXPORT GpuPreferences { // Turns on calling TRACE for every GL call. bool enable_gpu_service_tracing = false; - // Enable OpenGL ES 3 APIs. - bool enable_es3_apis = true; - // Use the Pass-through command decoder, skipping all validation and state // tracking. bool use_passthrough_cmd_decoder = false; diff --git a/chromium/gpu/command_buffer/service/gpu_switches.cc b/chromium/gpu/command_buffer/service/gpu_switches.cc index 50ff573a5cf..21f51cb1d4b 100644 --- a/chromium/gpu/command_buffer/service/gpu_switches.cc +++ b/chromium/gpu/command_buffer/service/gpu_switches.cc @@ -62,4 +62,8 @@ const char kGLShaderIntermOutput[] = "gl-shader-interm-output"; // round intermediate values in ANGLE. const char kEmulateShaderPrecision[] = "emulate-shader-precision"; +// Use the Pass-through command decoder, skipping all validation and state +// tracking. +const char kUsePassthroughCmdDecoder[] = "use-passthrough-cmd-decoder"; + } // namespace switches diff --git a/chromium/gpu/command_buffer/service/gpu_switches.h b/chromium/gpu/command_buffer/service/gpu_switches.h index f1a75801430..ef27cc7b4a2 100644 --- a/chromium/gpu/command_buffer/service/gpu_switches.h +++ b/chromium/gpu/command_buffer/service/gpu_switches.h @@ -28,6 +28,7 @@ GPU_EXPORT extern const char kDisableGpuShaderDiskCache[]; GPU_EXPORT extern const char kEnableThreadedTextureMailboxes[]; GPU_EXPORT extern const char kGLShaderIntermOutput[]; GPU_EXPORT extern const char kEmulateShaderPrecision[]; +GPU_EXPORT extern const char kUsePassthroughCmdDecoder[]; } // namespace switches diff --git a/chromium/gpu/command_buffer/service/gpu_tracer.cc b/chromium/gpu/command_buffer/service/gpu_tracer.cc index 960dcdf65b3..e3f8f631e60 100644 --- a/chromium/gpu/command_buffer/service/gpu_tracer.cc +++ b/chromium/gpu/command_buffer/service/gpu_tracer.cc @@ -7,8 +7,6 @@ #include #include -#include - #include "base/bind.h" #include "base/location.h" #include "base/single_thread_task_runner.h" @@ -35,8 +33,6 @@ constexpr const char* kGpuTraceSourceNames[] = { static_assert(NUM_TRACER_SOURCES == arraysize(kGpuTraceSourceNames), "Trace source names must match enumeration."); -static TraceOutputter* g_outputter_thread = NULL; - TraceMarker::TraceMarker(const std::string& category, const std::string& name) : category_(category), name_(name), @@ -45,23 +41,16 @@ TraceMarker::TraceMarker(const std::string& category, const std::string& name) TraceMarker::TraceMarker(const TraceMarker& other) = default; -TraceMarker::~TraceMarker() { -} +TraceMarker::~TraceMarker() {} -scoped_refptr TraceOutputter::Create(const std::string& name) { - if (!g_outputter_thread) { - g_outputter_thread = new TraceOutputter(name); - } - return g_outputter_thread; -} +TraceOutputter::TraceOutputter() : named_thread_("Dummy Trace") {} -TraceOutputter::TraceOutputter(const std::string& name) - : named_thread_(name.c_str()) { +TraceOutputter::TraceOutputter(const std::string& name) : named_thread_(name) { named_thread_.Start(); named_thread_.Stop(); } -TraceOutputter::~TraceOutputter() { g_outputter_thread = NULL; } +TraceOutputter::~TraceOutputter() {} void TraceOutputter::TraceDevice(GpuTracerSource source, const std::string& category, @@ -124,7 +113,7 @@ void TraceOutputter::TraceServiceEnd(GpuTracerSource source, "channel", kGpuTraceSourceNames[source]); } -GPUTrace::GPUTrace(scoped_refptr outputter, +GPUTrace::GPUTrace(Outputter* outputter, gl::GPUTimingClient* gpu_timing_client, const GpuTracerSource source, const std::string& category, @@ -141,8 +130,7 @@ GPUTrace::GPUTrace(scoped_refptr outputter, gpu_timer_ = gpu_timing_client->CreateGPUTimer(false); } -GPUTrace::~GPUTrace() { -} +GPUTrace::~GPUTrace() {} void GPUTrace::Destroy(bool have_context) { if (gpu_timer_.get()) { @@ -183,7 +171,7 @@ void GPUTrace::Process() { } } -GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) +GPUTracer::GPUTracer(GLES2Decoder* decoder) : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( TRACE_DISABLED_BY_DEFAULT("gpu.service"))), gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( @@ -191,17 +179,16 @@ GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) decoder_(decoder) { DCHECK(decoder_); gl::GLContext* context = decoder_->GetGLContext(); - if (context) { + if (context) gpu_timing_client_ = context->CreateGPUTimingClient(); - } else { + else gpu_timing_client_ = new gl::GPUTimingClient(); - } + outputter_ = decoder_->outputter(); disjoint_time_ = gpu_timing_client_->GetCurrentCPUTime(); } -GPUTracer::~GPUTracer() { -} +GPUTracer::~GPUTracer() {} void GPUTracer::Destroy(bool have_context) { ClearOngoingTraces(have_context); @@ -213,10 +200,6 @@ bool GPUTracer::BeginDecoding() { gpu_executing_ = true; if (IsTracing()) { - if (!outputter_) { - outputter_ = CreateOutputter(gpu_timing_client_->GetTimerTypeName()); - } - CheckDisjointStatus(); // Begin a Trace for all active markers for (int n = 0; n < NUM_TRACER_SOURCES; n++) { @@ -271,10 +254,6 @@ bool GPUTracer::Begin(const std::string& category, const std::string& name, // Push new marker from given 'source' markers_[source].push_back(TraceMarker(category, name)); - if (!outputter_) { - outputter_ = CreateOutputter(gpu_timing_client_->GetTimerTypeName()); - } - // Create trace if (IsTracing()) { began_device_traces_ |= (*gpu_trace_dev_category != 0); @@ -380,10 +359,6 @@ const std::string& GPUTracer::CurrentName(GpuTracerSource source) const { return base::EmptyString(); } -scoped_refptr GPUTracer::CreateOutputter(const std::string& name) { - return TraceOutputter::Create(name); -} - bool GPUTracer::CheckDisjointStatus() { const int64_t current_time = gpu_timing_client_->GetCurrentCPUTime(); if (*gpu_trace_dev_category == 0) diff --git a/chromium/gpu/command_buffer/service/gpu_tracer.h b/chromium/gpu/command_buffer/service/gpu_tracer.h index 746ebd08f7e..654c64c88ee 100644 --- a/chromium/gpu/command_buffer/service/gpu_tracer.h +++ b/chromium/gpu/command_buffer/service/gpu_tracer.h @@ -8,12 +8,12 @@ #include -#include #include -#include #include #include +#include "base/containers/circular_deque.h" +#include "base/containers/stack.h" #include "base/macros.h" #include "base/threading/thread.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" @@ -55,7 +55,7 @@ struct TraceMarker { // Traces GPU Commands. class GPU_EXPORT GPUTracer { public: - explicit GPUTracer(gles2::GLES2Decoder* decoder); + explicit GPUTracer(GLES2Decoder* decoder); virtual ~GPUTracer(); void Destroy(bool have_context); @@ -84,31 +84,29 @@ class GPU_EXPORT GPUTracer { const std::string& CurrentName(GpuTracerSource source) const; protected: - // Trace Processing. - virtual scoped_refptr CreateOutputter(const std::string& name); + scoped_refptr gpu_timing_client_; + const unsigned char* gpu_trace_srv_category; + const unsigned char* gpu_trace_dev_category; + private: bool CheckDisjointStatus(); void ClearOngoingTraces(bool have_context); - scoped_refptr gpu_timing_client_; - scoped_refptr outputter_; + Outputter* outputter_ = nullptr; std::vector markers_[NUM_TRACER_SOURCES]; - std::deque > finished_traces_; - - const unsigned char* gpu_trace_srv_category; - const unsigned char* gpu_trace_dev_category; - gles2::GLES2Decoder* decoder_; + base::circular_deque> finished_traces_; + GLES2Decoder* decoder_; int64_t disjoint_time_ = 0; - bool gpu_executing_ = false; bool began_device_traces_ = false; - private: DISALLOW_COPY_AND_ASSIGN(GPUTracer); }; -class Outputter : public base::RefCounted { +class GPU_EXPORT Outputter { public: + virtual ~Outputter() {} + virtual void TraceDevice(GpuTracerSource source, const std::string& category, const std::string& name, @@ -122,15 +120,14 @@ class Outputter : public base::RefCounted { virtual void TraceServiceEnd(GpuTracerSource source, const std::string& category, const std::string& name) = 0; - - protected: - virtual ~Outputter() {} - friend class base::RefCounted; }; -class TraceOutputter : public Outputter { +class GPU_EXPORT TraceOutputter : public Outputter { public: - static scoped_refptr Create(const std::string& name); + TraceOutputter(); + explicit TraceOutputter(const std::string& name); + ~TraceOutputter() override; + void TraceDevice(GpuTracerSource source, const std::string& category, const std::string& name, @@ -145,25 +142,20 @@ class TraceOutputter : public Outputter { const std::string& category, const std::string& name) override; - protected: - friend class base::RefCounted; - explicit TraceOutputter(const std::string& name); - ~TraceOutputter() override; - + private: base::Thread named_thread_; uint64_t local_trace_device_id_ = 0; uint64_t local_trace_service_id_ = 0; - std::stack trace_service_id_stack_[NUM_TRACER_SOURCES]; + base::stack trace_service_id_stack_[NUM_TRACER_SOURCES]; - private: DISALLOW_COPY_AND_ASSIGN(TraceOutputter); }; class GPU_EXPORT GPUTrace : public base::RefCounted { public: - GPUTrace(scoped_refptr outputter, + GPUTrace(Outputter* outputter, gl::GPUTimingClient* gpu_timing_client, const GpuTracerSource source, const std::string& category, @@ -190,7 +182,7 @@ class GPU_EXPORT GPUTrace const GpuTracerSource source_ = kTraceGroupInvalid; const std::string category_; const std::string name_; - scoped_refptr outputter_; + Outputter* outputter_ = nullptr; std::unique_ptr 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 ac2ab7b5101..1b00d6c7597 100644 --- a/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc +++ b/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc @@ -5,6 +5,7 @@ #include #include "base/bind.h" +#include "base/memory/ptr_util.h" #include "gpu/command_buffer/client/client_test_helper.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/gpu_service_test.h" @@ -33,28 +34,25 @@ int64_t FakeCpuTime() { class MockOutputter : public Outputter { public: MockOutputter() {} + ~MockOutputter() override {} + MOCK_METHOD5(TraceDevice, void(GpuTracerSource source, const std::string& category, const std::string& name, int64_t start_time, int64_t end_time)); - MOCK_METHOD3(TraceServiceBegin, void(GpuTracerSource source, const std::string& category, const std::string& name)); - MOCK_METHOD3(TraceServiceEnd, void(GpuTracerSource source, const std::string& category, const std::string& name)); - - protected: - ~MockOutputter() {} }; class GPUTracerTester : public GPUTracer { public: - explicit GPUTracerTester(gles2::GLES2Decoder* decoder) + explicit GPUTracerTester(GLES2Decoder* decoder) : GPUTracer(decoder), tracing_enabled_(0) { gpu_timing_client_->SetCpuTimeForTesting(base::Bind(&FakeCpuTime)); @@ -69,20 +67,8 @@ class GPUTracerTester : public GPUTracer { tracing_enabled_ = enabled ? 1 : 0; } - void SetOutputter(scoped_refptr outputter) { - set_outputter_ = outputter; - } - - protected: - scoped_refptr CreateOutputter(const std::string& name) override { - if (set_outputter_.get()) { - return set_outputter_; - } - return new MockOutputter(); - } - + private: unsigned char tracing_enabled_; - scoped_refptr set_outputter_; }; class BaseGpuTest : public GpuServiceTest { @@ -117,14 +103,10 @@ class BaseGpuTest : public GpuServiceTest { gpu_timing_client_ = GetGLContext()->CreateGPUTimingClient(); gpu_timing_client_->SetCpuTimeForTesting(base::Bind(&FakeCpuTime)); gl_fake_queries_.Reset(); - - outputter_ref_ = new MockOutputter(); } void TearDown() override { - outputter_ref_ = NULL; gpu_timing_client_ = NULL; - gl_fake_queries_.Reset(); GpuServiceTest::TearDown(); } @@ -216,7 +198,7 @@ class BaseGpuTest : public GpuServiceTest { gl::GPUTimingFake gl_fake_queries_; scoped_refptr gpu_timing_client_; - scoped_refptr outputter_ref_; + MockOutputter outputter_; }; // Test GPUTrace calls all the correct gl calls. @@ -239,7 +221,7 @@ class BaseGpuTraceTest : public BaseGpuTest { const int64_t expect_end_time = (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time; - ExpectOutputterMocks(outputter_ref_.get(), tracing_service, tracing_device, + ExpectOutputterMocks(&outputter_, tracing_service, tracing_device, tracer_source, category_name, trace_name, expect_start_time, expect_end_time); @@ -247,8 +229,8 @@ class BaseGpuTraceTest : public BaseGpuTest { ExpectTraceQueryMocks(); scoped_refptr trace = new GPUTrace( - outputter_ref_, gpu_timing_client_.get(), tracer_source, - category_name, trace_name, tracing_service, tracing_device); + &outputter_, gpu_timing_client_.get(), tracer_source, category_name, + trace_name, tracing_service, tracing_device); gl_fake_queries_.SetCurrentGLTime(start_timestamp); g_fakeCPUTime = expect_start_time; @@ -279,8 +261,6 @@ class BaseGpuTraceTest : public BaseGpuTest { // Destroy trace after we are done. trace->Destroy(true); - - outputter_ref_ = NULL; } }; @@ -337,17 +317,14 @@ class BaseGpuTracerTest : public BaseGpuTest { ExpectTracerOffsetQueryMocks(); FakeCommandBufferServiceBase command_buffer_service; - MockGLES2Decoder decoder(&command_buffer_service); + MockOutputter outputter; + MockGLES2Decoder decoder(&command_buffer_service, &outputter); EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext())); GPUTracerTester tracer(&decoder); tracer.SetTracingEnabled(true); - tracer.SetOutputter(outputter_ref_); - ASSERT_TRUE(tracer.BeginDecoding()); ASSERT_TRUE(tracer.EndDecoding()); - - outputter_ref_ = NULL; } void DoDisabledTracingTest() { @@ -356,11 +333,11 @@ class BaseGpuTracerTest : public BaseGpuTest { const GpuTracerSource source = static_cast(0); FakeCommandBufferServiceBase command_buffer_service; - MockGLES2Decoder decoder(&command_buffer_service); + MockOutputter outputter; + MockGLES2Decoder decoder(&command_buffer_service, &outputter); EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext())); GPUTracerTester tracer(&decoder); tracer.SetTracingEnabled(false); - tracer.SetOutputter(outputter_ref_); ASSERT_TRUE(tracer.BeginDecoding()); ASSERT_TRUE(tracer.Begin("disabled_category", "disabled_name", source)); @@ -384,13 +361,12 @@ class BaseGpuTracerTest : public BaseGpuTest { (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time; FakeCommandBufferServiceBase command_buffer_service; - MockGLES2Decoder decoder(&command_buffer_service); + MockOutputter outputter; + MockGLES2Decoder decoder(&command_buffer_service, &outputter); EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext())); GPUTracerTester tracer(&decoder); tracer.SetTracingEnabled(true); - tracer.SetOutputter(outputter_ref_); - gl_fake_queries_.SetCurrentGLTime(start_timestamp); g_fakeCPUTime = expect_start_time; @@ -412,8 +388,8 @@ class BaseGpuTracerTest : public BaseGpuTest { std::string source_trace_name = trace_name + num_char; const GpuTracerSource source = static_cast(i); - ExpectOutputterBeginMocks(outputter_ref_.get(), source, - source_category, source_trace_name); + ExpectOutputterBeginMocks(&outputter, source, source_category, + source_trace_name); ASSERT_TRUE(tracer.Begin(source_category, source_trace_name, source)); } for (int i = 0; i < NUM_TRACER_SOURCES; ++i) { @@ -430,7 +406,7 @@ class BaseGpuTracerTest : public BaseGpuTest { const bool valid_timer = gpu_timing_client_->IsAvailable(); const GpuTracerSource source = static_cast(i); - ExpectOutputterEndMocks(outputter_ref_.get(), source, source_category, + ExpectOutputterEndMocks(&outputter, source, source_category, source_trace_name, expect_start_time + i, expect_end_time + i, true, valid_timer); // Check if the current category/name are correct for this source. @@ -441,7 +417,6 @@ class BaseGpuTracerTest : public BaseGpuTest { } ASSERT_TRUE(tracer.EndDecoding()); tracer.ProcessTraces(); - outputter_ref_ = NULL; } void DoOngoingTracerMarkerTest() { @@ -459,10 +434,10 @@ class BaseGpuTracerTest : public BaseGpuTest { const bool valid_timer = gpu_timing_client_->IsAvailable(); FakeCommandBufferServiceBase command_buffer_service; - MockGLES2Decoder decoder(&command_buffer_service); + MockOutputter outputter; + MockGLES2Decoder decoder(&command_buffer_service, &outputter); EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext())); GPUTracerTester tracer(&decoder); - tracer.SetOutputter(outputter_ref_); // Create trace marker while traces are disabled. gl_fake_queries_.SetCurrentGLTime(start_timestamp); @@ -485,9 +460,9 @@ class BaseGpuTracerTest : public BaseGpuTest { ASSERT_TRUE(tracer.BeginDecoding()); // End decoding at time start+2. - ExpectOutputterEndMocks(outputter_ref_.get(), source, category_name, - trace_name, expect_start_time + 1, - expect_start_time + 2, true, valid_timer); + ExpectOutputterEndMocks(&outputter, source, category_name, trace_name, + expect_start_time + 1, expect_start_time + 2, true, + valid_timer); gl_fake_queries_.SetCurrentGLTime( start_timestamp + (2 * base::Time::kNanosecondsPerMicrosecond)); @@ -506,9 +481,9 @@ class BaseGpuTracerTest : public BaseGpuTest { start_timestamp + (4 * base::Time::kNanosecondsPerMicrosecond)); g_fakeCPUTime = expect_start_time + 4; - ExpectOutputterEndMocks(outputter_ref_.get(), source, category_name, - trace_name, expect_start_time + 3, - expect_start_time + 4, true, valid_timer); + ExpectOutputterEndMocks(&outputter, source, category_name, trace_name, + expect_start_time + 3, expect_start_time + 4, true, + valid_timer); ASSERT_TRUE(tracer.End(source)); // Increment time before we end decoding to test trace does not stop here. @@ -538,13 +513,12 @@ class BaseGpuTracerTest : public BaseGpuTest { (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time; FakeCommandBufferServiceBase command_buffer_service; - MockGLES2Decoder decoder(&command_buffer_service); + MockOutputter outputter; + MockGLES2Decoder decoder(&command_buffer_service, &outputter); EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext())); GPUTracerTester tracer(&decoder); tracer.SetTracingEnabled(true); - tracer.SetOutputter(outputter_ref_); - gl_fake_queries_.SetCurrentGLTime(start_timestamp); g_fakeCPUTime = expect_start_time; @@ -552,8 +526,7 @@ class BaseGpuTracerTest : public BaseGpuTest { ExpectTraceQueryMocks(); - ExpectOutputterBeginMocks(outputter_ref_.get(), source, - category_name, trace_name); + ExpectOutputterBeginMocks(&outputter, source, category_name, trace_name); ASSERT_TRUE(tracer.Begin(category_name, trace_name, source)); gl_fake_queries_.SetCurrentGLTime(end_timestamp); @@ -570,18 +543,14 @@ class BaseGpuTracerTest : public BaseGpuTest { gl_fake_queries_.SetDisjoint(); ASSERT_TRUE(disjoint_client->CheckAndResetTimerErrors()); - ExpectDisjointOutputMocks(outputter_ref_.get(), - expect_start_time, expect_end_time); + ExpectDisjointOutputMocks(&outputter, expect_start_time, expect_end_time); - ExpectOutputterEndMocks(outputter_ref_.get(), source, - category_name, trace_name, + ExpectOutputterEndMocks(&outputter, source, category_name, trace_name, expect_start_time, expect_end_time, true, false); ASSERT_TRUE(tracer.End(source)); ASSERT_TRUE(tracer.EndDecoding()); tracer.ProcessTraces(); - - outputter_ref_ = NULL; } void DoOutsideDisjointTest() { @@ -601,11 +570,11 @@ class BaseGpuTracerTest : public BaseGpuTest { (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time; FakeCommandBufferServiceBase command_buffer_service; - MockGLES2Decoder decoder(&command_buffer_service); + MockOutputter outputter; + MockGLES2Decoder decoder(&command_buffer_service, &outputter); EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext())); EXPECT_CALL(decoder, MakeCurrent()).WillRepeatedly(Return(true)); GPUTracerTester tracer(&decoder); - tracer.SetOutputter(outputter_ref_); // Start a trace before tracing is enabled. tracer.SetTracingEnabled(false); @@ -619,21 +588,19 @@ class BaseGpuTracerTest : public BaseGpuTest { g_fakeCPUTime = expect_start_time; // Disjoints before we start tracing anything should not do anything. - ExpectNoDisjointOutputMocks(outputter_ref_.get()); + ExpectNoDisjointOutputMocks(&outputter); gl_fake_queries_.SetDisjoint(); ExpectTraceQueryMocks(); - ExpectOutputterBeginMocks(outputter_ref_.get(), source, - category_name, trace_name); + ExpectOutputterBeginMocks(&outputter, source, category_name, trace_name); ASSERT_TRUE(tracer.BeginDecoding()); // Set times so each source has a different time. gl_fake_queries_.SetCurrentGLTime(end_timestamp); g_fakeCPUTime = expect_end_time; - ExpectOutputterEndMocks(outputter_ref_.get(), source, category_name, - trace_name, expect_start_time, - expect_end_time, true, true); + ExpectOutputterEndMocks(&outputter, source, category_name, trace_name, + expect_start_time, expect_end_time, true, true); ASSERT_TRUE(tracer.End(source)); ASSERT_TRUE(tracer.EndDecoding()); @@ -740,7 +707,7 @@ class GPUTracerTest : public GpuServiceTest { void SetUp() override { g_fakeCPUTime = 0; GpuServiceTest::SetUpWithGLVersion("3.2", ""); - decoder_.reset(new MockGLES2Decoder(&command_buffer_service_)); + decoder_.reset(new MockGLES2Decoder(&command_buffer_service_, &outputter_)); EXPECT_CALL(*decoder_, GetGLContext()) .Times(AtMost(1)) .WillRepeatedly(Return(GetGLContext())); @@ -752,7 +719,9 @@ class GPUTracerTest : public GpuServiceTest { decoder_ = nullptr; GpuServiceTest::TearDown(); } + FakeCommandBufferServiceBase command_buffer_service_; + MockOutputter outputter_; std::unique_ptr decoder_; std::unique_ptr tracer_tester_; }; diff --git a/chromium/gpu/command_buffer/service/mailbox_manager_sync.cc b/chromium/gpu/command_buffer/service/mailbox_manager_sync.cc index d92d29f93ca..a515c57a191 100644 --- a/chromium/gpu/command_buffer/service/mailbox_manager_sync.cc +++ b/chromium/gpu/command_buffer/service/mailbox_manager_sync.cc @@ -7,8 +7,8 @@ #include #include -#include +#include "base/containers/queue.h" #include "base/memory/ptr_util.h" #include "base/synchronization/lock.h" #include "gpu/command_buffer/common/sync_token.h" @@ -32,7 +32,7 @@ base::LazyInstance::DestructorAtExit g_lock = typedef std::map> SyncTokenToFenceMap; base::LazyInstance::DestructorAtExit g_sync_point_to_fence = LAZY_INSTANCE_INITIALIZER; -base::LazyInstance>::DestructorAtExit +base::LazyInstance>::DestructorAtExit g_sync_points = LAZY_INSTANCE_INITIALIZER; #endif @@ -43,7 +43,7 @@ void CreateFenceLocked(const SyncToken& sync_token) { gl::GetGLImplementation() == gl::kGLImplementationStubGL) return; - std::queue& sync_points = g_sync_points.Get(); + base::queue& sync_points = g_sync_points.Get(); SyncTokenToFenceMap& sync_point_to_fence = g_sync_point_to_fence.Get(); if (sync_token.release_count()) { while (!sync_points.empty() && diff --git a/chromium/gpu/command_buffer/service/query_manager.h b/chromium/gpu/command_buffer/service/query_manager.h index e230b22df9e..ba0c34a68c9 100644 --- a/chromium/gpu/command_buffer/service/query_manager.h +++ b/chromium/gpu/command_buffer/service/query_manager.h @@ -7,11 +7,11 @@ #include -#include #include #include #include "base/atomicops.h" +#include "base/containers/circular_deque.h" #include "base/containers/hash_tables.h" #include "base/logging.h" #include "base/macros.h" @@ -298,18 +298,18 @@ class GPU_EXPORT QueryManager { unsigned query_count_; // Info for each query in the system. - typedef base::hash_map > QueryMap; + using QueryMap = base::hash_map>; QueryMap queries_; - typedef base::hash_set GeneratedQueryIds; + using GeneratedQueryIds = base::hash_set; GeneratedQueryIds generated_query_ids_; // A map of targets -> Query for current active queries. - typedef std::map > ActiveQueryMap; + using ActiveQueryMap = std::map>; ActiveQueryMap active_queries_; // Queries waiting for completion. - typedef std::deque > QueryQueue; + using QueryQueue = base::circular_deque>; QueryQueue pending_queries_; scoped_refptr gpu_timing_client_; diff --git a/chromium/gpu/command_buffer/service/query_manager_unittest.cc b/chromium/gpu/command_buffer/service/query_manager_unittest.cc index 8c6f6ba801a..117528b4bb5 100644 --- a/chromium/gpu/command_buffer/service/query_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/query_manager_unittest.cc @@ -14,6 +14,7 @@ #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/gpu_service_test.h" +#include "gpu/command_buffer/service/gpu_tracer.h" #include "gpu/command_buffer/service/query_manager.h" #include "gpu/command_buffer/service/test_helper.h" #include "testing/gtest/include/gtest/gtest.h" @@ -69,7 +70,8 @@ class QueryManagerTest : public GpuServiceTest { buffer = command_buffer_service_->CreateTransferBufferHelper( kSharedBufferSize, &shared_memory2_id_); memset(buffer->memory(), kInitialMemoryValue, kSharedBufferSize); - decoder_.reset(new MockGLES2Decoder(command_buffer_service_.get())); + decoder_.reset( + new MockGLES2Decoder(command_buffer_service_.get(), &outputter_)); TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), extension_expectations); EXPECT_CALL(*decoder_.get(), GetGLContext()) @@ -122,6 +124,7 @@ class QueryManagerTest : public GpuServiceTest { manager_->EndQuery(query, submit_count); } + TraceOutputter outputter_; std::unique_ptr command_buffer_service_; std::unique_ptr decoder_; std::unique_ptr manager_; diff --git a/chromium/gpu/command_buffer/service/sampler_manager.cc b/chromium/gpu/command_buffer/service/sampler_manager.cc index 9b8ec3c4b65..1f9ca3e01b5 100644 --- a/chromium/gpu/command_buffer/service/sampler_manager.cc +++ b/chromium/gpu/command_buffer/service/sampler_manager.cc @@ -112,7 +112,7 @@ GLenum Sampler::SetParameterf( case GL_TEXTURE_WRAP_T: case GL_TEXTURE_COMPARE_FUNC: case GL_TEXTURE_COMPARE_MODE: { - GLint iparam = static_cast(param); + GLint iparam = static_cast(std::round(param)); return SetParameteri(feature_info, pname, iparam); } case GL_TEXTURE_MIN_LOD: diff --git a/chromium/gpu/command_buffer/service/scheduler.cc b/chromium/gpu/command_buffer/service/scheduler.cc index f240ab9a54e..91f813cb6bf 100644 --- a/chromium/gpu/command_buffer/service/scheduler.cc +++ b/chromium/gpu/command_buffer/service/scheduler.cc @@ -7,6 +7,8 @@ #include #include "base/callback.h" +#include "base/containers/circular_deque.h" +#include "base/containers/flat_set.h" #include "base/memory/ptr_util.h" #include "base/stl_util.h" #include "base/trace_event/trace_event.h" @@ -83,6 +85,10 @@ class Scheduler::Sequence { // Remove a release sync token fence. void RemoveReleaseFence(const SyncToken& sync_token, uint32_t order_num); + void AddClientWait(CommandBufferId command_buffer_id); + + void RemoveClientWait(CommandBufferId command_buffer_id); + private: enum RunningState { IDLE, SCHEDULED, RUNNING }; @@ -122,7 +128,7 @@ class Scheduler::Sequence { // Deque of tasks. Tasks are inserted at the back with increasing order number // generated from SyncPointOrderData. If a running task needs to be continued, // it is inserted at the front with the same order number. - std::deque tasks_; + base::circular_deque tasks_; // List of fences that this sequence is waiting on. Fences are inserted in // increasing order number but may be removed out of order. Tasks are blocked @@ -134,6 +140,8 @@ class Scheduler::Sequence { // non-empty, the priority of the sequence is raised. std::vector release_fences_; + base::flat_set client_waits_; + DISALLOW_COPY_AND_ASSIGN(Sequence); }; @@ -174,9 +182,10 @@ Scheduler::Sequence::~Sequence() { } SchedulingPriority Scheduler::Sequence::GetSchedulingPriority() const { - if (!release_fences_.empty()) - return std::min(priority_, SchedulingPriority::kHigh); - return priority_; + SchedulingPriority priority = priority_; + if (!release_fences_.empty() || !client_waits_.empty()) + priority = std::min(priority, SchedulingPriority::kHigh); + return priority; } bool Scheduler::Sequence::NeedsRescheduling() const { @@ -201,6 +210,13 @@ void Scheduler::Sequence::SetEnabled(bool enabled) { return; DCHECK_EQ(running_state_, enabled ? IDLE : RUNNING); enabled_ = enabled; + if (enabled) { + TRACE_EVENT_ASYNC_BEGIN1("gpu", "SequenceEnabled", this, "sequence_id", + sequence_id_.GetUnsafeValue()); + } else { + TRACE_EVENT_ASYNC_END1("gpu", "SequenceEnabled", this, "sequence_id", + sequence_id_.GetUnsafeValue()); + } } Scheduler::SchedulingState Scheduler::Sequence::SetScheduled() { @@ -273,6 +289,14 @@ void Scheduler::Sequence::RemoveReleaseFence(const SyncToken& sync_token, base::Erase(release_fences_, Fence{sync_token, order_num}); } +void Scheduler::Sequence::AddClientWait(CommandBufferId command_buffer_id) { + client_waits_.insert(command_buffer_id); +} + +void Scheduler::Sequence::RemoveClientWait(CommandBufferId command_buffer_id) { + client_waits_.erase(command_buffer_id); +} + Scheduler::Scheduler(scoped_refptr task_runner, SyncPointManager* sync_point_manager) : task_runner_(std::move(task_runner)), @@ -334,6 +358,26 @@ void Scheduler::DisableSequence(SequenceId sequence_id) { sequence->SetEnabled(false); } +void Scheduler::RaisePriorityForClientWait(SequenceId sequence_id, + CommandBufferId command_buffer_id) { + DCHECK(thread_checker_.CalledOnValidThread()); + base::AutoLock auto_lock(lock_); + Sequence* sequence = GetSequence(sequence_id); + DCHECK(sequence); + sequence->AddClientWait(command_buffer_id); + TryScheduleSequence(sequence); +} + +void Scheduler::ResetPriorityForClientWait(SequenceId sequence_id, + CommandBufferId command_buffer_id) { + DCHECK(thread_checker_.CalledOnValidThread()); + base::AutoLock auto_lock(lock_); + Sequence* sequence = GetSequence(sequence_id); + DCHECK(sequence); + sequence->RemoveClientWait(command_buffer_id); + TryScheduleSequence(sequence); +} + void Scheduler::ScheduleTask(Task task) { base::AutoLock auto_lock(lock_); ScheduleTaskHelper(std::move(task)); diff --git a/chromium/gpu/command_buffer/service/scheduler.h b/chromium/gpu/command_buffer/service/scheduler.h index 850107ac883..179df74ec2e 100644 --- a/chromium/gpu/command_buffer/service/scheduler.h +++ b/chromium/gpu/command_buffer/service/scheduler.h @@ -14,6 +14,7 @@ #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" +#include "gpu/command_buffer/common/command_buffer_id.h" #include "gpu/command_buffer/common/scheduling_priority.h" #include "gpu/command_buffer/common/sync_token.h" #include "gpu/command_buffer/service/sequence_id.h" @@ -63,6 +64,15 @@ class GPU_EXPORT Scheduler { // Disables the sequence. void DisableSequence(SequenceId sequence_id); + // Raise priority of sequence for client wait (WaitForGetOffset/TokenInRange) + // on given command buffer. + void RaisePriorityForClientWait(SequenceId sequence_id, + CommandBufferId command_buffer_id); + + // Reset priority of sequence if it was increased for a client wait. + void ResetPriorityForClientWait(SequenceId sequence_id, + CommandBufferId command_buffer_id); + // Schedules task (closure) to run on the sequence. The task is blocked until // the sync token fences are released or determined to be invalid. Tasks are // run in the order in which they are submitted. @@ -99,7 +109,7 @@ class GPU_EXPORT Scheduler { const; SequenceId sequence_id; - SchedulingPriority priority = SchedulingPriority::kLowest; + SchedulingPriority priority = SchedulingPriority::kLow; uint32_t order_num = 0; }; diff --git a/chromium/gpu/command_buffer/service/scheduler_unittest.cc b/chromium/gpu/command_buffer/service/scheduler_unittest.cc index 1037ab9fdce..9c0be7e2ac7 100644 --- a/chromium/gpu/command_buffer/service/scheduler_unittest.cc +++ b/chromium/gpu/command_buffer/service/scheduler_unittest.cc @@ -99,7 +99,7 @@ TEST_F(SchedulerTest, ContinuedTasksRunFirst) { TEST_F(SchedulerTest, SequencesRunInPriorityOrder) { SequenceId sequence_id1 = - scheduler()->CreateSequence(SchedulingPriority::kLowest); + scheduler()->CreateSequence(SchedulingPriority::kLow); bool ran1 = false; scheduler()->ScheduleTask(Scheduler::Task(sequence_id1, GetClosure([&] { ran1 = true; }), @@ -113,7 +113,7 @@ TEST_F(SchedulerTest, SequencesRunInPriorityOrder) { std::vector())); SequenceId sequence_id3 = - scheduler()->CreateSequence(SchedulingPriority::kHighest); + scheduler()->CreateSequence(SchedulingPriority::kHigh); bool ran3 = false; scheduler()->ScheduleTask(Scheduler::Task(sequence_id3, GetClosure([&] { ran3 = true; }), @@ -173,7 +173,7 @@ TEST_F(SchedulerTest, SequencesOfSamePriorityRunInOrder) { TEST_F(SchedulerTest, SequenceWaitsForFence) { SequenceId sequence_id1 = - scheduler()->CreateSequence(SchedulingPriority::kHighest); + scheduler()->CreateSequence(SchedulingPriority::kHigh); SequenceId sequence_id2 = scheduler()->CreateSequence(SchedulingPriority::kNormal); @@ -261,7 +261,7 @@ TEST_F(SchedulerTest, ReleaseSequenceIsPrioritized) { std::vector())); SequenceId sequence_id2 = - scheduler()->CreateSequence(SchedulingPriority::kLowest); + scheduler()->CreateSequence(SchedulingPriority::kLow); CommandBufferNamespace namespace_id = CommandBufferNamespace::GPU_IO; CommandBufferId command_buffer_id = CommandBufferId::FromUnsafeValue(1); scoped_refptr release_state = @@ -280,7 +280,7 @@ TEST_F(SchedulerTest, ReleaseSequenceIsPrioritized) { bool ran3 = false; SyncToken sync_token(namespace_id, 0, command_buffer_id, release); SequenceId sequence_id3 = - scheduler()->CreateSequence(SchedulingPriority::kHighest); + scheduler()->CreateSequence(SchedulingPriority::kHigh); scheduler()->ScheduleTask(Scheduler::Task( sequence_id3, GetClosure([&] { ran3 = true; }), {sync_token})); @@ -302,7 +302,7 @@ TEST_F(SchedulerTest, ReleaseSequenceIsPrioritized) { TEST_F(SchedulerTest, ReleaseSequenceShouldYield) { SequenceId sequence_id1 = - scheduler()->CreateSequence(SchedulingPriority::kLowest); + scheduler()->CreateSequence(SchedulingPriority::kLow); CommandBufferNamespace namespace_id = CommandBufferNamespace::GPU_IO; CommandBufferId command_buffer_id = CommandBufferId::FromUnsafeValue(1); scoped_refptr release_state = @@ -323,7 +323,7 @@ TEST_F(SchedulerTest, ReleaseSequenceShouldYield) { bool ran2 = false; SyncToken sync_token(namespace_id, 0, command_buffer_id, release); SequenceId sequence_id2 = - scheduler()->CreateSequence(SchedulingPriority::kHighest); + scheduler()->CreateSequence(SchedulingPriority::kHigh); scheduler()->ScheduleTask(Scheduler::Task( sequence_id2, GetClosure([&] { ran2 = true; }), {sync_token})); @@ -418,5 +418,69 @@ TEST_F(SchedulerTest, WaitOnSelfShouldNotBlockSequence) { release_state->Destroy(); } +TEST_F(SchedulerTest, ClientWaitIsPrioritized) { + SequenceId sequence_id1 = + scheduler()->CreateSequence(SchedulingPriority::kNormal); + + bool ran1 = false; + scheduler()->ScheduleTask(Scheduler::Task(sequence_id1, + GetClosure([&] { ran1 = true; }), + std::vector())); + + SequenceId sequence_id2 = + scheduler()->CreateSequence(SchedulingPriority::kLow); + CommandBufferId command_buffer_id = CommandBufferId::FromUnsafeValue(1); + bool ran2 = false; + scheduler()->ScheduleTask(Scheduler::Task(sequence_id2, + GetClosure([&] { ran2 = true; }), + std::vector())); + + bool ran3 = false; + SequenceId sequence_id3 = + scheduler()->CreateSequence(SchedulingPriority::kHigh); + scheduler()->ScheduleTask(Scheduler::Task(sequence_id3, + GetClosure([&] { ran3 = true; }), + std::vector())); + + scheduler()->RaisePriorityForClientWait(sequence_id2, command_buffer_id); + + task_runner()->RunPendingTasks(); + EXPECT_FALSE(ran1); + EXPECT_TRUE(ran2); + EXPECT_FALSE(ran3); + + task_runner()->RunPendingTasks(); + EXPECT_FALSE(ran1); + EXPECT_TRUE(ran3); + + task_runner()->RunPendingTasks(); + EXPECT_TRUE(ran1); + + ran1 = ran2 = ran3 = false; + scheduler()->ScheduleTask(Scheduler::Task(sequence_id1, + GetClosure([&] { ran1 = true; }), + std::vector())); + scheduler()->ScheduleTask(Scheduler::Task(sequence_id2, + GetClosure([&] { ran2 = true; }), + std::vector())); + scheduler()->ScheduleTask(Scheduler::Task(sequence_id3, + GetClosure([&] { ran3 = true; }), + std::vector())); + + scheduler()->ResetPriorityForClientWait(sequence_id2, command_buffer_id); + + task_runner()->RunPendingTasks(); + EXPECT_FALSE(ran1); + EXPECT_FALSE(ran2); + EXPECT_TRUE(ran3); + + task_runner()->RunPendingTasks(); + EXPECT_TRUE(ran1); + EXPECT_FALSE(ran2); + + task_runner()->RunPendingTasks(); + EXPECT_TRUE(ran2); +} + } // namespace } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/service_discardable_manager_unittest.cc b/chromium/gpu/command_buffer/service/service_discardable_manager_unittest.cc index 32131398662..fa759064c4d 100644 --- a/chromium/gpu/command_buffer/service/service_discardable_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/service_discardable_manager_unittest.cc @@ -7,6 +7,7 @@ #include "gpu/command_buffer/client/client_test_helper.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/gpu_service_test.h" +#include "gpu/command_buffer/service/gpu_tracer.h" #include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager_impl.h" #include "gpu/command_buffer/service/memory_tracking.h" @@ -67,7 +68,7 @@ class ServiceDiscardableManagerTest : public GpuServiceTest { protected: void SetUp() override { GpuServiceTest::SetUp(); - decoder_.reset(new MockGLES2Decoder(&command_buffer_service_)); + decoder_.reset(new MockGLES2Decoder(&command_buffer_service_, &outputter_)); feature_info_ = new FeatureInfo(); context_group_ = scoped_refptr(new ContextGroup( gpu_preferences_, false, &mailbox_manager_, nullptr, nullptr, nullptr, @@ -114,6 +115,7 @@ class ServiceDiscardableManagerTest : public GpuServiceTest { } MailboxManagerImpl mailbox_manager_; + TraceOutputter outputter_; ImageManager image_manager_; ServiceDiscardableManager discardable_manager_; GpuPreferences gpu_preferences_; diff --git a/chromium/gpu/command_buffer/service/service_utils.cc b/chromium/gpu/command_buffer/service/service_utils.cc index e8f2b6195ec..7e86f9f3c16 100644 --- a/chromium/gpu/command_buffer/service/service_utils.cc +++ b/chromium/gpu/command_buffer/service/service_utils.cc @@ -7,6 +7,7 @@ #include "base/command_line.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/gpu_switches.h" #include "ui/gl/gl_switches.h" #if defined(USE_EGL) @@ -31,6 +32,8 @@ gl::GLContextAttribs GenerateGLContextAttribs( // decoder attribs.global_texture_share_group = true; + attribs.robust_resource_initialization = true; + // Request a specific context version instead of always 3.0 if (IsWebGL2OrES3ContextType(attribs_helper.context_type)) { attribs.client_major_es_version = 3; @@ -55,6 +58,10 @@ gl::GLContextAttribs GenerateGLContextAttribs( return attribs; } +bool UsePassthroughCommandDecoder(const base::CommandLine* command_line) { + return command_line->HasSwitch(switches::kUsePassthroughCmdDecoder); +} + bool PassthroughCommandDecoderSupported() { #if defined(USE_EGL) // Using the passthrough command buffer requires that specific ANGLE diff --git a/chromium/gpu/command_buffer/service/service_utils.h b/chromium/gpu/command_buffer/service/service_utils.h index 5eae2d3b8b1..5817aced601 100644 --- a/chromium/gpu/command_buffer/service/service_utils.h +++ b/chromium/gpu/command_buffer/service/service_utils.h @@ -5,6 +5,7 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_SERVICE_UTILS_H_ #define GPU_COMMAND_BUFFER_SERVICE_SERVICE_UTILS_H_ +#include "base/command_line.h" #include "gpu/gpu_export.h" #include "ui/gl/gl_context.h" @@ -18,6 +19,10 @@ GPU_EXPORT gl::GLContextAttribs GenerateGLContextAttribs( const ContextCreationAttribHelper& attribs_helper, const ContextGroup* context_group); +// Returns true if the passthrough command decoder has been requested +GPU_EXPORT bool UsePassthroughCommandDecoder( + const base::CommandLine* command_line); + // Returns true if the driver supports creating passthrough command decoders GPU_EXPORT bool PassthroughCommandDecoderSupported(); diff --git a/chromium/gpu/command_buffer/service/shader_translator.cc b/chromium/gpu/command_buffer/service/shader_translator.cc index a22b67970d9..dda5586f334 100644 --- a/chromium/gpu/command_buffer/service/shader_translator.cc +++ b/chromium/gpu/command_buffer/service/shader_translator.cc @@ -169,10 +169,10 @@ bool ShaderTranslator::Init(GLenum shader_type, shader_output_language, resources); } - compile_options_ = - SH_OBJECT_CODE | SH_VARIABLES | SH_ENFORCE_PACKING_RESTRICTIONS | - SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH | - SH_CLAMP_INDIRECT_ARRAY_BOUNDS; + compile_options_ = SH_OBJECT_CODE | SH_VARIABLES | + SH_ENFORCE_PACKING_RESTRICTIONS | + SH_LIMIT_EXPRESSION_COMPLEXITY | + SH_LIMIT_CALL_STACK_DEPTH | SH_CLAMP_INDIRECT_ARRAY_BOUNDS; if (gl_shader_interm_output) compile_options_ |= SH_INTERMEDIATE_TREE; compile_options_ |= driver_bug_workarounds; diff --git a/chromium/gpu/command_buffer/service/shader_translator_unittest.cc b/chromium/gpu/command_buffer/service/shader_translator_unittest.cc index d548498259d..8962c633304 100644 --- a/chromium/gpu/command_buffer/service/shader_translator_unittest.cc +++ b/chromium/gpu/command_buffer/service/shader_translator_unittest.cc @@ -245,7 +245,8 @@ TEST_F(ShaderTranslatorTest, GetAttributes) { // There should be one attribute with following characteristics: // name:vPosition type:GL_FLOAT_VEC4 size:0. EXPECT_EQ(1u, attrib_map.size()); - AttributeMap::const_iterator iter = attrib_map.find("vPosition"); + // The shader translator adds a "_u" prefix to user-defined names. + AttributeMap::const_iterator iter = attrib_map.find("_uvPosition"); EXPECT_TRUE(iter != attrib_map.end()); EXPECT_EQ(static_cast(GL_FLOAT_VEC4), iter->second.type); EXPECT_EQ(0u, iter->second.arraySize); @@ -289,20 +290,21 @@ TEST_F(ShaderTranslatorTest, GetUniforms) { // 2. name:bar[1].foo.color[0] type:GL_FLOAT_VEC4 size:1 // However, there will be only one entry "bar" in the map. EXPECT_EQ(1u, uniform_map.size()); - UniformMap::const_iterator iter = uniform_map.find("bar"); + // The shader translator adds a "_u" prefix to user-defined names. + UniformMap::const_iterator iter = uniform_map.find("_ubar"); EXPECT_TRUE(iter != uniform_map.end()); // First uniform. const sh::ShaderVariable* info; std::string original_name; - EXPECT_TRUE(iter->second.findInfoByMappedName( - "bar[0].foo.color[0]", &info, &original_name)); + EXPECT_TRUE(iter->second.findInfoByMappedName("_ubar[0]._ufoo._ucolor[0]", + &info, &original_name)); EXPECT_EQ(static_cast(GL_FLOAT_VEC4), info->type); EXPECT_EQ(1u, info->arraySize); EXPECT_STREQ("color", info->name.c_str()); EXPECT_STREQ("bar[0].foo.color[0]", original_name.c_str()); // Second uniform. - EXPECT_TRUE(iter->second.findInfoByMappedName( - "bar[1].foo.color[0]", &info, &original_name)); + EXPECT_TRUE(iter->second.findInfoByMappedName("_ubar[1]._ufoo._ucolor[0]", + &info, &original_name)); EXPECT_EQ(static_cast(GL_FLOAT_VEC4), info->type); EXPECT_EQ(1u, info->arraySize); EXPECT_STREQ("color", info->name.c_str()); 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 48600b3ca65..9a1e1e0f4ec 100644 --- a/chromium/gpu/command_buffer/service/sync_point_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/sync_point_manager_unittest.cc @@ -5,9 +5,9 @@ #include #include -#include #include "base/bind.h" +#include "base/containers/queue.h" #include "base/memory/ptr_util.h" #include "gpu/command_buffer/service/sync_point_manager.h" #include "testing/gtest/include/gtest/gtest.h" @@ -29,7 +29,7 @@ class SyncPointManagerTest : public testing::Test { struct SyncPointStream { scoped_refptr order_data; scoped_refptr client_state; - std::queue order_numbers; + base::queue order_numbers; SyncPointStream(SyncPointManager* sync_point_manager, CommandBufferNamespace namespace_id, diff --git a/chromium/gpu/command_buffer/service/test_helper.cc b/chromium/gpu/command_buffer/service/test_helper.cc index 27686d752e8..b81ec7496cf 100644 --- a/chromium/gpu/command_buffer/service/test_helper.cc +++ b/chromium/gpu/command_buffer/service/test_helper.cc @@ -624,26 +624,9 @@ void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( } if (!enable_es3 && !gl::HasExtension(extension_set, "GL_EXT_color_buffer_half_float") && - (gl_info.is_es || gl_info.IsAtLeastGL(3, 0))) { - EXPECT_CALL( - *gl, - TexImage2D(GL_TEXTURE_2D, 0, GL_R16F, width, width, 0, GL_RED, _, _)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL( - *gl, - TexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, width, width, 0, GL_RG, _, _)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, - TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, width, 0, - GL_RGBA, _, _)) + (gl_info.IsAtLeastGLES(3, 0) || gl_info.IsAtLeastGL(3, 0))) { + EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, width, 0, + GL_RGBA, GL_HALF_FLOAT, nullptr)) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) @@ -1263,4 +1246,3 @@ sh::OutputVariable TestHelper::ConstructOutputVariable( } // namespace gles2 } // namespace gpu - diff --git a/chromium/gpu/command_buffer/service/texture_manager.cc b/chromium/gpu/command_buffer/service/texture_manager.cc index acd6afabe7d..9dafeeaed65 100644 --- a/chromium/gpu/command_buffer/service/texture_manager.cc +++ b/chromium/gpu/command_buffer/service/texture_manager.cc @@ -350,6 +350,11 @@ bool SizedFormatAvailable(const FeatureInfo* feature_info, if (immutable) return true; + if (feature_info->feature_flags().ext_texture_norm16 && + internal_format == GL_R16_EXT) { + return true; + } + if ((feature_info->feature_flags().chromium_image_ycbcr_420v && internal_format == GL_RGB_YCBCR_420V_CHROMIUM) || (feature_info->feature_flags().chromium_image_ycbcr_422 && diff --git a/chromium/gpu/command_buffer/service/texture_manager_unittest.cc b/chromium/gpu/command_buffer/service/texture_manager_unittest.cc index 92a2c7675c2..5847b1f76fb 100644 --- a/chromium/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/texture_manager_unittest.cc @@ -19,6 +19,7 @@ #include "gpu/command_buffer/service/gl_stream_texture_image.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/gpu_service_test.h" +#include "gpu/command_buffer/service/gpu_tracer.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/mocks.h" @@ -87,7 +88,7 @@ class TextureManagerTest : public GpuServiceTest { TestHelper::SetupTextureManagerInitExpectations( gl_.get(), false, false, false, {}, kUseDefaultTextures); manager_->Initialize(); - error_state_.reset(new ::testing::StrictMock()); + error_state_.reset(new ::testing::StrictMock()); } void TearDown() override { @@ -677,9 +678,9 @@ class TextureTestBase : public GpuServiceTest { kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kMaxArrayTextureLayers, kUseDefaultTextures, nullptr, &discardable_manager_)); - decoder_.reset(new ::testing::StrictMock( - &command_buffer_service_)); - error_state_.reset(new ::testing::StrictMock()); + decoder_.reset(new ::testing::StrictMock( + &command_buffer_service_, &outputter_)); + error_state_.reset(new ::testing::StrictMock()); manager_->CreateTexture(kClient1Id, kService1Id); texture_ref_ = manager_->GetTexture(kClient1Id); ASSERT_TRUE(texture_ref_.get() != NULL); @@ -711,6 +712,7 @@ class TextureTestBase : public GpuServiceTest { } FakeCommandBufferServiceBase command_buffer_service_; + TraceOutputter outputter_; std::unique_ptr decoder_; std::unique_ptr error_state_; scoped_refptr feature_info_; -- cgit v1.2.1