Added sf::VertexBuffer class.

This commit is contained in:
binary1248 2017-10-24 18:57:26 +02:00 committed by Lukas Dürrenberger
parent fe39af4ec8
commit 61cdcd47ca
10 changed files with 1165 additions and 47 deletions

View file

@ -72,6 +72,8 @@ set(DRAWABLES_SRC
${INCROOT}/Text.hpp
${SRCROOT}/VertexArray.cpp
${INCROOT}/VertexArray.hpp
${SRCROOT}/VertexBuffer.cpp
${INCROOT}/VertexBuffer.hpp
)
source_group("drawables" FILES ${DRAWABLES_SRC})

View file

@ -53,6 +53,19 @@
#define GLEXT_GL_CLAMP GL_CLAMP_TO_EDGE
#define GLEXT_GL_CLAMP_TO_EDGE GL_CLAMP_TO_EDGE
// Core since 1.1
// 1.1 does not support GL_STREAM_DRAW so we just define it to GL_DYNAMIC_DRAW
#define GLEXT_vertex_buffer_object true
#define GLEXT_GL_ARRAY_BUFFER GL_ARRAY_BUFFER
#define GLEXT_GL_DYNAMIC_DRAW GL_DYNAMIC_DRAW
#define GLEXT_GL_STATIC_DRAW GL_STATIC_DRAW
#define GLEXT_GL_STREAM_DRAW GL_DYNAMIC_DRAW
#define GLEXT_glBindBuffer glBindBuffer
#define GLEXT_glBufferData glBufferData
#define GLEXT_glBufferSubData glBufferSubData
#define GLEXT_glDeleteBuffers glDeleteBuffers
#define GLEXT_glGenBuffers glGenBuffers
// The following extensions are listed chronologically
// Extension macro first, followed by tokens then
// functions according to the corresponding specification
@ -114,6 +127,9 @@
// Core since 3.0
#define GLEXT_framebuffer_blit false
// Core since 3.0 - NV_copy_buffer
#define GLEXT_copy_buffer false
// Core since 3.0 - EXT_sRGB
#ifdef GL_EXT_sRGB
#define GLEXT_texture_sRGB GL_EXT_sRGB
@ -168,6 +184,22 @@
#define GLEXT_blend_func_separate sfogl_ext_EXT_blend_func_separate
#define GLEXT_glBlendFuncSeparate glBlendFuncSeparateEXT
// Core since 1.5 - ARB_vertex_buffer_object
#define GLEXT_vertex_buffer_object sfogl_ext_ARB_vertex_buffer_object
#define GLEXT_GL_ARRAY_BUFFER GL_ARRAY_BUFFER_ARB
#define GLEXT_GL_DYNAMIC_DRAW GL_DYNAMIC_DRAW_ARB
#define GLEXT_GL_READ_ONLY GL_READ_ONLY_ARB
#define GLEXT_GL_STATIC_DRAW GL_STATIC_DRAW_ARB
#define GLEXT_GL_STREAM_DRAW GL_STREAM_DRAW_ARB
#define GLEXT_GL_WRITE_ONLY GL_WRITE_ONLY_ARB
#define GLEXT_glBindBuffer glBindBufferARB
#define GLEXT_glBufferData glBufferDataARB
#define GLEXT_glBufferSubData glBufferSubDataARB
#define GLEXT_glDeleteBuffers glDeleteBuffersARB
#define GLEXT_glGenBuffers glGenBuffersARB
#define GLEXT_glMapBuffer glMapBufferARB
#define GLEXT_glUnmapBuffer glUnmapBufferARB
// Core since 2.0 - ARB_shading_language_100
#define GLEXT_shading_language_100 sfogl_ext_ARB_shading_language_100
@ -254,6 +286,12 @@
#define GLEXT_GL_DRAW_FRAMEBUFFER_BINDING GL_DRAW_FRAMEBUFFER_BINDING_EXT
#define GLEXT_GL_READ_FRAMEBUFFER_BINDING GL_READ_FRAMEBUFFER_BINDING_EXT
// Core since 3.1 - ARB_copy_buffer
#define GLEXT_copy_buffer sfogl_ext_ARB_copy_buffer
#define GLEXT_GL_COPY_READ_BUFFER GL_COPY_READ_BUFFER
#define GLEXT_GL_COPY_WRITE_BUFFER GL_COPY_WRITE_BUFFER
#define GLEXT_glCopyBufferSubData glCopyBufferSubData
// Core since 3.2 - ARB_geometry_shader4
#define GLEXT_geometry_shader4 sfogl_ext_ARB_geometry_shader4
#define GLEXT_GL_GEOMETRY_SHADER GL_GEOMETRY_SHADER_ARB

