blob: 3fc2ebc9fcb7ef50f62f6c2a8035b90979a56426 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <set>
#include <utility>
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/containers/flat_set.h"
#include "base/containers/queue.h"
#include "base/containers/span.h"
#include "base/debug/alias.h"
#include "base/debug/dump_without_crashing.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/ranges.h"
#include "base/numerics/safe_math.h"
#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "gpu/command_buffer/common/debug_marker_manager.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/command_buffer/service/buffer_manager.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/context_state.h"
#include "gpu/command_buffer/service/decoder_client.h"
#include "gpu/command_buffer/service/error_state.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/framebuffer_manager.h"
#include "gpu/command_buffer/service/gl_stream_texture_image.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.h"
#include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
#include "gpu/command_buffer/service/gles2_cmd_copy_tex_image.h"
#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h"
#include "gpu/command_buffer/service/gles2_cmd_srgb_converter.h"
#include "gpu/command_buffer/service/gles2_cmd_validation.h"
#include "gpu/command_buffer/service/gles2_query_manager.h"
#include "gpu/command_buffer/service/gpu_fence_manager.h"
#include "gpu/command_buffer/service/gpu_state_tracer.h"
#include "gpu/command_buffer/service/gpu_tracer.h"
#include "gpu/command_buffer/service/image_factory.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/memory_tracking.h"
#include "gpu/command_buffer/service/path_manager.h"
#include "gpu/command_buffer/service/program_manager.h"
#include "gpu/command_buffer/service/renderbuffer_manager.h"
#include "gpu/command_buffer/service/sampler_manager.h"
#include "gpu/command_buffer/service/service_discardable_manager.h"
#include "gpu/command_buffer/service/shader_manager.h"
#include "gpu/command_buffer/service/shader_translator.h"
#include "gpu/command_buffer/service/shared_image_factory.h"
#include "gpu/command_buffer/service/shared_image_representation.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/command_buffer/service/transform_feedback_manager.h"
#include "gpu/command_buffer/service/validating_abstract_texture_impl.h"
#include "gpu/command_buffer/service/vertex_array_manager.h"
#include "gpu/command_buffer/service/vertex_attrib_manager.h"
#include "gpu/config/gpu_preferences.h"
#include "third_party/angle/src/image_util/loadimage.h"
#include "third_party/smhasher/src/City.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/ipc/color/gfx_param_traits.h"
#include "ui/gfx/overlay_transform.h"
#include "ui/gfx/transform.h"
#include "ui/gl/ca_renderer_layer_params.h"
#include "ui/gl/dc_renderer_layer_params.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_fence.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/gpu_timing.h"
#include "ui/gl/init/create_gr_gl_interface.h"
#include "ui/gl/scoped_make_current.h"
#if defined(OS_MACOSX)
#include <IOSurface/IOSurface.h>
// Note that this must be included after gl_bindings.h to avoid conflicts.
#include <OpenGL/CGLIOSurface.h>
#endif
namespace gpu {
namespace gles2 {
namespace {
const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
const char kWEBGLMultiDrawExtension[] = "GL_WEBGL_multi_draw";
const char kWEBGLMultiDrawInstancedExtension[] =
"GL_WEBGL_multi_draw_instanced";
gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
switch (plane_transform) {
case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
return gfx::OVERLAY_TRANSFORM_NONE;
case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
return gfx::OVERLAY_TRANSFORM_ROTATE_90;
case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
return gfx::OVERLAY_TRANSFORM_ROTATE_180;
case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
return gfx::OVERLAY_TRANSFORM_ROTATE_270;
default:
return gfx::OVERLAY_TRANSFORM_INVALID;
}
}
template <typename MANAGER_TYPE, typename OBJECT_TYPE>
GLuint GetClientId(const MANAGER_TYPE* manager, const OBJECT_TYPE* object) {
DCHECK(manager);
GLuint client_id = 0;
if (object) {
manager->GetClientId(object->service_id(), &client_id);
}
return client_id;
}
template <typename OBJECT_TYPE>
GLuint GetServiceId(const OBJECT_TYPE* object) {
return object ? object->service_id() : 0;
}
struct Vec4f {
explicit Vec4f(const Vec4& data) {
data.GetValues(v);
}
GLfloat v[4];
};
struct TexSubCoord3D {
TexSubCoord3D(int _xoffset, int _yoffset, int _zoffset,
int _width, int _height, int _depth)
: xoffset(_xoffset),
yoffset(_yoffset),
zoffset(_zoffset),
width(_width),
height(_height),
depth(_depth) {}
int xoffset;
int yoffset;
int zoffset;
int width;
int height;
int depth;
};
// Check if all |ref| bits are set in |bits|.
bool AllBitsSet(GLbitfield bits, GLbitfield ref) {
DCHECK_NE(0u, ref);
return ((bits & ref) == ref);
}
// Check if any of |ref| bits are set in |bits|.
bool AnyBitsSet(GLbitfield bits, GLbitfield ref) {
DCHECK_NE(0u, ref);
return ((bits & ref) != 0);
}
// Check if any bits are set in |bits| other than the bits in |ref|.
bool AnyOtherBitsSet(GLbitfield bits, GLbitfield ref) {
DCHECK_NE(0u, ref);
GLbitfield mask = ~ref;
return ((bits & mask) != 0);
}
void APIENTRY GLDebugMessageCallback(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const GLvoid* user_param) {
Logger* error_logger = static_cast<Logger*>(const_cast<void*>(user_param));
LogGLDebugMessage(source, type, id, severity, length, message, error_logger);
}
} // namespace
class GLES2DecoderImpl;
// Local versions of the SET_GL_ERROR macros
#define LOCAL_SET_GL_ERROR(error, function_name, msg) \
ERRORSTATE_SET_GL_ERROR(error_state_.get(), error, function_name, msg)
#define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state_.get(), function_name, \
static_cast<uint32_t>(value), label)
#define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_.get(), function_name)
#define LOCAL_PEEK_GL_ERROR(function_name) \
ERRORSTATE_PEEK_GL_ERROR(error_state_.get(), function_name)
#define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_.get()) function_name)
#define LOCAL_PERFORMANCE_WARNING(msg) \
PerformanceWarning(__FILE__, __LINE__, msg)
#define LOCAL_RENDER_WARNING(msg) \
RenderWarning(__FILE__, __LINE__, msg)
// Check that certain assumptions the code makes are true. There are places in
// the code where shared memory is passed direclty to GL. Example, glUniformiv,
// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
// a few others) are 32bits. If they are not 32bits the code will have to change
// to call those GL functions with service side memory and then copy the results
// to shared memory, converting the sizes.
static_assert(sizeof(GLint) == sizeof(uint32_t), // NOLINT
"GLint should be the same size as uint32_t");
static_assert(sizeof(GLsizei) == sizeof(uint32_t), // NOLINT
"GLsizei should be the same size as uint32_t");
static_assert(sizeof(GLfloat) == sizeof(float), // NOLINT
"GLfloat should be the same size as float");
// TODO(kbr): the use of this anonymous namespace core dumps the
// linker on Mac OS X 10.6 when the symbol ordering file is used
// namespace {
// Return true if a character belongs to the ASCII subset as defined in
// GLSL ES 1.0 spec section 3.1.
static bool CharacterIsValidForGLES(unsigned char c) {
// Printing characters are valid except " $ ` @ \ ' DEL.
if (c >= 32 && c <= 126 &&
c != '"' &&
c != '$' &&
c != '`' &&
c != '@' &&
c != '\\' &&
c != '\'') {
return true;
}
// Horizontal tab, line feed, vertical tab, form feed, carriage return
// are also valid.
if (c >= 9 && c <= 13) {
return true;
}
return false;
}
static bool StringIsValidForGLES(const std::string& str) {
return str.length() == 0 ||
std::find_if_not(str.begin(), str.end(), CharacterIsValidForGLES) ==
str.end();
}
// This class prevents any GL errors that occur when it is in scope from
// being reported to the client.
class ScopedGLErrorSuppressor {
public:
explicit ScopedGLErrorSuppressor(
const char* function_name, ErrorState* error_state);
~ScopedGLErrorSuppressor();
private:
const char* function_name_;
ErrorState* error_state_;
DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
};
// Temporarily changes a decoder's bound texture and restore it when this
// object goes out of scope. Also temporarily switches to using active texture
// unit zero in case the client has changed that to something invalid.
class ScopedTextureBinder {
public:
explicit ScopedTextureBinder(ContextState* state,
ErrorState* error_state,
GLuint id,
GLenum target);
~ScopedTextureBinder();
private:
ContextState* state_;
ErrorState* error_state_;
GLenum target_;
DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
};
// Temporarily changes a decoder's bound render buffer and restore it when this
// object goes out of scope.
class ScopedRenderBufferBinder {
public:
explicit ScopedRenderBufferBinder(ContextState* state,
ErrorState* error_state,
GLuint id);
~ScopedRenderBufferBinder();
private:
ContextState* state_;
ErrorState* error_state_;
DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
};
// Temporarily changes a decoder's bound frame buffer and restore it when this
// object goes out of scope.
class ScopedFramebufferBinder {
public:
explicit ScopedFramebufferBinder(GLES2DecoderImpl* decoder, GLuint id);
~ScopedFramebufferBinder();
private:
GLES2DecoderImpl* decoder_;
DISALLOW_COPY_AND_ASSIGN(ScopedFramebufferBinder);
};
// Temporarily changes a decoder's bound frame buffer to a resolved version of
// the multisampled offscreen render buffer if that buffer is multisampled, and,
// if it is bound or enforce_internal_framebuffer is true. If internal is
// true, the resolved framebuffer is not visible to the parent.
class ScopedResolvedFramebufferBinder {
public:
explicit ScopedResolvedFramebufferBinder(GLES2DecoderImpl* decoder,
bool enforce_internal_framebuffer,
bool internal);
~ScopedResolvedFramebufferBinder();
private:
GLES2DecoderImpl* decoder_;
bool resolve_and_bind_;
DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFramebufferBinder);
};
// Temporarily create and bind a single sample copy of the currently bound
// framebuffer using CopyTexImage2D. This is useful as a workaround for drivers
// that have broken implementations of ReadPixels on multisampled framebuffers.
// See http://crbug.com/890002
class ScopedFramebufferCopyBinder {
public:
explicit ScopedFramebufferCopyBinder(GLES2DecoderImpl* decoder,
GLint x = 0,
GLint y = 0,
GLint width = 0,
GLint height = 0);
~ScopedFramebufferCopyBinder();
private:
GLES2DecoderImpl* decoder_;
std::unique_ptr<ScopedFramebufferBinder> framebuffer_binder_;
GLuint temp_texture_;
GLuint temp_framebuffer_;
DISALLOW_COPY_AND_ASSIGN(ScopedFramebufferCopyBinder);
};
// Temporarily changes a decoder's PIXEL_UNPACK_BUFFER to 0 and set pixel unpack
// params to default, and restore them when this object goes out of scope.
class ScopedPixelUnpackState {
public:
explicit ScopedPixelUnpackState(ContextState* state);
~ScopedPixelUnpackState();
private:
ContextState* state_;
DISALLOW_COPY_AND_ASSIGN(ScopedPixelUnpackState);
};
// Encapsulates an OpenGL texture.
class BackTexture {
public:
explicit BackTexture(GLES2DecoderImpl* decoder);
~BackTexture();
// Create a new render texture.
void Create();
// Set the initial size and format of a render texture or resize it.
bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
// Copy the contents of the currently bound frame buffer.
void Copy();
// Destroy the render texture. This must be explicitly called before
// destroying this object.
void Destroy();
// Invalidate the texture. This can be used when a context is lost and it is
// not possible to make it current in order to free the resource.
void Invalidate();
// The bind point for the texture.
GLenum Target();
scoped_refptr<TextureRef> texture_ref() { return texture_ref_; }
GLuint id() const {
return texture_ref_ ? texture_ref_->service_id() : 0;
}
gfx::Size size() const {
return size_;
}
gl::GLApi* api() const;
private:
// The texture must be bound to Target() before calling this method.
// Returns whether the operation was successful.
bool AllocateNativeGpuMemoryBuffer(const gfx::Size& size,
GLenum format,
bool zero);
// The texture must be bound to Target() before calling this method.
void DestroyNativeGpuMemoryBuffer(bool have_context);
MemoryTypeTracker memory_tracker_;
size_t bytes_allocated_;
gfx::Size size_;
GLES2DecoderImpl* decoder_;
scoped_refptr<TextureRef> texture_ref_;
// The image that backs the texture, if its backed by a native
// GpuMemoryBuffer.
scoped_refptr<gl::GLImage> image_;
DISALLOW_COPY_AND_ASSIGN(BackTexture);
};
// Encapsulates an OpenGL render buffer of any format.
class BackRenderbuffer {
public:
explicit BackRenderbuffer(GLES2DecoderImpl* decoder);
~BackRenderbuffer();
// Create a new render buffer.
void Create();
// Set the initial size and format of a render buffer or resize it.
bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
// Destroy the render buffer. This must be explicitly called before destroying
// this object.
void Destroy();
// Invalidate the render buffer. This can be used when a context is lost and
// it is not possible to make it current in order to free the resource.
void Invalidate();
GLuint id() const {
return id_;
}
gl::GLApi* api() const;
private:
GLES2DecoderImpl* decoder_;
MemoryTypeTracker memory_tracker_;
size_t bytes_allocated_;
GLuint id_;
DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
};
// Encapsulates an OpenGL frame buffer.
class BackFramebuffer {
public:
explicit BackFramebuffer(GLES2DecoderImpl* decoder);
~BackFramebuffer();
// Create a new frame buffer.
void Create();
// Attach a color render buffer to a frame buffer.
void AttachRenderTexture(BackTexture* texture);
// Attach a render buffer to a frame buffer. Note that this unbinds any
// currently bound frame buffer.
void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
// Destroy the frame buffer. This must be explicitly called before destroying
// this object.
void Destroy();
// Invalidate the frame buffer. This can be used when a context is lost and it
// is not possible to make it current in order to free the resource.
void Invalidate();
// See glCheckFramebufferStatusEXT.
GLenum CheckStatus();
GLuint id() const {
return id_;
}
gl::GLApi* api() const;
private:
GLES2DecoderImpl* decoder_;
GLuint id_;
DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
};
struct FenceCallback {
FenceCallback() : fence(gl::GLFence::Create()) { DCHECK(fence); }
FenceCallback(FenceCallback&&) = default;
FenceCallback& operator=(FenceCallback&&) = default;
std::vector<base::OnceClosure> callbacks;
std::unique_ptr<gl::GLFence> fence;
};
// For ensuring that client-side glRenderbufferStorageMultisampleEXT
// calls go down the correct code path.
enum ForcedMultisampleMode {
kForceExtMultisampledRenderToTexture,
kDoNotForce
};
// } // anonymous namespace.
// static
const unsigned int GLES2Decoder::kDefaultStencilMask =
static_cast<unsigned int>(-1);
bool GLES2Decoder::GetServiceTextureId(uint32_t client_texture_id,
uint32_t* service_texture_id) {
return false;
}
uint32_t GLES2Decoder::GetAndClearBackbufferClearBitsForTest() {
return 0;
}
GLES2Decoder::GLES2Decoder(CommandBufferServiceBase* command_buffer_service,
Outputter* outputter)
: CommonDecoder(command_buffer_service), outputter_(outputter) {
DCHECK(outputter_);
}
GLES2Decoder::~GLES2Decoder() = default;
bool GLES2Decoder::initialized() const {
return initialized_;
}
TextureBase* GLES2Decoder::GetTextureBase(uint32_t client_id) {
return nullptr;
}
void GLES2Decoder::SetLevelInfo(uint32_t client_id,
int level,
unsigned internal_format,
unsigned width,
unsigned height,
unsigned depth,
unsigned format,
unsigned type,
const gfx::Rect& cleared_rect) {}
void GLES2Decoder::BeginDecoding() {}
void GLES2Decoder::EndDecoding() {}
base::StringPiece GLES2Decoder::GetLogPrefix() {
return GetLogger()->GetLogPrefix();
}
void GLES2Decoder::SetLogCommands(bool log_commands) {
log_commands_ = log_commands;
}
Outputter* GLES2Decoder::outputter() const {
return outputter_;
}
// This class implements GLES2Decoder so we don't have to expose all the GLES2
// cmd stuff to outside this class.
class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
public:
GLES2DecoderImpl(DecoderClient* client,
CommandBufferServiceBase* command_buffer_service,
Outputter* outputter,
ContextGroup* group);
~GLES2DecoderImpl() override;
error::Error DoCommands(unsigned int num_commands,
const volatile void* buffer,
int num_entries,
int* entries_processed) override;
template <bool DebugImpl>
error::Error DoCommandsImpl(unsigned int num_commands,
const volatile void* buffer,
int num_entries,
int* entries_processed);
// Overridden from GLES2Decoder.
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;
void Destroy(bool have_context) override;
void SetSurface(const scoped_refptr<gl::GLSurface>& surface) override;
void ReleaseSurface() override;
void TakeFrontBuffer(const Mailbox& mailbox) override;
void ReturnFrontBuffer(const Mailbox& mailbox, bool is_lost) override;
bool ResizeOffscreenFramebuffer(const gfx::Size& size) override;
bool MakeCurrent() override;
gl::GLApi* api() const { return state_.api(); }
GLES2Util* GetGLES2Util() override { return &util_; }
gl::GLContext* GetGLContext() override { return context_.get(); }
gl::GLSurface* GetGLSurface() override { return surface_.get(); }
ContextGroup* GetContextGroup() override { return group_.get(); }
const FeatureInfo* GetFeatureInfo() const override {
return feature_info_.get();
}
Capabilities GetCapabilities() override;
void RestoreState(const ContextState* prev_state) override;
void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
void RestoreAllTextureUnitAndSamplerBindings(
const ContextState* prev_state) const override {
state_.RestoreAllTextureUnitAndSamplerBindings(prev_state);
}
void RestoreActiveTextureUnitBinding(unsigned int target) const override {
state_.RestoreActiveTextureUnitBinding(target);
}
void RestoreBufferBindings() const override {
state_.RestoreBufferBindings();
}
void RestoreGlobalState() const override {
state_.RestoreGlobalState(nullptr);
}
void RestoreProgramBindings() const override {
state_.RestoreProgramSettings(nullptr, false);
}
void RestoreTextureUnitBindings(unsigned unit) const override {
state_.RestoreTextureUnitBindings(unit, nullptr);
}
void RestoreVertexAttribArray(unsigned index) override {
RestoreStateForAttrib(index, true);
}
void RestoreBufferBinding(unsigned int target) override;
void RestoreFramebufferBindings() const override;
void RestoreRenderbufferBindings() override;
void RestoreTextureState(unsigned service_id) const override;
void ClearDeviceWindowRectangles() const;
void RestoreDeviceWindowRectangles() const override;
void ClearAllAttributes() const override;
void RestoreAllAttributes() const override;
QueryManager* GetQueryManager() override { return query_manager_.get(); }
void SetQueryCallback(unsigned int query_client_id,
base::OnceClosure callback) override;
GpuFenceManager* GetGpuFenceManager() override {
return gpu_fence_manager_.get();
}
FramebufferManager* GetFramebufferManager() override {
return framebuffer_manager_.get();
}
TransformFeedbackManager* GetTransformFeedbackManager() override {
return transform_feedback_manager_.get();
}
VertexArrayManager* GetVertexArrayManager() override {
return vertex_array_manager_.get();
}
ImageManager* GetImageManagerForTest() override {
return group_->image_manager();
}
bool HasPendingQueries() const override;
void ProcessPendingQueries(bool did_finish) override;
bool HasMoreIdleWork() const override;
void PerformIdleWork() override;
bool HasPollingWork() const override;
void PerformPollingWork() override;
void WaitForReadPixels(base::OnceClosure callback) override;
Logger* GetLogger() override;
void BeginDecoding() override;
void EndDecoding() override;
ErrorState* GetErrorState() override;
const ContextState* GetContextState() override { return &state_; }
std::unique_ptr<AbstractTexture> CreateAbstractTexture(GLenum target,
GLenum internal_format,
GLsizei width,
GLsizei height,
GLsizei depth,
GLint border,
GLenum format,
GLenum type) override;
scoped_refptr<ShaderTranslatorInterface> GetTranslator(GLenum type) override;
scoped_refptr<ShaderTranslatorInterface> GetOrCreateTranslator(GLenum type);
void SetIgnoreCachedStateForTest(bool ignore) override;
void SetForceShaderNameHashingForTest(bool force) override;
uint32_t GetAndClearBackbufferClearBitsForTest() override;
void ProcessFinishedAsyncTransfers();
bool GetServiceTextureId(uint32_t client_texture_id,
uint32_t* service_texture_id) override;
TextureBase* GetTextureBase(uint32_t client_id) override;
void SetLevelInfo(uint32_t client_id,
int level,
unsigned internal_format,
unsigned width,
unsigned height,
unsigned depth,
unsigned format,
unsigned type,
const gfx::Rect& cleared_rect) override;
// Restores the current state to the user's settings.
void RestoreCurrentFramebufferBindings();
// Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
void ApplyDirtyState();
// These check the state of the currently bound framebuffer or the
// backbuffer if no framebuffer is bound.
// Check with all attached and enabled color attachments.
bool BoundFramebufferAllowsChangesToAlphaChannel();
bool BoundFramebufferHasDepthAttachment();
bool BoundFramebufferHasStencilAttachment();
// Overriden from ErrorStateClient.
void OnContextLostError() override;
void OnOutOfMemoryError() override;
// Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
void EnsureRenderbufferBound();
// Helpers to facilitate calling into compatible extensions.
void RenderbufferStorageMultisampleWithWorkaround(GLenum target,
GLsizei samples,
GLenum internal_format,
GLsizei width,
GLsizei height,
ForcedMultisampleMode mode);
void RenderbufferStorageMultisampleHelper(GLenum target,
GLsizei samples,
GLenum internal_format,
GLsizei width,
GLsizei height,
ForcedMultisampleMode mode);
bool RegenerateRenderbufferIfNeeded(Renderbuffer* renderbuffer);
PathManager* path_manager() { return group_->path_manager(); }
void SetCopyTextureResourceManagerForTest(
CopyTextureCHROMIUMResourceManager* copy_texture_resource_manager)
override {
copy_texture_chromium_.reset(copy_texture_resource_manager);
}
void SetCopyTexImageBlitterForTest(
CopyTexImageResourceManager* copy_tex_image_blit) override {
copy_tex_image_blit_.reset(copy_tex_image_blit);
}
// ServiceFontManager::Client implementation.
scoped_refptr<gpu::Buffer> GetShmBuffer(uint32_t shm_id);
private:
friend class ScopedFramebufferBinder;
friend class ScopedResolvedFramebufferBinder;
friend class ScopedFramebufferCopyBinder;
friend class BackFramebuffer;
friend class BackRenderbuffer;
friend class BackTexture;
enum FramebufferOperation {
kFramebufferDiscard,
kFramebufferInvalidate,
kFramebufferInvalidateSub
};
enum BindIndexedBufferFunctionType {
kBindBufferBase,
kBindBufferRange
};
const char* GetCommandName(unsigned int command_id) const;
// Initialize or re-initialize the shader translator.
bool InitializeShaderTranslator();
void DestroyShaderTranslator();
void UpdateCapabilities();
// Helpers for the glGen and glDelete functions.
bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
void DeleteTexturesHelper(GLsizei n, const volatile GLuint* client_ids);
bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
void DeleteBuffersHelper(GLsizei n, const volatile GLuint* client_ids);
bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
void DeleteFramebuffersHelper(GLsizei n, const volatile GLuint* client_ids);
bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
void DeleteRenderbuffersHelper(GLsizei n, const volatile GLuint* client_ids);
bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
void DeleteQueriesEXTHelper(GLsizei n, const volatile GLuint* client_ids);
bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
void DeleteVertexArraysOESHelper(GLsizei n,
const volatile GLuint* client_ids);
bool GenPathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
bool DeletePathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
bool GenSamplersHelper(GLsizei n, const GLuint* client_ids);
void DeleteSamplersHelper(GLsizei n, const volatile GLuint* client_ids);
bool GenTransformFeedbacksHelper(GLsizei n, const GLuint* client_ids);
void DeleteTransformFeedbacksHelper(GLsizei n,
const volatile GLuint* client_ids);
void DeleteSyncHelper(GLuint sync);
bool UnmapBufferHelper(Buffer* buffer, GLenum target);
// Workarounds
void OnFboChanged() const;
void OnUseFramebuffer() const;
void UpdateFramebufferSRGB(Framebuffer* framebuffer);
// TODO(gman): Cache these pointers?
BufferManager* buffer_manager() {
return group_->buffer_manager();
}
RenderbufferManager* renderbuffer_manager() {
return group_->renderbuffer_manager();
}
FramebufferManager* framebuffer_manager() {
return framebuffer_manager_.get();
}
ProgramManager* program_manager() {
return group_->program_manager();
}
SamplerManager* sampler_manager() {
return group_->sampler_manager();
}
ShaderManager* shader_manager() {
return group_->shader_manager();
}
ShaderTranslatorCache* shader_translator_cache() {
return group_->shader_translator_cache();
}
const TextureManager* texture_manager() const {
return group_->texture_manager();
}
TextureManager* texture_manager() {
return group_->texture_manager();
}
MailboxManager* mailbox_manager() {
return group_->mailbox_manager();
}
ImageManager* image_manager() { return group_->image_manager(); }
VertexArrayManager* vertex_array_manager() {
return vertex_array_manager_.get();
}
MemoryTracker* memory_tracker() {
return group_->memory_tracker();
}
const gl::GLVersionInfo& gl_version_info() {
return feature_info_->gl_version_info();
}
bool IsOffscreenBufferMultisampled() const {
return offscreen_target_samples_ > 0;
}
// Creates a Texture for the given texture.
TextureRef* CreateTexture(
GLuint client_id, GLuint service_id) {
return texture_manager()->CreateTexture(client_id, service_id);
}
// Gets the texture info for the given texture. Returns nullptr if none
// exists.
TextureRef* GetTexture(GLuint client_id) const {
return texture_manager()->GetTexture(client_id);
}
// Deletes the texture info for the given texture.
void RemoveTexture(GLuint client_id) {
texture_manager()->RemoveTexture(client_id);
}
// Creates a Sampler for the given sampler.
Sampler* CreateSampler(
GLuint client_id, GLuint service_id) {
return sampler_manager()->CreateSampler(client_id, service_id);
}
// Gets the sampler info for the given sampler. Returns nullptr if none
// exists.
Sampler* GetSampler(GLuint client_id) {
return sampler_manager()->GetSampler(client_id);
}
// Deletes the sampler info for the given sampler.
void RemoveSampler(GLuint client_id) {
sampler_manager()->RemoveSampler(client_id);
}
// Creates a TransformFeedback for the given transformfeedback.
TransformFeedback* CreateTransformFeedback(
GLuint client_id, GLuint service_id) {
return transform_feedback_manager_->CreateTransformFeedback(
client_id, service_id);
}
// Gets the TransformFeedback info for the given transformfeedback.
// Returns nullptr if none exists.
TransformFeedback* GetTransformFeedback(GLuint client_id) {
return transform_feedback_manager_->GetTransformFeedback(client_id);
}
// Deletes the TransformFeedback info for the given transformfeedback.
void RemoveTransformFeedback(GLuint client_id) {
transform_feedback_manager_->RemoveTransformFeedback(client_id);
}
// Get the size (in pixels) of the currently bound frame buffer (either FBO
// or regular back buffer).
gfx::Size GetBoundReadFramebufferSize();
// Get the service side ID for the bound read framebuffer.
// If it's back buffer, 0 is returned.
GLuint GetBoundReadFramebufferServiceId();
// Get the service side ID for the bound draw framebuffer.
// If it's back buffer, 0 is returned.
GLuint GetBoundDrawFramebufferServiceId() const;
// Get the format/type of the currently bound frame buffer (either FBO or
// regular back buffer).
// If the color image is a renderbuffer, returns 0 for type.
GLenum GetBoundReadFramebufferTextureType();
GLenum GetBoundReadFramebufferInternalFormat();
// Get the i-th draw buffer's internal format/type from the bound framebuffer.
// If no framebuffer is bound, or no image is attached, or the DrawBuffers
// setting for that image is GL_NONE, return 0.
GLenum GetBoundColorDrawBufferType(GLint drawbuffer_i);
GLenum GetBoundColorDrawBufferInternalFormat(GLint drawbuffer_i);
GLsizei GetBoundFramebufferSamples(GLenum target);
// Return 0 if no depth attachment.
GLenum GetBoundFramebufferDepthFormat(GLenum target);
// Return 0 if no stencil attachment.
GLenum GetBoundFramebufferStencilFormat(GLenum target);
gfx::Vector2d GetBoundFramebufferDrawOffset() const {
if (GetBoundDrawFramebuffer() || offscreen_target_frame_buffer_.get())
return gfx::Vector2d();
return surface_->GetDrawOffset();
}
void MarkDrawBufferAsCleared(GLenum buffer, GLint drawbuffer_i);
// Wrapper for CompressedTexImage{2|3}D commands.
error::Error DoCompressedTexImage(
GLenum target,
GLint level,
GLenum internal_format,
GLsizei width,
GLsizei height,
GLsizei depth,
GLint border,
GLsizei image_size,
const void* data,
ContextState::Dimension dimension);
// Wrapper for CompressedTexSubImage{2|3}D.
error::Error DoCompressedTexSubImage(
GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint zoffset,
GLsizei width,
GLsizei height,
GLsizei depth,
GLenum format,
GLsizei imageSize,
const void* data,
ContextState::Dimension dimension);
// Validate if |format| is valid for CopyTex{Sub}Image functions.
// If not, generate a GL error and return false.
bool ValidateCopyTexFormat(const char* func_name, GLenum internal_format,
GLenum read_format, GLenum read_type);
// Wrapper for CopyTexImage2D.
void DoCopyTexImage2D(
GLenum target,
GLint level,
GLenum internal_format,
GLint x,
GLint y,
GLsizei width,
GLsizei height,
GLint border);
// Wrapper for SwapBuffers.
void DoSwapBuffers(uint64_t swap_id, GLbitfield flags);
// Wrapper for SwapBuffersWithBoundsCHROMIUM.
void DoSwapBuffersWithBoundsCHROMIUM(uint64_t swap_id,
GLsizei count,
const volatile GLint* rects,
GLbitfield flags);
// Callback for async SwapBuffers.
void FinishAsyncSwapBuffers(uint64_t swap_id,
gfx::SwapResult result,
std::unique_ptr<gfx::GpuFence>);
void FinishSwapBuffers(gfx::SwapResult result);
void DoCommitOverlayPlanes(uint64_t swap_id, GLbitfield flags);
// Wrapper for CopyTexSubImage2D.
void DoCopyTexSubImage2D(
GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint x,
GLint y,
GLsizei width,
GLsizei height);
// Wrapper for CopyTexSubImage3D.
void DoCopyTexSubImage3D(
GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint zoffset,
GLint x,
GLint y,
GLsizei width,
GLsizei height);
// Wrapper for glCopyBufferSubData.
void DoCopyBufferSubData(GLenum readtarget,
GLenum writetarget,
GLintptr readoffset,
GLintptr writeoffset,
GLsizeiptr size);
void DoCopyTextureCHROMIUM(GLuint source_id,
GLint source_level,
GLenum dest_target,
GLuint dest_id,
GLint dest_level,
GLenum internal_format,
GLenum dest_type,
GLboolean unpack_flip_y,
GLboolean unpack_premultiply_alpha,
GLboolean unpack_unmultiply_alpha);
void DoCopySubTextureCHROMIUM(GLuint source_id,
GLint source_level,
GLenum dest_target,
GLuint dest_id,
GLint dest_level,
GLint xoffset,
GLint yoffset,
GLint x,
GLint y,
GLsizei width,
GLsizei height,
GLboolean unpack_flip_y,
GLboolean unpack_premultiply_alpha,
GLboolean unpack_unmultiply_alpha);
// Helper for DoTexStorage2DEXT and DoTexStorage3D.
void TexStorageImpl(GLenum target,
GLsizei levels,
GLenum internal_format,
GLsizei width,
GLsizei height,
GLsizei depth,
ContextState::Dimension dimension,
const char* function_name);
// Wrapper for TexStorage2DEXT.
void DoTexStorage2DEXT(GLenum target,
GLsizei levels,
GLenum internal_format,
GLsizei width,
GLsizei height);
// Wrapper for TexStorage3D.
void DoTexStorage3D(GLenum target,
GLsizei levels,
GLenum internal_format,
GLsizei width,
GLsizei height,
GLsizei depth);
void DoTexStorage2DImageCHROMIUM(GLenum target,
GLenum internal_format,
GLenum buffer_usage,
GLsizei width,
GLsizei height);
void DoProduceTextureDirectCHROMIUM(GLuint texture,
const volatile GLbyte* key);
void DoCreateAndConsumeTextureINTERNAL(GLuint client_id,
const volatile GLbyte* key);
void DoCreateAndTexStorage2DSharedImageINTERNAL(GLuint client_id,
const volatile GLbyte* data);
void DoBeginSharedImageAccessDirectCHROMIUM(GLuint client_id, GLenum mode);
void DoEndSharedImageAccessDirectCHROMIUM(GLuint client_id);
void DoApplyScreenSpaceAntialiasingCHROMIUM();
void BindImage(uint32_t client_texture_id,
uint32_t texture_target,
gl::GLImage* image,
bool can_bind_to_sampler) override;
void DoBindTexImage2DCHROMIUM(
GLenum target,
GLint image_id);
void DoBindTexImage2DWithInternalformatCHROMIUM(GLenum target,
GLenum internalformat,
GLint image_id);
// Common implementation of DoBindTexImage2DCHROMIUM entry points.
void BindTexImage2DCHROMIUMImpl(const char* function_name,
GLenum target,
GLenum internalformat,
GLint image_id);
void DoReleaseTexImage2DCHROMIUM(
GLenum target,
GLint image_id);
void DoTraceEndCHROMIUM(void);
void DoDrawBuffersEXT(GLsizei count, const volatile GLenum* bufs);
void DoLoseContextCHROMIUM(GLenum current, GLenum other);
void DoFlushDriverCachesCHROMIUM(void);
void DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
const volatile GLfloat* matrix);
void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
void DoScheduleCALayerInUseQueryCHROMIUM(GLsizei count,
const volatile GLuint* textures);
void DoFlushMappedBufferRange(
GLenum target, GLintptr offset, GLsizeiptr size);
void DoScheduleDCLayerCHROMIUM(GLuint y_texture_id,
GLuint uv_texture_id,
GLint z_order,
GLint content_x,
GLint content_y,
GLint content_width,
GLint content_height,
GLint quad_x,
GLint quad_y,
GLint quad_width,
GLint quad_height,
GLfloat transform_c1r1,
GLfloat transform_c2r1,
GLfloat transform_c1r2,
GLfloat transform_c2r2,
GLfloat transform_tx,
GLfloat transform_ty,
GLboolean is_clipped,
GLint clip_x,
GLint clip_y,
GLint clip_width,
GLint clip_height,
GLuint protected_video_type);
// Creates a Program for the given program.
Program* CreateProgram(GLuint client_id, GLuint service_id) {
return program_manager()->CreateProgram(client_id, service_id);
}
// Gets the program info for the given program. Returns nullptr if none
// exists.
Program* GetProgram(GLuint client_id) {
return program_manager()->GetProgram(client_id);
}
#if defined(NDEBUG)
void LogClientServiceMapping(
const char* /* function_name */,
GLuint /* client_id */,
GLuint /* service_id */) {
}
template<typename T>
void LogClientServiceForInfo(
T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
}
#else
void LogClientServiceMapping(
const char* function_name, GLuint client_id, GLuint service_id) {
if (service_logging_) {
VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
<< ": client_id = " << client_id
<< ", service_id = " << service_id;
}
}
template<typename T>
void LogClientServiceForInfo(
T* info, GLuint client_id, const char* function_name) {
if (info) {
LogClientServiceMapping(function_name, client_id, info->service_id());
}
}
#endif
// Gets the program info for the given program. If it's not a program
// generates a GL error. Returns nullptr if not program.
Program* GetProgramInfoNotShader(
GLuint client_id, const char* function_name) {
Program* program = GetProgram(client_id);
if (!program) {
if (GetShader(client_id)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, function_name, "shader passed for program");
} else {
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
}
}
LogClientServiceForInfo(program, client_id, function_name);
return program;
}
// Creates a Shader for the given shader.
Shader* CreateShader(
GLuint client_id,
GLuint service_id,
GLenum shader_type) {
return shader_manager()->CreateShader(
client_id, service_id, shader_type);
}
// Gets the shader info for the given shader. Returns nullptr if none exists.
Shader* GetShader(GLuint client_id) {
return shader_manager()->GetShader(client_id);
}
// Gets the shader info for the given shader. If it's not a shader generates a
// GL error. Returns nullptr if not shader.
Shader* GetShaderInfoNotProgram(
GLuint client_id, const char* function_name) {
Shader* shader = GetShader(client_id);
if (!shader) {
if (GetProgram(client_id)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, function_name, "program passed for shader");
} else {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE, function_name, "unknown shader");
}
}
LogClientServiceForInfo(shader, client_id, function_name);
return shader;
}
// Creates a buffer info for the given buffer.
void CreateBuffer(GLuint client_id, GLuint service_id) {
return buffer_manager()->CreateBuffer(client_id, service_id);
}
// Gets the buffer info for the given buffer.
Buffer* GetBuffer(GLuint client_id) {
Buffer* buffer = buffer_manager()->GetBuffer(client_id);
return buffer;
}
// Creates a framebuffer info for the given framebuffer.
void CreateFramebuffer(GLuint client_id, GLuint service_id) {
return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
}
// Gets the framebuffer info for the given framebuffer.
Framebuffer* GetFramebuffer(GLuint client_id) {
return framebuffer_manager()->GetFramebuffer(client_id);
}
// Removes the framebuffer info for the given framebuffer.
void RemoveFramebuffer(GLuint client_id) {
framebuffer_manager()->RemoveFramebuffer(client_id);
}
// Creates a renderbuffer info for the given renderbuffer.
void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
return renderbuffer_manager()->CreateRenderbuffer(
client_id, service_id);
}
// Gets the renderbuffer info for the given renderbuffer.
Renderbuffer* GetRenderbuffer(GLuint client_id) {
return renderbuffer_manager()->GetRenderbuffer(client_id);
}
// Removes the renderbuffer info for the given renderbuffer.
void RemoveRenderbuffer(GLuint client_id) {
renderbuffer_manager()->RemoveRenderbuffer(client_id);
}
// Gets the vertex attrib manager for the given vertex array.
VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
VertexAttribManager* info =
vertex_array_manager()->GetVertexAttribManager(client_id);
return info;
}
// Removes the vertex attrib manager for the given vertex array.
void RemoveVertexAttribManager(GLuint client_id) {
vertex_array_manager()->RemoveVertexAttribManager(client_id);
}
// Creates a vertex attrib manager for the given vertex array.
scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
GLuint client_id,
GLuint service_id,
bool client_visible) {
return vertex_array_manager()->CreateVertexAttribManager(
client_id, service_id, group_->max_vertex_attribs(), client_visible,
feature_info_->IsWebGL2OrES3Context());
}
void DoBindAttribLocation(GLuint client_id,
GLuint index,
const std::string& name);
error::Error DoBindFragDataLocation(GLuint program_id,
GLuint colorName,
const std::string& name);
error::Error DoBindFragDataLocationIndexed(GLuint program_id,
GLuint colorName,
GLuint index,
const std::string& name);
void DoBindUniformLocationCHROMIUM(GLuint client_id,
GLint location,
const std::string& name);
error::Error GetAttribLocationHelper(GLuint client_id,
uint32_t location_shm_id,
uint32_t location_shm_offset,
const std::string& name_str);
error::Error GetUniformLocationHelper(GLuint client_id,
uint32_t location_shm_id,
uint32_t location_shm_offset,
const std::string& name_str);
error::Error GetFragDataLocationHelper(GLuint client_id,
uint32_t location_shm_id,
uint32_t location_shm_offset,
const std::string& name_str);
error::Error GetFragDataIndexHelper(GLuint program_id,
uint32_t index_shm_id,
uint32_t index_shm_offset,
const std::string& name_str);
// Wrapper for glShaderSource.
void DoShaderSource(
GLuint client_id, GLsizei count, const char** data, const GLint* length);
// Wrapper for glTransformFeedbackVaryings.
void DoTransformFeedbackVaryings(
GLuint client_program_id, GLsizei count, const char* const* varyings,
GLenum buffer_mode);
// Clear any textures used by the current program.
bool ClearUnclearedTextures();
// Clears any uncleared attachments attached to the given frame buffer.
// Returns false if there was a generated GL error.
void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
// overridden from GLES2Decoder
bool ClearLevel(Texture* texture,
unsigned target,
int level,
unsigned format,
unsigned type,
int xoffset,
int yoffset,
int width,
int height) override;
// Helper function for ClearLevel that attempts to clear using a glClear call
// to a temporary FBO, rather than using glTexSubImage2D.
bool ClearLevelUsingGL(Texture* texture,
uint32_t channels,
unsigned target,
int level,
int xoffset,
int yoffset,
int width,
int height);
// overridden from GLES2Decoder
bool ClearCompressedTextureLevel(Texture* texture,
unsigned target,
int level,
unsigned format,
int width,
int height) override;
bool IsCompressedTextureFormat(unsigned format) override;
// overridden from GLES2Decoder
bool ClearLevel3D(Texture* texture,
unsigned target,
int level,
unsigned format,
unsigned type,
int width,
int height,
int depth) override;
// Restore all GL state that affects clearing.
void RestoreClearState();
// Remembers the state of some capabilities.
// Returns: true if glEnable/glDisable should actually be called.
bool SetCapabilityState(GLenum cap, bool enabled);
// Check that the currently bound read framebuffer's color image
// isn't the target texture of the glCopyTex{Sub}Image{2D|3D}.
bool FormsTextureCopyingFeedbackLoop(
TextureRef* texture,
GLint level,
GLint layer);
// Check if a framebuffer meets our requirements.
// Generates |gl_error| if the framebuffer is incomplete.
bool CheckFramebufferValid(
Framebuffer* framebuffer,
GLenum target,
GLenum gl_error,
const char* func_name);
bool CheckBoundDrawFramebufferValid(const char* func_name);
// Generates |gl_error| if the bound read fbo is incomplete.
bool CheckBoundReadFramebufferValid(const char* func_name, GLenum gl_error);
// This is only used by DoBlitFramebufferCHROMIUM which operates read/draw
// framebuffer at the same time.
bool CheckBoundFramebufferValid(const char* func_name);
// Checks if the current program exists and is valid. If not generates the
// appropriate GL error. Returns true if the current program is in a usable
// state.
bool CheckCurrentProgram(const char* function_name);
// Checks if the current program exists and is valid and that location is not
// -1. If the current program is not valid generates the appropriate GL
// error. Returns true if the current program is in a usable state and
// location is not -1.
bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
// Checks if the current program samples a texture that is also the color
// image of the current bound framebuffer, i.e., the source and destination
// of the draw operation are the same.
bool CheckDrawingFeedbackLoops();
bool SupportsDrawBuffers() const;
// Checks if a draw buffer's format and its corresponding fragment shader
// output's type are compatible, i.e., a signed integer typed variable is
// incompatible with a float or unsigned integer buffer.
// If incompaticle, generates an INVALID_OPERATION to avoid undefined buffer
// contents and return false.
// Otherwise, filter out the draw buffers that are not written to but are not
// NONE through DrawBuffers, to be on the safe side. Return true.
bool ValidateAndAdjustDrawBuffers(const char* function_name);
// Filter out the draw buffers that have no images attached but are not NONE
// through DrawBuffers, to be on the safe side.
void AdjustDrawBuffers();
// Checks if all active uniform blocks in the current program are backed by
// a buffer of sufficient size.
// If not, generates an INVALID_OPERATION to avoid undefined behavior in
// shader execution and return false.
bool ValidateUniformBlockBackings(const char* function_name);
// Checks if |api_type| is valid for the given uniform
// If the api type is not valid generates the appropriate GL
// error. Returns true if |api_type| is valid for the uniform
bool CheckUniformForApiType(const Program::UniformInfo* info,
const char* function_name,
Program::UniformApiType api_type);
// Gets the type of a uniform for a location in the current program. Sets GL
// errors if the current program is not valid. Returns true if the current
// program is valid and the location exists. Adjusts count so it
// does not overflow the uniform.
bool PrepForSetUniformByLocation(GLint fake_location,
const char* function_name,
Program::UniformApiType api_type,
GLint* real_location,
GLenum* type,
GLsizei* count);
// Gets the service id for any simulated backbuffer fbo.
GLuint GetBackbufferServiceId() const;
// Helper for glGetBooleanv, glGetFloatv and glGetIntegerv. Returns
// false if pname is unhandled.
bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
// Helper for glGetVertexAttrib
void GetVertexAttribHelper(
const VertexAttrib* attrib, GLenum pname, GLint* param);
// Wrapper for glActiveTexture
void DoActiveTexture(GLenum texture_unit);
// Wrapper for glAttachShader
void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
// Wrapper for glBindBuffer since we need to track the current targets.
void DoBindBuffer(GLenum target, GLuint buffer);
// Wrapper for glBindBufferBase since we need to track the current targets.
void DoBindBufferBase(GLenum target, GLuint index, GLuint buffer);
// Wrapper for glBindBufferRange since we need to track the current targets.
void DoBindBufferRange(GLenum target, GLuint index, GLuint buffer,
GLintptr offset, GLsizeiptr size);
// Helper for DoBindBufferBase and DoBindBufferRange.
void BindIndexedBufferImpl(GLenum target, GLuint index, GLuint buffer,
GLintptr offset, GLsizeiptr size,
BindIndexedBufferFunctionType function_type,
const char* function_name);
// Wrapper for glBindFramebuffer since we need to track the current targets.
void DoBindFramebuffer(GLenum target, GLuint framebuffer);
// Wrapper for glBindRenderbuffer since we need to track the current targets.
void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
// Wrapper for glBindTexture since we need to track the current targets.
void DoBindTexture(GLenum target, GLuint texture);
// Wrapper for glBindSampler since we need to track the current targets.
void DoBindSampler(GLuint unit, GLuint sampler);
// Wrapper for glBindTransformFeedback since we need to emulate ES3 behaviors
// for BindBufferRange on Desktop GL lower than 4.2.
void DoBindTransformFeedback(GLenum target, GLuint transform_feedback);
// Wrapper for glBeginTransformFeedback.
void DoBeginTransformFeedback(GLenum primitive_mode);
// Wrapper for glEndTransformFeedback.
void DoEndTransformFeedback();
// Wrapper for glPauseTransformFeedback.
void DoPauseTransformFeedback();
// Wrapper for glResumeTransformFeedback.
void DoResumeTransformFeedback();
// Wrapper for glBindVertexArrayOES
void DoBindVertexArrayOES(GLuint array);
void EmulateVertexArrayState();
// Wrapper for glBlitFramebufferCHROMIUM.
void DoBlitFramebufferCHROMIUM(
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
// Wrapper for glBufferSubData.
void DoBufferSubData(
GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
// Wrapper for glCheckFramebufferStatus
GLenum DoCheckFramebufferStatus(GLenum target);
// Wrapper for glClear*()
error::Error DoClear(GLbitfield mask);
void DoClearBufferiv(GLenum buffer,
GLint drawbuffer,
const volatile GLint* value);
void DoClearBufferuiv(GLenum buffer,
GLint drawbuffer,
const volatile GLuint* value);
void DoClearBufferfv(GLenum buffer,
GLint drawbuffer,
const volatile GLfloat* value);
void DoClearBufferfi(
GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
// Wrappers for various state.
void DoDepthRangef(GLclampf znear, GLclampf zfar);
void DoSampleCoverage(GLclampf value, GLboolean invert);
// Wrapper for glCompileShader.
void DoCompileShader(GLuint shader);
// Wrapper for glDetachShader
void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
// Wrapper for glDisable
void DoDisable(GLenum cap);
// Wrapper for glDisableVertexAttribArray.
void DoDisableVertexAttribArray(GLuint index);
// Wrapper for glDiscardFramebufferEXT, since we need to track undefined
// attachments.
void DoDiscardFramebufferEXT(GLenum target,
GLsizei count,
const volatile GLenum* attachments);
void DoInvalidateFramebuffer(GLenum target,
GLsizei count,
const volatile GLenum* attachments);
void DoInvalidateSubFramebuffer(GLenum target,
GLsizei count,
const volatile GLenum* attachments,
GLint x,
GLint y,
GLsizei width,
GLsizei height);
// Helper for DoDiscardFramebufferEXT, DoInvalidate{Sub}Framebuffer.
void InvalidateFramebufferImpl(GLenum target,
GLsizei count,
const volatile GLenum* attachments,
GLint x,
GLint y,
GLsizei width,
GLsizei height,
const char* function_name,
FramebufferOperation op);
// Wrapper for glEnable
void DoEnable(GLenum cap);
// Wrapper for glEnableVertexAttribArray.
void DoEnableVertexAttribArray(GLuint index);
// Wrapper for glFinish.
void DoFinish();
// Wrapper for glFlush.
void DoFlush();
// Wrapper for glFramebufferParameteri.
void DoFramebufferParameteri(GLenum target, GLenum pname, GLint param);
// Wrapper for glFramebufferRenderbufffer.
void DoFramebufferRenderbuffer(
GLenum target, GLenum attachment, GLenum renderbuffertarget,
GLuint renderbuffer);
// Wrapper for glFramebufferTexture2D.
void DoFramebufferTexture2D(
GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
GLint level);
// Wrapper for glFramebufferTexture2DMultisampleEXT.
void DoFramebufferTexture2DMultisample(
GLenum target, GLenum attachment, GLenum textarget,
GLuint texture, GLint level, GLsizei samples);
// Common implementation for both DoFramebufferTexture2D wrappers.
void DoFramebufferTexture2DCommon(const char* name,
GLenum target, GLenum attachment, GLenum textarget,
GLuint texture, GLint level, GLsizei samples);
// Wrapper for glFramebufferTextureLayer.
void DoFramebufferTextureLayer(
GLenum target, GLenum attachment, GLuint texture, GLint level,
GLint layer);
// Wrapper for glFramebufferTextureLayer.
void DoFramebufferTextureMultiviewLayeredANGLE(GLenum target,
GLenum attachment,
GLuint texture,
GLint level,
GLint base_view_index,
GLsizei num_views);
// Wrapper for glGenerateMipmap
void DoGenerateMipmap(GLenum target);
// Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
// to account for different pname values defined in different extension
// variants.
GLenum AdjustGetPname(GLenum pname);
// Wrapper for DoGetBooleanv.
void DoGetBooleanv(GLenum pname, GLboolean* params, GLsizei params_size);
// Wrapper for DoGetFloatv.
void DoGetFloatv(GLenum pname, GLfloat* params, GLsizei params_size);
// Wrapper for glGetFramebufferAttachmentParameteriv.
void DoGetFramebufferAttachmentParameteriv(GLenum target,
GLenum attachment,
GLenum pname,
GLint* params,
GLsizei params_size);
// Wrapper for glGetInteger64v.
void DoGetInteger64v(GLenum pname, GLint64* params, GLsizei params_size);
// Wrapper for glGetIntegerv.
void DoGetIntegerv(GLenum pname, GLint* params, GLsizei params_size);
// Helper for DoGetIntegeri_v and DoGetInteger64i_v.
template <typename TYPE>
void GetIndexedIntegerImpl(
const char* function_name, GLenum target, GLuint index, TYPE* data);
// Wrapper for glGetIntegeri_v.
void DoGetIntegeri_v(GLenum target,
GLuint index,
GLint* params,
GLsizei params_size);
// Wrapper for glGetInteger64i_v.
void DoGetInteger64i_v(GLenum target,
GLuint index,
GLint64* params,
GLsizei params_size);
// Gets the max value in a range in a buffer.
GLuint DoGetMaxValueInBufferCHROMIUM(
GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
// Wrapper for glGetBufferParameteri64v.
void DoGetBufferParameteri64v(GLenum target,
GLenum pname,
GLint64* params,
GLsizei params_size);
// Wrapper for glGetBufferParameteriv.
void DoGetBufferParameteriv(GLenum target,
GLenum pname,
GLint* params,
GLsizei params_size);
// Wrapper for glGetProgramiv.
void DoGetProgramiv(GLuint program_id,
GLenum pname,
GLint* params,
GLsizei params_size);
// Wrapper for glRenderbufferParameteriv.
void DoGetRenderbufferParameteriv(GLenum target,
GLenum pname,
GLint* params,
GLsizei params_size);
// Wrappers for glGetSamplerParameter.
void DoGetSamplerParameterfv(GLuint client_id,
GLenum pname,
GLfloat* params,
GLsizei params_size);
void DoGetSamplerParameteriv(GLuint client_id,
GLenum pname,
GLint* params,
GLsizei params_size);
// Wrapper for glGetShaderiv
void DoGetShaderiv(GLuint shader,
GLenum pname,
GLint* params,
GLsizei params_size);
// Wrapper for glGetSynciv.
void DoGetSynciv(GLuint sync_id,
GLenum pname,
GLsizei num_values,
GLsizei* length,
GLint* values);
// Helper for DoGetTexParameter{f|i}v.
void GetTexParameterImpl(
GLenum target, GLenum pname, GLfloat* fparams, GLint* iparams,
const char* function_name);
// Wrappers for glGetTexParameter.
void DoGetTexParameterfv(GLenum target,
GLenum pname,
GLfloat* params,
GLsizei params_size);
void DoGetTexParameteriv(GLenum target,
GLenum pname,
GLint* params,
GLsizei params_size);
// Wrappers for glGetVertexAttrib.
template <typename T>
void DoGetVertexAttribImpl(GLuint index, GLenum pname, T* params);
void DoGetVertexAttribfv(GLuint index,
GLenum pname,
GLfloat* params,
GLsizei params_size);
void DoGetVertexAttribiv(GLuint index,
GLenum pname,
GLint* params,
GLsizei params_size);
void DoGetVertexAttribIiv(GLuint index,
GLenum pname,
GLint* params,
GLsizei params_size);
void DoGetVertexAttribIuiv(GLuint index,
GLenum pname,
GLuint* params,
GLsizei params_size);
// Wrappers for glIsXXX functions.
bool DoIsEnabled(GLenum cap);
bool DoIsBuffer(GLuint client_id);
bool DoIsFramebuffer(GLuint client_id);
bool DoIsProgram(GLuint client_id);
bool DoIsRenderbuffer(GLuint client_id);
bool DoIsShader(GLuint client_id);
bool DoIsTexture(GLuint client_id);
bool DoIsSampler(GLuint client_id);
bool DoIsTransformFeedback(GLuint client_id);
bool DoIsVertexArrayOES(GLuint client_id);
bool DoIsPathCHROMIUM(GLuint client_id);
bool DoIsSync(GLuint client_id);
void DoLineWidth(GLfloat width);
// Wrapper for glLinkProgram
void DoLinkProgram(GLuint program);
// Wrapper for glMultiDrawArraysWEBGL
void DoMultiDrawArraysWEBGL(GLenum mode,
const GLint* firsts,
const GLsizei* counts,
GLsizei drawcount);
// Wrapper for glMultiDrawArraysInstancedWEBGL
void DoMultiDrawArraysInstancedWEBGL(GLenum mode,
const GLint* firsts,
const GLsizei* counts,
const GLsizei* instance_counts,
GLsizei drawcount);
// Wrapper for glMultiDrawElementsWEBGL
void DoMultiDrawElementsWEBGL(GLenum mode,
const GLsizei* counts,
GLenum type,
const GLsizei* offsets,
GLsizei drawcount);
// Wrapper for glMultiDrawElementsInstancedWEBGL
void DoMultiDrawElementsInstancedWEBGL(GLenum mode,
const GLsizei* counts,
GLenum type,
const GLsizei* offsets,
const GLsizei* instance_counts,
GLsizei drawcount);
// Wrapper for glOverlayPromotionHintCHROMIUIM
void DoOverlayPromotionHintCHROMIUM(GLuint client_id,
GLboolean promotion_hint,
GLint display_x,
GLint display_y,
GLint display_width,
GLint display_height);
// Wrapper for glSetDrawRectangleCHROMIUM
void DoSetDrawRectangleCHROMIUM(GLint x, GLint y, GLint width, GLint height);
void DoSetEnableDCLayersCHROMIUM(GLboolean enable);
// Wrapper for glReadBuffer
void DoReadBuffer(GLenum src);
// Wrapper for glRenderbufferStorage.
void DoRenderbufferStorage(
GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
// Handler for glRenderbufferStorageMultisampleCHROMIUM.
void DoRenderbufferStorageMultisampleCHROMIUM(
GLenum target, GLsizei samples, GLenum internalformat,
GLsizei width, GLsizei height);
// Handler for glRenderbufferStorageMultisampleEXT
// (multisampled_render_to_texture).
void DoRenderbufferStorageMultisampleEXT(
GLenum target, GLsizei samples, GLenum internalformat,
GLsizei width, GLsizei height);
// Wrapper for glFenceSync.
GLsync DoFenceSync(GLenum condition, GLbitfield flags);
// Common validation for multisample extensions.
bool ValidateRenderbufferStorageMultisample(GLsizei samples,
GLenum internalformat,
GLsizei width,
GLsizei height);
// Verifies that the currently bound multisample renderbuffer is valid
// Very slow! Only done on platforms with driver bugs that return invalid
// buffers under memory pressure
bool VerifyMultisampleRenderbufferIntegrity(
GLuint renderbuffer, GLenum format);
// Wrapper for glReleaseShaderCompiler.
void DoReleaseShaderCompiler();
// Wrappers for glSamplerParameter functions.
void DoSamplerParameterf(GLuint client_id, GLenum pname, GLfloat param);
void DoSamplerParameteri(GLuint client_id, GLenum pname, GLint param);
void DoSamplerParameterfv(GLuint client_id,
GLenum pname,
const volatile GLfloat* params);
void DoSamplerParameteriv(GLuint client_id,
GLenum pname,
const volatile GLint* params);
// Wrappers for glTexParameter functions.
void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
void DoTexParameteri(GLenum target, GLenum pname, GLint param);
void DoTexParameterfv(GLenum target,
GLenum pname,
const volatile GLfloat* params);
void DoTexParameteriv(GLenum target,
GLenum pname,
const volatile GLint* params);
// Wrappers for glUniform1i and glUniform1iv as according to the GLES2
// spec only these 2 functions can be used to set sampler uniforms.
void DoUniform1i(GLint fake_location, GLint v0);
void DoUniform1iv(GLint fake_location,
GLsizei count,
const volatile GLint* value);
void DoUniform2iv(GLint fake_location,
GLsizei count,
const volatile GLint* value);
void DoUniform3iv(GLint fake_location,
GLsizei count,
const volatile GLint* value);
void DoUniform4iv(GLint fake_location,
GLsizei count,
const volatile GLint* value);
void DoUniform1ui(GLint fake_location, GLuint v0);
void DoUniform1uiv(GLint fake_location,
GLsizei count,
const volatile GLuint* value);
void DoUniform2uiv(GLint fake_location,
GLsizei count,
const volatile GLuint* value);
void DoUniform3uiv(GLint fake_location,
GLsizei count,
const volatile GLuint* value);
void DoUniform4uiv(GLint fake_location,
GLsizei count,
const volatile GLuint* value);
// Wrappers for glUniformfv because some drivers don't correctly accept
// bool uniforms.
void DoUniform1fv(GLint fake_location,
GLsizei count,
const volatile GLfloat* value);
void DoUniform2fv(GLint fake_location,
GLsizei count,
const volatile GLfloat* value);
void DoUniform3fv(GLint fake_location,
GLsizei count,
const volatile GLfloat* value);
void DoUniform4fv(GLint fake_location,
GLsizei count,
const volatile GLfloat* value);
void DoUniformMatrix2fv(GLint fake_location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value);
void DoUniformMatrix3fv(GLint fake_location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value);
void DoUniformMatrix4fv(GLint fake_location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value);
void DoUniformMatrix4fvStreamTextureMatrixCHROMIUM(
GLint fake_location,
GLboolean transpose,
const volatile GLfloat* default_value);
void DoUniformMatrix2x3fv(GLint fake_location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value);
void DoUniformMatrix2x4fv(GLint fake_location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value);
void DoUniformMatrix3x2fv(GLint fake_location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value);
void DoUniformMatrix3x4fv(GLint fake_location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value);
void DoUniformMatrix4x2fv(GLint fake_location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value);
void DoUniformMatrix4x3fv(GLint fake_location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value);
template <typename T>
bool SetVertexAttribValue(
const char* function_name, GLuint index, const T* value);
// Wrappers for glVertexAttrib??
void DoVertexAttrib1f(GLuint index, GLfloat v0);
void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
void DoVertexAttrib4f(
GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
void DoVertexAttrib1fv(GLuint index, const volatile GLfloat* v);
void DoVertexAttrib2fv(GLuint index, const volatile GLfloat* v);
void DoVertexAttrib3fv(GLuint index, const volatile GLfloat* v);
void DoVertexAttrib4fv(GLuint index, const volatile GLfloat* v);
void DoVertexAttribI4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3);
void DoVertexAttribI4iv(GLuint index, const volatile GLint* v);
void DoVertexAttribI4ui(
GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
void DoVertexAttribI4uiv(GLuint index, const volatile GLuint* v);
// Wrapper for glViewport
void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
// Wrapper for glScissor
void DoScissor(GLint x, GLint y, GLsizei width, GLsizei height);
// Wrapper for glUseProgram
void DoUseProgram(GLuint program);
// Wrapper for glValidateProgram.
void DoValidateProgram(GLuint program_client_id);
void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
void DoPopGroupMarkerEXT(void);
// Gets the number of values that will be returned by glGetXXX. Returns
// false if pname is unknown.
bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
// Checks if every attribute's type set by vertexAttrib API match
// the type of corresponding attribute in vertex shader.
bool AttribsTypeMatch();
// Verifies that front/back stencil settings match, per WebGL specification:
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.11
bool ValidateStencilStateForDraw(const char* function_name);
// Checks if the current program and vertex attributes are valid for drawing.
bool IsDrawValid(
const char* function_name, GLuint max_vertex_accessed, bool instanced,
GLsizei primcount);
// Returns true if successful, simulated will be true if attrib0 was
// simulated.
bool SimulateAttrib0(
const char* function_name, GLuint max_vertex_accessed, bool* simulated);
void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
// Copies the image to the texture currently bound to |textarget|. The image
// state of |texture| is updated to reflect the new state.
void DoCopyTexImage(Texture* texture, GLenum textarget, gl::GLImage* image);
// If the texture has an image but that image is not bound or copied to the
// texture, this will first attempt to bind it, and if that fails
// DoCopyTexImage on it. texture_unit is the texture unit it should be bound
// to, or 0 if it doesn't matter - setting it to 0 will cause the previous
// binding to be restored after the operation. This returns true if a copy
// or bind happened and the caller needs to restore the previous texture
// binding.
bool DoBindOrCopyTexImageIfNeeded(Texture* texture,
GLenum textarget,
GLuint texture_unit);
void DoUnpremultiplyAndDitherCopyCHROMIUM(GLuint source_id,
GLuint dest_id,
GLint x,
GLint y,
GLsizei width,
GLsizei height);
void DoWindowRectanglesEXT(GLenum mode, GLsizei n, const volatile GLint* box);
void DoSetReadbackBufferShadowAllocationINTERNAL(GLuint buffer_id,
GLuint shm_id,
GLuint shm_offset,
GLuint size);
// Returns false if textures were replaced.
bool PrepareTexturesForRender();
void RestoreStateForTextures();
// Returns true if GL_FIXED attribs were simulated.
bool SimulateFixedAttribs(
const char* function_name,
GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
void RestoreStateForSimulatedFixedAttribs();
bool CheckMultiDrawArraysVertices(const char* function_name,
bool instanced,
const GLint* firsts,
const GLsizei* counts,
const GLsizei* primcounts,
GLsizei drawcount,
GLuint* total_max_vertex_accessed,
GLsizei* total_max_primcount);
bool CheckMultiDrawElementsVertices(const char* function_name,
bool instanced,
const GLsizei* counts,
GLenum type,
const int32_t* offsets,
const GLsizei* primcounts,
GLsizei drawcount,
Buffer* element_array_buffer,
GLuint* total_max_vertex_accessed,
GLsizei* total_max_primcount);
bool CheckTransformFeedback(const char* function_name,
bool instanced,
GLenum mode,
const GLsizei* counts,
const GLsizei* primcounts,
GLsizei drawcount,
GLsizei* transform_feedback_vertices);
// Handle MultiDrawArrays and MultiDrawElements for both instanced and
// non-instanced cases (primcount is always 1 for non-instanced).
error::Error DoMultiDrawArrays(const char* function_name,
bool instanced,
GLenum mode,
const GLint* firsts,
const GLsizei* counts,
const GLsizei* primcounts,
GLsizei drawcount);
error::Error DoMultiDrawElements(const char* function_name,
bool instanced,
GLenum mode,
const GLsizei* counts,
GLenum type,
const int32_t* offsets,
const GLsizei* primcounts,
GLsizei drawcount);
GLenum GetBindTargetForSamplerType(GLenum type) {
switch (type) {
case GL_SAMPLER_2D:
case GL_SAMPLER_2D_SHADOW:
case GL_INT_SAMPLER_2D:
case GL_UNSIGNED_INT_SAMPLER_2D:
return GL_TEXTURE_2D;
case GL_SAMPLER_CUBE:
case GL_SAMPLER_CUBE_SHADOW:
case GL_INT_SAMPLER_CUBE:
case GL_UNSIGNED_INT_SAMPLER_CUBE:
return GL_TEXTURE_CUBE_MAP;
case GL_SAMPLER_EXTERNAL_OES:
return GL_TEXTURE_EXTERNAL_OES;
case GL_SAMPLER_2D_RECT_ARB:
return GL_TEXTURE_RECTANGLE_ARB;
case GL_SAMPLER_3D:
case GL_INT_SAMPLER_3D:
case GL_UNSIGNED_INT_SAMPLER_3D:
return GL_TEXTURE_3D;
case GL_SAMPLER_2D_ARRAY:
case GL_SAMPLER_2D_ARRAY_SHADOW:
case GL_INT_SAMPLER_2D_ARRAY:
case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
return GL_TEXTURE_2D_ARRAY;
default:
NOTREACHED();
return 0;
}
}
// Gets the framebuffer info for a particular target.
Framebuffer* GetFramebufferInfoForTarget(GLenum target) const {
Framebuffer* framebuffer = nullptr;
switch (target) {
case GL_FRAMEBUFFER:
case GL_DRAW_FRAMEBUFFER_EXT:
framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
break;
case GL_READ_FRAMEBUFFER_EXT:
framebuffer = framebuffer_state_.bound_read_framebuffer.get();
break;
default:
NOTREACHED();
break;
}
return framebuffer;
}
Renderbuffer* GetRenderbufferInfoForTarget(
GLenum target) {
Renderbuffer* renderbuffer = nullptr;
switch (target) {
case GL_RENDERBUFFER:
renderbuffer = state_.bound_renderbuffer.get();
break;
default:
NOTREACHED();
break;
}
return renderbuffer;
}
// Validates the program and location for a glGetUniform call and returns
// a SizeResult setup to receive the result. Returns true if glGetUniform
// should be called.
template <class T>
bool GetUniformSetup(GLuint program,
GLint fake_location,
uint32_t shm_id,
uint32_t shm_offset,
error::Error* error,
GLint* real_location,
GLuint* service_id,
SizedResult<T>** result,
GLenum* result_type,
GLsizei* result_size);
bool WasContextLost() const override;
bool WasContextLostByRobustnessExtension() const override;
void MarkContextLost(error::ContextLostReason reason) override;
bool CheckResetStatus() override;
bool ValidateCompressedTexDimensions(
const char* function_name, GLenum target, GLint level,
GLsizei width, GLsizei height, GLsizei depth, GLenum format);
bool ValidateCompressedTexFuncData(const char* function_name,
GLsizei width,
GLsizei height,
GLsizei depth,
GLenum format,
GLsizei size,
const GLvoid* data);
bool ValidateCompressedTexSubDimensions(
const char* function_name,
GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth, GLenum format,
Texture* texture);
bool ValidateCopyTextureCHROMIUMTextures(const char* function_name,
GLenum dest_target,
TextureRef* source_texture_ref,
TextureRef* dest_texture_ref);
bool CanUseCopyTextureCHROMIUMInternalFormat(GLenum dest_internal_format);
void CopySubTextureHelper(const char* function_name,
GLuint source_id,
GLint source_level,
GLenum dest_target,
GLuint dest_id,
GLint dest_level,
GLint xoffset,
GLint yoffset,
GLint x,
GLint y,
GLsizei width,
GLsizei height,
GLboolean unpack_flip_y,
GLboolean unpack_premultiply_alpha,
GLboolean unpack_unmultiply_alpha,
GLboolean dither);
void RenderWarning(const char* filename, int line, const std::string& msg);
void PerformanceWarning(
const char* filename, int line, const std::string& msg);
const FeatureInfo::FeatureFlags& features() const {
return feature_info_->feature_flags();
}
const GpuDriverBugWorkarounds& workarounds() const {
return feature_info_->workarounds();
}
bool ShouldDeferDraws() {
return !offscreen_target_frame_buffer_.get() &&
framebuffer_state_.bound_draw_framebuffer.get() == nullptr &&
surface_->DeferDraws();
}
bool ShouldDeferReads() {
return !offscreen_target_frame_buffer_.get() &&
framebuffer_state_.bound_read_framebuffer.get() == nullptr &&
surface_->DeferDraws();
}
bool IsRobustnessSupported() {
return has_robustness_extension_ &&
context_->WasAllocatedUsingRobustnessExtension();
}
error::Error WillAccessBoundFramebufferForDraw() {
if (ShouldDeferDraws())
return error::kDeferCommandUntilLater;
if (!offscreen_target_frame_buffer_.get() &&
!framebuffer_state_.bound_draw_framebuffer.get() &&
!surface_->SetBackbufferAllocation(true))
return error::kLostContext;
return error::kNoError;
}
error::Error WillAccessBoundFramebufferForRead() {
if (ShouldDeferReads())
return error::kDeferCommandUntilLater;
if (!offscreen_target_frame_buffer_.get() &&
!framebuffer_state_.bound_read_framebuffer.get() &&
!surface_->SetBackbufferAllocation(true))
return error::kLostContext;
return error::kNoError;
}
// Whether the back buffer exposed to the client has an alpha channel. Note
// that this is potentially different from whether the implementation of the
// back buffer has an alpha channel.
bool ClientExposedBackBufferHasAlpha() const {
if (back_buffer_draw_buffer_ == GL_NONE)
return false;
if (offscreen_target_frame_buffer_.get()) {
return offscreen_buffer_should_have_alpha_;
}
return (back_buffer_color_format_ == GL_RGBA ||
back_buffer_color_format_ == GL_RGBA8);
}
// If the back buffer has a non-emulated alpha channel, the clear color should
// be 0. Otherwise, the clear color should be 1.
GLfloat BackBufferAlphaClearColor() const {
return offscreen_buffer_should_have_alpha_ ? 0.f : 1.f;
}
// Set remaining commands to process to 0 to force DoCommands to return
// and allow context preemption and GPU watchdog checks in CommandExecutor().
void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
void ProcessPendingReadPixels(bool did_finish);
void FinishReadPixels(GLsizei width,
GLsizei height,
GLsizei format,
GLsizei type,
uint32_t pixels_shm_id,
uint32_t pixels_shm_offset,
uint32_t result_shm_id,
uint32_t result_shm_offset,
GLint pack_alignment,
GLenum read_format,
GLuint buffer);
// Checks to see if the inserted fence has completed.
void ProcessDescheduleUntilFinished();
void DoBindFragmentInputLocationCHROMIUM(GLuint program_id,
GLint location,
const std::string& name);
// If |texture_manager_version_| doesn't match the current version, then this
// will rebind all external textures to match their current service_id.
void RestoreAllExternalTextureBindingsIfNeeded() override;
const SamplerState& GetSamplerStateForTextureUnit(GLenum target, GLuint unit);
// copyTexImage2D doesn't work on OSX under very specific conditions.
// Returns whether those conditions have been met. If this method returns
// true, |source_texture_service_id| and |source_texture_target| are also
// populated, since they are needed to implement the workaround.
bool NeedsCopyTextureImageWorkaround(GLenum internal_format,
int32_t channels_exist,
GLuint* source_texture_service_id,
GLenum* source_texture_target);
// Whether a texture backed by a Chromium Image needs to emulate GL_RGB format
// using GL_RGBA and glColorMask.
bool ChromiumImageNeedsRGBEmulation();
// The GL_CHROMIUM_schedule_ca_layer extension requires that SwapBuffers and
// equivalent functions reset shared state.
void ClearScheduleCALayerState();
// Helper method to call glClear workaround.
void ClearFramebufferForWorkaround(GLbitfield mask);
bool SupportsSeparateFramebufferBinds() const {
return (feature_info_->feature_flags().chromium_framebuffer_multisample ||
feature_info_->IsWebGL2OrES3Context());
}
GLenum GetDrawFramebufferTarget() const {
return SupportsSeparateFramebufferBinds() ?
GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
}
GLenum GetReadFramebufferTarget() const {
return SupportsSeparateFramebufferBinds() ?
GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
}
Framebuffer* GetBoundDrawFramebuffer() const {
return framebuffer_state_.bound_draw_framebuffer.get();
}
Framebuffer* GetBoundReadFramebuffer() const {
GLenum target = GetReadFramebufferTarget();
return GetFramebufferInfoForTarget(target);
}
bool InitializeCopyTexImageBlitter(const char* function_name);
bool InitializeCopyTextureCHROMIUM(const char* function_name);
bool InitializeSRGBConverter(const char* function_name);
void UnbindTexture(TextureRef* texture_ref,
bool supports_separate_framebuffer_binds);
void OnAbstractTextureDestroyed(ValidatingAbstractTextureImpl* texture,
scoped_refptr<TextureRef> texture_ref);
void ReadBackBuffersIntoShadowCopies(
base::flat_set<scoped_refptr<Buffer>> buffers_to_shadow_copy);
// Compiles the given shader and exits command processing early.
void CompileShaderAndExitCommandProcessingEarly(Shader* shader);
// Notify the watchdog thread of progress, preventing time-outs when a
// command takes a long time. May be no-op when using in-process command
// buffer.
void ReportProgress();
// Generate a member function prototype for each command in an automated and
// typesafe way.
#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
DecoderClient* client_;
// The GL context this decoder renders to on behalf of the client.
scoped_refptr<gl::GLSurface> surface_;
scoped_refptr<gl::GLContext> context_;
// The ContextGroup for this decoder uses to track resources.
scoped_refptr<ContextGroup> group_;
DebugMarkerManager debug_marker_manager_;
Logger logger_;
std::unique_ptr<ErrorState> error_state_;
// All the state for this context.
ContextState state_;
std::unique_ptr<TransformFeedbackManager> transform_feedback_manager_;
// Current width and height of the offscreen frame buffer.
gfx::Size offscreen_size_;
// Util to help with GL.
GLES2Util util_;
// The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
GLuint attrib_0_buffer_id_;
// The value currently in attrib_0.
Vec4 attrib_0_value_;
// Whether or not the attrib_0 buffer holds the attrib_0_value.
bool attrib_0_buffer_matches_value_;
// The size of attrib 0.
GLsizei attrib_0_size_;
// The buffer used to simulate GL_FIXED attribs.
GLuint fixed_attrib_buffer_id_;
// The size of fiixed attrib buffer.
GLsizei fixed_attrib_buffer_size_;
// The offscreen frame buffer that the client renders to. With EGL, the
// depth and stencil buffers are separate. With regular GL there is a single
// packed depth stencil buffer in offscreen_target_depth_render_buffer_.
// offscreen_target_stencil_render_buffer_ is unused.
std::unique_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
std::unique_ptr<BackTexture> offscreen_target_color_texture_;
std::unique_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
std::unique_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
std::unique_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
// The format of the texture or renderbuffer backing the offscreen
// framebuffer. Also the format of the texture backing the saved offscreen
// framebuffer.
GLenum offscreen_target_color_format_;
GLenum offscreen_target_depth_format_;
GLenum offscreen_target_stencil_format_;
GLsizei offscreen_target_samples_;
GLboolean offscreen_target_buffer_preserved_;
GLint max_offscreen_framebuffer_size_;
// Whether or not offscreen color buffers exist in front/back pairs that
// can be swapped.
GLboolean offscreen_single_buffer_;
// The saved copy of the backbuffer after a call to SwapBuffers.
std::unique_ptr<BackTexture> offscreen_saved_color_texture_;
// For simplicity, |offscreen_saved_color_texture_| is always bound to
// |offscreen_saved_frame_buffer_|.
std::unique_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
// When a client requests ownership of the swapped front buffer, all
// information is saved in this structure, and |in_use| is set to true. When a
// client releases ownership, |in_use| is set to false.
//
// An instance of this struct, with |in_use| = false may be reused instead of
// making a new BackTexture.
struct SavedBackTexture {
std::unique_ptr<BackTexture> back_texture;
bool in_use;
};
std::vector<SavedBackTexture> saved_back_textures_;
// If there's a SavedBackTexture that's not in use, takes that. Otherwise,
// generates a new back texture.
void CreateBackTexture();
size_t create_back_texture_count_for_test_ = 0;
// Releases all saved BackTextures that are not in use by a client.
void ReleaseNotInUseBackTextures();
// Releases all saved BackTextures.
void ReleaseAllBackTextures(bool have_context);
size_t GetSavedBackTextureCountForTest() override;
size_t GetCreatedBackTextureCountForTest() override;
// The copy that is used as the destination for multi-sample resolves.
std::unique_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
std::unique_ptr<BackTexture> offscreen_resolved_color_texture_;
GLenum offscreen_saved_color_format_;
// Whether the client requested an offscreen buffer with an alpha channel.
bool offscreen_buffer_should_have_alpha_;
std::unique_ptr<FramebufferManager> framebuffer_manager_;
std::unique_ptr<GLES2QueryManager> query_manager_;
std::unique_ptr<GpuFenceManager> gpu_fence_manager_;
std::unique_ptr<VertexArrayManager> vertex_array_manager_;
base::flat_set<scoped_refptr<Buffer>> writes_submitted_but_not_completed_;
// The format of the back buffer_
GLenum back_buffer_color_format_;
bool back_buffer_has_depth_;
bool back_buffer_has_stencil_;
// Tracks read buffer and draw buffer for backbuffer, whether it's onscreen
// or offscreen.
// TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_
// setting is set correctly when SwapBuffers().
GLenum back_buffer_read_buffer_;
GLenum back_buffer_draw_buffer_;
bool surfaceless_;
// Backbuffer attachments that are currently undefined.
uint32_t backbuffer_needs_clear_bits_;
uint64_t swaps_since_resize_;
// The current decoder error communicates the decoder error through command
// processing functions that do not return the error value. Should be set only
// if not returning an error.
error::Error current_decoder_error_;
bool has_fragment_precision_high_ = false;
scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
// Cached from ContextGroup
const Validators* validators_;
scoped_refptr<FeatureInfo> feature_info_;
int frame_number_;
// Number of commands remaining to be processed in DoCommands().
int commands_to_process_;
bool has_robustness_extension_;
bool context_was_lost_;
bool reset_by_robustness_extension_;
bool supports_post_sub_buffer_;
bool supports_swap_buffers_with_bounds_;
bool supports_commit_overlay_planes_;
bool supports_async_swap_;
bool supports_dc_layers_ = false;
// These flags are used to override the state of the shared feature_info_
// member. Because the same FeatureInfo instance may be shared among many
// contexts, the assumptions on the availablity of extensions in WebGL
// contexts may be broken. These flags override the shared state to preserve
// WebGL semantics.
bool derivatives_explicitly_enabled_;
bool frag_depth_explicitly_enabled_;
bool draw_buffers_explicitly_enabled_;
bool shader_texture_lod_explicitly_enabled_;
bool multi_draw_explicitly_enabled_;
bool multi_draw_instanced_explicitly_enabled_;
bool compile_shader_always_succeeds_;
// An optional behaviour to lose the context and group when OOM.
bool lose_context_when_out_of_memory_;
// Forces the backbuffer to use native GMBs rather than a TEXTURE_2D texture.
bool should_use_native_gmb_for_backbuffer_;
// Log extra info.
bool service_logging_;
std::unique_ptr<ApplyFramebufferAttachmentCMAAINTELResourceManager>
apply_framebuffer_attachment_cmaa_intel_;
std::unique_ptr<CopyTexImageResourceManager> copy_tex_image_blit_;
std::unique_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_chromium_;
std::unique_ptr<SRGBConverter> srgb_converter_;
std::unique_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
// Cached values of the currently assigned viewport dimensions.
GLsizei viewport_max_width_;
GLsizei viewport_max_height_;
// Cached value for the number of stencil bits for the default framebuffer.
GLint num_stencil_bits_;
// States related to each manager.
DecoderTextureState texture_state_;
DecoderFramebufferState framebuffer_state_;
std::unique_ptr<GPUTracer> gpu_tracer_;
std::unique_ptr<GPUStateTracer> gpu_state_tracer_;
const unsigned char* gpu_decoder_category_;
int gpu_trace_level_;
bool gpu_trace_commands_;
bool gpu_debug_commands_;
base::queue<FenceCallback> pending_readpixel_fences_;
// 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_;
// Used to validate multisample renderbuffers if needed
typedef base::hash_map<GLenum, GLuint> TextureMap;
TextureMap validation_textures_;
GLuint validation_fbo_multisample_;
GLuint validation_fbo_;
typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
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 command
uint8_t cmd_flags; // How to handle this command
uint16_t arg_count; // How many arguments are expected for this command.