static bool load_vb_buffer(struct shader_attrib *attrib, struct gs_vertex_buffer *vb, GLint id) { GLenum type; GLint width; GLuint buffer; bool success = true; buffer = get_vb_buffer(vb, attrib->type, attrib->index, &width, &type); if (!buffer) { blog(LOG_ERROR, "Vertex buffer does not have the required " "inputs for vertex shader"); return false; } if (!gl_bind_buffer(GL_ARRAY_BUFFER, buffer)) return false; glVertexAttribPointer(id, width, type, GL_TRUE, 0, 0); if (!gl_success("glVertexAttribPointer")) success = false; glEnableVertexAttribArray(id); if (!gl_success("glEnableVertexAttribArray")) success = false; if (!gl_bind_buffer(GL_ARRAY_BUFFER, 0)) success = false; return success; }
void vbo::unbind(const std::array<i32, e_shader_attribute_max>& attributes) const { if(m_used_size != 0) { gl_bind_buffer(GL_ARRAY_BUFFER, m_handle); if(attributes.at(e_shader_attribute_position) >= 0) { gl_disable_vertex_attribute(attributes.at(e_shader_attribute_position)); } if(attributes.at(e_shader_attribute_texcoord) >= 0) { gl_disable_vertex_attribute(attributes.at(e_shader_attribute_texcoord)); } if(attributes.at(e_shader_attribute_normal) >= 0) { gl_disable_vertex_attribute(attributes.at(e_shader_attribute_normal)); } if(attributes.at(e_shader_attribute_tangent) >= 0) { gl_disable_vertex_attribute(attributes.at(e_shader_attribute_tangent)); } if(attributes.at(e_shader_attribute_color) >= 0) { gl_disable_vertex_attribute(attributes.at(e_shader_attribute_color)); } if(attributes.at(e_shader_attribute_extra) >= 0) { gl_disable_vertex_attribute(attributes.at(e_shader_attribute_extra)); } gl_bind_buffer(GL_ARRAY_BUFFER, NULL); } }
void device_stage_texture(device_t device, stagesurf_t dst, texture_t src) { struct gs_texture_2d *tex2d = (struct gs_texture_2d*)src; if (!can_stage(dst, tex2d)) goto failed; if (!gl_copy_texture(device, dst->texture, GL_TEXTURE_2D, tex2d->base.texture, GL_TEXTURE_2D, dst->width, dst->height)) goto failed; if (!gl_bind_texture(GL_TEXTURE_2D, dst->texture)) goto failed; if (!gl_bind_buffer(GL_PIXEL_PACK_BUFFER, dst->pack_buffer)) goto failed; glGetTexImage(GL_TEXTURE_2D, 0, dst->gl_format, dst->gl_type, 0); if (!gl_success("glGetTexImage")) goto failed; gl_bind_buffer(GL_PIXEL_PACK_BUFFER, 0); gl_bind_texture(GL_TEXTURE_2D, 0); return; failed: gl_bind_buffer(GL_PIXEL_PACK_BUFFER, 0); gl_bind_texture(GL_TEXTURE_2D, 0); blog(LOG_ERROR, "device_stage_texture (GL) failed"); }
render_target::render_target(const graphics_context_shared_ptr& graphics_context, GLint format, const glm::ivec2& size, const texture_shared_ptr& custom_attachment) : m_graphics_context(graphics_context), m_size(size), m_format(format), m_is_custom_color_attachment(custom_attachment != nullptr) { if(!m_is_custom_color_attachment) { gl_create_textures(1, &m_color_attachment); gl_bind_texture(GL_TEXTURE_2D, m_color_attachment); gl_texture_parameter_i(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gl_texture_parameter_i(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gl_texture_parameter_i(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); gl_texture_parameter_i(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); gl_texture_image2d(GL_TEXTURE_2D, 0, format, m_size.x, m_size.y, 0, format, GL_UNSIGNED_BYTE, NULL); } else { m_color_attachment = custom_attachment->get_texture_id(); } gl_create_render_buffers(1, &m_depth_attachment); gl_bind_render_buffer(GL_RENDERBUFFER, m_depth_attachment); gl_create_render_buffer_storage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_size.x, m_size.y); gl_create_frame_buffers(1, &m_frame_buffer); gl_bind_frame_buffer(GL_FRAMEBUFFER, m_frame_buffer); gl_attach_frame_buffer_texture2d(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_attachment, 0); gl_attach_frame_buffer_render_buffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depth_attachment); assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); #if defined(__PBO__) ui32 size = m_size.x * m_size.y; if(m_format == GL_RGBA) { size *= 4; } else if(m_format == GL_RGB) { size *= 3; } gl_create_buffers(1, &m_pixel_buffer); gl_bind_buffer(GL_PIXEL_PACK_BUFFER, m_pixel_buffer); gl_push_buffer_data(GL_PIXEL_PACK_BUFFER, size, NULL, GL_STREAM_READ); gl_bind_buffer(GL_PIXEL_PACK_BUFFER, 0); #endif }
void stagesurface_unmap(stagesurf_t stagesurf) { if (!gl_bind_buffer(GL_PIXEL_PACK_BUFFER, stagesurf->pack_buffer)) return; glUnmapBuffer(GL_PIXEL_PACK_BUFFER); gl_success("glUnmapBuffer"); gl_bind_buffer(GL_PIXEL_PACK_BUFFER, 0); }
void ibo::unbind(void) const { if(m_used_size != 0) { gl_bind_buffer(GL_ELEMENT_ARRAY_BUFFER, NULL); } }
void ibo::bind(void) const { if(m_used_size != 0) { gl_bind_buffer(GL_ELEMENT_ARRAY_BUFFER, m_handle); } }
void ibo::unlock(ui32 size) { assert(m_data != nullptr); assert(m_allocated_size != 0); m_used_size = size > 0 && size < m_allocated_size ? size : m_allocated_size; gl_bind_buffer(GL_ELEMENT_ARRAY_BUFFER, m_handle); gl_push_buffer_data(GL_ELEMENT_ARRAY_BUFFER, sizeof(ui16) * m_used_size, m_data, m_mode); }
bool stagesurface_map(stagesurf_t stagesurf, uint8_t **data, uint32_t *linesize) { if (!gl_bind_buffer(GL_PIXEL_PACK_BUFFER, stagesurf->pack_buffer)) goto fail; *data = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); if (!gl_success("glMapBuffer")) goto fail; gl_bind_buffer(GL_PIXEL_PACK_BUFFER, 0); *linesize = stagesurf->bytes_per_pixel * stagesurf->width; return true; fail: blog(LOG_ERROR, "stagesurf_map (GL) failed"); return false; }
void device_load_indexbuffer(device_t device, indexbuffer_t ib) { if (ib == device->cur_index_buffer) return; device->cur_index_buffer = ib; if (!gl_bind_buffer(GL_ELEMENT_ARRAY_BUFFER, ib->buffer)) blog(LOG_ERROR, "device_load_indexbuffer (GL) failed"); }
/* Apparently for mac, PBOs won't do an asynchronous transfer unless you use * FBOs aong with glReadPixels, which is really dumb. */ void device_stage_texture(device_t device, stagesurf_t dst, texture_t src) { struct gs_texture_2d *tex2d = (struct gs_texture_2d*)src; struct fbo_info *fbo; GLint last_fbo; bool success = false; if (!can_stage(dst, tex2d)) goto failed; if (!gl_bind_buffer(GL_PIXEL_PACK_BUFFER, dst->pack_buffer)) goto failed; fbo = get_fbo(device, dst->width, dst->height, dst->format); if (!gl_get_integer_v(GL_READ_FRAMEBUFFER_BINDING, &last_fbo)) goto failed_unbind_buffer; if (!gl_bind_framebuffer(GL_READ_FRAMEBUFFER, fbo->fbo)) goto failed_unbind_buffer; glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0, src->gl_target, src->texture, 0); if (!gl_success("glFrameBufferTexture2D")) goto failed_unbind_all; glReadPixels(0, 0, dst->width, dst->height, dst->gl_format, dst->gl_type, 0); if (!gl_success("glReadPixels")) goto failed_unbind_all; success = true; failed_unbind_all: gl_bind_framebuffer(GL_READ_FRAMEBUFFER, last_fbo); failed_unbind_buffer: gl_bind_buffer(GL_PIXEL_PACK_BUFFER, 0); failed: if (!success) blog(LOG_ERROR, "device_stage_texture (GL) failed"); }
void vbo::bind(const std::array<i32, e_shader_attribute_max>& attributes) const { if(m_used_size != 0) { gl_bind_buffer(GL_ARRAY_BUFFER, m_handle); if(attributes.at(e_shader_attribute_position) >= 0) { gl_enable_vertex_attribute(attributes.at(e_shader_attribute_position)); gl_bind_vertex_attribute(attributes.at(e_shader_attribute_position), 3, GL_FLOAT, GL_FALSE, sizeof(vertex_attribute), (GLvoid*)offsetof(vertex_attribute, m_position)); } if(attributes.at(e_shader_attribute_texcoord) >= 0) { gl_enable_vertex_attribute(attributes.at(e_shader_attribute_texcoord)); gl_bind_vertex_attribute(attributes.at(e_shader_attribute_texcoord), 2, GL_UNSIGNED_SHORT, GL_TRUE, sizeof(vertex_attribute), (GLvoid*)offsetof(vertex_attribute, m_texcoord)); } if(attributes.at(e_shader_attribute_normal) >= 0) { gl_enable_vertex_attribute(attributes.at(e_shader_attribute_normal)); gl_bind_vertex_attribute(attributes.at(e_shader_attribute_normal), 4, GL_BYTE, GL_TRUE, sizeof(vertex_attribute), (GLvoid*)offsetof(vertex_attribute, m_normal)); } if(attributes[e_shader_attribute_tangent] >= 0) { gl_enable_vertex_attribute(attributes.at(e_shader_attribute_tangent)); gl_bind_vertex_attribute(attributes.at(e_shader_attribute_tangent), 4, GL_BYTE, GL_TRUE, sizeof(vertex_attribute), (GLvoid*)offsetof(vertex_attribute, m_tangent)); } if(attributes.at(e_shader_attribute_color) >= 0) { gl_enable_vertex_attribute(attributes.at(e_shader_attribute_color)); gl_bind_vertex_attribute(attributes.at(e_shader_attribute_color), 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(vertex_attribute), (GLvoid*)offsetof(vertex_attribute, m_color)); } if(attributes.at(e_shader_attribute_extra) >= 0) { gl_enable_vertex_attribute(attributes.at(e_shader_attribute_extra)); gl_bind_vertex_attribute(attributes.at(e_shader_attribute_extra), 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(vertex_attribute), (GLvoid*)offsetof(vertex_attribute, m_extra)); } } }
static bool create_pixel_pack_buffer(struct gs_stage_surface *surf) { GLsizeiptr size; bool success = true; if (!gl_gen_buffers(1, &surf->pack_buffer)) return false; if (!gl_bind_buffer(GL_PIXEL_PACK_BUFFER, surf->pack_buffer)) return false; size = surf->width * surf->bytes_per_pixel; size = (size+3) & 0xFFFFFFFC; /* align width to 4-byte boundry */ size *= surf->height; glBufferData(GL_PIXEL_PACK_BUFFER, size, 0, GL_DYNAMIC_READ); if (!gl_success("glBufferData")) success = false; if (!gl_bind_buffer(GL_PIXEL_PACK_BUFFER, 0)) success = false; return success; }
bool load_vb_buffers(struct gs_program *program, struct gs_vertex_buffer *vb, struct gs_index_buffer *ib) { struct gs_shader *shader = program->vertex_shader; size_t i; if (!gl_bind_vertex_array(vb->vao)) return false; for (i = 0; i < shader->attribs.num; i++) { struct shader_attrib *attrib = shader->attribs.array+i; if (!load_vb_buffer(attrib, vb, program->attribs.array[i])) return false; } if (ib && !gl_bind_buffer(GL_ELEMENT_ARRAY_BUFFER, ib->buffer)) return false; return true; }
void render_target::end(ui8* data) { if(data) { #if defined(__PBO__) glReadBuffer(GL_COLOR_ATTACHMENT0); gl_bind_buffer(GL_PIXEL_PACK_BUFFER, m_pixel_buffer); glReadPixels(0, 0, m_size.x, m_size.y, m_format, GL_UNSIGNED_BYTE, NULL); ui8* pointer = static_cast<ui8*>(glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY)); if (pointer) { ui32 size = m_size.x * m_size.y; if(m_format == GL_RGBA) { size *= 4; } else if(m_format == GL_RGB) { size *= 3; } memcpy(data, pointer, size); glUnmapBuffer(GL_PIXEL_PACK_BUFFER); } #else glReadPixels(0, 0, m_size.x, m_size.y, m_format, GL_UNSIGNED_BYTE, data); #endif } assert(m_graphics_context != nullptr); gl_bind_frame_buffer(GL_FRAMEBUFFER, m_graphics_context->get_frame_buffer()); gl_viewport(0, 0, m_graphics_context->get_width(), m_graphics_context->get_height()); }