View file

@ -7,6 +7,7 @@ EXT_blend_minmax
EXT_blend_subtract
ARB_multitexture
EXT_blend_func_separate
ARB_vertex_buffer_object
ARB_shading_language_100
ARB_shader_objects
ARB_vertex_shader
@ -16,4 +17,5 @@ EXT_blend_equation_separate
EXT_texture_sRGB
EXT_framebuffer_object
EXT_framebuffer_blit
ARB_copy_buffer
ARB_geometry_shader4

View file

@ -39,6 +39,7 @@ int sfogl_ext_EXT_blend_minmax = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_blend_subtract = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_multitexture = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_blend_func_separate = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_vertex_buffer_object = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_shading_language_100 = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_shader_objects = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_vertex_shader = sfogl_LOAD_FAILED;
@ -48,6 +49,7 @@ int sfogl_ext_EXT_blend_equation_separate = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_texture_sRGB = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_framebuffer_object = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_framebuffer_blit = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_copy_buffer = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_geometry_shader4 = sfogl_LOAD_FAILED;
void (GL_FUNCPTR *sf_ptrc_glBlendEquationEXT)(GLenum) = NULL;
@ -254,6 +256,69 @@ static int Load_EXT_blend_func_separate()
return numFailed;
}
void (GL_FUNCPTR *sf_ptrc_glBindBufferARB)(GLenum, GLuint) = NULL;
void (GL_FUNCPTR *sf_ptrc_glBufferDataARB)(GLenum, GLsizeiptrARB, const void*, GLenum) = NULL;
void (GL_FUNCPTR *sf_ptrc_glBufferSubDataARB)(GLenum, GLintptrARB, GLsizeiptrARB, const void*) = NULL;
void (GL_FUNCPTR *sf_ptrc_glDeleteBuffersARB)(GLsizei, const GLuint*) = NULL;
void (GL_FUNCPTR *sf_ptrc_glGenBuffersARB)(GLsizei, GLuint*) = NULL;
void (GL_FUNCPTR *sf_ptrc_glGetBufferParameterivARB)(GLenum, GLenum, GLint*) = NULL;
void (GL_FUNCPTR *sf_ptrc_glGetBufferPointervARB)(GLenum, GLenum, void**) = NULL;
void (GL_FUNCPTR *sf_ptrc_glGetBufferSubDataARB)(GLenum, GLintptrARB, GLsizeiptrARB, void*) = NULL;
GLboolean (GL_FUNCPTR *sf_ptrc_glIsBufferARB)(GLuint) = NULL;
void* (GL_FUNCPTR *sf_ptrc_glMapBufferARB)(GLenum, GLenum) = NULL;
GLboolean (GL_FUNCPTR *sf_ptrc_glUnmapBufferARB)(GLenum) = NULL;
static int Load_ARB_vertex_buffer_object()
{
int numFailed = 0;
sf_ptrc_glBindBufferARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLuint)>(glLoaderGetProcAddress("glBindBufferARB"));
if (!sf_ptrc_glBindBufferARB)
numFailed++;
sf_ptrc_glBufferDataARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLsizeiptrARB, const void*, GLenum)>(glLoaderGetProcAddress("glBufferDataARB"));
if (!sf_ptrc_glBufferDataARB)
numFailed++;
sf_ptrc_glBufferSubDataARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLintptrARB, GLsizeiptrARB, const void*)>(glLoaderGetProcAddress("glBufferSubDataARB"));
if (!sf_ptrc_glBufferSubDataARB)
numFailed++;
sf_ptrc_glDeleteBuffersARB = reinterpret_cast<void (GL_FUNCPTR *)(GLsizei, const GLuint*)>(glLoaderGetProcAddress("glDeleteBuffersARB"));
if (!sf_ptrc_glDeleteBuffersARB)
numFailed++;
sf_ptrc_glGenBuffersARB = reinterpret_cast<void (GL_FUNCPTR *)(GLsizei, GLuint*)>(glLoaderGetProcAddress("glGenBuffersARB"));
if (!sf_ptrc_glGenBuffersARB)
numFailed++;
sf_ptrc_glGetBufferParameterivARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLenum, GLint*)>(glLoaderGetProcAddress("glGetBufferParameterivARB"));
if (!sf_ptrc_glGetBufferParameterivARB)
numFailed++;
sf_ptrc_glGetBufferPointervARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLenum, void**)>(glLoaderGetProcAddress("glGetBufferPointervARB"));
if (!sf_ptrc_glGetBufferPointervARB)
numFailed++;
sf_ptrc_glGetBufferSubDataARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLintptrARB, GLsizeiptrARB, void*)>(glLoaderGetProcAddress("glGetBufferSubDataARB"));
if (!sf_ptrc_glGetBufferSubDataARB)
numFailed++;
sf_ptrc_glIsBufferARB = reinterpret_cast<GLboolean (GL_FUNCPTR *)(GLuint)>(glLoaderGetProcAddress("glIsBufferARB"));
if (!sf_ptrc_glIsBufferARB)
numFailed++;
sf_ptrc_glMapBufferARB = reinterpret_cast<void* (GL_FUNCPTR *)(GLenum, GLenum)>(glLoaderGetProcAddress("glMapBufferARB"));
if (!sf_ptrc_glMapBufferARB)
numFailed++;
sf_ptrc_glUnmapBufferARB = reinterpret_cast<GLboolean (GL_FUNCPTR *)(GLenum)>(glLoaderGetProcAddress("glUnmapBufferARB"));
if (!sf_ptrc_glUnmapBufferARB)
numFailed++;
return numFailed;
}
void (GL_FUNCPTR *sf_ptrc_glAttachObjectARB)(GLhandleARB, GLhandleARB) = NULL;
void (GL_FUNCPTR *sf_ptrc_glCompileShaderARB)(GLhandleARB) = NULL;
GLhandleARB (GL_FUNCPTR *sf_ptrc_glCreateProgramObjectARB)() = NULL;
@ -814,6 +879,19 @@ static int Load_EXT_framebuffer_blit()
return numFailed;
}
void (GL_FUNCPTR *sf_ptrc_glCopyBufferSubData)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr) = NULL;
static int Load_ARB_copy_buffer()
{
int numFailed = 0;
sf_ptrc_glCopyBufferSubData = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr)>(glLoaderGetProcAddress("glCopyBufferSubData"));
if (!sf_ptrc_glCopyBufferSubData)
numFailed++;
return numFailed;
}
void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureARB)(GLenum, GLenum, GLuint, GLint) = NULL;
void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureFaceARB)(GLenum, GLenum, GLuint, GLint, GLenum) = NULL;
void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureLayerARB)(GLenum, GLenum, GLuint, GLint, GLint) = NULL;
@ -850,13 +928,14 @@ typedef struct sfogl_StrToExtMap_s
PFN_LOADFUNCPOINTERS LoadExtension;
} sfogl_StrToExtMap;
static sfogl_StrToExtMap ExtensionMap[16] = {
static sfogl_StrToExtMap ExtensionMap[18] = {
{"GL_SGIS_texture_edge_clamp", &sfogl_ext_SGIS_texture_edge_clamp, NULL},
{"GL_EXT_texture_edge_clamp", &sfogl_ext_EXT_texture_edge_clamp, NULL},
{"GL_EXT_blend_minmax", &sfogl_ext_EXT_blend_minmax, Load_EXT_blend_minmax},
{"GL_EXT_blend_subtract", &sfogl_ext_EXT_blend_subtract, NULL},
{"GL_ARB_multitexture", &sfogl_ext_ARB_multitexture, Load_ARB_multitexture},
{"GL_EXT_blend_func_separate", &sfogl_ext_EXT_blend_func_separate, Load_EXT_blend_func_separate},
{"GL_ARB_vertex_buffer_object", &sfogl_ext_ARB_vertex_buffer_object, Load_ARB_vertex_buffer_object},
{"GL_ARB_shading_language_100", &sfogl_ext_ARB_shading_language_100, NULL},
{"GL_ARB_shader_objects", &sfogl_ext_ARB_shader_objects, Load_ARB_shader_objects},
{"GL_ARB_vertex_shader", &sfogl_ext_ARB_vertex_shader, Load_ARB_vertex_shader},
@ -866,10 +945,11 @@ static sfogl_StrToExtMap ExtensionMap[16] = {
{"GL_EXT_texture_sRGB", &sfogl_ext_EXT_texture_sRGB, NULL},
{"GL_EXT_framebuffer_object", &sfogl_ext_EXT_framebuffer_object, Load_EXT_framebuffer_object},
{"GL_EXT_framebuffer_blit", &sfogl_ext_EXT_framebuffer_blit, Load_EXT_framebuffer_blit},
{"GL_ARB_copy_buffer", &sfogl_ext_ARB_copy_buffer, Load_ARB_copy_buffer},
{"GL_ARB_geometry_shader4", &sfogl_ext_ARB_geometry_shader4, Load_ARB_geometry_shader4}
};
static int g_extensionMapSize = 16;
static int g_extensionMapSize = 18;
static void ClearExtensionVars()
@ -880,6 +960,7 @@ static void ClearExtensionVars()
sfogl_ext_EXT_blend_subtract = sfogl_LOAD_FAILED;
sfogl_ext_ARB_multitexture = sfogl_LOAD_FAILED;
sfogl_ext_EXT_blend_func_separate = sfogl_LOAD_FAILED;
sfogl_ext_ARB_vertex_buffer_object = sfogl_LOAD_FAILED;
sfogl_ext_ARB_shading_language_100 = sfogl_LOAD_FAILED;
sfogl_ext_ARB_shader_objects = sfogl_LOAD_FAILED;
sfogl_ext_ARB_vertex_shader = sfogl_LOAD_FAILED;
@ -889,6 +970,7 @@ static void ClearExtensionVars()
sfogl_ext_EXT_texture_sRGB = sfogl_LOAD_FAILED;
sfogl_ext_EXT_framebuffer_object = sfogl_LOAD_FAILED;
sfogl_ext_EXT_framebuffer_blit = sfogl_LOAD_FAILED;
sfogl_ext_ARB_copy_buffer = sfogl_LOAD_FAILED;
sfogl_ext_ARB_geometry_shader4 = sfogl_LOAD_FAILED;
}

View file

@ -176,6 +176,7 @@ extern int sfogl_ext_EXT_blend_minmax;
extern int sfogl_ext_EXT_blend_subtract;
extern int sfogl_ext_ARB_multitexture;
extern int sfogl_ext_EXT_blend_func_separate;
extern int sfogl_ext_ARB_vertex_buffer_object;
extern int sfogl_ext_ARB_shading_language_100;
extern int sfogl_ext_ARB_shader_objects;
extern int sfogl_ext_ARB_vertex_shader;
@ -185,6 +186,7 @@ extern int sfogl_ext_EXT_blend_equation_separate;
extern int sfogl_ext_EXT_texture_sRGB;
extern int sfogl_ext_EXT_framebuffer_object;
extern int sfogl_ext_EXT_framebuffer_blit;
extern int sfogl_ext_ARB_copy_buffer;
extern int sfogl_ext_ARB_geometry_shader4;
#define GL_CLAMP_TO_EDGE_SGIS 0x812F
@ -240,6 +242,38 @@ extern int sfogl_ext_ARB_geometry_shader4;
#define GL_BLEND_SRC_ALPHA_EXT 0x80CB
#define GL_BLEND_SRC_RGB_EXT 0x80C9
#define GL_ARRAY_BUFFER_ARB 0x8892
#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
#define GL_BUFFER_ACCESS_ARB 0x88BB
#define GL_BUFFER_MAPPED_ARB 0x88BC
#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
#define GL_BUFFER_SIZE_ARB 0x8764
#define GL_BUFFER_USAGE_ARB 0x8765
#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
#define GL_DYNAMIC_COPY_ARB 0x88EA
#define GL_DYNAMIC_DRAW_ARB 0x88E8
#define GL_DYNAMIC_READ_ARB 0x88E9
#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
#define GL_READ_ONLY_ARB 0x88B8
#define GL_READ_WRITE_ARB 0x88BA
#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
#define GL_STATIC_COPY_ARB 0x88E6
#define GL_STATIC_DRAW_ARB 0x88E4
#define GL_STATIC_READ_ARB 0x88E5
#define GL_STREAM_COPY_ARB 0x88E2
#define GL_STREAM_DRAW_ARB 0x88E0
#define GL_STREAM_READ_ARB 0x88E1
#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
#define GL_WRITE_ONLY_ARB 0x88B9
#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
#define GL_BOOL_ARB 0x8B56
@ -385,6 +419,9 @@ extern int sfogl_ext_ARB_geometry_shader4;
#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
#define GL_COPY_READ_BUFFER 0x8F36
#define GL_COPY_WRITE_BUFFER 0x8F37
#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9
@ -1022,6 +1059,32 @@ extern void (GL_FUNCPTR *sf_ptrc_glBlendFuncSeparateEXT)(GLenum, GLenum, GLenum,
#define glBlendFuncSeparateEXT sf_ptrc_glBlendFuncSeparateEXT
#endif // GL_EXT_blend_func_separate
#ifndef GL_ARB_vertex_buffer_object
#define GL_ARB_vertex_buffer_object 1
extern void (GL_FUNCPTR *sf_ptrc_glBindBufferARB)(GLenum, GLuint);
#define glBindBufferARB sf_ptrc_glBindBufferARB
extern void (GL_FUNCPTR *sf_ptrc_glBufferDataARB)(GLenum, GLsizeiptrARB, const void*, GLenum);
#define glBufferDataARB sf_ptrc_glBufferDataARB
extern void (GL_FUNCPTR *sf_ptrc_glBufferSubDataARB)(GLenum, GLintptrARB, GLsizeiptrARB, const void*);
#define glBufferSubDataARB sf_ptrc_glBufferSubDataARB
extern void (GL_FUNCPTR *sf_ptrc_glDeleteBuffersARB)(GLsizei, const GLuint*);
#define glDeleteBuffersARB sf_ptrc_glDeleteBuffersARB
extern void (GL_FUNCPTR *sf_ptrc_glGenBuffersARB)(GLsizei, GLuint*);
#define glGenBuffersARB sf_ptrc_glGenBuffersARB
extern void (GL_FUNCPTR *sf_ptrc_glGetBufferParameterivARB)(GLenum, GLenum, GLint*);
#define glGetBufferParameterivARB sf_ptrc_glGetBufferParameterivARB
extern void (GL_FUNCPTR *sf_ptrc_glGetBufferPointervARB)(GLenum, GLenum, void**);
#define glGetBufferPointervARB sf_ptrc_glGetBufferPointervARB
extern void (GL_FUNCPTR *sf_ptrc_glGetBufferSubDataARB)(GLenum, GLintptrARB, GLsizeiptrARB, void*);
#define glGetBufferSubDataARB sf_ptrc_glGetBufferSubDataARB
extern GLboolean (GL_FUNCPTR *sf_ptrc_glIsBufferARB)(GLuint);
#define glIsBufferARB sf_ptrc_glIsBufferARB
extern void* (GL_FUNCPTR *sf_ptrc_glMapBufferARB)(GLenum, GLenum);
#define glMapBufferARB sf_ptrc_glMapBufferARB
extern GLboolean (GL_FUNCPTR *sf_ptrc_glUnmapBufferARB)(GLenum);
#define glUnmapBufferARB sf_ptrc_glUnmapBufferARB
#endif // GL_ARB_vertex_buffer_object
#ifndef GL_ARB_shader_objects
#define GL_ARB_shader_objects 1
@ -1254,6 +1317,12 @@ extern void (GL_FUNCPTR *sf_ptrc_glBlitFramebufferEXT)(GLint, GLint, GLint, GLin
#define glBlitFramebufferEXT sf_ptrc_glBlitFramebufferEXT
#endif // GL_EXT_framebuffer_blit
#ifndef GL_ARB_copy_buffer
#define GL_ARB_copy_buffer 1
extern void (GL_FUNCPTR *sf_ptrc_glCopyBufferSubData)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr);
#define glCopyBufferSubData sf_ptrc_glCopyBufferSubData
#endif // GL_ARB_copy_buffer
#ifndef GL_ARB_geometry_shader4
#define GL_ARB_geometry_shader4 1
extern void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureARB)(GLenum, GLenum, GLuint, GLint);

View file

@ -30,10 +30,21 @@
#include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/VertexArray.hpp>
#include <SFML/Graphics/VertexBuffer.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/System/Err.hpp>
#include <cassert>
#include <iostream>
#include <algorithm>
// GL_QUADS is unavailable on OpenGL ES, thus we need to define GL_QUADS ourselves
#ifdef SFML_OPENGL_ES
#define GL_QUADS 0
#endif // SFML_OPENGL_ES
namespace
{
@ -211,17 +222,13 @@ void RenderTarget::draw(const Vertex* vertices, std::size_t vertexCount,
err() << "sf::Quads primitive type is not supported on OpenGL ES platforms, drawing skipped" << std::endl;
return;
}
#define GL_QUADS 0
#endif
if (setActive(true))
{
// First set the persistent OpenGL states if it's the very first call
if (!m_cache.glStatesSet)
resetGLStates();
// Check if the vertex count is low enough so that we can pre-transform them
bool useVertexCache = (vertexCount <= StatesCache::VertexCacheSize);
if (useVertexCache)
{
// Pre-transform the vertices and store them into the vertex cache
@ -232,32 +239,9 @@ void RenderTarget::draw(const Vertex* vertices, std::size_t vertexCount,
vertex.color = vertices[i].color;
vertex.texCoords = vertices[i].texCoords;
}
// Since vertices are transformed, we must use an identity transform to render them
if (!m_cache.useVertexCache)
glCheck(glLoadIdentity());
}
else
{
applyTransform(states.transform);
}
// Apply the view
if (m_cache.viewChanged)
applyCurrentView();
// Apply the blend mode
if (states.blendMode != m_cache.lastBlendMode)
applyBlendMode(states.blendMode);
// Apply the texture
Uint64 textureId = states.texture ? states.texture->m_cacheId : 0;
if (textureId != m_cache.lastTextureId)
applyTexture(states.texture);
// Apply the shader
if (states.shader)
applyShader(states.shader);
setupDraw(useVertexCache, states);
// Check if texture coordinates array is needed, and update client state accordingly
bool enableTexCoordsArray = (states.texture || states.shader);
@ -292,22 +276,8 @@ void RenderTarget::draw(const Vertex* vertices, std::size_t vertexCount,
glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 12));
}
// Find the OpenGL primitive type
static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES,
GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS};
GLenum mode = modes[type];
// Draw the primitives
glCheck(glDrawArrays(mode, 0, static_cast<GLsizei>(vertexCount)));
// Unbind the shader, if any
if (states.shader)
applyShader(NULL);
// If the texture we used to draw belonged to a RenderTexture, then forcibly unbind that texture.
// This prevents a bug where some drivers do not clear RenderTextures properly.
if (states.texture && states.texture->m_fboAttachment)
applyTexture(NULL);
drawPrimitives(type, 0, vertexCount);
cleanupDraw(states);
// Update the cache
m_cache.useVertexCache = useVertexCache;
@ -316,6 +286,73 @@ void RenderTarget::draw(const Vertex* vertices, std::size_t vertexCount,
}
////////////////////////////////////////////////////////////
void RenderTarget::draw(const VertexBuffer& vertexBuffer, const RenderStates& states)
{
draw(vertexBuffer, 0, vertexBuffer.getVertexCount(), states);
}
////////////////////////////////////////////////////////////
void RenderTarget::draw(const VertexBuffer& vertexBuffer, std::size_t firstVertex,
std::size_t vertexCount, const RenderStates& states)
{
// VertexBuffer not supported?
if (!VertexBuffer::isAvailable())
{
err() << "sf::VertexBuffer is not available, drawing skipped" << std::endl;
return;
}
// Sanity check
if (firstVertex > vertexBuffer.getVertexCount())
return;
// Clamp vertexCount to something that makes sense
vertexCount = std::min(vertexCount, vertexBuffer.getVertexCount() - firstVertex);
// Nothing to draw?
if (!vertexCount || !vertexBuffer.getNativeHandle())
return;
// GL_QUADS is unavailable on OpenGL ES
#ifdef SFML_OPENGL_ES
if (vertexBuffer.getPrimitiveType() == Quads)
{
err() << "sf::Quads primitive type is not supported on OpenGL ES platforms, drawing skipped" << std::endl;
return;
}
#endif
if (setActive(true))
{
setupDraw(false, states);
// Bind vertex buffer
VertexBuffer::bind(&vertexBuffer);
// Always enable texture coordinates
if (!m_cache.texCoordsArrayEnabled)
glCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
glCheck(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), reinterpret_cast<const void*>(0)));
glCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), reinterpret_cast<const void*>(8)));
glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), reinterpret_cast<const void*>(12)));
drawPrimitives(vertexBuffer.getPrimitiveType(), firstVertex, vertexCount);
// Unbind vertex buffer
VertexBuffer::bind(NULL);
cleanupDraw(states);
// Update the cache
m_cache.useVertexCache = false;
m_cache.texCoordsArrayEnabled = true;
}
}
////////////////////////////////////////////////////////////
void RenderTarget::pushGLStates()
{
@ -372,6 +409,7 @@ void RenderTarget::resetGLStates()
{
// Check here to make sure a context change does not happen after activate(true)
bool shaderAvailable = Shader::isAvailable();
bool vertexBufferAvailable = VertexBuffer::isAvailable();
// Workaround for states not being properly reset on
// macOS unless a context switch really takes place
@ -411,6 +449,9 @@ void RenderTarget::resetGLStates()
if (shaderAvailable)
applyShader(NULL);
if (vertexBufferAvailable)
glCheck(VertexBuffer::bind(NULL));
m_cache.texCoordsArrayEnabled = true;
m_cache.useVertexCache = false;
@ -527,6 +568,70 @@ void RenderTarget::applyShader(const Shader* shader)
Shader::bind(shader);
}
////////////////////////////////////////////////////////////
void RenderTarget::setupDraw(bool useVertexCache, const RenderStates& states)
{
// First set the persistent OpenGL states if it's the very first call
if (!m_cache.glStatesSet)
resetGLStates();
if (useVertexCache)
{
// Since vertices are transformed, we must use an identity transform to render them
if (!m_cache.useVertexCache)
glCheck(glLoadIdentity());
}
else
{
applyTransform(states.transform);
}
// Apply the view
if (m_cache.viewChanged)
applyCurrentView();
// Apply the blend mode
if (states.blendMode != m_cache.lastBlendMode)
applyBlendMode(states.blendMode);
// Apply the texture
Uint64 textureId = states.texture ? states.texture->m_cacheId : 0;
if (textureId != m_cache.lastTextureId)
applyTexture(states.texture);
// Apply the shader
if (states.shader)
applyShader(states.shader);
}
////////////////////////////////////////////////////////////
void RenderTarget::drawPrimitives(PrimitiveType type, std::size_t firstVertex, std::size_t vertexCount)
{
// Find the OpenGL primitive type
static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES,
GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS};
GLenum mode = modes[type];
// Draw the primitives
glCheck(glDrawArrays(mode, firstVertex, static_cast<GLsizei>(vertexCount)));
}
////////////////////////////////////////////////////////////
void RenderTarget::cleanupDraw(const RenderStates& states)
{
// Unbind the shader, if any
if (states.shader)
applyShader(NULL);
// If the texture we used to draw belonged to a RenderTexture, then forcibly unbind that texture.
// This prevents a bug where some drivers do not clear RenderTextures properly.
if (states.texture && states.texture->m_fboAttachment)
applyTexture(NULL);
}
} // namespace sf

