// 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 #include #include #include #include "../common/gles2_cmd_utils.h" #include "../common/scoped_ptr.h" #include "../client/gles2_cmd_helper.h" #include "../client/ring_buffer.h" #define GLES2_SUPPORT_CLIENT_SIDE_BUFFERS 1 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; 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" #if defined(GLES2_SUPPORT_CLIENT_SIDE_BUFFERS) 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); #else void BindBuffer(GLenum target, GLuint buffer) { if (IsReservedId(buffer)) { SetGLError(GL_INVALID_OPERATION, "glBindBuffer: reserved buffer id"); return; } if (buffer != 0) { id_allocator_.MarkAsUsed(buffer); } helper_->BindBuffer(target, buffer); } void DeleteBuffers(GLsizei n, const GLuint* buffers) { FreeIds(n, buffers); helper_->DeleteBuffersImmediate(n, buffers); } void DisableVertexAttribArray(GLuint index) { helper_->DisableVertexAttribArray(index); } void DrawArrays(GLenum mode, GLint first, GLsizei count) { if (count < 0) { SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0"); return; } helper_->DrawArrays(mode, first, count); } void EnableVertexAttribArray(GLuint index) { helper_->EnableVertexAttribArray(index); } void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) { typedef GetVertexAttribfv::Result Result; Result* result = GetResultAs(); result->SetNumResults(0); helper_->GetVertexAttribfv( index, pname, result_shm_id(), result_shm_offset()); WaitForCmd(); result->CopyResult(params); } void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) { typedef GetVertexAttribiv::Result Result; Result* result = GetResultAs(); result->SetNumResults(0); helper_->GetVertexAttribiv( index, pname, result_shm_id(), result_shm_offset()); WaitForCmd(); result->CopyResult(params); } #endif 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 T *AllocTyped(unsigned int count) { return static_cast(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 T GetResultAs() const { return static_cast(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* 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; } #if defined(GLES2_SUPPORT_CLIENT_SIDE_BUFFERS) // 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); #endif GLES2Util util_; GLES2CmdHelper* helper_; scoped_ptr buffer_id_handler_; scoped_ptr framebuffer_id_handler_; scoped_ptr renderbuffer_id_handler_; scoped_ptr program_and_shader_id_handler_; scoped_ptr texture_id_handler_; AlignedRingBuffer transfer_buffer_; int transfer_buffer_id_; void* result_buffer_; uint32 result_shm_offset_; std::string last_error_; // pack alignment as last set by glPixelStorei GLint pack_alignment_; // unpack alignment as last set by glPixelStorei GLint unpack_alignment_; #if defined(GLES2_SUPPORT_CLIENT_SIDE_BUFFERS) // 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 client_side_buffer_helper_; GLuint reserved_ids_[2]; #endif // 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 GLStringMap; GLStringMap gl_strings_; typedef std::map MappedBufferMap; MappedBufferMap mapped_buffers_; typedef std::map MappedTextureMap; MappedTextureMap mapped_textures_; scoped_ptr mapped_memory_; DISALLOW_COPY_AND_ASSIGN(GLES2Implementation); }; } // namespace gles2 } // namespace gpu #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_H_