blob: 6ea1632de79037a9417c3a62fe0727db149f6f97 [file] [log] [blame]
// Copyright (c) 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file contains the GLES2DecoderPassthroughImpl class.
#include <algorithm>
#include <memory>
#include <set>
#include <unordered_map>
#include <vector>
#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/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/image_manager.h"
#include "gpu/command_buffer/service/logger.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/passthrough_abstract_texture_impl.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_image.h"
#include "ui/gl/gl_surface.h"
namespace gl {
class GLFence;
namespace gpu {
class SharedImageRepresentationGLTexturePassthrough;
namespace gles2 {
class ContextGroup;
class GPUTracer;
class PassthroughAbstractTextureImpl;
struct MappedBuffer {
GLsizeiptr size;
GLbitfield original_access;
GLbitfield filtered_access;
uint8_t* map_ptr;
int32_t data_shm_id;
uint32_t data_shm_offset;
struct PassthroughResources {
// api is null if we don't have a context (e.g. lost).
void Destroy(gl::GLApi* api);
// Resources stores a shared list of textures pending deletion.
// If we have don't context when this function is called, we can mark
// these textures as lost context and drop all references to them.
void DestroyPendingTextures(bool has_context);
// If there are any textures pending destruction.
bool HasTexturesPendingDestruction() const;
// 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>>
// Mapping of client texture IDs to
// SharedImageRepresentationGLTexturePassthroughs.
// TODO(ericrk): Remove this once TexturePassthrough holds a reference to
// the SharedImageRepresentationGLTexturePassthrough itself.
// A set of yet-to-be-deleted TexturePassthrough, which should be tossed
// whenever a context switch happens or the resources is destroyed.
// 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
std::unordered_map<GLuint, MappedBuffer> mapped_buffer_map;
class ScopedFramebufferBindingReset {
explicit ScopedFramebufferBindingReset(gl::GLApi* api);
gl::GLApi* api_;
GLint draw_framebuffer_;
GLint read_framebuffer_;
class ScopedRenderbufferBindingReset {
explicit ScopedRenderbufferBindingReset(gl::GLApi* api);
gl::GLApi* api_;
GLint renderbuffer_;
class ScopedTexture2DBindingReset {
explicit ScopedTexture2DBindingReset(gl::GLApi* api);
gl::GLApi* api_;
GLint texture_;
class GPU_GLES2_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder {
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 TakeFrontBuffer(const Mailbox& mailbox) override;
void ReturnFrontBuffer(const Mailbox& mailbox, bool is_lost) override;
// Resize an offscreen frame buffer.
bool ResizeOffscreenFramebuffer(const gfx::Size& size) 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;
// 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) const 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;
size_t GetSavedBackTextureCountForTest() override;
size_t GetCreatedBackTextureCountForTest() 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;
// 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;
// Gets the ImageManager for this context.
ImageManager* GetImageManagerForTest() 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;
// 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;
std::unique_ptr<AbstractTexture> CreateAbstractTexture(
unsigned target,
unsigned internal_format,
int width,
int height,
int depth,
int border,
unsigned format,
unsigned type) 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 BindImage(uint32_t client_texture_id,
uint32_t texture_target,
gl::GLImage* image,
bool can_bind_to_sampler) override;
void OnDebugMessage(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message);
void SetCopyTextureResourceManagerForTest(
CopyTextureCHROMIUMResourceManager* copy_texture_resource_manager)
void SetCopyTexImageBlitterForTest(
CopyTexImageResourceManager* copy_tex_image_blit) override;
void OnAbstractTextureDestroyed(PassthroughAbstractTextureImpl*,
// Allow unittests to inspect internal state tracking
friend class GLES2DecoderPassthroughTestBase;
const char* GetCommandName(unsigned int command_id) const;
void SetOptionalExtensionsRequestedForTesting(bool request_extensions);
void* GetScratchMemory(size_t size);
template <typename T>
T* GetTypedScratchMemory(size_t count) {
return reinterpret_cast<T*>(GetScratchMemory(count * sizeof(T)));
template <typename T, typename GLGetFunction>
error::Error GetNumericHelper(GLenum pname,
GLsizei bufsize,
GLsizei* length,
T* params,
GLGetFunction get_call) {
// Get a scratch buffer to hold the result of the query
T* scratch_params = GetTypedScratchMemory<T>(bufsize);
get_call(pname, bufsize, length, scratch_params);
// Update the results of the query, if needed
error::Error error = PatchGetNumericResults(pname, *length, scratch_params);
if (error != error::kNoError) {
*length = 0;
return error;
// Copy into the destination
DCHECK(*length <= bufsize);
std::copy(scratch_params, scratch_params + *length, params);
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);
void InsertError(GLenum error, const std::string& message);
GLenum PopError();
bool FlushErrors();
bool IsRobustnessSupported();
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 UpdateTextureSizeFromTexturePassthrough(TexturePassthrough* texture,
GLuint client_id);
void UpdateTextureSizeFromTarget(GLenum target);
void UpdateTextureSizeFromClientID(GLuint client_id);
error::Error BindTexImage2DCHROMIUMImpl(GLenum target,
GLenum internalformat,
GLint image_id);
void VerifyServiceTextureObjectsExist();
bool IsEmulatedFramebufferBound(GLenum target) const;
const FeatureInfo::FeatureFlags& features() const {
return feature_info_->feature_flags();
void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
error::Error CheckSwapBuffersResult(gfx::SwapResult result,
const char* function_name);
// Issue BindTexImage / CopyTexImage calls for |passthrough_texture|, if
// they're pending.
void BindOnePendingImage(GLenum target, TexturePassthrough* texture);
// Issue BindTexImage / CopyTexImage calls for any GLImages that
// requested it in BindImage, and are currently bound to textures that
// are bound to samplers (i.e., are in |textures_pending_binding_|).
void BindPendingImagesForSamplers();
// Fail-fast inline version of BindPendingImagesForSamplers.
inline void BindPendingImagesForSamplersIfNeeded() {
if (!textures_pending_binding_.empty())
// Fail-fast version of BindPendingImages that operates on a single texture
// that's specified by |client_id|.
inline void BindPendingImageForClientIDIfNeeded(int client_id) {
scoped_refptr<TexturePassthrough> texture = nullptr;
// We could keep track of the number of |is_bind_pending| textures in
// |resources_|, and elide all of this if it's zero.
if (!resources_->texture_object_map.GetServiceID(client_id, &texture))
if (texture && texture->is_bind_pending())
BindOnePendingImage(texture->target(), texture.get());
inline void RemovePendingBindingTexture(GLenum target, GLuint unit) {
// Note that this code was found to be faster than running base::EraseIf.
size_t num_pending = textures_pending_binding_.size();
for (size_t index = 0; index < num_pending; ++index) {
TexturePendingBinding& pending = textures_pending_binding_[index];
if ( == target && pending.unit == unit) {
textures_pending_binding_.erase(textures_pending_binding_.begin() +
DecoderClient* client_ = nullptr;
// A set of raw pointers to currently living PassthroughAbstractTextures
// which allow us to properly signal to them when we are destroyed.
base::flat_set<PassthroughAbstractTextureImpl*> abstract_textures_;
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);
#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];
// The GLApi to make the gl calls on.
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
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
MailboxManager* mailbox_manager_ = nullptr;
std::unique_ptr<GpuFenceManager> gpu_fence_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(const BoundTexture&);
BoundTexture& operator=(const BoundTexture&);
BoundTexture& operator=(BoundTexture&&);
GLuint client_id = 0;
scoped_refptr<TexturePassthrough> texture;
// Tracked viewport and scissor state for surface offset
GLint viewport_[4] = {0, 0, 0, 0};
GLint scissor_[4] = {0, 0, 0, 0};
gfx::Vector2d GetSurfaceDrawOffset() const;
void ApplySurfaceDrawOffset();
// 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 =
std::array<std::array<BoundTexture, kMaxTextureUnits>, kNumTextureTypes>
// [target, texture unit, texture] where texture has a bound GLImage that
// requires bind / copy before draw.
struct TexturePendingBinding {
TexturePendingBinding(GLenum target,
GLuint unit,
base::WeakPtr<TexturePassthrough> texture);
TexturePendingBinding(const TexturePendingBinding& other);
TexturePendingBinding(TexturePendingBinding&& other);
TexturePendingBinding& operator=(const TexturePendingBinding& other);
TexturePendingBinding& operator=(TexturePendingBinding&& other);
GLenum target;
GLuint unit;
base::WeakPtr<TexturePassthrough> texture;
std::vector<TexturePendingBinding> textures_pending_binding_;
// State tracking of currently bound buffers
std::unordered_map<GLenum, GLuint> bound_buffers_;
// Track the service-id to type of all queries for validation
struct QueryInfo {
GLenum type = GL_NONE;
std::unordered_map<GLuint, QueryInfo> query_info_map_;
// All queries that are waiting for their results to be ready
struct PendingQuery {
PendingQuery(const PendingQuery&) = delete;
PendingQuery& operator=(const PendingQuery&) = delete;
PendingQuery& operator=(PendingQuery&&);
GLenum target = GL_NONE;
GLuint service_id = 0;
scoped_refptr<gpu::Buffer> shm;
QuerySync* sync = nullptr;
base::subtle::Atomic32 submit_count = 0;
std::unique_ptr<gl::GLFence> commands_completed_fence;
std::vector<base::OnceClosure> callbacks;
std::unique_ptr<gl::GLFence> buffer_shadow_update_fence = nullptr;
BufferShadowUpdateMap buffer_shadow_updates;
base::circular_deque<PendingQuery> pending_queries_;
// Currently active queries
struct ActiveQuery {
ActiveQuery(const ActiveQuery&) = delete;
ActiveQuery& operator=(const ActiveQuery&) = delete;
ActiveQuery& operator=(ActiveQuery&&);
GLuint service_id = 0;
scoped_refptr<gpu::Buffer> shm;
QuerySync* sync = nullptr;
std::unordered_map<GLenum, ActiveQuery> active_queries_;
// Pending async ReadPixels calls
struct PendingReadPixels {
PendingReadPixels& operator=(PendingReadPixels&&);
std::unique_ptr<gl::GLFence> 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<GLuint> waiting_async_pack_queries;
base::circular_deque<PendingReadPixels> pending_read_pixels_;
struct BufferShadowUpdate {
BufferShadowUpdate& operator=(BufferShadowUpdate&&);
scoped_refptr<gpu::Buffer> shm;
GLuint shm_offset = 0;
GLuint size = 0;
BufferShadowUpdateMap buffer_shadow_updates_;
// Error state
std::set<GLenum> errors_;
// Checks if an error has been generated since the last call to
// CheckErrorCallbackState
bool CheckErrorCallbackState();
bool had_error_callback_ = false;
// 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(
gl::GLApi* api,
const EmulatedDefaultFramebufferFormat& format_in);
void Resize(const gfx::Size& new_size);
void Destroy(bool have_context);
gl::GLApi* api;
scoped_refptr<TexturePassthrough> texture;
gfx::Size size;
EmulatedDefaultFramebufferFormat format;
struct EmulatedDefaultFramebuffer {
gl::GLApi* api,
const EmulatedDefaultFramebufferFormat& format_in,
const FeatureInfo* feature_info);
// Set a new color buffer, return the old one
std::unique_ptr<EmulatedColorBuffer> SetColorBuffer(
std::unique_ptr<EmulatedColorBuffer> 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);
gl::GLApi* api;
// 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<EmulatedColorBuffer> 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;
EmulatedDefaultFramebufferFormat emulated_default_framebuffer_format_;
std::unique_ptr<EmulatedDefaultFramebuffer> emulated_back_buffer_;
std::unique_ptr<EmulatedColorBuffer> emulated_front_buffer_;
bool offscreen_single_buffer_;
bool offscreen_target_buffer_preserved_;
std::vector<std::unique_ptr<EmulatedColorBuffer>> in_use_color_textures_;
std::vector<std::unique_ptr<EmulatedColorBuffer>> available_color_textures_;
size_t create_color_buffer_count_for_test_;
// Maximum 2D resource sizes for limiting offscreen framebuffer sizes
GLint max_2d_texture_size_ = 0;
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_;
// 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 has_robustness_extension_;
bool context_lost_;
bool reset_by_robustness_extension_;
bool lose_context_when_out_of_memory_;
// Cache of scratch memory
std::vector<uint8_t> scratch_memory_;
// After a second fence is inserted, both the GpuChannelMessageQueue and
// CommandExecutor are descheduled. Once the first fence has completed, both
// get rescheduled.
std::vector<std::unique_ptr<gl::GLFence>> deschedule_until_finished_fences_;
base::WeakPtrFactory<GLES2DecoderPassthroughImpl> weak_ptr_factory_;
// 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