View file

@ -0,0 +1,363 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/VertexBuffer.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Vertex.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <cstring>
namespace
{
sf::Mutex isAvailableMutex;
GLenum usageToGlEnum(sf::VertexBuffer::Usage usage)
{
switch (usage)
{
case sf::VertexBuffer::Static: return GLEXT_GL_STATIC_DRAW;
case sf::VertexBuffer::Dynamic: return GLEXT_GL_DYNAMIC_DRAW;
default: return GLEXT_GL_STREAM_DRAW;
}
}
}
namespace sf
{
////////////////////////////////////////////////////////////
VertexBuffer::VertexBuffer() :
m_buffer (0),
m_size (0),
m_primitiveType(Points),
m_usage (Stream)
{
}
////////////////////////////////////////////////////////////
VertexBuffer::VertexBuffer(PrimitiveType type) :
m_buffer (0),
m_size (0),
m_primitiveType(type),
m_usage (Stream)
{
}
////////////////////////////////////////////////////////////
VertexBuffer::VertexBuffer(VertexBuffer::Usage usage) :
m_buffer (0),
m_size (0),
m_primitiveType(Points),
m_usage (usage)
{
}
////////////////////////////////////////////////////////////
VertexBuffer::VertexBuffer(PrimitiveType type, VertexBuffer::Usage usage) :
m_buffer (0),
m_size (0),
m_primitiveType(type),
m_usage (usage)
{
}
////////////////////////////////////////////////////////////
VertexBuffer::VertexBuffer(const VertexBuffer& copy) :
m_buffer (0),
m_size (0),
m_primitiveType(copy.m_primitiveType),
m_usage (copy.m_usage)
{
if (copy.m_buffer && copy.m_size)
{
if (!create(copy.m_size))
{
err() << "Could not create vertex buffer for copying" << std::endl;
return;
}
if (!update(copy))
err() << "Could not copy vertex buffer" << std::endl;
}
}
////////////////////////////////////////////////////////////
VertexBuffer::~VertexBuffer()
{
if (m_buffer)
{
TransientContextLock contextLock;
glCheck(GLEXT_glDeleteBuffers(1, &m_buffer));
}
}
////////////////////////////////////////////////////////////
bool VertexBuffer::create(std::size_t vertexCount)
{
if (!isAvailable())
return false;
TransientContextLock contextLock;
if (!m_buffer)
glCheck(GLEXT_glGenBuffers(1, &m_buffer));
if (!m_buffer)
{
err() << "Could not create vertex buffer, generation failed" << std::endl;
return false;
}
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));
glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, 0, usageToGlEnum(m_usage)));
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, 0));
m_size = vertexCount;
return true;
}
////////////////////////////////////////////////////////////
std::size_t VertexBuffer::getVertexCount() const
{
return m_size;
}
////////////////////////////////////////////////////////////
bool VertexBuffer::update(const Vertex* vertices)
{
return update(vertices, m_size, 0);
}
////////////////////////////////////////////////////////////
bool VertexBuffer::update(const Vertex* vertices, std::size_t vertexCount, unsigned int offset)
{
// Sanity checks
if (!m_buffer)
return false;
if (!vertices)
return false;
if (offset && (offset + vertexCount > m_size))
return false;
TransientContextLock contextLock;
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));
// Check if we need to resize or orphan the buffer
if (vertexCount >= m_size)
{
glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, 0, usageToGlEnum(m_usage)));
m_size = vertexCount;
}
glCheck(GLEXT_glBufferSubData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * offset, sizeof(Vertex) * vertexCount, vertices));
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, 0));
return true;
}
////////////////////////////////////////////////////////////
bool VertexBuffer::update(const VertexBuffer& vertexBuffer)
{
#ifdef SFML_OPENGL_ES
return false;
#else
if (!m_buffer || !vertexBuffer.m_buffer)
return false;
TransientContextLock contextLock;
// Make sure that extensions are initialized
sf::priv::ensureExtensionsInit();
if (GLEXT_copy_buffer)
{
glCheck(GLEXT_glBindBuffer(GLEXT_GL_COPY_READ_BUFFER, vertexBuffer.m_buffer));
glCheck(GLEXT_glBindBuffer(GLEXT_GL_COPY_WRITE_BUFFER, m_buffer));
glCheck(GLEXT_glCopyBufferSubData(GLEXT_GL_COPY_READ_BUFFER, GLEXT_GL_COPY_WRITE_BUFFER, 0, 0, sizeof(Vertex) * vertexBuffer.m_size));
glCheck(GLEXT_glBindBuffer(GLEXT_GL_COPY_WRITE_BUFFER, 0));
glCheck(GLEXT_glBindBuffer(GLEXT_GL_COPY_READ_BUFFER, 0));
return true;
}
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));
glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexBuffer.m_size, 0, usageToGlEnum(m_usage)));
void* destination = 0;
glCheck(destination = GLEXT_glMapBuffer(GLEXT_GL_ARRAY_BUFFER, GLEXT_GL_WRITE_ONLY));
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, vertexBuffer.m_buffer));
void* source = 0;
glCheck(source = GLEXT_glMapBuffer(GLEXT_GL_ARRAY_BUFFER, GLEXT_GL_READ_ONLY));
std::memcpy(destination, source, sizeof(Vertex) * vertexBuffer.m_size);
GLboolean sourceResult = GL_FALSE;
glCheck(sourceResult = GLEXT_glUnmapBuffer(GLEXT_GL_ARRAY_BUFFER));
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));
GLboolean destinationResult = GL_FALSE;
glCheck(destinationResult = GLEXT_glUnmapBuffer(GLEXT_GL_ARRAY_BUFFER));
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, 0));
if ((sourceResult == GL_FALSE) || (destinationResult == GL_FALSE))
return false;
return true;
#endif // SFML_OPENGL_ES
}
////////////////////////////////////////////////////////////
VertexBuffer& VertexBuffer::operator =(const VertexBuffer& right)
{
VertexBuffer temp(right);
swap(temp);
return *this;
}
////////////////////////////////////////////////////////////
void VertexBuffer::swap(VertexBuffer& right)
{
std::swap(m_size, right.m_size);
std::swap(m_buffer, right.m_buffer);
std::swap(m_primitiveType, right.m_primitiveType);
std::swap(m_usage, right.m_usage);
}
////////////////////////////////////////////////////////////
unsigned int VertexBuffer::getNativeHandle() const
{
return m_buffer;
}
////////////////////////////////////////////////////////////
void VertexBuffer::bind(const VertexBuffer* vertexBuffer)
{
if (!isAvailable())
return;
TransientContextLock lock;
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, vertexBuffer ? vertexBuffer->m_buffer : 0));
}
////////////////////////////////////////////////////////////
void VertexBuffer::setPrimitiveType(PrimitiveType type)
{
m_primitiveType = type;
}
////////////////////////////////////////////////////////////
PrimitiveType VertexBuffer::getPrimitiveType() const
{
return m_primitiveType;
}
////////////////////////////////////////////////////////////
void VertexBuffer::setUsage(VertexBuffer::Usage usage)
{
m_usage = usage;
}
////////////////////////////////////////////////////////////
VertexBuffer::Usage VertexBuffer::getUsage() const
{
return m_usage;
}
////////////////////////////////////////////////////////////
bool VertexBuffer::isAvailable()
{
Lock lock(isAvailableMutex);
static bool checked = false;
static bool available = false;
if (!checked)
{
checked = true;
TransientContextLock contextLock;
// Make sure that extensions are initialized
sf::priv::ensureExtensionsInit();
available = GLEXT_vertex_buffer_object;
}
return available;
}
////////////////////////////////////////////////////////////
void VertexBuffer::draw(RenderTarget& target, RenderStates states) const
{
if (m_buffer && m_size)
target.draw(*this, 0, m_size, states);
}
} // namespace sf