blob: 1017ef1f9144e8cee6d3231af312a1237bc0aad5 [file] [log] [blame]
// Copyright (c) 2009 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_GLES2_IMPLEMENTATION_H_
#define GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_H_
#include <GLES2/gl2.h>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
#include "../common/gles2_cmd_utils.h"
#include "../common/scoped_ptr.h"
#include "../client/gles2_cmd_helper.h"
#include "../client/ring_buffer.h"
// TODO(gman): replace with logging code expansion.
#define GPU_CLIENT_LOG(args)
namespace gpu {
class MappedMemoryManager;
namespace gles2 {
class ClientSideBufferHelper;
// Base class for IdHandlers
class IdHandlerInterface {
public:
IdHandlerInterface() { }
virtual ~IdHandlerInterface() { }
// Makes some ids at or above id_offset.
virtual void MakeIds(GLuint id_offset, GLsizei n, GLuint* ids) = 0;
// Frees some ids.
virtual void FreeIds(GLsizei n, const GLuint* ids) = 0;
// Marks an id as used for glBind functions. id = 0 does nothing.
virtual bool MarkAsUsedForBind(GLuint id) = 0;
};
// This class emulates GLES2 over command buffers. It can be used by a client
// program so that the program does not need deal with shared memory and command
// buffer management. See gl2_lib.h. Note that there is a performance gain to
// be had by changing your code to use command buffers directly by using the
// GLES2CmdHelper but that entails changing your code to use and deal with
// shared memory and synchronization issues.
class GLES2Implementation {
public:
// The maxiumum result size from simple GL get commands.
static const size_t kMaxSizeOfSimpleResult = 16 * sizeof(uint32); // NOLINT.
// used for testing only. If more things are reseved add them here.
static const unsigned int kStartingOffset = kMaxSizeOfSimpleResult;
// The bucket used for results. Public for testing only.
static const uint32 kResultBucketId = 1;
// Alignment of allocations.
static const unsigned int kAlignment = 4;
// GL names for the buffers used to emulate client side buffers.
static const GLuint kClientSideArrayId = 0xFEDCBA98u;
static const GLuint kClientSideElementArrayId = 0xFEDCBA99u;
// Number of swap buffers allowed before waiting.
static const size_t kMaxSwapBuffers = 2;
GLES2Implementation(
GLES2CmdHelper* helper,
size_t transfer_buffer_size,
void* transfer_buffer,
int32 transfer_buffer_id,
bool share_resources);
~GLES2Implementation();
// The GLES2CmdHelper being used by this GLES2Implementation. You can use
// this to issue cmds at a lower level for certain kinds of optimization.
GLES2CmdHelper* helper() const {
return helper_;
}
// Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in
// this file instead of having to edit some template or the code generator.
#include "../client/gles2_implementation_autogen.h"
void BindBuffer(GLenum target, GLuint buffer);
void DeleteBuffers(GLsizei n, const GLuint* buffers);
void DisableVertexAttribArray(GLuint index);
void DrawArrays(GLenum mode, GLint first, GLsizei count);
void EnableVertexAttribArray(GLuint index);
void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
GLuint MakeTextureId() {
GLuint id;
texture_id_handler_->MakeIds(0, 1, &id);
return id;
}
void FreeTextureId(GLuint id) {
texture_id_handler_->FreeIds(1, &id);
}
private:
// Wraps RingBufferWrapper to provide aligned allocations.
class AlignedRingBuffer : public RingBufferWrapper {
public:
AlignedRingBuffer(RingBuffer::Offset base_offset,
unsigned int size,
CommandBufferHelper *helper,
void *base)
: RingBufferWrapper(base_offset, size, helper, base) {
}
static unsigned int RoundToAlignment(unsigned int size) {
return (size + kAlignment - 1) & ~(kAlignment - 1);
}
// Overrriden from RingBufferWrapper
void *Alloc(unsigned int size) {
return RingBufferWrapper::Alloc(RoundToAlignment(size));
}
// Overrriden from RingBufferWrapper
template <typename T> T *AllocTyped(unsigned int count) {
return static_cast<T *>(Alloc(count * sizeof(T)));
}
};
// Base class for mapped resources.
struct MappedResource {
MappedResource(GLenum _access, int _shm_id, void* mem, unsigned int offset)
: access(_access),
shm_id(_shm_id),
shm_memory(mem),
shm_offset(offset) {
}
// access mode. Currently only GL_WRITE_ONLY is valid
GLenum access;
// Shared memory ID for buffer.
int shm_id;
// Address of shared memory
void* shm_memory;
// Offset of shared memory
unsigned int shm_offset;
};
// Used to track mapped textures.
struct MappedTexture : public MappedResource {
MappedTexture(
GLenum access,
int shm_id,
void* shm_mem,
unsigned int shm_offset,
GLenum _target,
GLint _level,
GLint _xoffset,
GLint _yoffset,
GLsizei _width,
GLsizei _height,
GLenum _format,
GLenum _type)
: MappedResource(access, shm_id, shm_mem, shm_offset),
target(_target),
level(_level),
xoffset(_xoffset),
yoffset(_yoffset),
width(_width),
height(_height),
format(_format),
type(_type) {
}
// These match the arguments to TexSubImage2D.
GLenum target;
GLint level;
GLint xoffset;
GLint yoffset;
GLsizei width;
GLsizei height;
GLenum format;
GLenum type;
};
// Used to track mapped buffers.
struct MappedBuffer : public MappedResource {
MappedBuffer(
GLenum access,
int shm_id,
void* shm_mem,
unsigned int shm_offset,
GLenum _target,
GLintptr _offset,
GLsizeiptr _size)
: MappedResource(access, shm_id, shm_mem, shm_offset),
target(_target),
offset(_offset),
size(_size) {
}
// These match the arguments to BufferSubData.
GLenum target;
GLintptr offset;
GLsizeiptr size;
};
// Gets the shared memory id for the result buffer.
uint32 result_shm_id() const {
return transfer_buffer_id_;
}
// Gets the shared memory offset for the result buffer.
uint32 result_shm_offset() const {
return result_shm_offset_;
}
// Gets the value of the result.
template <typename T>
T GetResultAs() const {
return static_cast<T>(result_buffer_);
}
// Gets the GLError through our wrapper.
GLenum GetGLError();
// Sets our wrapper for the GLError.
void SetGLError(GLenum error, const char* msg);
// Returns the last error and clears it. Useful for debugging.
const std::string& GetLastError() {
return last_error_;
}
// Waits for all commands to execute.
void WaitForCmd();
// TODO(gman): These bucket functions really seem like they belong in
// CommandBufferHelper (or maybe BucketHelper?). Unfortunately they need
// a transfer buffer to function which is currently managed by this class.
// Gets the contents of a bucket.
void GetBucketContents(uint32 bucket_id, std::vector<int8>* data);
// Sets the contents of a bucket.
void SetBucketContents(uint32 bucket_id, const void* data, size_t size);
// Sets the contents of a bucket as a string.
void SetBucketAsCString(uint32 bucket_id, const char* str);
// Gets the contents of a bucket as a string. Returns false if there is no
// string available which is a separate case from the empty string.
bool GetBucketAsString(uint32 bucket_id, std::string* str);
// Sets the contents of a bucket as a string.
void SetBucketAsString(uint32 bucket_id, const std::string& str);
// Returns true if id is reserved.
bool IsBufferReservedId(GLuint id);
bool IsFramebufferReservedId(GLuint id) { return false; }
bool IsRenderbufferReservedId(GLuint id) { return false; }
bool IsTextureReservedId(GLuint id) { return false; }
// Helper for GetVertexAttrib
bool GetVertexAttribHelper(GLuint index, GLenum pname, uint32* param);
// Asks the service for the max index in an element array buffer.
GLsizei GetMaxIndexInElementArrayBuffer(
GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
GLES2Util util_;
GLES2CmdHelper* helper_;
scoped_ptr<IdHandlerInterface> buffer_id_handler_;
scoped_ptr<IdHandlerInterface> framebuffer_id_handler_;
scoped_ptr<IdHandlerInterface> renderbuffer_id_handler_;
scoped_ptr<IdHandlerInterface> program_and_shader_id_handler_;
scoped_ptr<IdHandlerInterface> texture_id_handler_;
AlignedRingBuffer transfer_buffer_;
int transfer_buffer_id_;
void* result_buffer_;
uint32 result_shm_offset_;
std::string last_error_;
std::queue<int32> swap_buffers_tokens_;
// pack alignment as last set by glPixelStorei
GLint pack_alignment_;
// unpack alignment as last set by glPixelStorei
GLint unpack_alignment_;
// The currently bound array buffer.
GLuint bound_array_buffer_id_;
// The currently bound element array buffer.
GLuint bound_element_array_buffer_id_;
// GL names for the buffers used to emulate client side buffers.
GLuint client_side_array_id_;
GLuint client_side_element_array_id_;
// Info for each vertex attribute saved so we can simulate client side
// buffers.
scoped_ptr<ClientSideBufferHelper> client_side_buffer_helper_;
GLuint reserved_ids_[2];
// Current GL error bits.
uint32 error_bits_;
// Map of GLenum to Strings for glGetString. We need to cache these because
// the pointer passed back to the client has to remain valid for eternity.
typedef std::map<uint32, std::set<std::string> > GLStringMap;
GLStringMap gl_strings_;
// Similar cache for glGetRequestableExtensionsCHROMIUM. We don't
// have an enum for this so handle it separately.
std::set<std::string> requestable_extensions_set_;
typedef std::map<const void*, MappedBuffer> MappedBufferMap;
MappedBufferMap mapped_buffers_;
typedef std::map<const void*, MappedTexture> MappedTextureMap;
MappedTextureMap mapped_textures_;
scoped_ptr<MappedMemoryManager> mapped_memory_;
DISALLOW_COPY_AND_ASSIGN(GLES2Implementation);
};
} // namespace gles2
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_H_