blob: 22a6e429f4d4720b1f2de8cccd12adc71d912d58 [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.
#ifndef GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_
#define GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_
#include <map>
#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/gpu_export.h"
namespace gpu {
namespace gles2 {
class BufferManager;
struct ContextState;
class ErrorState;
class FeatureInfo;
class TestHelper;
// Info about Buffers currently in the system.
class GPU_EXPORT Buffer : public base::RefCounted<Buffer> {
public:
Buffer(BufferManager* manager, GLuint service_id);
GLuint service_id() const {
return service_id_;
}
GLenum target() const {
return target_;
}
GLsizeiptr size() const {
return size_;
}
GLenum usage() const {
return usage_;
}
// Gets the maximum value in the buffer for the given range interpreted as
// the given type. Returns false if offset and count are out of range.
// offset is in bytes.
// count is in elements of type.
bool GetMaxValueForRange(GLuint offset, GLsizei count, GLenum type,
GLuint* max_value);
// Returns a pointer to shadowed data.
const void* GetRange(GLintptr offset, GLsizeiptr size) const;
bool IsDeleted() const {
return deleted_;
}
bool IsValid() const {
return target() && !IsDeleted();
}
bool IsClientSideArray() const {
return is_client_side_array_;
}
private:
friend class BufferManager;
friend class BufferManagerTestBase;
friend class base::RefCounted<Buffer>;
// Represents a range in a buffer.
class Range {
public:
Range(GLuint offset, GLsizei count, GLenum type)
: offset_(offset),
count_(count),
type_(type) {
}
// A less functor provided for std::map so it can find ranges.
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_;
}
return lhs.type_ < rhs.type_;
}
};
private:
GLuint offset_;
GLsizei count_;
GLenum type_;
};
~Buffer();
void set_target(GLenum target) {
DCHECK_EQ(target_, 0u); // you can only set this once.
target_ = target;
}
bool shadowed() const {
return shadowed_;
}
void MarkAsDeleted() {
deleted_ = true;
}
// Sets the size, usage and initial data of a buffer.
// If shadow is true then if data is NULL buffer will be initialized to 0.
void SetInfo(
GLsizeiptr size, GLenum usage, bool shadow, const GLvoid* data,
bool is_client_side_array);
// Sets a range of data for this buffer. Returns false if the offset or size
// is out of range.
bool SetRange(
GLintptr offset, GLsizeiptr size, const GLvoid * data);
// Clears any cache of index ranges.
void ClearCache();
// Check if an offset, size range is valid for the current buffer.
bool CheckRange(GLintptr offset, GLsizeiptr size) const;
// The manager that owns this Buffer.
BufferManager* manager_;
// A copy of the data in the buffer. This data is only kept if the target
// is backed_ = true.
scoped_ptr<int8[]> shadow_;
// Size of buffer.
GLsizeiptr size_;
// True if deleted.
bool deleted_;
// Whether or not the data is shadowed.
bool shadowed_;
// Whether or not this Buffer is not uploaded to the GPU but just
// sitting in local memory.
bool is_client_side_array_;
// Service side buffer id.
GLuint service_id_;
// The type of buffer. 0 = unset, GL_BUFFER_ARRAY = vertex data,
// GL_ELEMENT_BUFFER_ARRAY = index data.
// Once set a buffer can not be used for something else.
GLenum target_;
// Usage of buffer.
GLenum usage_;
// A map of ranges to the highest value in that range of a certain type.
typedef std::map<Range, GLuint, Range::Less> RangeToMaxValueMap;
RangeToMaxValueMap range_set_;
};
// This class keeps track of the buffers and their sizes so we can do
// bounds checking.
//
// NOTE: To support shared resources an instance of this class will need to be
// shared by multiple GLES2Decoders.
class GPU_EXPORT BufferManager {
public:
BufferManager(MemoryTracker* memory_tracker, FeatureInfo* feature_info);
~BufferManager();
// Must call before destruction.
void Destroy(bool have_context);
// Creates a Buffer for the given buffer.
void CreateBuffer(GLuint client_id, GLuint service_id);
// Gets the buffer info for the given buffer.
Buffer* GetBuffer(GLuint client_id);
// Removes a buffer info for the given buffer.
void RemoveBuffer(GLuint client_id);
// Gets a client id for a given service id.
bool GetClientId(GLuint service_id, GLuint* client_id) const;
// Validates a glBufferSubData, and then calls DoBufferData if validation was
// successful.
void ValidateAndDoBufferSubData(
ContextState* context_state, GLenum target, GLintptr offset,
GLsizeiptr size, const GLvoid * data);
// Validates a glBufferData, and then calls DoBufferData if validation was
// successful.
void ValidateAndDoBufferData(
ContextState* context_state, GLenum target, GLsizeiptr size,
const GLvoid * data, GLenum usage);
// Validates a glGetBufferParameteriv, and then calls GetBufferParameteriv if
// validation was successful.
void ValidateAndDoGetBufferParameteriv(
ContextState* context_state, GLenum target, GLenum pname, GLint* params);
// Sets the target of a buffer. Returns false if the target can not be set.
bool SetTarget(Buffer* buffer, GLenum target);
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_tracker_->GetMemRepresented();
}
// Tells for a given usage if this would be a client side array.
bool IsUsageClientSideArray(GLenum usage);
// Tells whether a buffer that is emulated using client-side arrays should be
// set to a non-zero size.
bool UseNonZeroSizeForClientSideArrayBuffer();
private:
friend class Buffer;
friend class TestHelper; // Needs access to DoBufferData.
friend class BufferManagerTestBase; // Needs access to DoBufferSubData.
void StartTracking(Buffer* buffer);
void StopTracking(Buffer* buffer);
Buffer* GetBufferInfoForTarget(ContextState* state, GLenum target);
// Does a glBufferSubData and updates the approriate accounting.
// Assumes the values have already been validated.
void DoBufferSubData(
ErrorState* error_state,
Buffer* buffer,
GLintptr offset,
GLsizeiptr size,
const GLvoid* data);
// Does a glBufferData and updates the approprate accounting. Currently
// Assumes the values have already been validated.
void DoBufferData(
ErrorState* error_state,
Buffer* buffer,
GLsizeiptr size,
GLenum usage,
const GLvoid* data);
// Sets the size, usage and initial data of a buffer.
// If data is NULL buffer will be initialized to 0 if shadowed.
void SetInfo(
Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data);
scoped_ptr<MemoryTypeTracker> memory_tracker_;
scoped_refptr<FeatureInfo> feature_info_;
// Info for each buffer in the system.
typedef base::hash_map<GLuint, scoped_refptr<Buffer> > BufferMap;
BufferMap buffers_;
// Whether or not buffers can be bound to multiple targets.
bool allow_buffers_on_multiple_targets_;
// Whether or not allow using GL_FIXED type for vertex attribs.
bool allow_fixed_attribs_;
// Counts the number of Buffer allocated with 'this' as its manager.
// Allows to check no Buffer will outlive this.
unsigned int buffer_count_;
bool have_context_;
bool use_client_side_arrays_for_stream_buffers_;
DISALLOW_COPY_AND_ASSIGN(BufferManager);
};
} // namespace gles2
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_