blob: 3deaaa28970a1f2ef828a7c63af04b1e4c7f85fc [file] [log] [blame]
// 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 <memory>
#include <optional>
#include <vector>
#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/ref_counted.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/mailbox.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/mailbox_manager.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/gpu_switching_observer.h"
namespace gl {
class GLFence;
class ProgressReporter;
}
namespace gpu {
class GLTexturePassthroughImageRepresentation;
namespace gles2 {
class ContextGroup;
class GPUTracer;
class MultiDrawManager;
class GLES2DecoderPassthroughImpl;
class GLES2ExternalFramebuffer;
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();
// 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(
const 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(); }
void EnsureClear(const GLES2DecoderPassthroughImpl*);
bool BeginAccess(GLenum mode, gl::GLApi* api);
void EndAccess();
bool ResumeAccessIfNeeded(gl::GLApi* api);
void SuspendAccessIfNeeded();
private:
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;
// Mapping of client buffer IDs that are mapped to the shared memory used to
// back the mapping so that it can be flushed when the buffer is unmapped
base::flat_map<GLuint, MappedBuffer> mapped_buffer_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;
class GPU_GLES2_EXPORT GLES2DecoderPassthroughImpl
: public GLES2Decoder,
public ui::GpuSwitchingObserver {
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,
const DisallowedFeatures& disallowed_features,
const ContextCreationAttribs& attrib_helper) 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;
void SetDefaultFramebufferSharedImage(const Mailbox& mailbox,
int samples,
bool preserve,
bool needs_depth,
bool needs_stencil) 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;
// 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 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;
// Implement GpuSwitchingObserver.
void OnGpuSwitched(gl::GpuPreference active_gpu_heuristic) 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);
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;
const char* GetCommandName(unsigned int command_id) const;
void SetOptionalExtensionsRequestedForTesting(bool request_extensions);
void InitializeFeatureInfo(ContextType context_type,
const DisallowedFeatures& disallowed_features,
bool force_reinitialize);
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);
template <typename T>
error::Error PatchGetBufferResults(GLenum target,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
T* params);
error::Error PatchGetFramebufferPixelLocalStorageParameterivANGLE(
GLint plane,
GLenum pname,
GLsizei length,
GLint* 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);
// 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;
void CheckSwapBuffersAsyncResult(const char* function_name,
uint64_t swap_id,
gfx::SwapCompletionResult result);
error::Error CheckSwapBuffersResult(gfx::SwapResult result,
const char* function_name);
bool OnlyHasPendingProgramCompletionQueries();
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 CommandInfo command_info[kNumCommands - kFirstGLES2Command];
// 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_;
// 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;
// Some objects may generate resources when they are bound even if they were
// not generated yet: texture, buffer, renderbuffer, framebuffer, transform
// feedback, vertex array
bool bind_generates_resource_;
// 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_;
// Mailboxes
raw_ptr<MailboxManager> mailbox_manager_ = nullptr;
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,
kUnkown = 7,
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;
base::TimeTicks commands_issued_timestamp;
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_;
std::unique_ptr<GLES2ExternalFramebuffer> external_default_framebuffer_;
// 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;
// Tracing
std::unique_ptr<GPUTracer> gpu_tracer_;
const unsigned char* gpu_decoder_category_ = nullptr;
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;
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 "base/time/time.h"
#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_