| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517 |
- /*
- Copyright (c) 2013 Daniele Bartolini, Michele Rossi
- Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- */
- #include <GL/glew.h>
- #include <algorithm>
- #include "Config.h"
- #include "Allocator.h"
- #include "Assert.h"
- #include "Types.h"
- #include "GLRenderer.h"
- #include "Log.h"
- #include "Vec4.h"
- #include "Mat3.h"
- #include "Mat4.h"
- #include "Device.h"
- #include "Hash.h"
- #include "StringUtils.h"
- namespace crown
- {
- //-----------------------------------------------------------------------------
- const GLenum PRIMITIVE_TYPE_TABLE[] =
- {
- GL_TRIANGLES,
- GL_POINTS,
- GL_LINES
- };
- //-----------------------------------------------------------------------------
- const GLenum TEXTURE_MIN_FILTER_TABLE[] =
- {
- 0, // Unused
- GL_NEAREST,
- GL_LINEAR,
- GL_NEAREST_MIPMAP_LINEAR,
- GL_LINEAR_MIPMAP_LINEAR
- };
- //-----------------------------------------------------------------------------
- const GLenum TEXTURE_MAG_FILTER_TABLE[] =
- {
- 0, // Unused
- GL_NEAREST,
- GL_LINEAR,
- GL_LINEAR,
- GL_LINEAR
- };
- //-----------------------------------------------------------------------------
- const GLenum TEXTURE_WRAP_TABLE[] =
- {
- 0, // Unused
- GL_CLAMP,
- GL_CLAMP_TO_EDGE,
- GL_CLAMP_TO_BORDER,
- GL_REPEAT
- };
- /// OpenGL renderer
- class RendererImplementation
- {
- public:
- //-----------------------------------------------------------------------------
- RendererImplementation()
- : m_max_texture_size(0), m_max_texture_units(0), m_max_vertex_indices(0), m_max_vertex_vertices(0),
- m_max_anisotropy(0.0f)
- {
- m_min_max_point_size[0] = 0.0f;
- m_min_max_point_size[1] = 0.0f;
- m_min_max_line_width[0] = 0.0f;
- m_min_max_line_width[1] = 0.0f;
- }
- //-----------------------------------------------------------------------------
- ~RendererImplementation()
- {
- }
- //-----------------------------------------------------------------------------
- void init()
- {
- m_gl_context.create_context();
- GLenum err = glewInit();
- CE_ASSERT(err == GLEW_OK, "Failed to initialize GLEW");
- GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_max_texture_size));
- GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &m_max_texture_units));
- GL_CHECK(glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &m_max_vertex_indices));
- GL_CHECK(glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &m_max_vertex_vertices));
- GL_CHECK(glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, &m_min_max_point_size[0]));
- GL_CHECK(glGetFloatv(GL_LINE_WIDTH_RANGE, &m_min_max_line_width[0]));
- Log::i("OpenGL Vendor : %s", glGetString(GL_VENDOR));
- Log::i("OpenGL Renderer : %s", glGetString(GL_RENDERER));
- Log::i("OpenGL Version : %s", glGetString(GL_VERSION));
- Log::i("GLSL Version : %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
- Log::d("Min Point Size : %f", m_min_max_point_size[0]);
- Log::d("Max Point Size : %f", m_min_max_point_size[1]);
- Log::d("Min Line Width : %f", m_min_max_line_width[0]);
- Log::d("Max Line Width : %f", m_min_max_line_width[1]);
- Log::d("Max Texture Size : %dx%d", m_max_texture_size, m_max_texture_size);
- Log::d("Max Texture Units : %d", m_max_texture_units);
- Log::d("Max Vertex Indices : %d", m_max_vertex_indices);
- Log::d("Max Vertex Vertices : %d", m_max_vertex_vertices);
- GL_CHECK(glDisable(GL_BLEND));
- GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
- GL_CHECK(glBlendEquation(GL_FUNC_ADD));
- GL_CHECK(glShadeModel(GL_SMOOTH));
- // Enable depth test
- GL_CHECK(glEnable(GL_DEPTH_TEST));
- GL_CHECK(glDepthFunc(GL_LEQUAL));
- GL_CHECK(glClearDepth(1.0));
- // Point sprites enabled by default
- GL_CHECK(glEnable(GL_POINT_SPRITE));
- GL_CHECK(glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE));
- Log::i("OpenGL Renderer initialized.");
- }
- //-----------------------------------------------------------------------------
- void shutdown()
- {
- m_gl_context.destroy_context();
- }
- //-----------------------------------------------------------------------------
- void render(RenderContext& context)
- {
- //RenderTargetId old_rt;
- //old_rt.id = INVALID_ID;
- uint8_t layer = 0xFF;
- for (uint32_t s = 0; s < context.m_num_states; s++)
- {
- const uint64_t key_s = context.m_keys[s];
- RenderKey key;
- key.decode(key_s);
- const RenderState& cur_state = context.m_states[s];
- const uint64_t flags = cur_state.m_flags;
- //const RenderTargetId& cur_rt = context.m_targets[layer];
- // Check if layer changed
- if (key.m_layer != layer)
- {
- layer = key.m_layer;
- // Viewport
- const ViewRect& viewport = context.m_viewports[layer];
- GL_CHECK(glViewport(viewport.m_x, viewport.m_y, viewport.m_width, viewport.m_height));
- // Clear frame/depth buffer
- const ClearState& clear = context.m_clears[layer];
- if (clear.m_flags & (CLEAR_COLOR | CLEAR_DEPTH))
- {
- GLbitfield gl_clear = (clear.m_flags & CLEAR_COLOR) ? GL_COLOR_BUFFER_BIT : 0;
- gl_clear |= (clear.m_flags & CLEAR_DEPTH) ? GL_DEPTH_BUFFER_BIT : 0;
- GL_CHECK(glClearColor(clear.m_color.r, clear.m_color.g, clear.m_color.b, clear.m_color.a));
- GL_CHECK(glClearDepth(clear.m_depth));
- GL_CHECK(glClear(gl_clear));
- }
- }
- // Scissor
- const ViewRect& scissor = context.m_scissors[layer];
- if (scissor.area() != 0)
- {
- GL_CHECK(glEnable(GL_SCISSOR_TEST));
- GL_CHECK(glScissor(scissor.m_x, scissor.m_y, scissor.m_width, scissor.m_height));
- }
- else
- {
- GL_CHECK(glDisable(GL_SCISSOR_TEST));
- }
- // Depth write
- if (flags & (STATE_DEPTH_WRITE))
- {
- GL_CHECK(glDepthMask(flags & STATE_DEPTH_WRITE));
- }
- // Color/Alpha write
- if (flags & (STATE_COLOR_WRITE | STATE_ALPHA_WRITE))
- {
- GLboolean cw = !!(flags & STATE_COLOR_WRITE);
- GLboolean aw = !!(flags & STATE_ALPHA_WRITE);
- GL_CHECK(glColorMask(cw, cw, cw, aw));
- }
- // Face culling
- if (flags & (STATE_CULL_CW | STATE_CULL_CCW))
- {
- if (flags & STATE_CULL_CW)
- {
- GL_CHECK(glEnable(GL_CULL_FACE));
- GL_CHECK(glCullFace(GL_BACK));
- }
- else if (flags & STATE_CULL_CCW)
- {
- GL_CHECK(glEnable(GL_CULL_FACE));
- GL_CHECK(glCullFace(GL_FRONT));
- }
- }
- else
- {
- GL_CHECK(glDisable(GL_CULL_FACE));
- }
- // Bind GPU program
- if (cur_state.program.id != INVALID_ID)
- {
- const GPUProgram& gpu_program = m_gpu_programs[cur_state.program.index];
- GL_CHECK(glUseProgram(gpu_program.m_id));
- for (uint8_t uniform = 0; uniform < gpu_program.m_num_stock_uniforms; uniform++)
- {
- const GLint& uniform_location = gpu_program.m_stock_uniform_locations[uniform];
- const Mat4& view = context.m_view_matrices[layer];
- const Mat4& projection = context.m_projection_matrices[layer];
- switch (gpu_program.m_stock_uniforms[uniform])
- {
- case UNIFORM_VIEW:
- {
- GL_CHECK(glUniformMatrix4fv(uniform_location, 1, GL_FALSE, view.to_float_ptr()));
- break;
- }
- case UNIFORM_MODEL:
- {
- GL_CHECK(glUniformMatrix4fv(uniform_location, 1, GL_FALSE, cur_state.pose.to_float_ptr()));
- break;
- }
- case UNIFORM_MODEL_VIEW:
- {
- GL_CHECK(glUniformMatrix4fv(uniform_location, 1, GL_FALSE, (view *
- cur_state.pose).to_float_ptr()));
- break;
- }
- case UNIFORM_MODEL_VIEW_PROJECTION:
- {
- GL_CHECK(glUniformMatrix4fv(uniform_location, 1, GL_FALSE, (projection * view *
- cur_state.pose).to_float_ptr()));
- break;
- }
- case UNIFORM_TIME_SINCE_START:
- {
- GL_CHECK(glUniform1f(uniform_location, device()->time_since_start()));
- break;
- }
- default:
- {
- CE_ASSERT(false, "Oops, wrong stock uniform!");
- break;
- }
- }
- }
- }
- else
- {
- GL_CHECK(glUseProgram(0));
- }
- // Bind array buffers
- const VertexBufferId& vb = cur_state.vb;
- if (vb.id != INVALID_ID)
- {
- const VertexBuffer& vertex_buffer = m_vertex_buffers[vb.index];
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer.m_id);
- const GPUProgram& gpu_program = m_gpu_programs[cur_state.program.index];
- gpu_program.bind_attributes(vertex_buffer.m_format);
- }
- else
- {
- GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
- }
- const IndexBufferId& ib = cur_state.ib;
- if (ib.id != INVALID_ID)
- {
- const IndexBuffer& index_buffer = m_index_buffers[ib.index];
- uint32_t prim_type = (flags & STATE_PRIMITIVE_MASK) >> STATE_PRIMITIVE_SHIFT;
- GLenum gl_prim_type = PRIMITIVE_TYPE_TABLE[prim_type];
- GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.m_id));
- GL_CHECK(glDrawElements(gl_prim_type, index_buffer.m_index_count, GL_UNSIGNED_SHORT, 0));
- }
- else
- {
- GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
- }
- // Bind textures
- {
- uint64_t flags = STATE_TEXTURE_0;
- for (uint32_t unit = 0; unit < STATE_MAX_TEXTURES; unit++)
- {
- const Sampler& sampler = cur_state.samplers[unit];
- if (sampler.sampler_id.id != INVALID_ID)
- {
- switch (sampler.flags & SAMPLER_MASK)
- {
- case SAMPLER_TEXTURE:
- {
- Texture& texture = m_textures[sampler.sampler_id.index];
- texture.commit(unit, sampler.flags);
- break;
- }
- default:
- {
- CE_ASSERT(false, "Oops, sampler unknown");
- break;
- }
- }
- }
- flags <<= 1;
- }
- }
- }
- GL_CHECK(glFinish());
- context.clear();
- m_gl_context.swap_buffers();
- }
- private:
- GLContext m_gl_context;
- // Limits
- int32_t m_max_texture_size;
- int32_t m_max_texture_units;
- int32_t m_max_vertex_indices;
- int32_t m_max_vertex_vertices;
- float m_max_anisotropy;
- float m_min_max_point_size[2];
- float m_min_max_line_width[2];
- VertexBuffer m_vertex_buffers[CROWN_MAX_VERTEX_BUFFERS];
- IndexBuffer m_index_buffers[CROWN_MAX_INDEX_BUFFERS];
- Texture m_textures[CROWN_MAX_TEXTURES];
- Shader m_shaders[CROWN_MAX_SHADERS];
- GPUProgram m_gpu_programs[CROWN_MAX_GPU_PROGRAMS];
- Uniform m_uniforms[CROWN_MAX_UNIFORMS];
- RenderTarget m_render_targets[CROWN_MAX_RENDER_TARGETS];
- private:
- friend class Renderer;
- };
- //-----------------------------------------------------------------------------
- Renderer::Renderer(Allocator& a)
- : m_allocator(a), m_impl(NULL), m_submit(&m_contexts[0]), m_draw(&m_contexts[1]), m_is_initialized(false)
- {
- m_impl = CE_NEW(a, RendererImplementation);
- }
- //-----------------------------------------------------------------------------
- Renderer::~Renderer()
- {
- CE_DELETE(m_allocator, m_impl);
- }
- //-----------------------------------------------------------------------------
- void Renderer::init_impl()
- {
- m_impl->init();
- }
- //-----------------------------------------------------------------------------
- void Renderer::shutdown_impl()
- {
- m_impl->shutdown();
- }
- //-----------------------------------------------------------------------------
- void Renderer::render_impl()
- {
- m_impl->render(*m_draw);
- }
- //-----------------------------------------------------------------------------
- void Renderer::create_vertex_buffer_impl(VertexBufferId id, size_t count, VertexFormat format, const void* vertices)
- {
- m_impl->m_vertex_buffers[id.index].create(count, format, vertices);
- }
- //-----------------------------------------------------------------------------
- void Renderer::update_vertex_buffer_impl(VertexBufferId id, size_t offset, size_t count, const void* vertices)
- {
- m_impl->m_vertex_buffers[id.index].update(offset, count, vertices);
- }
- //-----------------------------------------------------------------------------
- void Renderer::destroy_vertex_buffer_impl(VertexBufferId id)
- {
- m_impl->m_vertex_buffers[id.index].destroy();
- }
- //-----------------------------------------------------------------------------
- void Renderer::create_index_buffer_impl(IndexBufferId id, size_t count, const void* indices)
- {
- m_impl->m_index_buffers[id.index].create(count, indices);
- }
- //-----------------------------------------------------------------------------
- void Renderer::destroy_index_buffer_impl(IndexBufferId id)
- {
- m_impl->m_index_buffers[id.index].destroy();
- }
- //-----------------------------------------------------------------------------
- void Renderer::create_texture_impl(TextureId id, uint32_t width, uint32_t height, PixelFormat format, const void* data)
- {
- m_impl->m_textures[id.index].create(width, height, format, data);
- }
- //-----------------------------------------------------------------------------
- void Renderer::update_texture_impl(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data)
- {
- m_impl->m_textures[id.index].update(x, y, width, height, data);
- }
- //-----------------------------------------------------------------------------
- void Renderer::destroy_texture_impl(TextureId id)
- {
- m_impl->m_textures[id.index].destroy();
- }
- //-----------------------------------------------------------------------------
- void Renderer::create_shader_impl(ShaderId id, ShaderType type, const char* text)
- {
- m_impl->m_shaders[id.index].create(type, text);
- }
- //-----------------------------------------------------------------------------
- void Renderer::destroy_shader_impl(ShaderId id)
- {
- m_impl->m_shaders[id.index].destroy();
- }
- //-----------------------------------------------------------------------------
- void Renderer::create_gpu_program_impl(GPUProgramId id, ShaderId vertex, ShaderId pixel)
- {
- Shader& vs = m_impl->m_shaders[vertex.index];
- Shader& ps = m_impl->m_shaders[pixel.index];
- m_impl->m_gpu_programs[id.index].create(vs, ps);
- }
- //-----------------------------------------------------------------------------
- void Renderer::destroy_gpu_program_impl(GPUProgramId id)
- {
- m_impl->m_gpu_programs[id.index].destroy();
- }
- // //-----------------------------------------------------------------------------
- // void Renderer::create_uniform_impl(UniformId id, const char* name, UniformType type)
- // {
- // }
- // //-----------------------------------------------------------------------------
- // void Renderer::destroy_uniform_impl(UniformId id)
- // {
- // }
- // //-----------------------------------------------------------------------------
- // void Renderer::create_render_target_impl(RenderTargetId id, uint16_t width, uint16_t height, RenderTargetFormat format)
- // {
- // }
- // //-----------------------------------------------------------------------------
- // void Renderer::destroy_render_target_impl(RenderTargetId id)
- // {
- // }
- } // namespace crown
|