| // Copyright 2016 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // This file contains the GLES2DecoderPassthroughImpl class. | |
| #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_PASSTHROUGH_H_ | |
| #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_PASSTHROUGH_H_ | |
| #include <algorithm> | |
| #include <array> | |
| #include <memory> | |
| #include <optional> | |
| #include <vector> | |
| #include "base/cancelable_callback.h" | |
| #include "base/containers/circular_deque.h" | |
| #include "base/containers/flat_map.h" | |
| #include "base/containers/flat_set.h" | |
| #include "base/memory/raw_ptr.h" | |
| #include "base/memory/scoped_refptr.h" | |
| #include "base/time/time.h" | |
| #include "build/build_config.h" | |
| #include "gpu/command_buffer/common/debug_marker_manager.h" | |
| #include "gpu/command_buffer/common/discardable_handle.h" | |
| #include "gpu/command_buffer/common/gles2_cmd_format.h" | |
| #include "gpu/command_buffer/common/gles2_cmd_utils.h" | |
| #include "gpu/command_buffer/common/sync_token.h" | |
| #include "gpu/command_buffer/service/client_service_map.h" | |
| #include "gpu/command_buffer/service/context_group.h" | |
| #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | |
| #include "gpu/command_buffer/service/logger.h" | |
| #include "gpu/command_buffer/service/shared_context_state.h" | |
| #include "gpu/command_buffer/service/shared_image/shared_image_representation.h" | |
| #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_surface.h" | |
| #include "ui/gl/scoped_make_current.h" | |
| namespace gl { | |
| class GLFence; | |
| class ProgressReporter; | |
| } | |
| namespace gpu { | |
| class GLTexturePassthroughImageRepresentation; | |
| namespace gles2 { | |
| class ContextGroup; | |
| class GPUTracer; | |
| class MultiDrawManager; | |
| class GLES2DecoderPassthroughImpl; | |
| class PassthroughProgramCache; | |
| struct MappedBuffer { | |
| GLsizeiptr size; | |
| GLbitfield original_access; | |
| GLbitfield filtered_access; | |
| raw_ptr<uint8_t, DanglingUntriaged | AllowPtrArithmetic> map_ptr; | |
| int32_t data_shm_id; | |
| uint32_t data_shm_offset; | |
| }; | |
| struct PassthroughResources { | |
| PassthroughResources(); | |
| ~PassthroughResources(); | |
| void MarkContextLost(); | |
| // api is null if we don't have a context (e.g. lost). | |
| void Destroy(gl::GLApi* api, gl::ProgressReporter* progress_reporter); | |
| void SuspendSharedImageAccessIfNeeded(); | |
| bool ResumeSharedImageAccessIfNeeded(gl::GLApi* api); | |
| // Mappings from client side IDs to service side IDs. | |
| ClientServiceMap<GLuint, GLuint> texture_id_map; | |
| ClientServiceMap<GLuint, GLuint> buffer_id_map; | |
| ClientServiceMap<GLuint, GLuint> renderbuffer_id_map; | |
| ClientServiceMap<GLuint, GLuint> sampler_id_map; | |
| ClientServiceMap<GLuint, GLuint> program_id_map; | |
| ClientServiceMap<GLuint, GLuint> shader_id_map; | |
| static_assert(sizeof(uintptr_t) == sizeof(GLsync), | |
| "GLsync not the same size as uintptr_t"); | |
| ClientServiceMap<GLuint, uintptr_t> sync_id_map; | |
| // Mapping of client texture IDs to TexturePassthrough objects used to make | |
| // sure all textures used by mailboxes are not deleted until all textures | |
| // using the mailbox are deleted | |
| ClientServiceMap<GLuint, scoped_refptr<TexturePassthrough>> | |
| texture_object_map; | |
| class SharedImageData { | |
| public: | |
| SharedImageData(); | |
| explicit SharedImageData( | |
| GLES2DecoderPassthroughImpl*, | |
| std::unique_ptr<GLTexturePassthroughImageRepresentation>); | |
| SharedImageData(SharedImageData&& other); | |
| SharedImageData(const SharedImageData&) = delete; | |
| SharedImageData& operator=(const SharedImageData&) = delete; | |
| ~SharedImageData(); | |
| SharedImageData& operator=(SharedImageData&& other); | |
| GLTexturePassthroughImageRepresentation* representation() const { | |
| return representation_.get(); | |
| } | |
| // Returns true between a successful BeginAccess and the following EndAccess | |
| // even if access is currently suspended. | |
| bool is_being_accessed() const { return access_mode_.has_value(); } | |
| bool BeginAccess(GLenum mode, gl::GLApi* api); | |
| void EndAccess(); | |
| bool ResumeAccessIfNeeded(gl::GLApi* api); | |
| void SuspendAccessIfNeeded(); | |
| private: | |
| void EnsureClear(GLES2DecoderPassthroughImpl*); | |
| std::unique_ptr<GLTexturePassthroughImageRepresentation> representation_; | |
| std::unique_ptr<GLTexturePassthroughImageRepresentation::ScopedAccess> | |
| scoped_access_; | |
| std::optional<GLenum> access_mode_; | |
| }; | |
| // Mapping of client texture IDs to GLTexturePassthroughImageRepresentations. | |
| // TODO(ericrk): Remove this once TexturePassthrough holds a reference to | |
| // the GLTexturePassthroughImageRepresentation itself. | |
| base::flat_map<GLuint, SharedImageData> texture_shared_image_map; | |
| }; | |
| // Impose an upper bound on the number ANGLE_shader_pixel_local_storage planes | |
| // so we can stack-allocate load/store ops. | |
| static constexpr GLsizei kPassthroughMaxPLSPlanes = 8; | |
| // Minimum idle delay before memory is trimmed for this context. Actual delay | |
| // can be higher. | |
| static constexpr base::TimeDelta kIdleTrimDelay = base::Seconds(1); | |
| class GPU_GLES2_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { | |
| public: | |
| GLES2DecoderPassthroughImpl(DecoderClient* client, | |
| CommandBufferServiceBase* command_buffer_service, | |
| Outputter* outputter, | |
| ContextGroup* group); | |
| ~GLES2DecoderPassthroughImpl() override; | |
| Error DoCommands(unsigned int num_commands, | |
| const volatile void* buffer, | |
| int num_entries, | |
| int* entries_processed) override; | |
| template <bool DebugImpl> | |
| Error DoCommandsImpl(unsigned int num_commands, | |
| const volatile void* buffer, | |
| int num_entries, | |
| int* entries_processed); | |
| base::WeakPtr<DecoderContext> AsWeakPtr() override; | |
| gpu::ContextResult Initialize(const scoped_refptr<gl::GLSurface>& surface, | |
| const scoped_refptr<gl::GLContext>& context, | |
| bool offscreen, | |
| ContextType context_type, | |
| bool lose_context_when_out_of_memory) override; | |
| // Destroys the graphics context. | |
| void Destroy(bool have_context) override; | |
| // Set the surface associated with the default FBO. | |
| void SetSurface(const scoped_refptr<gl::GLSurface>& surface) override; | |
| // Releases the surface associated with the GL context. | |
| // The decoder should not be used until a new surface is set. | |
| void ReleaseSurface() override; | |
| // Make this decoder's GL context current. | |
| bool MakeCurrent() override; | |
| gl::GLApi* api() const { return api_; } | |
| // Gets the GLES2 Util which holds info. | |
| GLES2Util* GetGLES2Util() override; | |
| // Gets the associated GLContext and GLSurface. | |
| gl::GLContext* GetGLContext() override; | |
| gl::GLSurface* GetGLSurface() override; | |
| // Gets the associated ContextGroup | |
| ContextGroup* GetContextGroup() override; | |
| const FeatureInfo* GetFeatureInfo() const override; | |
| Capabilities GetCapabilities() override; | |
| GLCapabilities GetGLCapabilities() override; | |
| // Restores all of the decoder GL state. | |
| void RestoreState(const ContextState* prev_state) override; | |
| // Restore States. | |
| void RestoreActiveTexture() const override; | |
| void RestoreAllTextureUnitAndSamplerBindings( | |
| const ContextState* prev_state) const override; | |
| void RestoreActiveTextureUnitBinding(unsigned int target) const override; | |
| void RestoreBufferBinding(unsigned int target) override; | |
| void RestoreBufferBindings() const override; | |
| void RestoreFramebufferBindings() const override; | |
| void RestoreRenderbufferBindings() override; | |
| void RestoreGlobalState() const override; | |
| void RestoreProgramBindings() const override; | |
| void RestoreTextureState(unsigned service_id) override; | |
| void RestoreTextureUnitBindings(unsigned unit) const override; | |
| void RestoreVertexAttribArray(unsigned index) override; | |
| void RestoreAllExternalTextureBindingsIfNeeded() override; | |
| void RestoreDeviceWindowRectangles() const override; | |
| void ClearAllAttributes() const override; | |
| void RestoreAllAttributes() const override; | |
| void SetIgnoreCachedStateForTest(bool ignore) override; | |
| void SetForceShaderNameHashingForTest(bool force) override; | |
| void ForceReinitializeFeatureInfoForTesting() { | |
| feature_info_->ForceReinitialize(); | |
| } | |
| // Gets the QueryManager for this context. | |
| QueryManager* GetQueryManager() override; | |
| // Set a callback to be called when a query is complete. | |
| void SetQueryCallback(unsigned int query_client_id, | |
| base::OnceClosure callback) override; | |
| void CancelAllQueries() override; | |
| // Gets the GpuFenceManager for this context. | |
| GpuFenceManager* GetGpuFenceManager() override; | |
| // Gets the FramebufferManager for this context. | |
| FramebufferManager* GetFramebufferManager() override; | |
| // Gets the TransformFeedbackManager for this context. | |
| TransformFeedbackManager* GetTransformFeedbackManager() override; | |
| // Gets the VertexArrayManager for this context. | |
| VertexArrayManager* GetVertexArrayManager() override; | |
| // Returns false if there are no pending queries. | |
| bool HasPendingQueries() const override; | |
| // Process any pending queries. | |
| void ProcessPendingQueries(bool did_finish) override; | |
| // Returns false if there is no idle work to be made. | |
| bool HasMoreIdleWork() const override; | |
| // Perform any idle work that needs to be made. | |
| void PerformIdleWork() override; | |
| bool HasPollingWork() const override; | |
| void PerformPollingWork() override; | |
| bool GetServiceTextureId(uint32_t client_texture_id, | |
| uint32_t* service_texture_id) override; | |
| TextureBase* GetTextureBase(uint32_t client_id) override; | |
| // Provides detail about a lost context if one occurred. | |
| // Clears a level sub area of a texture | |
| // Returns false if a GL error should be generated. | |
| bool ClearLevel(Texture* texture, | |
| unsigned target, | |
| int level, | |
| unsigned format, | |
| unsigned type, | |
| int xoffset, | |
| int yoffset, | |
| int width, | |
| int height) override; | |
| // Clears a level sub area of a compressed 2D texture. | |
| // Returns false if a GL error should be generated. | |
| bool ClearCompressedTextureLevel(Texture* texture, | |
| unsigned target, | |
| int level, | |
| unsigned format, | |
| int width, | |
| int height) override; | |
| // Clears a level sub area of a compressed 3D texture. | |
| // Returns false if a GL error should be generated. | |
| bool ClearCompressedTextureLevel3D(Texture* texture, | |
| unsigned target, | |
| int level, | |
| unsigned format, | |
| int width, | |
| int height, | |
| int depth) override; | |
| // Indicates whether a given internal format is one for a compressed | |
| // texture. | |
| bool IsCompressedTextureFormat(unsigned format) override; | |
| // Clears a level of a 3D texture. | |
| // Returns false if a GL error should be generated. | |
| bool ClearLevel3D(Texture* texture, | |
| unsigned target, | |
| int level, | |
| unsigned format, | |
| unsigned type, | |
| int width, | |
| int height, | |
| int depth) override; | |
| ErrorState* GetErrorState() override; | |
| void BindFramebuffer(unsigned target, uint32_t service_id) const override; | |
| void WaitForReadPixels(base::OnceClosure callback) override; | |
| // Returns true if the context was lost either by GL_ARB_robustness, forced | |
| // context loss or command buffer parse error. | |
| bool WasContextLost() const override; | |
| // Returns true if the context was lost specifically by GL_ARB_robustness. | |
| bool WasContextLostByRobustnessExtension() const override; | |
| // Lose this context. | |
| void MarkContextLost(error::ContextLostReason reason) override; | |
| // Update lost context state for use when making calls to the GL context | |
| // directly, and needing to know if they failed due to loss. | |
| bool CheckResetStatus() override; | |
| Logger* GetLogger() override; | |
| void BeginDecoding() override; | |
| void EndDecoding() override; | |
| const ContextState* GetContextState() override; | |
| scoped_refptr<ShaderTranslatorInterface> GetTranslator(GLenum type) override; | |
| void OnDebugMessage(GLenum source, | |
| GLenum type, | |
| GLuint id, | |
| GLenum severity, | |
| GLsizei length, | |
| const GLchar* message); | |
| GLsizeiptr BlobCacheGet(const void* key, | |
| GLsizeiptr key_size, | |
| void* value, | |
| GLsizeiptr value_size); | |
| void BlobCacheSet(const void* key, | |
| GLsizeiptr key_size, | |
| const void* value, | |
| GLsizeiptr value_size); | |
| void SetCopyTextureResourceManagerForTest( | |
| CopyTextureCHROMIUMResourceManager* copy_texture_resource_manager) | |
| override; | |
| void SetCopyTexImageBlitterForTest( | |
| CopyTexImageResourceManager* copy_tex_image_blit) override; | |
| const FeatureInfo::FeatureFlags& features() const { | |
| return feature_info_->feature_flags(); | |
| } | |
| class ScopedPixelLocalStorageInterrupt { | |
| public: | |
| ScopedPixelLocalStorageInterrupt(const GLES2DecoderPassthroughImpl*); | |
| ~ScopedPixelLocalStorageInterrupt(); | |
| private: | |
| raw_ptr<const GLES2DecoderPassthroughImpl> impl_; | |
| }; | |
| private: | |
| // Allow unittests to inspect internal state tracking | |
| friend class GLES2DecoderPassthroughTestBase; | |
| // Uses FlushErrors() to detect failures when clearing shared images. | |
| friend class PassthroughResources::SharedImageData; | |
| const char* GetCommandName(unsigned int command_id) const; | |
| void SetOptionalExtensionsRequestedForTesting(bool request_extensions); | |
| template <typename T, typename GLGetFunction> | |
| error::Error GetNumericHelper(GLenum pname, | |
| GLsizei bufsize, | |
| GLsizei* length, | |
| T* params, | |
| GLGetFunction get_call) { | |
| get_call(pname, bufsize, length, params); | |
| // Update the results of the query, if needed | |
| const error::Error error = PatchGetNumericResults(pname, *length, params); | |
| if (error != error::kNoError) { | |
| *length = 0; | |
| return error; | |
| } | |
| return error::kNoError; | |
| } | |
| template <typename T> | |
| error::Error PatchGetNumericResults(GLenum pname, GLsizei length, T* params); | |
| error::Error PatchGetFramebufferAttachmentParameter(GLenum target, | |
| GLenum attachment, | |
| GLenum pname, | |
| GLsizei length, | |
| GLint* params); | |
| error::Error PatchGetFramebufferPixelLocalStorageParameterivANGLE( | |
| GLint plane, | |
| GLenum pname, | |
| GLsizei length, | |
| GLint* params); | |
| error::Error PatchGetFramebufferPixelLocalStorageParameteruivANGLE( | |
| GLint plane, | |
| GLenum pname, | |
| GLsizei length, | |
| GLuint* params); | |
| void InsertError(GLenum error, const std::string& message); | |
| GLenum PopError(); | |
| bool FlushErrors(); | |
| bool IsIgnoredCap(GLenum cap) const; | |
| bool IsEmulatedQueryTarget(GLenum target) const; | |
| error::Error ProcessQueries(bool did_finish); | |
| void RemovePendingQuery(GLuint service_id); | |
| struct BufferShadowUpdate; | |
| // BufferShadowUpdateMap's key is a buffer client id. | |
| using BufferShadowUpdateMap = base::flat_map<GLuint, BufferShadowUpdate>; | |
| void ReadBackBuffersIntoShadowCopies(const BufferShadowUpdateMap& updates); | |
| error::Error ProcessReadPixels(bool did_finish); | |
| // Validates the use of shm_offset as either an offset in a shmem, or in the | |
| // unpack buffer. When using unpack buffers, data will be a zero-length span | |
| // with the address corresponding to the offset in the unpack buffer. (so its | |
| // .data() and .size() are the arguments to pass to the TexImage family of | |
| // functions, without additional changes needed). | |
| // image_size is the corresponding argument passed to CompressedTex[Sub]Image | |
| // functions so it can be validated against the shmem size when there is no | |
| // unpack buffer. | |
| error::Error ValidateAndGetTexImageData(base::span<const uint8_t>* data, | |
| uint32_t shm_id, | |
| uint32_t shm_offset, | |
| uint32_t image_size = 0); | |
| // Checks to see if the inserted fence has completed. | |
| void ProcessDescheduleUntilFinished(); | |
| void UpdateTextureBinding(GLenum target, | |
| GLuint client_id, | |
| TexturePassthrough* texture); | |
| void RebindTexture(TexturePassthrough* texture); | |
| void UpdateTextureSizeFromTexturePassthrough(TexturePassthrough* texture, | |
| GLuint client_id); | |
| void UpdateTextureSizeFromTarget(GLenum target); | |
| void UpdateTextureSizeFromClientID(GLuint client_id); | |
| // Some operations like binding a VAO will update the element array buffer | |
| // binding without an explicit glBindBuffer. This function is extremely | |
| // expensive, and it is crucial that it be called only when the command | |
| // decoder's notion of the element array buffer absolutely has to be | |
| // up-to-date. | |
| void LazilyUpdateCurrentlyBoundElementArrayBuffer(); | |
| void VerifyServiceTextureObjectsExist(); | |
| bool IsEmulatedFramebufferBound(GLenum target) const; | |
| void ExitCommandProcessingEarly() override; | |
| bool OnlyHasPendingProgramCompletionQueries(); | |
| void BuildRequestableExtensionString(); | |
| bool CanRedefineBoundTexture(GLenum target); | |
| PassthroughProgramCache* get_passthrough_program_cache() const; | |
| int commands_to_process_; | |
| DebugMarkerManager debug_marker_manager_; | |
| Logger logger_; | |
| #define GLES2_CMD_OP(name) \ | |
| Error Handle##name(uint32_t immediate_data_size, const volatile void* data); | |
| GLES2_COMMAND_LIST(GLES2_CMD_OP) | |
| #undef GLES2_CMD_OP | |
| using CmdHandler = | |
| Error (GLES2DecoderPassthroughImpl::*)(uint32_t immediate_data_size, | |
| const volatile void* data); | |
| // A struct to hold info about each command. | |
| struct CommandInfo { | |
| CmdHandler cmd_handler; | |
| uint8_t arg_flags; // How to handle the arguments for this scommand | |
| uint8_t cmd_flags; // How to handle this command | |
| uint16_t arg_count; // How many arguments are expected for this command. | |
| }; | |
| // A table of CommandInfo for all the commands. | |
| static const std::array<CommandInfo, kNumCommands - kFirstGLES2Command> | |
| command_info; | |
| // The GLApi to make the gl calls on. | |
| raw_ptr<gl::GLApi> api_ = nullptr; | |
| // The GL context this decoder renders to on behalf of the client. | |
| scoped_refptr<gl::GLSurface> surface_; | |
| scoped_refptr<gl::GLContext> context_; | |
| bool offscreen_; | |
| // The ContextGroup for this decoder uses to track resources. | |
| scoped_refptr<ContextGroup> group_; | |
| scoped_refptr<FeatureInfo> feature_info_; | |
| // By default, all requestable extensions should be loaded at initialization | |
| // time. Can be disabled for testing with only specific extensions enabled. | |
| bool request_optional_extensions_ = true; | |
| // Set of extension strings that are valid to request by a client. Other | |
| // extension requests are ignored. | |
| gfx::ExtensionSet requestable_extensions_; | |
| std::string requestable_extension_string_; | |
| // Mappings from client side IDs to service side IDs for shared objects | |
| raw_ptr<PassthroughResources> resources_ = nullptr; | |
| // Mappings from client side IDs to service side IDs for per-context objects | |
| ClientServiceMap<GLuint, GLuint> framebuffer_id_map_; | |
| ClientServiceMap<GLuint, GLuint> transform_feedback_id_map_; | |
| ClientServiceMap<GLuint, GLuint> query_id_map_; | |
| ClientServiceMap<GLuint, GLuint> vertex_array_id_map_; | |
| std::unique_ptr<GpuFenceManager> gpu_fence_manager_; | |
| std::unique_ptr<MultiDrawManager> multi_draw_manager_; | |
| // State tracking of currently bound 2D textures (client IDs) | |
| size_t active_texture_unit_; | |
| enum class TextureTarget : uint8_t { | |
| k2D = 0, | |
| kCubeMap = 1, | |
| k2DArray = 2, | |
| k3D = 3, | |
| k2DMultisample = 4, | |
| kExternal = 5, | |
| kRectangle = 6, | |
| kBuffer = 7, | |
| kCubeMapArray = 8, | |
| k2DMultisampleArray = 9, | |
| kUnkown = 10, | |
| kCount = kUnkown, | |
| }; | |
| static TextureTarget GLenumToTextureTarget(GLenum target); | |
| struct BoundTexture { | |
| BoundTexture(); | |
| ~BoundTexture(); | |
| BoundTexture(const BoundTexture&); | |
| BoundTexture(BoundTexture&&); | |
| BoundTexture& operator=(const BoundTexture&); | |
| BoundTexture& operator=(BoundTexture&&); | |
| GLuint client_id = 0; | |
| scoped_refptr<TexturePassthrough> texture; | |
| }; | |
| // Use a limit that is at least ANGLE's IMPLEMENTATION_MAX_ACTIVE_TEXTURES | |
| // constant | |
| static constexpr size_t kMaxTextureUnits = 64; | |
| static constexpr size_t kNumTextureTypes = | |
| static_cast<size_t>(TextureTarget::kCount); | |
| std::array<std::array<BoundTexture, kMaxTextureUnits>, kNumTextureTypes> | |
| bound_textures_; | |
| // State tracking of currently bound buffers | |
| base::flat_map<GLenum, GLuint> bound_buffers_; | |
| // Lazy tracking of the bound element array buffer when changing VAOs. | |
| bool bound_element_array_buffer_dirty_; | |
| // Track the service-id to type of all queries for validation | |
| struct QueryInfo { | |
| GLenum type = GL_NONE; | |
| }; | |
| base::flat_map<GLuint, QueryInfo> query_info_map_; | |
| // All queries that are waiting for their results to be ready | |
| struct PendingQuery { | |
| PendingQuery(); | |
| ~PendingQuery(); | |
| PendingQuery(const PendingQuery&) = delete; | |
| PendingQuery(PendingQuery&&); | |
| PendingQuery& operator=(const PendingQuery&) = delete; | |
| PendingQuery& operator=(PendingQuery&&); | |
| GLenum target = GL_NONE; | |
| GLuint service_id = 0; | |
| scoped_refptr<gpu::Buffer> shm; | |
| raw_ptr<QuerySync> sync = nullptr; | |
| base::subtle::Atomic32 submit_count = 0; | |
| std::unique_ptr<gl::GLFence> commands_completed_fence; | |
| base::TimeDelta commands_issued_time; | |
| std::vector<base::OnceClosure> callbacks; | |
| std::unique_ptr<gl::GLFence> buffer_shadow_update_fence; | |
| BufferShadowUpdateMap buffer_shadow_updates; | |
| GLuint program_service_id = 0u; | |
| }; | |
| base::circular_deque<PendingQuery> pending_queries_; | |
| // Currently active queries | |
| struct ActiveQuery { | |
| ActiveQuery(); | |
| ~ActiveQuery(); | |
| ActiveQuery(const ActiveQuery&) = delete; | |
| ActiveQuery(ActiveQuery&&); | |
| ActiveQuery& operator=(const ActiveQuery&) = delete; | |
| ActiveQuery& operator=(ActiveQuery&&); | |
| GLuint service_id = 0; | |
| scoped_refptr<gpu::Buffer> shm; | |
| raw_ptr<QuerySync> sync = nullptr; | |
| // Time at which the commands for this query started processing. This is | |
| // used to ensure we only include the time when the decoder is scheduled in | |
| // the |active_time|. Used for GL_COMMANDS_ISSUED_CHROMIUM type query. | |
| base::TimeTicks command_processing_start_time; | |
| base::TimeDelta active_time; | |
| }; | |
| base::flat_map<GLenum, ActiveQuery> active_queries_; | |
| // Pending async ReadPixels calls | |
| struct PendingReadPixels { | |
| PendingReadPixels(); | |
| PendingReadPixels(const PendingReadPixels&) = delete; | |
| PendingReadPixels& operator=(const PendingReadPixels&) = delete; | |
| PendingReadPixels(PendingReadPixels&&); | |
| PendingReadPixels& operator=(PendingReadPixels&&); | |
| ~PendingReadPixels(); | |
| std::unique_ptr<gl::GLFence> fence; | |
| 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<GLuint> waiting_async_pack_queries; | |
| }; | |
| base::circular_deque<PendingReadPixels> pending_read_pixels_; | |
| struct BufferShadowUpdate { | |
| BufferShadowUpdate(); | |
| BufferShadowUpdate(const BufferShadowUpdate&) = delete; | |
| BufferShadowUpdate& operator=(const BufferShadowUpdate&) = delete; | |
| BufferShadowUpdate(BufferShadowUpdate&&); | |
| BufferShadowUpdate& operator=(BufferShadowUpdate&&); | |
| ~BufferShadowUpdate(); | |
| scoped_refptr<gpu::Buffer> shm; | |
| GLuint shm_offset = 0; | |
| GLuint size = 0; | |
| }; | |
| BufferShadowUpdateMap buffer_shadow_updates_; | |
| // Error state | |
| base::flat_set<GLenum> errors_; | |
| // Checks if an error has been generated since the last call to | |
| // CheckErrorCallbackState | |
| bool CheckErrorCallbackState(); | |
| bool had_error_callback_ = false; | |
| struct EmulatedDefaultFramebuffer { | |
| EmulatedDefaultFramebuffer(const GLES2DecoderPassthroughImpl*); | |
| EmulatedDefaultFramebuffer(const EmulatedDefaultFramebuffer&) = delete; | |
| EmulatedDefaultFramebuffer& operator=(const EmulatedDefaultFramebuffer&) = | |
| delete; | |
| ~EmulatedDefaultFramebuffer(); | |
| gl::GLApi* api() const { return impl_->api(); } | |
| bool Initialize(const gfx::Size& size); | |
| void Destroy(bool have_context); | |
| raw_ptr<const GLES2DecoderPassthroughImpl> impl_; | |
| // Service ID of the framebuffer | |
| GLuint framebuffer_service_id = 0; | |
| // Color buffer texture | |
| scoped_refptr<TexturePassthrough> texture; | |
| }; | |
| GLenum emulated_default_framebuffer_format_; | |
| std::unique_ptr<EmulatedDefaultFramebuffer> emulated_back_buffer_; | |
| // Maximum 2D resource sizes for limiting offscreen framebuffer sizes | |
| GLint max_renderbuffer_size_ = 0; | |
| GLint max_offscreen_framebuffer_size_ = 0; | |
| // State tracking of currently bound draw and read framebuffers (client IDs) | |
| GLuint bound_draw_framebuffer_; | |
| GLuint bound_read_framebuffer_; | |
| // If this context supports both read and draw framebuffer bindings | |
| bool supports_separate_fbo_bindings_ = false; | |
| // Tracks if the context has ever called glBeginPixelLocalStorageANGLE. If it | |
| // has, we need to start using the pixel local storage interrupt mechanism. | |
| bool has_activated_pixel_local_storage_ = false; | |
| // Creates lazily and holds a SharedContextState on a GLContext that is in the | |
| // same share group as the command decoder's context. This is done so that | |
| // skia operations can be performed on textures from the context and not worry | |
| // about state tracking. | |
| class LazySharedContextState { | |
| public: | |
| static std::unique_ptr<LazySharedContextState> Create( | |
| GLES2DecoderPassthroughImpl* impl); | |
| explicit LazySharedContextState(GLES2DecoderPassthroughImpl* impl); | |
| ~LazySharedContextState(); | |
| SharedContextState* shared_context_state() { | |
| return shared_context_state_.get(); | |
| } | |
| private: | |
| bool Initialize(); | |
| raw_ptr<GLES2DecoderPassthroughImpl> impl_ = nullptr; | |
| scoped_refptr<SharedContextState> shared_context_state_; | |
| }; | |
| std::unique_ptr<LazySharedContextState> lazy_context_; | |
| // Makes `context` current for its lifetime, first interrupting pixel local | |
| // storage if the decoder's context is current. On destruction, restores the | |
| // previously current context and verifies that the decoder's context is | |
| // current again. If it is not, the decoder's context is marked as lost and | |
| // pixel local storage is not restored, so no further work runs on the wrong | |
| // context. | |
| class ScopedSharedContextCurrent { | |
| public: | |
| ScopedSharedContextCurrent(GLES2DecoderPassthroughImpl* impl, | |
| gl::GLContext* context, | |
| gl::GLSurface* surface); | |
| ScopedSharedContextCurrent(const ScopedSharedContextCurrent&) = delete; | |
| ScopedSharedContextCurrent& operator=(const ScopedSharedContextCurrent&) = | |
| delete; | |
| ~ScopedSharedContextCurrent(); | |
| // Returns whether `context` was successfully made current. | |
| bool IsContextCurrent(); | |
| private: | |
| raw_ptr<GLES2DecoderPassthroughImpl> impl_; | |
| bool decoder_context_was_current_ = false; | |
| bool pixel_local_storage_interrupted_ = false; | |
| std::optional<ui::ScopedMakeCurrent> scoped_make_current_; | |
| }; | |
| // Returns whether the decoder's context is current, according to both | |
| // Chromium's and the underlying GL implementation's bookkeeping. | |
| bool IsDecoderContextCurrent() const; | |
| // Tracing | |
| std::unique_ptr<GPUTracer> gpu_tracer_; | |
| int gpu_trace_level_; | |
| bool gpu_trace_commands_; | |
| bool gpu_debug_commands_; | |
| // Context lost state | |
| bool context_lost_; | |
| bool reset_by_robustness_extension_; | |
| bool lose_context_when_out_of_memory_; | |
| // After a second fence is inserted, both the GpuChannelMessageQueue and | |
| // CommandExecutor are descheduled. Once the first fence has completed, both | |
| // get rescheduled. | |
| base::circular_deque<std::unique_ptr<gl::GLFence>> | |
| deschedule_until_finished_fences_; | |
| GLuint linking_program_service_id_ = 0u; | |
| void ScheduleIdleMemoryTrim(); | |
| void PostIdleMemoryTrimTask(); | |
| void PerformIdleMemoryTrim(); | |
| base::TimeTicks last_active_time_; | |
| base::CancelableOnceClosure idle_trim_cb_; | |
| base::WeakPtrFactory<GLES2DecoderPassthroughImpl> weak_ptr_factory_{this}; | |
| class ScopedEnableTextureRectangleInShaderCompiler; | |
| // Include the prototypes of all the doer functions from a separate header to | |
| // keep this file clean. | |
| #include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h" | |
| }; | |
| } // namespace gles2 | |
| } // namespace gpu | |
| #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_PASSTHROUGH_H_ |