blob: 5f6623e05124e28dbb8f3985d9c3c0972367ee11 [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_CLIENT_TRANSFER_BUFFER_H_
#define GPU_COMMAND_BUFFER_CLIENT_TRANSFER_BUFFER_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "gpu/command_buffer/client/ring_buffer.h"
#include "gpu/command_buffer/common/buffer.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/gpu_export.h"
namespace gpu {
class CommandBufferHelper;
// Interface for managing the transfer buffer.
class GPU_EXPORT TransferBufferInterface {
public:
TransferBufferInterface() { }
virtual ~TransferBufferInterface() { }
virtual bool Initialize(
unsigned int buffer_size,
unsigned int result_size,
unsigned int min_buffer_size,
unsigned int max_buffer_size,
unsigned int alignment,
unsigned int size_to_flush) = 0;
virtual int GetShmId() = 0;
virtual void* GetResultBuffer() = 0;
virtual int GetResultOffset() = 0;
virtual void Free() = 0;
virtual bool HaveBuffer() const = 0;
// Allocates up to size bytes.
virtual void* AllocUpTo(unsigned int size, unsigned int* size_allocated) = 0;
// Allocates size bytes.
// Note: Alloc will fail if it can not return size bytes.
virtual void* Alloc(unsigned int size) = 0;
virtual RingBuffer::Offset GetOffset(void* pointer) const = 0;
virtual void DiscardBlock(void* p) = 0;
virtual void FreePendingToken(void* p, unsigned int token) = 0;
virtual unsigned int GetSize() const = 0;
virtual unsigned int GetFreeSize() const = 0;
};
// Class that manages the transfer buffer.
class GPU_EXPORT TransferBuffer : public TransferBufferInterface {
public:
TransferBuffer(CommandBufferHelper* helper);
~TransferBuffer() override;
// Overridden from TransferBufferInterface.
bool Initialize(unsigned int default_buffer_size,
unsigned int result_size,
unsigned int min_buffer_size,
unsigned int max_buffer_size,
unsigned int alignment,
unsigned int size_to_flush) override;
int GetShmId() override;
void* GetResultBuffer() override;
int GetResultOffset() override;
void Free() override;
bool HaveBuffer() const override;
void* AllocUpTo(unsigned int size, unsigned int* size_allocated) override;
void* Alloc(unsigned int size) override;
RingBuffer::Offset GetOffset(void* pointer) const override;
void DiscardBlock(void* p) override;
void FreePendingToken(void* p, unsigned int token) override;
unsigned int GetSize() const override;
unsigned int GetFreeSize() const override;
// These are for testing.
unsigned int GetCurrentMaxAllocationWithoutRealloc() const;
unsigned int GetMaxAllocation() const;
private:
// Tries to reallocate the ring buffer if it's not large enough for size.
void ReallocateRingBuffer(unsigned int size);
void AllocateRingBuffer(unsigned int size);
CommandBufferHelper* helper_;
std::unique_ptr<RingBuffer> ring_buffer_;
// size reserved for results
unsigned int result_size_;
// default size. Size we want when starting or re-allocating
unsigned int default_buffer_size_;
// min size we'll consider successful
unsigned int min_buffer_size_;
// max size we'll let the buffer grow
unsigned int max_buffer_size_;
// alignment for allocations
unsigned int alignment_;
// Size at which to do an async flush. 0 = never.
unsigned int size_to_flush_;
// Number of bytes since we last flushed.
unsigned int bytes_since_last_flush_;
// the current buffer.
scoped_refptr<gpu::Buffer> buffer_;
// id of buffer. -1 = no buffer
int32_t buffer_id_;
// address of result area
void* result_buffer_;
// offset to result area
uint32_t result_shm_offset_;
// false if we failed to allocate min_buffer_size
bool usable_;
};
// A class that will manage the lifetime of a transferbuffer allocation.
class GPU_EXPORT ScopedTransferBufferPtr {
public:
ScopedTransferBufferPtr(
unsigned int size,
CommandBufferHelper* helper,
TransferBufferInterface* transfer_buffer)
: buffer_(NULL),
size_(0),
helper_(helper),
transfer_buffer_(transfer_buffer) {
Reset(size);
}
// Constructs an empty and invalid allocation that should be Reset() later.
ScopedTransferBufferPtr(CommandBufferHelper* helper,
TransferBufferInterface* transfer_buffer)
: buffer_(NULL),
size_(0),
helper_(helper),
transfer_buffer_(transfer_buffer) {}
~ScopedTransferBufferPtr() {
Release();
}
bool valid() const {
return buffer_ != NULL;
}
unsigned int size() const {
return size_;
}
int shm_id() const {
return transfer_buffer_->GetShmId();
}
RingBuffer::Offset offset() const {
return transfer_buffer_->GetOffset(buffer_);
}
void* address() const {
return buffer_;
}
void Release();
void Discard();
void Reset(unsigned int new_size);
private:
void* buffer_;
unsigned int size_;
CommandBufferHelper* helper_;
TransferBufferInterface* transfer_buffer_;
DISALLOW_COPY_AND_ASSIGN(ScopedTransferBufferPtr);
};
template <typename T>
class ScopedTransferBufferArray : public ScopedTransferBufferPtr {
public:
ScopedTransferBufferArray(
unsigned int num_elements,
CommandBufferHelper* helper, TransferBufferInterface* transfer_buffer)
: ScopedTransferBufferPtr(
num_elements * sizeof(T), helper, transfer_buffer) {
}
T* elements() {
return static_cast<T*>(address());
}
unsigned int num_elements() const {
return size() / sizeof(T);
}
};
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_CLIENT_TRANSFER_BUFFER_H_