#ifndef GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_
#define GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <map>
#include <memory>
#include <unordered_map>
#include <vector>
#include "base/check_op.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/trace_event/memory_dump_provider.h"
#include "gpu/command_buffer/common/buffer.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/gpu_gles2_export.h"
namespace gpu {
namespace gles2 {
class BufferManager;
struct ContextState;
class ErrorState;
class FeatureInfo;
class IndexedBufferBindingHost;
class TestHelper;
class GPU_GLES2_EXPORT Buffer : public base::RefCounted<Buffer> {
public:
struct MappedRange {
GLintptr offset;
GLsizeiptr size;
GLenum access;
raw_ptr<void, DanglingUntriaged> pointer;
scoped_refptr<gpu::Buffer> shm;
unsigned int shm_offset;
MappedRange(GLintptr offset, GLsizeiptr size, GLenum access, void* pointer,
scoped_refptr<gpu::Buffer> shm, unsigned int shm_offset);
~MappedRange();
void* GetShmPointer() const;
};
Buffer(BufferManager* manager, GLuint service_id);
GLenum initial_target() const { return initial_target_; }
GLuint service_id() const {
return service_id_;
}
GLsizeiptr size() const {
return size_;
}
GLenum usage() const {
return usage_;
}
bool shadowed() const {
return !shadow_.empty();
}
bool GetMaxValueForRange(GLuint offset, GLsizei count, GLenum type,
bool primitive_restart_enabled, GLuint* max_value);
const void* GetRange(GLintptr offset, GLsizeiptr size) const;
bool CheckRange(GLintptr offset, GLsizeiptr size) const;
void SetRange(GLintptr offset, GLsizeiptr size, const GLvoid * data);
bool IsDeleted() const {
return deleted_;
}
bool IsValid() const {
return initial_target() && !IsDeleted();
}
bool IsClientSideArray() const {
return is_client_side_array_;
}
void SetMappedRange(GLintptr offset, GLsizeiptr size, GLenum access,
void* pointer, scoped_refptr<gpu::Buffer> shm,
unsigned int shm_offset);
void RemoveMappedRange();
const MappedRange* GetMappedRange() const {
return mapped_range_.get();
}
void OnBind(GLenum target, bool indexed);
void OnUnbind(GLenum target, bool indexed);
bool IsBoundForTransformFeedback() const {
return transform_feedback_indexed_binding_count_ > 0;
}
bool IsBoundForTransformFeedbackAndOther() const {
return transform_feedback_indexed_binding_count_ > 0 &&
non_transform_feedback_binding_count_ > 0;
}
bool IsDoubleBoundForTransformFeedback() const {
return transform_feedback_indexed_binding_count_ > 1;
}
void SetReadbackShadowAllocation(scoped_refptr<gpu::Buffer> shm,
uint32_t shm_offset);
scoped_refptr<gpu::Buffer> TakeReadbackShadowAllocation(void** data);
private:
friend class BufferManager;
friend class BufferManagerTestBase;
friend class base::RefCounted<Buffer>;
class Range {
public:
Range(GLuint offset, GLsizei count, GLenum type,
bool primitive_restart_enabled)
: offset_(offset),
count_(count),
type_(type),
primitive_restart_enabled_(primitive_restart_enabled) {
}
struct Less {
bool operator() (const Range& lhs, const Range& rhs) const {
if (lhs.offset_ != rhs.offset_) {
return lhs.offset_ < rhs.offset_;
}
if (lhs.count_ != rhs.count_) {
return lhs.count_ < rhs.count_;
}
if (lhs.type_ != rhs.type_) {
return lhs.type_ < rhs.type_;
}
return lhs.primitive_restart_enabled_ < rhs.primitive_restart_enabled_;
}
};
private:
GLuint offset_;
GLsizei count_;
GLenum type_;
bool primitive_restart_enabled_;
};
~Buffer();
void set_initial_target(GLenum target) {
DCHECK_EQ(0u, initial_target_);
initial_target_ = target;
}
void MarkAsDeleted() {
deleted_ = true;
}
const GLvoid* StageShadow(bool use_shadow,
GLsizeiptr size,
const GLvoid* data);
void SetInfo(GLsizeiptr size,
GLenum usage,
bool use_shadow,
bool is_client_side_array);
void ClearCache();
raw_ptr<BufferManager> manager_;
std::vector<uint8_t> shadow_;
GLsizeiptr size_;
bool deleted_;
bool is_client_side_array_;
int non_transform_feedback_binding_count_ = 0;
int transform_feedback_indexed_binding_count_ = 0;
GLuint service_id_;
GLenum initial_target_;
GLenum usage_;
std::unique_ptr<MappedRange> mapped_range_;
typedef std::map<Range, GLuint, Range::Less> RangeToMaxValueMap;
RangeToMaxValueMap range_set_;
scoped_refptr<gpu::Buffer> readback_shm_;
uint32_t readback_shm_offset_ = 0;
};
class GPU_GLES2_EXPORT BufferManager
: public base::trace_event::MemoryDumpProvider {
public:
BufferManager(scoped_refptr<MemoryTracker> memory_tracker,
FeatureInfo* feature_info);
BufferManager(const BufferManager&) = delete;
BufferManager& operator=(const BufferManager&) = delete;
~BufferManager() override;
void MarkContextLost();
void Destroy();
void CreateBuffer(GLuint client_id, GLuint service_id);
Buffer* GetBuffer(GLuint client_id);
void RemoveBuffer(GLuint client_id);
bool GetClientId(GLuint service_id, GLuint* client_id) const;
void ValidateAndDoBufferSubData(ContextState* context_state,
ErrorState* error_state,
GLenum target,
GLintptr offset,
GLsizeiptr size,
const GLvoid* data);
void ValidateAndDoBufferData(ContextState* context_state,
ErrorState* error_state,
GLenum target,
GLsizeiptr size,
const GLvoid* data,
GLenum usage);
void ValidateAndDoCopyBufferSubData(ContextState* context_state,
ErrorState* error_state,
GLenum readtarget,
GLenum writetarget,
GLintptr readoffset,
GLintptr writeoffset,
GLsizeiptr size);
void ValidateAndDoGetBufferParameteri64v(ContextState* context_state,
ErrorState* error_state,
GLenum target,
GLenum pname,
GLint64* params);
void ValidateAndDoGetBufferParameteriv(ContextState* context_state,
ErrorState* error_state,
GLenum target,
GLenum pname,
GLint* params);
bool SetTarget(Buffer* buffer, GLenum target);
void set_max_buffer_size(GLsizeiptr max_buffer_size) {
max_buffer_size_ = max_buffer_size;
}
void set_allow_buffers_on_multiple_targets(bool allow) {
allow_buffers_on_multiple_targets_ = allow;
}
void set_allow_fixed_attribs(bool allow) {
allow_fixed_attribs_ = allow;
}
size_t mem_represented() const {
return memory_type_tracker_->GetMemRepresented();
}
bool IsUsageClientSideArray(GLenum usage);
bool UseNonZeroSizeForClientSideArrayBuffer();
void SetPrimitiveRestartFixedIndexIfNecessary(GLenum type);
Buffer* GetBufferInfoForTarget(ContextState* state, GLenum target) const;
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
Buffer* RequestBufferAccess(ContextState* context_state,
ErrorState* error_state,
GLenum target,
GLintptr offset,
GLsizeiptr size,
const char* func_name);
Buffer* RequestBufferAccess(ContextState* context_state,
ErrorState* error_state,
GLenum target,
const char* func_name);
bool RequestBufferAccess(ErrorState* error_state,
Buffer* buffer,
const char* func_name,
const char* error_message_format,
...);
bool RequestBufferAccess(ErrorState* error_state,
Buffer* buffer,
GLintptr offset,
GLsizeiptr size,
const char* func_name,
const char* error_message);
bool RequestBuffersAccess(ErrorState* error_state,
const IndexedBufferBindingHost* bindings,
const std::vector<GLsizeiptr>& variable_sizes,
GLsizei count,
const char* func_name,
const char* message_tag);
private:
friend class Buffer;
friend class TestHelper;
friend class BufferManagerTestBase;
friend class IndexedBufferBindingHostTest;
void StartTracking(Buffer* buffer);
void StopTracking(Buffer* buffer);
void DoBufferSubData(
Buffer* buffer,
GLenum target,
GLintptr offset,
GLsizeiptr size,
const GLvoid* data);
void DoBufferData(
ErrorState* error_state,
Buffer* buffer,
GLenum target,
GLsizeiptr size,
GLenum usage,
const GLvoid* data);
void DoCopyBufferSubData(
Buffer* readbuffer,
GLenum readtarget,
GLintptr readoffset,
Buffer* writebuffer,
GLenum writetarget,
GLintptr writeoffset,
GLsizeiptr size);
bool UseShadowBuffer(GLenum target, GLenum usage);
void SetInfo(Buffer* buffer,
GLenum target,
GLsizeiptr size,
GLenum usage,
bool use_shadow);
bool RequestBufferAccessV(ErrorState* error_state,
Buffer* buffer,
const char* func_name,
const char* error_message_format,
va_list varargs);
std::unique_ptr<MemoryTypeTracker> memory_type_tracker_;
scoped_refptr<FeatureInfo> feature_info_;
typedef std::unordered_map<GLuint, scoped_refptr<Buffer>> BufferMap;
BufferMap buffers_;
GLsizeiptr max_buffer_size_;
bool allow_buffers_on_multiple_targets_;
bool allow_fixed_attribs_;
unsigned int buffer_count_;
GLuint primitive_restart_fixed_index_;
bool lost_context_;
bool use_client_side_arrays_for_stream_buffers_;
};
}
}
#endif