From be989cdde9ff917304e08044a8836c594478f436 Mon Sep 17 00:00:00 2001 From: Noel Berry Date: Wed, 23 Dec 2020 16:16:09 -0800 Subject: [PATCH] refactoring rendering backend a little --- CMakeLists.txt | 17 +- private/blah/internal/graphics.h | 68 - private/blah/internal/graphics_backend.h | 24 + private/blah/internal/graphics_backend_gl.cpp | 1495 ++++++++++++++++ private/blah/internal/graphics_opengl.cpp | 1569 ----------------- private/blah/internal/input.h | 57 - private/blah/internal/input_backend.h | 54 + private/blah/internal/platform.h | 120 -- private/blah/internal/platform_backend.h | 117 ++ ...orm_sdl2.cpp => platform_backend_sdl2.cpp} | 153 +- public/blah/app.cpp | 70 +- public/blah/app.h | 9 - public/blah/drawing/batch.cpp | 32 +- public/blah/drawing/batch.h | 5 +- public/blah/drawing/subtexture.cpp | 2 +- public/blah/filesystem.cpp | 16 +- public/blah/graphics/framebuffer.h | 12 +- public/blah/graphics/graphics.cpp | 129 +- public/blah/graphics/graphics.h | 14 +- public/blah/graphics/material.cpp | 55 +- public/blah/graphics/material.h | 11 +- public/blah/graphics/mesh.h | 6 - public/blah/graphics/shader.h | 6 - public/blah/graphics/texture.h | 6 - public/blah/input/input.cpp | 32 +- public/blah/streams/filestream.cpp | 18 +- public/blah/streams/stream.cpp | 1 - 27 files changed, 1914 insertions(+), 2184 deletions(-) delete mode 100644 private/blah/internal/graphics.h create mode 100644 private/blah/internal/graphics_backend.h create mode 100644 private/blah/internal/graphics_backend_gl.cpp delete mode 100644 private/blah/internal/graphics_opengl.cpp delete mode 100644 private/blah/internal/input.h create mode 100644 private/blah/internal/input_backend.h delete mode 100644 private/blah/internal/platform.h create mode 100644 private/blah/internal/platform_backend.h rename private/blah/internal/{platform_sdl2.cpp => platform_backend_sdl2.cpp} (75%) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd33948..5dd9900 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,8 +17,8 @@ add_library(blah public/blah/time.cpp public/blah/time.h - public/blah/graphics/graphics.cpp public/blah/graphics/graphics.h + public/blah/graphics/graphics.cpp public/blah/graphics/texture.h public/blah/graphics/framebuffer.h public/blah/graphics/shader.h @@ -27,8 +27,8 @@ add_library(blah public/blah/graphics/material.h public/blah/graphics/material.cpp - public/blah/input/input.cpp public/blah/input/input.h + public/blah/input/input.cpp public/blah/input/virtual_stick.cpp public/blah/input/virtual_stick.h public/blah/input/virtual_button.cpp @@ -94,14 +94,15 @@ add_library(blah public/blah/streams/stream.cpp public/blah/streams/stream.h + private/blah/internal/graphics_backend.h + private/blah/internal/graphics_backend_gl.cpp + private/blah/internal/input_backend.h + private/blah/internal/platform_backend.h + private/blah/internal/platform_backend_sdl2.cpp + private/blah/third_party/stb_image.h private/blah/third_party/stb_image_write.h - private/blah/third_party/stb_truetype.h - private/blah/internal/graphics.h - private/blah/internal/graphics_opengl.cpp - private/blah/internal/input.h - private/blah/internal/platform.h - private/blah/internal/platform_sdl2.cpp) + private/blah/third_party/stb_truetype.h) target_include_directories(blah PUBLIC diff --git a/private/blah/internal/graphics.h b/private/blah/internal/graphics.h deleted file mode 100644 index 75649a1..0000000 --- a/private/blah/internal/graphics.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once -#include - -namespace Blah -{ - namespace Internal - { - class GraphicsDevice; - - // graphics device metadata used to instantiate and destroy - // devices of specific apis - struct GraphicsDeviceInfo - { - GfxAPI api; - bool (*supported)(); - GraphicsDevice* (*create)(); - void (*destroy)(GraphicsDevice*); - }; - - // graphics implementations - extern GraphicsDeviceInfo OpenGL_DeviceInfo; - - // graphics device - // each graphics implementation needs to implement this - // ex. one for opengl, one for vulkan, etc - class GraphicsDevice - { - public: - bool valid = false; - GraphicsInfo info; - - virtual ~GraphicsDevice() = default; - virtual void startup() = 0; - virtual void update() = 0; - virtual void shutdown() = 0; - virtual void before_render() = 0; - virtual void after_render() = 0; - - virtual TextureRef create_texture(int width, int height, TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y, TextureFormat format) = 0; - virtual FrameBufferRef create_framebuffer(int width, int height, const TextureFormat* attachments, int attachmentCount) = 0; - virtual ShaderRef create_shader(const ShaderData* data) = 0; - virtual MeshRef create_mesh() = 0; - virtual void render(RenderCall* call) = 0; - virtual void clear(const FrameBufferRef& target, uint32_t rgba) = 0; - }; - - namespace Graphics - { - // Picks a graphics API based on the available APIs - GfxAPI pick_api(); - - // Initializes the Graphics with the given API - bool init(GfxAPI api); - - // Is called internally by the Application every update - void frame(); - - // Is called internally by the Application before every render - void before_render(); - - // Is called internally by the Application after every render - void after_render(); - - // Called when the Application is shutting down - void shutdown(); - } - } -} \ No newline at end of file diff --git a/private/blah/internal/graphics_backend.h b/private/blah/internal/graphics_backend.h new file mode 100644 index 0000000..0f43c31 --- /dev/null +++ b/private/blah/internal/graphics_backend.h @@ -0,0 +1,24 @@ +#pragma once +#include + +namespace Blah +{ + namespace GraphicsBackend + { + bool init(); + void shutdown(); + + const GraphicsInfo* info(); + GraphicsRenderer renderer(); + void frame(); + void before_render(); + void after_render(); + void render(RenderCall* call); + void clear(const FrameBufferRef& target, uint32_t rgba); + + TextureRef create_texture(int width, int height, TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y, TextureFormat format); + FrameBufferRef create_framebuffer(int width, int height, const TextureFormat* attachments, int attachmentCount); + ShaderRef create_shader(const ShaderData* data); + MeshRef create_mesh(); + } +} \ No newline at end of file diff --git a/private/blah/internal/graphics_backend_gl.cpp b/private/blah/internal/graphics_backend_gl.cpp new file mode 100644 index 0000000..2c17213 --- /dev/null +++ b/private/blah/internal/graphics_backend_gl.cpp @@ -0,0 +1,1495 @@ +#ifdef BLAH_USE_OPENGL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#define APIENTRY +#endif + +// OpenGL Value Types +typedef ptrdiff_t GLintptr; +typedef ptrdiff_t GLsizeiptr; +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef signed char GLbyte; /* 1-byte signed */ +typedef short GLshort; /* 2-byte signed */ +typedef int GLint; /* 4-byte signed */ +typedef unsigned char GLubyte; /* 1-byte unsigned */ +typedef unsigned short GLushort; /* 2-byte unsigned */ +typedef unsigned int GLuint; /* 4-byte unsigned */ +typedef int GLsizei; /* 4-byte signed */ +typedef float GLfloat; /* single precision float */ +typedef float GLclampf; /* single precision float in [0,1] */ +typedef double GLdouble; /* double precision float */ +typedef double GLclampd; /* double precision float in [0,1] */ +typedef char GLchar; + +// OpenGL Constants +#define GL_DONT_CARE 0x1100 +#define GL_ZERO 0x0000 +#define GL_ONE 0x0001 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_HALF_FLOAT 0x140B +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_5_5_5_1_REV 0x8366 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_COLOR_BUFFER_BIT 0x4000 +#define GL_DEPTH_BUFFER_BIT 0x0100 +#define GL_STENCIL_BUFFER_BIT 0x0400 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_DEPTH_TEST 0x0B71 +#define GL_STENCIL_TEST 0x0B90 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_CULL_FACE 0x0B44 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_BLEND 0x0BE2 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_SRC1_ALPHA 0x8589 +#define GL_SRC1_COLOR 0x88F9 +#define GL_ONE_MINUS_SRC1_COLOR 0x88FA +#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_INVERT 0x150A +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_RED 0x1903 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_RGB8 0x8051 +#define GL_RGBA8 0x8058 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGBA16 0x805B +#define GL_BGRA 0x80E1 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_RG 0x8227 +#define GL_RG8 0x822B +#define GL_RG16 0x822C +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_RGBA32F 0x8814 +#define GL_RGBA16F 0x881A +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_TEXTURE0 0x84C0 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_RENDERBUFFER 0x8D41 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_SAMPLES_PASSED 0x8914 +#define GL_MULTISAMPLE 0x809D +#define GL_MAX_SAMPLES 0x8D57 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_SAMPLER_2D 0x8B5E +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT4 0x8B5C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_DEBUG_SOURCE_API 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION 0x824A +#define GL_DEBUG_SOURCE_OTHER 0x824B +#define GL_DEBUG_TYPE_ERROR 0x824C +#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 +#define GL_DEBUG_TYPE_POP_GROUP 0x826A +#define GL_DEBUG_TYPE_MARKER 0x8268 +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E +#define GL_DEBUG_TYPE_PORTABILITY 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#define GL_DEBUG_TYPE_OTHER 0x8251 +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#define GL_DEBUG_SEVERITY_LOW 0x9148 +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#define GL_DEBUG_OUTPUT 0x92E0 +#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 + +// OpenGL Functions +#define GL_FUNCTIONS \ + GL_FUNC(DebugMessageCallback, void, DEBUGPROC callback, const void* userParam) \ + GL_FUNC(GetString, const GLubyte*, GLenum name) \ + GL_FUNC(Flush, void, void) \ + GL_FUNC(Enable, void, GLenum mode) \ + GL_FUNC(Disable, void, GLenum mode) \ + GL_FUNC(Clear, void, GLenum mask) \ + GL_FUNC(ClearColor, void, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) \ + GL_FUNC(ClearDepth, void, GLdouble depth) \ + GL_FUNC(ClearStencil, void, GLint stencil) \ + GL_FUNC(DepthMask, void, GLboolean enabled) \ + GL_FUNC(DepthFunc, void, GLenum func) \ + GL_FUNC(Viewport, void, GLint x, GLint y, GLint width, GLint height) \ + GL_FUNC(Scissor, void, GLint x, GLint y, GLint width, GLint height) \ + GL_FUNC(CullFace, void, GLenum mode) \ + GL_FUNC(BlendEquation, void, GLenum eq) \ + GL_FUNC(BlendEquationSeparate, void, GLenum modeRGB, GLenum modeAlpha) \ + GL_FUNC(BlendFunc, void, GLenum sfactor, GLenum dfactor) \ + GL_FUNC(BlendFuncSeparate, void, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) \ + GL_FUNC(BlendColor, void, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) \ + GL_FUNC(ColorMask, void, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) \ + GL_FUNC(GetIntegerv, void, GLenum name, GLint* data) \ + GL_FUNC(GenTextures, void, GLint n, void* textures) \ + GL_FUNC(GenRenderbuffers, void, GLint n, void* textures) \ + GL_FUNC(GenFramebuffers, void, GLint n, void* textures) \ + GL_FUNC(ActiveTexture, void, GLuint id) \ + GL_FUNC(BindTexture, void, GLenum target, GLuint id) \ + GL_FUNC(BindRenderbuffer, void, GLenum target, GLuint id) \ + GL_FUNC(BindFramebuffer, void, GLenum target, GLuint id) \ + GL_FUNC(TexImage2D, void, GLenum target, GLint level, GLenum internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, void* data) \ + GL_FUNC(FramebufferRenderbuffer, void, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) \ + GL_FUNC(FramebufferTexture2D, void, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) \ + GL_FUNC(TexParameteri, void, GLenum target, GLenum name, GLint param) \ + GL_FUNC(RenderbufferStorage, void, GLenum target, GLenum internalformat, GLint width, GLint height) \ + GL_FUNC(GetTexImage, void, GLenum target, GLint level, GLenum format, GLenum type, void* data) \ + GL_FUNC(DrawElements, void, GLenum mode, GLint count, GLenum type, void* indices) \ + GL_FUNC(DrawElementsInstanced, void, GLenum mode, GLint count, GLenum type, void* indices, GLint amount) \ + GL_FUNC(DeleteTextures, void, GLint n, GLuint* textures) \ + GL_FUNC(DeleteRenderbuffers, void, GLint n, GLuint* renderbuffers) \ + GL_FUNC(DeleteFramebuffers, void, GLint n, GLuint* textures) \ + GL_FUNC(GenVertexArrays, void, GLint n, GLuint* arrays) \ + GL_FUNC(BindVertexArray, void, GLuint id) \ + GL_FUNC(GenBuffers, void, GLint n, GLuint* arrays) \ + GL_FUNC(BindBuffer, void, GLenum target, GLuint buffer) \ + GL_FUNC(BufferData, void, GLenum target, GLsizeiptr size, const void* data, GLenum usage) \ + GL_FUNC(BufferSubData, void, GLenum target, GLintptr offset, GLsizeiptr size, const void* data) \ + GL_FUNC(DeleteBuffers, void, GLint n, GLuint* buffers) \ + GL_FUNC(DeleteVertexArrays, void, GLint n, GLuint* arrays) \ + GL_FUNC(EnableVertexAttribArray, void, GLuint location) \ + GL_FUNC(DisableVertexAttribArray, void, GLuint location) \ + GL_FUNC(VertexAttribPointer, void, GLuint index, GLint size, GLenum type, GLboolean normalized, GLint stride, const void* pointer) \ + GL_FUNC(VertexAttribDivisor, void, GLuint index, GLuint divisor) \ + GL_FUNC(CreateShader, GLuint, GLenum type) \ + GL_FUNC(AttachShader, void, GLuint program, GLuint shader) \ + GL_FUNC(DetachShader, void, GLuint program, GLuint shader) \ + GL_FUNC(DeleteShader, void, GLuint shader) \ + GL_FUNC(ShaderSource, void, GLuint shader, GLsizei count, const GLchar** string, const GLint* length) \ + GL_FUNC(CompileShader, void, GLuint shader) \ + GL_FUNC(GetShaderiv, void, GLuint shader, GLenum pname, GLint* result) \ + GL_FUNC(GetShaderInfoLog, void, GLuint shader, GLint maxLength, GLsizei* length, GLchar* infoLog) \ + GL_FUNC(CreateProgram, GLuint, ) \ + GL_FUNC(DeleteProgram, void, GLuint program) \ + GL_FUNC(LinkProgram, void, GLuint program) \ + GL_FUNC(GetProgramiv, void, GLuint program, GLenum pname, GLint* result) \ + GL_FUNC(GetProgramInfoLog, void, GLuint program, GLint maxLength, GLsizei* length, GLchar* infoLog) \ + GL_FUNC(GetActiveUniform, void, GLuint program, GLuint index, GLint bufSize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) \ + GL_FUNC(GetActiveAttrib, void, GLuint program, GLuint index, GLint bufSize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) \ + GL_FUNC(UseProgram, void, GLuint program) \ + GL_FUNC(GetUniformLocation, GLint, GLuint program, const GLchar* name) \ + GL_FUNC(GetAttribLocation, GLint, GLuint program, const GLchar* name) \ + GL_FUNC(Uniform1f, void, GLint location, GLfloat v0) \ + GL_FUNC(Uniform2f, void, GLint location, GLfloat v0, GLfloat v1) \ + GL_FUNC(Uniform3f, void, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) \ + GL_FUNC(Uniform4f, void, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) \ + GL_FUNC(Uniform1fv, void, GLint location, GLint count, const GLfloat* value) \ + GL_FUNC(Uniform2fv, void, GLint location, GLint count, const GLfloat* value) \ + GL_FUNC(Uniform3fv, void, GLint location, GLint count, const GLfloat* value) \ + GL_FUNC(Uniform4fv, void, GLint location, GLint count, const GLfloat* value) \ + GL_FUNC(Uniform1i, void, GLint location, GLint v0) \ + GL_FUNC(Uniform2i, void, GLint location, GLint v0, GLint v1) \ + GL_FUNC(Uniform3i, void, GLint location, GLint v0, GLint v1, GLint v2) \ + GL_FUNC(Uniform4i, void, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) \ + GL_FUNC(Uniform1iv, void, GLint location, GLint count, const GLint* value) \ + GL_FUNC(Uniform2iv, void, GLint location, GLint count, const GLint* value) \ + GL_FUNC(Uniform3iv, void, GLint location, GLint count, const GLint* value) \ + GL_FUNC(Uniform4iv, void, GLint location, GLint count, const GLint* value) \ + GL_FUNC(Uniform1ui, void, GLint location, GLuint v0) \ + GL_FUNC(Uniform2ui, void, GLint location, GLuint v0, GLuint v1) \ + GL_FUNC(Uniform3ui, void, GLint location, GLuint v0, GLuint v1, GLuint v2) \ + GL_FUNC(Uniform4ui, void, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) \ + GL_FUNC(Uniform1uiv, void, GLint location, GLint count, const GLint* value) \ + GL_FUNC(Uniform2uiv, void, GLint location, GLint count, const GLint* value) \ + GL_FUNC(Uniform3uiv, void, GLint location, GLint count, const GLint* value) \ + GL_FUNC(Uniform4uiv, void, GLint location, GLint count, const GLint* value) \ + GL_FUNC(UniformMatrix2fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ + GL_FUNC(UniformMatrix3fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ + GL_FUNC(UniformMatrix4fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ + GL_FUNC(UniformMatrix2x3fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ + GL_FUNC(UniformMatrix3x2fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ + GL_FUNC(UniformMatrix2x4fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ + GL_FUNC(UniformMatrix4x2fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ + GL_FUNC(UniformMatrix3x4fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ + GL_FUNC(UniformMatrix4x3fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ + GL_FUNC(PixelStorei, void, GLenum pname, GLint param) + +// Debug Function Delegate +typedef void (APIENTRY* DEBUGPROC)(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam); + +namespace Blah +{ + // GL function pointers + struct GL + { + #define GL_FUNC(name, ret, ...) typedef ret (*name ## Func) (__VA_ARGS__); name ## Func name; + GL_FUNCTIONS + #undef GL_FUNC + }; + + // static state + GL gl; + void* gl_context; + int gl_max_color_attachments; + int gl_max_element_indices; + int gl_max_element_vertices; + int gl_max_renderbuffer_size; + int gl_max_samples; + int gl_max_texture_image_units; + int gl_max_texture_size; + GraphicsInfo gl_info; + + // debug callback + void APIENTRY gl_message_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) + { + // these are basically never useful + if (severity == GL_DEBUG_SEVERITY_NOTIFICATION && + type == GL_DEBUG_TYPE_OTHER) + return; + + const char* typeName = ""; + const char* severityName = ""; + + switch (type) + { + case GL_DEBUG_TYPE_ERROR: typeName = "ERROR"; break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: typeName = "DEPRECATED BEHAVIOR"; break; + case GL_DEBUG_TYPE_MARKER: typeName = "MARKER"; break; + case GL_DEBUG_TYPE_OTHER: typeName = "OTHER"; break; + case GL_DEBUG_TYPE_PERFORMANCE: typeName = "PEROFRMANCE"; break; + case GL_DEBUG_TYPE_POP_GROUP: typeName = "POP GROUP"; break; + case GL_DEBUG_TYPE_PORTABILITY: typeName = "PORTABILITY"; break; + case GL_DEBUG_TYPE_PUSH_GROUP: typeName = "PUSH GROUP"; break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: typeName = "UNDEFINED BEHAVIOR"; break; + } + + switch (severity) + { + case GL_DEBUG_SEVERITY_HIGH: severityName = "HIGH"; break; + case GL_DEBUG_SEVERITY_MEDIUM: severityName = "MEDIUM"; break; + case GL_DEBUG_SEVERITY_LOW: severityName = "LOW"; break; + case GL_DEBUG_SEVERITY_NOTIFICATION: severityName = "NOTIFICATION"; break; + } + + if (type == GL_DEBUG_TYPE_ERROR) + Log::error("GL (%s:%s) %s", typeName, severityName, message); + else if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) + Log::warn("GL (%s:%s) %s", typeName, severityName, message); + else + Log::print("GL (%s) %s", typeName, message); + } + + // assign attributes + GLuint gl_mesh_assign_attributes(GLuint buffer, GLenum buffer_type, const VertexAttribute* vertex_attributes, int vertex_attribute_count, int stride, GLint divisor) + { + // bind + gl.BindBuffer(buffer_type, buffer); + + // TODO: disable existing enabled attributes .. + // ... + // ... + + // enable attributes + size_t ptr = 0; + for (int n = 0; n < vertex_attribute_count; n++) + { + const VertexAttribute* attrib = (vertex_attributes + n); + + for (int i = 0, loc = 0; i < (int)attrib->components; i += 4, loc++) + { + int components = attrib->components - i; + if (components > 4) + components = 4; + + GLenum type = GL_UNSIGNED_BYTE; + size_t component_size = 0; + if (attrib->type == VertexAttributeType::Byte) + { + type = GL_UNSIGNED_BYTE; + component_size = 1; + } + else if (attrib->type == VertexAttributeType::Short) + { + type = GL_SHORT; + component_size = 2; + } + else if (attrib->type == VertexAttributeType::Int) + { + type = GL_INT; + component_size = 4; + } + else if (attrib->type == VertexAttributeType::Float) + { + type = GL_FLOAT; + component_size = 4; + } + + uint32_t location = (uint32_t)(attrib->index + loc); + gl.EnableVertexAttribArray(location); + gl.VertexAttribPointer(location, components, type, attrib->normalized, stride, (void*)ptr); + gl.VertexAttribDivisor(location, divisor); + + ptr += components * component_size; + } + } + + return stride; + } + + // convert blend op enum + GLenum gl_get_blend_func(BlendOp operation) + { + switch (operation) + { + case BlendOp::Add: return GL_FUNC_ADD; + case BlendOp::Subtract: return GL_FUNC_SUBTRACT; + case BlendOp::ReverseSubtract: return GL_FUNC_REVERSE_SUBTRACT; + case BlendOp::Min: return GL_MIN; + case BlendOp::Max: return GL_MAX; + }; + return GL_FUNC_ADD; + } + + // convert blend factor enum + GLenum gl_get_blend_factor(BlendFactor factor) + { + switch (factor) + { + case BlendFactor::Zero: return GL_ZERO; + case BlendFactor::One: return GL_ONE; + case BlendFactor::SrcColor: return GL_SRC_COLOR; + case BlendFactor::OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR; + case BlendFactor::DstColor: return GL_DST_COLOR; + case BlendFactor::OneMinusDstColor: return GL_ONE_MINUS_DST_COLOR; + case BlendFactor::SrcAlpha: return GL_SRC_ALPHA; + case BlendFactor::OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA; + case BlendFactor::DstAlpha: return GL_DST_ALPHA; + case BlendFactor::OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA; + case BlendFactor::ConstantColor: return GL_CONSTANT_COLOR; + case BlendFactor::OneMinusConstantColor: return GL_ONE_MINUS_CONSTANT_COLOR; + case BlendFactor::ConstantAlpha: return GL_CONSTANT_ALPHA; + case BlendFactor::OneMinusConstantAlpha: return GL_ONE_MINUS_CONSTANT_ALPHA; + case BlendFactor::SrcAlphaSaturate: return GL_SRC_ALPHA_SATURATE; + case BlendFactor::Src1Color: return GL_SRC1_COLOR; + case BlendFactor::OneMinusSrc1Color: return GL_ONE_MINUS_SRC1_COLOR; + case BlendFactor::Src1Alpha: return GL_SRC1_ALPHA; + case BlendFactor::OneMinusSrc1Alpha: return GL_ONE_MINUS_SRC1_ALPHA; + }; + + return GL_ZERO; + } + + class OpenGL_Texture : public Texture + { + private: + GLuint m_id; + int m_width; + int m_height; + TextureWrap m_wrap_x; + TextureWrap m_wrap_y; + TextureFilter m_filter; + TextureFormat m_format; + GLenum m_gl_internal_format; + GLenum m_gl_format; + GLenum m_gl_type; + + public: + bool framebuffer_parent; + + OpenGL_Texture(int width, int height, TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y, TextureFormat format) + { + m_id = 0; + m_width = width; + m_height = height; + m_wrap_x = wrap_x; + m_wrap_y = wrap_y; + m_filter = filter; + m_format = format; + framebuffer_parent = false; + m_gl_internal_format = GL_RED; + m_gl_format = GL_RED; + m_gl_type = GL_UNSIGNED_BYTE; + + if (width > gl_max_texture_size || height > gl_max_texture_size) + { + Log::error("Exceeded Max Texture Size of %i", gl_max_texture_size); + return; + } + + if (format == TextureFormat::R) + { + m_gl_internal_format = GL_RED; + m_gl_format = GL_RED; + m_gl_type = GL_UNSIGNED_BYTE; + } + else if (format == TextureFormat::RG) + { + m_gl_internal_format = GL_RG; + m_gl_format = GL_RG; + m_gl_type = GL_UNSIGNED_BYTE; + } + else if (format == TextureFormat::RGB) + { + m_gl_internal_format = GL_RGB; + m_gl_format = GL_RGB; + m_gl_type = GL_UNSIGNED_BYTE; + } + else if (format == TextureFormat::RGBA) + { + m_gl_internal_format = GL_RGBA; + m_gl_format = GL_RGBA; + m_gl_type = GL_UNSIGNED_BYTE; + } + else if (format == TextureFormat::DepthStencil) + { + m_gl_internal_format = GL_DEPTH24_STENCIL8; + m_gl_format = GL_DEPTH_STENCIL; + m_gl_type = GL_UNSIGNED_INT_24_8; + } + else + { + Log::error("Invalid Texture Format %i", format); + return; + } + + gl.GenTextures(1, &m_id); + gl.ActiveTexture(GL_TEXTURE0); + gl.BindTexture(GL_TEXTURE_2D, m_id); + + gl.TexImage2D(GL_TEXTURE_2D, 0, m_gl_internal_format, width, height, 0, m_gl_format, m_gl_type, nullptr); + gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (m_filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); + gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (m_filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); + gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (m_wrap_x == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); + gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (m_wrap_y == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); + } + + ~OpenGL_Texture() + { + if (m_id > 0) + gl.DeleteTextures(1, &m_id); + } + + GLuint gl_id() const + { + return m_id; + } + + virtual int width() const override + { + return m_width; + } + + virtual int height() const override + { + return m_height; + } + + virtual TextureFormat format() const override + { + return m_format; + } + + virtual void set_filter(TextureFilter filter) override + { + m_filter = filter; + + gl.BindTexture(GL_TEXTURE_2D, m_id); + gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); + gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); + } + + virtual TextureFilter get_filter() const override + { + return m_filter; + } + + virtual void set_wrap(TextureWrap x, TextureWrap y) override + { + m_wrap_x = x; + m_wrap_y = y; + + gl.BindTexture(GL_TEXTURE_2D, m_id); + gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (x == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); + gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (y == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); + } + + virtual TextureWrap get_wrap_x() const override + { + return m_wrap_x; + } + + virtual TextureWrap get_wrap_y() const override + { + return m_wrap_y; + } + + virtual void set_data(unsigned char* data) override + { + gl.ActiveTexture(GL_TEXTURE0); + gl.BindTexture(GL_TEXTURE_2D, m_id); + gl.TexImage2D(GL_TEXTURE_2D, 0, m_gl_internal_format, m_width, m_height, 0, m_gl_format, m_gl_type, data); + } + + virtual void get_data(unsigned char* data) override + { + gl.ActiveTexture(GL_TEXTURE0); + gl.BindTexture(GL_TEXTURE_2D, m_id); + gl.GetTexImage(GL_TEXTURE_2D, 0, m_gl_internal_format, m_gl_type, data); + } + + virtual bool is_framebuffer() const override + { + return framebuffer_parent; + } + + }; + + class OpenGL_FrameBuffer : public FrameBuffer + { + private: + GLuint m_id; + int m_width; + int m_height; + StackVector m_attachments; + + public: + + OpenGL_FrameBuffer(int width, int height, const TextureFormat* attachments, int attachmentCount) + { + gl.GenFramebuffers(1, &m_id); + m_width = width; + m_height = height; + + gl.BindFramebuffer(GL_FRAMEBUFFER, m_id); + + for (int i = 0; i < attachmentCount; i++) + { + auto tex = Graphics::create_texture(width, height, attachments[i]); + auto gltex = ((OpenGL_Texture*)tex.get()); + + gltex->framebuffer_parent = true; + m_attachments.push_back(tex); + + if (attachments[i] != TextureFormat::DepthStencil) + { + gl.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, gltex->gl_id(), 0); + } + else + { + gl.FramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, gltex->gl_id(), 0); + } + } + } + + ~OpenGL_FrameBuffer() + { + if (m_id > 0) + { + gl.DeleteFramebuffers(1, &m_id); + m_id = 0; + } + } + + GLuint gl_id() const + { + return m_id; + } + + virtual Attachments& attachments() override + { + return m_attachments; + } + + virtual const Attachments& attachments() const override + { + return m_attachments; + } + + virtual TextureRef& attachment(int index) override + { + return m_attachments[index]; + } + + virtual const TextureRef& attachment(int index) const override + { + return m_attachments[index]; + } + + virtual int width() const override + { + return m_width; + } + + virtual int height() const override + { + return m_height; + } + }; + + class OpenGL_Shader : public Shader + { + private: + GLuint m_id; + Attributes m_attributes; + Uniforms m_uniforms; + + public: + GLint uniforms_loc[BLAH_UNIFORMS] = { 0 }; + + OpenGL_Shader(const ShaderData* data) + { + m_id = 0; + + // vertex shader + if (data->vertex == nullptr) + { + Log::error("Vertex Shader is required"); + return; + } + + if (data->fragment == nullptr) + { + Log::error("Fragment Shader is required"); + return; + } + + GLchar log[1024]; + GLsizei log_length = 0; + + GLuint vertex_shader = gl.CreateShader(GL_VERTEX_SHADER); + { + const GLchar* source = (const GLchar*)data->vertex; + gl.ShaderSource(vertex_shader, 1, &source, nullptr); + gl.CompileShader(vertex_shader); + gl.GetShaderInfoLog(vertex_shader, 1024, &log_length, log); + + if (log_length > 0) + { + gl.DeleteShader(vertex_shader); + Log::error(log); + return; + } + } + + GLuint fragment_shader = gl.CreateShader(GL_FRAGMENT_SHADER); + { + const GLchar* source = (const GLchar*)data->fragment; + gl.ShaderSource(fragment_shader, 1, &source, nullptr); + gl.CompileShader(fragment_shader); + gl.GetShaderInfoLog(fragment_shader, 1024, &log_length, log); + + if (log_length > 0) + { + gl.DeleteShader(fragment_shader); + Log::error(log); + return; + } + } + + GLuint id = gl.CreateProgram(); + gl.AttachShader(id, vertex_shader); + gl.AttachShader(id, fragment_shader); + gl.LinkProgram(id); + gl.GetProgramInfoLog(id, 1024, &log_length, log); + + if (log_length > 0) + { + gl.DetachShader(id, vertex_shader); + gl.DetachShader(id, fragment_shader); + gl.DeleteShader(vertex_shader); + gl.DeleteShader(fragment_shader); + + Log::error(log); + return; + } + + // ready to go + m_id = id; + + // get attributes + { + GLint active_attributes = 0; + gl.GetProgramiv(id, GL_ACTIVE_ATTRIBUTES, &active_attributes); + if (active_attributes > BLAH_ATTRIBUTES) + { + Log::warn("Exceeding maximum shader attributes (%i / %i)", active_attributes, BLAH_ATTRIBUTES); + active_attributes = BLAH_ATTRIBUTES; + } + + for (int i = 0; i < active_attributes; i++) + { + GLsizei length; + GLsizei size; + GLenum type; + GLchar name[BLAH_ATTRIBUTE_NAME]; + + gl.GetActiveAttrib(id, i, BLAH_ATTRIBUTE_NAME - 1, &length, &size, &type, name); + name[length] = '\0'; + + ShaderAttribute attr; + attr.name = name; + attr.semantic_name = ""; + attr.semantic_location = 0; + m_attributes.push_back(attr); + } + } + + // get uniforms + { + GLint active_uniforms = 0; + gl.GetProgramiv(id, GL_ACTIVE_UNIFORMS, &active_uniforms); + if (active_uniforms > BLAH_UNIFORMS) + { + Log::warn("Exceeding maximum shader uniforms (%i / %i)", active_uniforms, BLAH_ATTRIBUTES); + active_uniforms = BLAH_UNIFORMS; + } + + for (int i = 0; i < active_uniforms; i++) + { + GLsizei length; + GLsizei size; + GLenum type; + GLchar name[BLAH_UNIFORM_NAME]; + + gl.GetActiveUniform(id, i, BLAH_UNIFORM_NAME - 1, &length, &size, &type, name); + name[length] = '\0'; + + // array names end with "[0]", and we don't want that + for (int n = 0; n < BLAH_UNIFORM_NAME; n++) + if (name[n] == '[') + { + if (name[n + 1] == '0' && name[n + 2] == ']') + { + name[n] = '\0'; + break; + } + } + + ShaderUniform uniform; + uniform.name = name; + uniform.type = UniformType::None; + uniform.array_length = size; + uniforms_loc[i] = gl.GetUniformLocation(id, name); + + if (type == GL_FLOAT) + uniform.type = UniformType::Float; + else if (type == GL_FLOAT_VEC2) + uniform.type = UniformType::Float2; + else if (type == GL_FLOAT_VEC3) + uniform.type = UniformType::Float3; + else if (type == GL_FLOAT_VEC4) + uniform.type = UniformType::Float4; + else if (type == GL_FLOAT_MAT3x2) + uniform.type = UniformType::Mat3x2; + else if (type == GL_FLOAT_MAT4) + uniform.type = UniformType::Mat4x4; + else if (type == GL_SAMPLER_2D) + uniform.type = UniformType::Texture; + else + { + Log::error("Unsupported Uniform Type. Must be either FLOAT, MAT3x2, MAT4, or SAMPLER_2D"); + break; + } + + m_uniforms.push_back(uniform); + } + } + } + + ~OpenGL_Shader() + { + if (m_id > 0) + gl.DeleteProgram(m_id); + m_id = 0; + } + + GLuint gl_id() const + { + return m_id; + } + + virtual Uniforms& uniforms() override + { + return m_uniforms; + } + + virtual const Uniforms& uniforms() const override + { + return m_uniforms; + } + + virtual Attributes& attributes() override + { + return m_attributes; + } + + virtual const Attributes& attributes() const override + { + return m_attributes; + } + }; + + class OpenGL_Mesh : public Mesh + { + private: + GLuint m_id; + GLuint m_index_buffer; + GLuint m_vertex_buffer; + GLuint m_instance_buffer; + int64_t m_index_count; + int64_t m_vertex_count; + int64_t m_instance_count; + uint16_t m_vertex_size; + uint16_t m_instance_size; + uint8_t m_vertex_attribs_enabled; + uint8_t m_instance_attribs_enabled; + GLuint m_vertex_attribs[BLAH_ATTRIBUTES]; + GLuint m_instance_attribs[BLAH_ATTRIBUTES]; + + public: + + OpenGL_Mesh() + { + m_id = 0; + m_index_buffer = 0; + m_vertex_buffer = 0; + m_instance_buffer = 0; + m_index_count = 0; + m_vertex_count = 0; + m_instance_count = 0; + m_vertex_size = 0; + m_instance_size = 0; + m_vertex_attribs_enabled = 0; + m_instance_attribs_enabled = 0; + m_vertex_attribs[0] = 0; + m_instance_attribs[0] = 0; + + gl.GenVertexArrays(1, &m_id); + } + + ~OpenGL_Mesh() + { + if (m_vertex_buffer != 0) + gl.DeleteBuffers(1, &m_vertex_buffer); + if (m_index_buffer != 0) + gl.DeleteBuffers(1, &m_index_buffer); + if (m_instance_buffer != 0) + gl.DeleteBuffers(1, &m_instance_buffer); + if (m_id != 0) + gl.DeleteVertexArrays(1, &m_id); + m_id = 0; + } + + GLuint gl_id() const + { + return m_id; + } + + virtual void vertex_format_internal(const VertexAttribute* attributes, int attribute_count, int stride = -1) override + { + gl.BindVertexArray(m_id); + { + if (m_vertex_buffer == 0) + gl.GenBuffers(1, &(m_vertex_buffer)); + + m_vertex_size = gl_mesh_assign_attributes(m_vertex_buffer, GL_ARRAY_BUFFER, attributes, attribute_count, stride, 0); + } + gl.BindVertexArray(0); + } + + virtual void instance_format_internal(const VertexAttribute* attributes, int attribute_count, int stride = -1) override + { + gl.BindVertexArray(m_id); + { + if (m_instance_buffer == 0) + gl.GenBuffers(1, &(m_instance_buffer)); + + m_instance_size = gl_mesh_assign_attributes(m_instance_buffer, GL_ARRAY_BUFFER, attributes, attribute_count, stride, 1); + } + gl.BindVertexArray(0); + } + + virtual void index_data(const void* indices, int64_t count) override + { + m_index_count = count; + + gl.BindVertexArray(m_id); + { + if (m_index_buffer == 0) + gl.GenBuffers(1, &(m_index_buffer)); + + gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer); + gl.BufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * count, indices, GL_DYNAMIC_DRAW); + } + gl.BindVertexArray(0); + } + + virtual void vertex_data(const void* vertices, int64_t count) override + { + if (m_vertex_buffer == 0 || m_vertex_size <= 0) + { + Log::error("You must assign a Vertex Format before setting Vertex Data"); + } + else + { + m_vertex_count = count; + + gl.BindVertexArray(m_id); + { + gl.BindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer); + gl.BufferData(GL_ARRAY_BUFFER, m_vertex_size * count, vertices, GL_DYNAMIC_DRAW); + } + gl.BindVertexArray(0); + } + } + + virtual void instance_data(const void* instances, int64_t count) override + { + if (m_instance_buffer == 0 || m_instance_size <= 0) + { + Log::error("You must assign an Instance Format before setting Instance Data"); + } + else + { + m_instance_count = count; + + gl.BindVertexArray(m_id); + { + gl.BindBuffer(GL_ARRAY_BUFFER, m_instance_buffer); + gl.BufferData(GL_ARRAY_BUFFER, m_instance_size * count, instances, GL_DYNAMIC_DRAW); + } + gl.BindVertexArray(0); + } + } + + virtual int64_t index_count() const override + { + return m_index_count; + } + + virtual int64_t vertex_count() const override + { + return m_vertex_count; + } + + virtual int64_t instance_count() const override + { + return m_instance_count; + } + }; + + bool GraphicsBackend::init() + { + // create gl context + gl_context = PlatformBackend::gl_context_create(); + if (gl_context == nullptr) + { + Log::error("Failed to create OpenGL Context"); + return false; + } + PlatformBackend::gl_context_make_current(gl_context); + + // bind opengl functions + #define GL_FUNC(name, ...) gl.name = (GL::name ## Func)(PlatformBackend::gl_get_func("gl" #name)); + GL_FUNCTIONS + #undef GL_FUNC + + // bind debug message callback + if (gl.DebugMessageCallback != nullptr) + { + gl.Enable(GL_DEBUG_OUTPUT); + gl.Enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + gl.DebugMessageCallback(gl_message_callback, nullptr); + } + + // get opengl info + gl.GetIntegerv(0x8CDF, &gl_max_color_attachments); + gl.GetIntegerv(0x80E9, &gl_max_element_indices); + gl.GetIntegerv(0x80E8, &gl_max_element_vertices); + gl.GetIntegerv(0x84E8, &gl_max_renderbuffer_size); + gl.GetIntegerv(0x8D57, &gl_max_samples); + gl.GetIntegerv(0x8872, &gl_max_texture_image_units); + gl.GetIntegerv(0x0D33, &gl_max_texture_size); + + // log + Log::print("OpenGL %s, %s", + gl.GetString(GL_VERSION), + gl.GetString(GL_RENDERER)); + + // don't include row padding + gl.PixelStorei(GL_PACK_ALIGNMENT, 1); + gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1); + + // assign info + gl_info.instancing = true; + gl_info.origin_bottom_left = true; + gl_info.max_texture_size = gl_max_texture_size; + + return true; + } + + GraphicsRenderer GraphicsBackend::renderer() + { + return GraphicsRenderer::OpenGL; + } + + void GraphicsBackend::shutdown() + { + PlatformBackend::gl_context_destroy(gl_context); + gl_context = nullptr; + } + + const GraphicsInfo* GraphicsBackend::info() + { + return &gl_info; + } + + void GraphicsBackend::frame() {} + void GraphicsBackend::before_render() {} + void GraphicsBackend::after_render() {} + + TextureRef GraphicsBackend::create_texture(int width, int height, TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y, TextureFormat format) + { + auto resource = new OpenGL_Texture(width, height, filter, wrap_x, wrap_y, format); + + if (resource->gl_id() <= 0) + { + delete resource; + return TextureRef(); + } + + return TextureRef(resource); + } + + FrameBufferRef GraphicsBackend::create_framebuffer(int width, int height, const TextureFormat* attachments, int attachmentCount) + { + auto resource = new OpenGL_FrameBuffer(width, height, attachments, attachmentCount); + + if (resource->gl_id() <= 0) + { + delete resource; + return FrameBufferRef(); + } + + return FrameBufferRef(resource); + } + + ShaderRef GraphicsBackend::create_shader(const ShaderData* data) + { + auto resource = new OpenGL_Shader(data); + + if (resource->gl_id() <= 0) + { + delete resource; + return ShaderRef(); + } + + return ShaderRef(resource); + } + + MeshRef GraphicsBackend::create_mesh() + { + auto resource = new OpenGL_Mesh(); + + if (resource->gl_id() <= 0) + { + delete resource; + return MeshRef(); + } + + return MeshRef(resource); + } + + void GraphicsBackend::render(RenderCall* call) + { + // Bind the Target + Point size; + if (!call->target) + { + gl.BindFramebuffer(GL_FRAMEBUFFER, 0); + size.x = App::draw_width(); + size.y = App::draw_height(); + } + else + { + auto framebuffer = (OpenGL_FrameBuffer*)call->target.get(); + gl.BindFramebuffer(GL_FRAMEBUFFER, framebuffer->gl_id()); + size.x = call->target->width(); + size.y = call->target->height(); + } + + auto shader_ref = call->material->shader(); + auto shader = (OpenGL_Shader*)shader_ref.get(); + auto mesh = (OpenGL_Mesh*)call->mesh.get(); + + // Use the Shader + // TODO: I don't love how material values are assigned or set here + { + gl.UseProgram(shader->gl_id()); + + // upload uniform values + int texture_slot = 0; + GLint texture_ids[64]; + + auto& uniforms = shader->uniforms(); + for (int i = 0; i < uniforms.size(); i++) + { + auto location = shader->uniforms_loc[i]; + auto& uniform = uniforms[i]; + + // Sampler 2D + if (uniform.type == UniformType::Texture) + { + for (int n = 0; n < uniform.array_length; n++) + { + auto tex = call->material->get_texture(i, n); + + gl.ActiveTexture(GL_TEXTURE0 + texture_slot); + + if (!tex) + { + gl.BindTexture(GL_TEXTURE_2D, 0); + } + else + { + gl.BindTexture(GL_TEXTURE_2D, ((OpenGL_Texture*)tex.get())->gl_id()); + } + + texture_ids[n] = texture_slot; + texture_slot++; + } + + gl.Uniform1iv(location, (GLint)uniform.array_length, &texture_ids[0]); + } + // Float + else if (uniform.type == UniformType::Float) + { + gl.Uniform1fv(location, (GLint)uniform.array_length, (const GLfloat*)call->material->get_value(i)); + } + // Float2 + else if (uniform.type == UniformType::Float2) + { + gl.Uniform2fv(location, (GLint)uniform.array_length, (const GLfloat*)call->material->get_value(i)); + } + // Float3 + else if (uniform.type == UniformType::Float3) + { + gl.Uniform3fv(location, (GLint)uniform.array_length, (const GLfloat*)call->material->get_value(i)); + } + // Float4 + else if (uniform.type == UniformType::Float4) + { + gl.Uniform4fv(location, (GLint)uniform.array_length, (const GLfloat*)call->material->get_value(i)); + } + // Matrix3x2 + else if (uniform.type == UniformType::Mat3x2) + { + gl.UniformMatrix3x2fv(location, (GLint)uniform.array_length, 0, (const GLfloat*)call->material->get_value(i)); + } + // Matrix4x4 + else if (uniform.type == UniformType::Mat4x4) + { + gl.UniformMatrix4fv(location, (GLint)uniform.array_length, 0, (const GLfloat*)call->material->get_value(i)); + } + } + } + + // Blend Mode + { + GLenum colorOp = gl_get_blend_func(call->blend.colorOp); + GLenum alphaOp = gl_get_blend_func(call->blend.alphaOp); + GLenum colorSrc = gl_get_blend_factor(call->blend.colorSrc); + GLenum colorDst = gl_get_blend_factor(call->blend.colorDst); + GLenum alphaSrc = gl_get_blend_factor(call->blend.alphaSrc); + GLenum alphaDst = gl_get_blend_factor(call->blend.alphaDst); + + gl.Enable(GL_BLEND); + gl.BlendEquationSeparate(colorOp, alphaOp); + gl.BlendFuncSeparate(colorSrc, colorDst, alphaSrc, alphaDst); + + gl.ColorMask( + ((int)call->blend.mask & (int)BlendMask::Red), + ((int)call->blend.mask & (int)BlendMask::Green), + ((int)call->blend.mask & (int)BlendMask::Blue), + ((int)call->blend.mask & (int)BlendMask::Alpha)); + + + unsigned char r = call->blend.rgba >> 24; + unsigned char g = call->blend.rgba >> 16; + unsigned char b = call->blend.rgba >> 8; + unsigned char a = call->blend.rgba; + + gl.BlendColor( + r / 255.0f, + g / 255.0f, + b / 255.0f, + a / 255.0f); + } + + // Depth Function + { + if (call->depth == Compare::None) + { + gl.Disable(GL_DEPTH_TEST); + } + else + { + gl.Enable(GL_DEPTH_TEST); + + switch (call->depth) + { + case Compare::None: break; + case Compare::Always: + gl.DepthFunc(GL_ALWAYS); + break; + case Compare::Equal: + gl.DepthFunc(GL_EQUAL); + break; + case Compare::Greater: + gl.DepthFunc(GL_GREATER); + break; + case Compare::GreatorOrEqual: + gl.DepthFunc(GL_GEQUAL); + break; + case Compare::Less: + gl.DepthFunc(GL_LESS); + break; + case Compare::LessOrEqual: + gl.DepthFunc(GL_LEQUAL); + break; + case Compare::Never: + gl.DepthFunc(GL_NEVER); + break; + case Compare::NotEqual: + gl.DepthFunc(GL_NOTEQUAL); + break; + } + } + } + + // Cull Mode + { + if (call->cull == Cull::None) + { + gl.Disable(GL_CULL_FACE); + } + else + { + gl.Enable(GL_CULL_FACE); + + if (call->cull == Cull::Back) + gl.CullFace(GL_BACK); + else if (call->cull == Cull::Front) + gl.CullFace(GL_FRONT); + else + gl.CullFace(GL_FRONT_AND_BACK); + } + } + + // Viewport + { + Rect viewport = call->viewport; + viewport.y = size.y - viewport.y - viewport.h; + + gl.Viewport((GLint)viewport.x, (GLint)viewport.y, (GLint)viewport.w, (GLint)viewport.h); + } + + // Scissor + { + if (!call->has_scissor) + { + gl.Disable(GL_SCISSOR_TEST); + } + else + { + Rect scissor = call->scissor; + scissor.y = size.y - scissor.y - scissor.h; + + if (scissor.w < 0) + scissor.w = 0; + if (scissor.h < 0) + scissor.h = 0; + + gl.Enable(GL_SCISSOR_TEST); + gl.Scissor((GLint)scissor.x, (GLint)scissor.y, (GLint)scissor.w, (GLint)scissor.h); + } + } + + // Draw the Mesh + { + gl.BindVertexArray(mesh->gl_id()); + + if (call->instance_count > 0) + { + gl.DrawElementsInstanced( + GL_TRIANGLES, + (GLint)(call->index_count), + GL_UNSIGNED_INT, + (void*)(sizeof(int) * call->index_start), + (GLint)call->instance_count); + } + else + { + gl.DrawElements( + GL_TRIANGLES, + (GLint)(call->index_count), + GL_UNSIGNED_INT, + (void*)(sizeof(int) * call->index_start)); + } + + gl.BindVertexArray(0); + } + } + + void GraphicsBackend::clear(const FrameBufferRef& target, uint32_t rgba) + { + if (!target) + { + gl.BindFramebuffer(GL_FRAMEBUFFER, 0); + } + else + { + auto framebuffer = (OpenGL_FrameBuffer*)target.get(); + if (framebuffer != nullptr) + gl.BindFramebuffer(GL_FRAMEBUFFER, framebuffer->gl_id()); + } + + unsigned char r = rgba >> 24; + unsigned char g = rgba >> 16; + unsigned char b = rgba >> 8; + unsigned char a = rgba; + + gl.Disable(GL_SCISSOR_TEST); + gl.ClearColor(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); + gl.Clear(GL_COLOR_BUFFER_BIT); + } +} + +#endif // BLAH_USE_OPENGL diff --git a/private/blah/internal/graphics_opengl.cpp b/private/blah/internal/graphics_opengl.cpp deleted file mode 100644 index add6273..0000000 --- a/private/blah/internal/graphics_opengl.cpp +++ /dev/null @@ -1,1569 +0,0 @@ -#include -#include - -#ifdef BLAH_USE_OPENGL - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#else -#define APIENTRY -#endif - -// OpenGL Value Types -typedef ptrdiff_t GLintptr; -typedef ptrdiff_t GLsizeiptr; -typedef unsigned int GLenum; -typedef unsigned char GLboolean; -typedef unsigned int GLbitfield; -typedef void GLvoid; -typedef signed char GLbyte; /* 1-byte signed */ -typedef short GLshort; /* 2-byte signed */ -typedef int GLint; /* 4-byte signed */ -typedef unsigned char GLubyte; /* 1-byte unsigned */ -typedef unsigned short GLushort; /* 2-byte unsigned */ -typedef unsigned int GLuint; /* 4-byte unsigned */ -typedef int GLsizei; /* 4-byte signed */ -typedef float GLfloat; /* single precision float */ -typedef float GLclampf; /* single precision float in [0,1] */ -typedef double GLdouble; /* double precision float */ -typedef double GLclampd; /* double precision float in [0,1] */ -typedef char GLchar; - -// OpenGL Constants -#define GL_DONT_CARE 0x1100 -#define GL_ZERO 0x0000 -#define GL_ONE 0x0001 -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_INT 0x1404 -#define GL_UNSIGNED_INT 0x1405 -#define GL_FLOAT 0x1406 -#define GL_HALF_FLOAT 0x140B -#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 -#define GL_UNSIGNED_SHORT_5_5_5_1_REV 0x8366 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 -#define GL_UNSIGNED_INT_24_8 0x84FA -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 -#define GL_EXTENSIONS 0x1F03 -#define GL_COLOR_BUFFER_BIT 0x4000 -#define GL_DEPTH_BUFFER_BIT 0x0100 -#define GL_STENCIL_BUFFER_BIT 0x0400 -#define GL_SCISSOR_TEST 0x0C11 -#define GL_DEPTH_TEST 0x0B71 -#define GL_STENCIL_TEST 0x0B90 -#define GL_LINE 0x1B01 -#define GL_FILL 0x1B02 -#define GL_CW 0x0900 -#define GL_CCW 0x0901 -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_FRONT_AND_BACK 0x0408 -#define GL_CULL_FACE 0x0B44 -#define GL_POLYGON_OFFSET_FILL 0x8037 -#define GL_TEXTURE_2D 0x0DE1 -#define GL_TEXTURE_3D 0x806F -#define GL_TEXTURE_CUBE_MAP 0x8513 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 -#define GL_BLEND 0x0BE2 -#define GL_SRC_COLOR 0x0300 -#define GL_ONE_MINUS_SRC_COLOR 0x0301 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 -#define GL_DST_ALPHA 0x0304 -#define GL_ONE_MINUS_DST_ALPHA 0x0305 -#define GL_DST_COLOR 0x0306 -#define GL_ONE_MINUS_DST_COLOR 0x0307 -#define GL_SRC_ALPHA_SATURATE 0x0308 -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 -#define GL_SRC1_ALPHA 0x8589 -#define GL_SRC1_COLOR 0x88F9 -#define GL_ONE_MINUS_SRC1_COLOR 0x88FA -#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB -#define GL_MIN 0x8007 -#define GL_MAX 0x8008 -#define GL_FUNC_ADD 0x8006 -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B -#define GL_NEVER 0x0200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 -#define GL_INVERT 0x150A -#define GL_KEEP 0x1E00 -#define GL_REPLACE 0x1E01 -#define GL_INCR 0x1E02 -#define GL_DECR 0x1E03 -#define GL_INCR_WRAP 0x8507 -#define GL_DECR_WRAP 0x8508 -#define GL_REPEAT 0x2901 -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_MIRRORED_REPEAT 0x8370 -#define GL_NEAREST 0x2600 -#define GL_LINEAR 0x2601 -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 -#define GL_COLOR_ATTACHMENT0 0x8CE0 -#define GL_DEPTH_ATTACHMENT 0x8D00 -#define GL_STENCIL_ATTACHMENT 0x8D20 -#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A -#define GL_RED 0x1903 -#define GL_RGB 0x1907 -#define GL_RGBA 0x1908 -#define GL_LUMINANCE 0x1909 -#define GL_RGB8 0x8051 -#define GL_RGBA8 0x8058 -#define GL_RGBA4 0x8056 -#define GL_RGB5_A1 0x8057 -#define GL_RGB10_A2_EXT 0x8059 -#define GL_RGBA16 0x805B -#define GL_BGRA 0x80E1 -#define GL_DEPTH_COMPONENT16 0x81A5 -#define GL_DEPTH_COMPONENT24 0x81A6 -#define GL_RG 0x8227 -#define GL_RG8 0x822B -#define GL_RG16 0x822C -#define GL_R16F 0x822D -#define GL_R32F 0x822E -#define GL_RG16F 0x822F -#define GL_RG32F 0x8230 -#define GL_RGBA32F 0x8814 -#define GL_RGBA16F 0x881A -#define GL_DEPTH24_STENCIL8 0x88F0 -#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 -#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 -#define GL_DEPTH_COMPONENT 0x1902 -#define GL_DEPTH_STENCIL 0x84F9 -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 -#define GL_TEXTURE_WRAP_R 0x8072 -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define GL_TEXTURE_BASE_LEVEL 0x813C -#define GL_TEXTURE_MAX_LEVEL 0x813D -#define GL_TEXTURE_LOD_BIAS 0x8501 -#define GL_PACK_ALIGNMENT 0x0D05 -#define GL_UNPACK_ALIGNMENT 0x0CF5 -#define GL_TEXTURE0 0x84C0 -#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 -#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_STREAM_DRAW 0x88E0 -#define GL_STATIC_DRAW 0x88E4 -#define GL_DYNAMIC_DRAW 0x88E8 -#define GL_MAX_VERTEX_ATTRIBS 0x8869 -#define GL_FRAMEBUFFER 0x8D40 -#define GL_READ_FRAMEBUFFER 0x8CA8 -#define GL_DRAW_FRAMEBUFFER 0x8CA9 -#define GL_RENDERBUFFER 0x8D41 -#define GL_MAX_DRAW_BUFFERS 0x8824 -#define GL_POINTS 0x0000 -#define GL_LINES 0x0001 -#define GL_LINE_STRIP 0x0003 -#define GL_TRIANGLES 0x0004 -#define GL_TRIANGLE_STRIP 0x0005 -#define GL_QUERY_RESULT 0x8866 -#define GL_QUERY_RESULT_AVAILABLE 0x8867 -#define GL_SAMPLES_PASSED 0x8914 -#define GL_MULTISAMPLE 0x809D -#define GL_MAX_SAMPLES 0x8D57 -#define GL_SAMPLE_MASK 0x8E51 -#define GL_FRAGMENT_SHADER 0x8B30 -#define GL_VERTEX_SHADER 0x8B31 -#define GL_ACTIVE_UNIFORMS 0x8B86 -#define GL_ACTIVE_ATTRIBUTES 0x8B89 -#define GL_FLOAT_VEC2 0x8B50 -#define GL_FLOAT_VEC3 0x8B51 -#define GL_FLOAT_VEC4 0x8B52 -#define GL_SAMPLER_2D 0x8B5E -#define GL_FLOAT_MAT3x2 0x8B67 -#define GL_FLOAT_MAT4 0x8B5C -#define GL_NUM_EXTENSIONS 0x821D -#define GL_DEBUG_SOURCE_API 0x8246 -#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 -#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 -#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 -#define GL_DEBUG_SOURCE_APPLICATION 0x824A -#define GL_DEBUG_SOURCE_OTHER 0x824B -#define GL_DEBUG_TYPE_ERROR 0x824C -#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 -#define GL_DEBUG_TYPE_POP_GROUP 0x826A -#define GL_DEBUG_TYPE_MARKER 0x8268 -#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D -#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E -#define GL_DEBUG_TYPE_PORTABILITY 0x824F -#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 -#define GL_DEBUG_TYPE_OTHER 0x8251 -#define GL_DEBUG_SEVERITY_HIGH 0x9146 -#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 -#define GL_DEBUG_SEVERITY_LOW 0x9148 -#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B -#define GL_DEBUG_OUTPUT 0x92E0 -#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 - -// OpenGL Functions -#define GL_FUNCTIONS \ - GL_FUNC(DebugMessageCallback, void, DEBUGPROC callback, const void* userParam) \ - GL_FUNC(GetString, const GLubyte*, GLenum name) \ - GL_FUNC(Flush, void, void) \ - GL_FUNC(Enable, void, GLenum mode) \ - GL_FUNC(Disable, void, GLenum mode) \ - GL_FUNC(Clear, void, GLenum mask) \ - GL_FUNC(ClearColor, void, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) \ - GL_FUNC(ClearDepth, void, GLdouble depth) \ - GL_FUNC(ClearStencil, void, GLint stencil) \ - GL_FUNC(DepthMask, void, GLboolean enabled) \ - GL_FUNC(DepthFunc, void, GLenum func) \ - GL_FUNC(Viewport, void, GLint x, GLint y, GLint width, GLint height) \ - GL_FUNC(Scissor, void, GLint x, GLint y, GLint width, GLint height) \ - GL_FUNC(CullFace, void, GLenum mode) \ - GL_FUNC(BlendEquation, void, GLenum eq) \ - GL_FUNC(BlendEquationSeparate, void, GLenum modeRGB, GLenum modeAlpha) \ - GL_FUNC(BlendFunc, void, GLenum sfactor, GLenum dfactor) \ - GL_FUNC(BlendFuncSeparate, void, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) \ - GL_FUNC(BlendColor, void, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) \ - GL_FUNC(ColorMask, void, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) \ - GL_FUNC(GetIntegerv, void, GLenum name, GLint* data) \ - GL_FUNC(GenTextures, void, GLint n, void* textures) \ - GL_FUNC(GenRenderbuffers, void, GLint n, void* textures) \ - GL_FUNC(GenFramebuffers, void, GLint n, void* textures) \ - GL_FUNC(ActiveTexture, void, GLuint id) \ - GL_FUNC(BindTexture, void, GLenum target, GLuint id) \ - GL_FUNC(BindRenderbuffer, void, GLenum target, GLuint id) \ - GL_FUNC(BindFramebuffer, void, GLenum target, GLuint id) \ - GL_FUNC(TexImage2D, void, GLenum target, GLint level, GLenum internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, void* data) \ - GL_FUNC(FramebufferRenderbuffer, void, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) \ - GL_FUNC(FramebufferTexture2D, void, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) \ - GL_FUNC(TexParameteri, void, GLenum target, GLenum name, GLint param) \ - GL_FUNC(RenderbufferStorage, void, GLenum target, GLenum internalformat, GLint width, GLint height) \ - GL_FUNC(GetTexImage, void, GLenum target, GLint level, GLenum format, GLenum type, void* data) \ - GL_FUNC(DrawElements, void, GLenum mode, GLint count, GLenum type, void* indices) \ - GL_FUNC(DrawElementsInstanced, void, GLenum mode, GLint count, GLenum type, void* indices, GLint amount) \ - GL_FUNC(DeleteTextures, void, GLint n, GLuint* textures) \ - GL_FUNC(DeleteRenderbuffers, void, GLint n, GLuint* renderbuffers) \ - GL_FUNC(DeleteFramebuffers, void, GLint n, GLuint* textures) \ - GL_FUNC(GenVertexArrays, void, GLint n, GLuint* arrays) \ - GL_FUNC(BindVertexArray, void, GLuint id) \ - GL_FUNC(GenBuffers, void, GLint n, GLuint* arrays) \ - GL_FUNC(BindBuffer, void, GLenum target, GLuint buffer) \ - GL_FUNC(BufferData, void, GLenum target, GLsizeiptr size, const void* data, GLenum usage) \ - GL_FUNC(BufferSubData, void, GLenum target, GLintptr offset, GLsizeiptr size, const void* data) \ - GL_FUNC(DeleteBuffers, void, GLint n, GLuint* buffers) \ - GL_FUNC(DeleteVertexArrays, void, GLint n, GLuint* arrays) \ - GL_FUNC(EnableVertexAttribArray, void, GLuint location) \ - GL_FUNC(DisableVertexAttribArray, void, GLuint location) \ - GL_FUNC(VertexAttribPointer, void, GLuint index, GLint size, GLenum type, GLboolean normalized, GLint stride, const void* pointer) \ - GL_FUNC(VertexAttribDivisor, void, GLuint index, GLuint divisor) \ - GL_FUNC(CreateShader, GLuint, GLenum type) \ - GL_FUNC(AttachShader, void, GLuint program, GLuint shader) \ - GL_FUNC(DetachShader, void, GLuint program, GLuint shader) \ - GL_FUNC(DeleteShader, void, GLuint shader) \ - GL_FUNC(ShaderSource, void, GLuint shader, GLsizei count, const GLchar** string, const GLint* length) \ - GL_FUNC(CompileShader, void, GLuint shader) \ - GL_FUNC(GetShaderiv, void, GLuint shader, GLenum pname, GLint* result) \ - GL_FUNC(GetShaderInfoLog, void, GLuint shader, GLint maxLength, GLsizei* length, GLchar* infoLog) \ - GL_FUNC(CreateProgram, GLuint, ) \ - GL_FUNC(DeleteProgram, void, GLuint program) \ - GL_FUNC(LinkProgram, void, GLuint program) \ - GL_FUNC(GetProgramiv, void, GLuint program, GLenum pname, GLint* result) \ - GL_FUNC(GetProgramInfoLog, void, GLuint program, GLint maxLength, GLsizei* length, GLchar* infoLog) \ - GL_FUNC(GetActiveUniform, void, GLuint program, GLuint index, GLint bufSize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) \ - GL_FUNC(GetActiveAttrib, void, GLuint program, GLuint index, GLint bufSize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) \ - GL_FUNC(UseProgram, void, GLuint program) \ - GL_FUNC(GetUniformLocation, GLint, GLuint program, const GLchar* name) \ - GL_FUNC(GetAttribLocation, GLint, GLuint program, const GLchar* name) \ - GL_FUNC(Uniform1f, void, GLint location, GLfloat v0) \ - GL_FUNC(Uniform2f, void, GLint location, GLfloat v0, GLfloat v1) \ - GL_FUNC(Uniform3f, void, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) \ - GL_FUNC(Uniform4f, void, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) \ - GL_FUNC(Uniform1fv, void, GLint location, GLint count, const GLfloat* value) \ - GL_FUNC(Uniform2fv, void, GLint location, GLint count, const GLfloat* value) \ - GL_FUNC(Uniform3fv, void, GLint location, GLint count, const GLfloat* value) \ - GL_FUNC(Uniform4fv, void, GLint location, GLint count, const GLfloat* value) \ - GL_FUNC(Uniform1i, void, GLint location, GLint v0) \ - GL_FUNC(Uniform2i, void, GLint location, GLint v0, GLint v1) \ - GL_FUNC(Uniform3i, void, GLint location, GLint v0, GLint v1, GLint v2) \ - GL_FUNC(Uniform4i, void, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) \ - GL_FUNC(Uniform1iv, void, GLint location, GLint count, const GLint* value) \ - GL_FUNC(Uniform2iv, void, GLint location, GLint count, const GLint* value) \ - GL_FUNC(Uniform3iv, void, GLint location, GLint count, const GLint* value) \ - GL_FUNC(Uniform4iv, void, GLint location, GLint count, const GLint* value) \ - GL_FUNC(Uniform1ui, void, GLint location, GLuint v0) \ - GL_FUNC(Uniform2ui, void, GLint location, GLuint v0, GLuint v1) \ - GL_FUNC(Uniform3ui, void, GLint location, GLuint v0, GLuint v1, GLuint v2) \ - GL_FUNC(Uniform4ui, void, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) \ - GL_FUNC(Uniform1uiv, void, GLint location, GLint count, const GLint* value) \ - GL_FUNC(Uniform2uiv, void, GLint location, GLint count, const GLint* value) \ - GL_FUNC(Uniform3uiv, void, GLint location, GLint count, const GLint* value) \ - GL_FUNC(Uniform4uiv, void, GLint location, GLint count, const GLint* value) \ - GL_FUNC(UniformMatrix2fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ - GL_FUNC(UniformMatrix3fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ - GL_FUNC(UniformMatrix4fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ - GL_FUNC(UniformMatrix2x3fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ - GL_FUNC(UniformMatrix3x2fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ - GL_FUNC(UniformMatrix2x4fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ - GL_FUNC(UniformMatrix4x2fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ - GL_FUNC(UniformMatrix3x4fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ - GL_FUNC(UniformMatrix4x3fv, void, GLint location, GLint count, GLboolean transpose, const GLfloat* value) \ - GL_FUNC(PixelStorei, void, GLenum pname, GLint param) - -// Debug Function Delegate -typedef void (APIENTRY* DEBUGPROC)(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam); - -namespace Blah -{ - namespace OpenGL - { - // GL function pointers - struct GL - { - #define GL_FUNC(name, ret, ...) typedef ret (*name ## Func) (__VA_ARGS__); name ## Func name; - GL_FUNCTIONS - #undef GL_FUNC - }; - - // static function pointers - // TODO: - // this should move into the Device, as on windows it's not guaranteed that these function - // pointers are the same between contexts. this doesn't matter right now since we only create - // a single context, but will potentially need to change. - // reference: https://wiki.libsdl.org/SDL_GL_GetProcAddress - GL gl; - - class Device : public Internal::GraphicsDevice - { - public: - void* context = nullptr; - - GLint max_color_attachments = 0; - GLint max_element_indices = 0; - GLint max_element_vertices = 0; - GLint max_renderbuffer_size = 0; - GLint max_samples = 0; - GLint max_texture_image_units = 0; - GLint max_texture_size = 0; - - inline virtual void startup() override; - inline virtual void shutdown() override; - inline virtual void update() override {} - inline virtual void before_render() override {} - inline virtual void after_render() override {} - - inline virtual TextureRef create_texture(int width, int height, TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y, TextureFormat format) override; - inline virtual FrameBufferRef create_framebuffer(int width, int height, const TextureFormat* attachments, int attachmentCount) override; - inline virtual ShaderRef create_shader(const ShaderData* data) override; - inline virtual MeshRef create_mesh() override; - inline virtual void render(RenderCall* call) override; - inline virtual void clear(const FrameBufferRef& target, uint32_t rgba) override; - }; - - // debug callback - void APIENTRY gl_message_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) - { - // these are basically never useful - if (severity == GL_DEBUG_SEVERITY_NOTIFICATION && - type == GL_DEBUG_TYPE_OTHER) - return; - - const char* typeName = ""; - const char* severityName = ""; - - switch (type) - { - case GL_DEBUG_TYPE_ERROR: typeName = "ERROR"; break; - case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: typeName = "DEPRECATED BEHAVIOR"; break; - case GL_DEBUG_TYPE_MARKER: typeName = "MARKER"; break; - case GL_DEBUG_TYPE_OTHER: typeName = "OTHER"; break; - case GL_DEBUG_TYPE_PERFORMANCE: typeName = "PEROFRMANCE"; break; - case GL_DEBUG_TYPE_POP_GROUP: typeName = "POP GROUP"; break; - case GL_DEBUG_TYPE_PORTABILITY: typeName = "PORTABILITY"; break; - case GL_DEBUG_TYPE_PUSH_GROUP: typeName = "PUSH GROUP"; break; - case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: typeName = "UNDEFINED BEHAVIOR"; break; - } - - switch (severity) - { - case GL_DEBUG_SEVERITY_HIGH: severityName = "HIGH"; break; - case GL_DEBUG_SEVERITY_MEDIUM: severityName = "MEDIUM"; break; - case GL_DEBUG_SEVERITY_LOW: severityName = "LOW"; break; - case GL_DEBUG_SEVERITY_NOTIFICATION: severityName = "NOTIFICATION"; break; - } - - if (type == GL_DEBUG_TYPE_ERROR) - Log::error("GL (%s:%s) %s", typeName, severityName, message); - else if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) - Log::warn("GL (%s:%s) %s", typeName, severityName, message); - else - Log::print("GL (%s) %s", typeName, message); - } - - // assign attributes - GLuint gl_mesh_assign_attributes(GLuint buffer, GLenum buffer_type, const VertexAttribute* vertex_attributes, int vertex_attribute_count, int stride, GLint divisor) - { - // bind - gl.BindBuffer(buffer_type, buffer); - - // TODO: disable existing enabled attributes .. - // ... - // ... - - // enable attributes - size_t ptr = 0; - for (int n = 0; n < vertex_attribute_count; n++) - { - const VertexAttribute* attrib = (vertex_attributes + n); - - for (int i = 0, loc = 0; i < (int)attrib->components; i += 4, loc++) - { - int components = attrib->components - i; - if (components > 4) - components = 4; - - GLenum type = GL_UNSIGNED_BYTE; - size_t component_size = 0; - if (attrib->type == VertexAttributeType::Byte) - { - type = GL_UNSIGNED_BYTE; - component_size = 1; - } - else if (attrib->type == VertexAttributeType::Short) - { - type = GL_SHORT; - component_size = 2; - } - else if (attrib->type == VertexAttributeType::Int) - { - type = GL_INT; - component_size = 4; - } - else if (attrib->type == VertexAttributeType::Float) - { - type = GL_FLOAT; - component_size = 4; - } - - uint32_t location = (uint32_t)(attrib->index + loc); - gl.EnableVertexAttribArray(location); - gl.VertexAttribPointer(location, components, type, attrib->normalized, stride, (void*)ptr); - gl.VertexAttribDivisor(location, divisor); - - ptr += components * component_size; - } - } - - return stride; - } - - // convert blend op enum - GLenum gl_get_blend_func(BlendOp operation) - { - switch (operation) - { - case BlendOp::Add: return GL_FUNC_ADD; - case BlendOp::Subtract: return GL_FUNC_SUBTRACT; - case BlendOp::ReverseSubtract: return GL_FUNC_REVERSE_SUBTRACT; - case BlendOp::Min: return GL_MIN; - case BlendOp::Max: return GL_MAX; - }; - return GL_FUNC_ADD; - } - - // convert blend factor enum - GLenum gl_get_blend_factor(BlendFactor factor) - { - switch (factor) - { - case BlendFactor::Zero: return GL_ZERO; - case BlendFactor::One: return GL_ONE; - case BlendFactor::SrcColor: return GL_SRC_COLOR; - case BlendFactor::OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR; - case BlendFactor::DstColor: return GL_DST_COLOR; - case BlendFactor::OneMinusDstColor: return GL_ONE_MINUS_DST_COLOR; - case BlendFactor::SrcAlpha: return GL_SRC_ALPHA; - case BlendFactor::OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA; - case BlendFactor::DstAlpha: return GL_DST_ALPHA; - case BlendFactor::OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA; - case BlendFactor::ConstantColor: return GL_CONSTANT_COLOR; - case BlendFactor::OneMinusConstantColor: return GL_ONE_MINUS_CONSTANT_COLOR; - case BlendFactor::ConstantAlpha: return GL_CONSTANT_ALPHA; - case BlendFactor::OneMinusConstantAlpha: return GL_ONE_MINUS_CONSTANT_ALPHA; - case BlendFactor::SrcAlphaSaturate: return GL_SRC_ALPHA_SATURATE; - case BlendFactor::Src1Color: return GL_SRC1_COLOR; - case BlendFactor::OneMinusSrc1Color: return GL_ONE_MINUS_SRC1_COLOR; - case BlendFactor::Src1Alpha: return GL_SRC1_ALPHA; - case BlendFactor::OneMinusSrc1Alpha: return GL_ONE_MINUS_SRC1_ALPHA; - }; - - return GL_ZERO; - } - - class OpenGL_Texture : public Texture - { - private: - GLuint m_id; - int m_width; - int m_height; - TextureWrap m_wrap_x; - TextureWrap m_wrap_y; - TextureFilter m_filter; - TextureFormat m_format; - GLenum m_gl_internal_format; - GLenum m_gl_format; - GLenum m_gl_type; - - public: - bool framebuffer_parent; - - OpenGL_Texture(Device* device, int width, int height, TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y, TextureFormat format) - { - m_id = 0; - m_width = width; - m_height = height; - m_wrap_x = wrap_x; - m_wrap_y = wrap_y; - m_filter = filter; - m_format = format; - framebuffer_parent = false; - m_gl_internal_format = GL_RED; - m_gl_format = GL_RED; - m_gl_type = GL_UNSIGNED_BYTE; - - if (width > device->max_texture_size || height > device->max_texture_size) - { - Log::error("Exceeded Max Texture Size of %i", device->max_texture_size); - return; - } - - if (format == TextureFormat::R) - { - m_gl_internal_format = GL_RED; - m_gl_format = GL_RED; - m_gl_type = GL_UNSIGNED_BYTE; - } - else if (format == TextureFormat::RG) - { - m_gl_internal_format = GL_RG; - m_gl_format = GL_RG; - m_gl_type = GL_UNSIGNED_BYTE; - } - else if (format == TextureFormat::RGB) - { - m_gl_internal_format = GL_RGB; - m_gl_format = GL_RGB; - m_gl_type = GL_UNSIGNED_BYTE; - } - else if (format == TextureFormat::RGBA) - { - m_gl_internal_format = GL_RGBA; - m_gl_format = GL_RGBA; - m_gl_type = GL_UNSIGNED_BYTE; - } - else if (format == TextureFormat::DepthStencil) - { - m_gl_internal_format = GL_DEPTH24_STENCIL8; - m_gl_format = GL_DEPTH_STENCIL; - m_gl_type = GL_UNSIGNED_INT_24_8; - } - else - { - Log::error("Invalid Texture Format %i", format); - return; - } - - gl.GenTextures(1, &m_id); - gl.ActiveTexture(GL_TEXTURE0); - gl.BindTexture(GL_TEXTURE_2D, m_id); - - gl.TexImage2D(GL_TEXTURE_2D, 0, m_gl_internal_format, width, height, 0, m_gl_format, m_gl_type, nullptr); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (m_filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (m_filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (m_wrap_x == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (m_wrap_y == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); - } - - ~OpenGL_Texture() - { - if (m_id > 0) - gl.DeleteTextures(1, &m_id); - } - - GLuint gl_id() const - { - return m_id; - } - - virtual int width() const override - { - return m_width; - } - - virtual int height() const override - { - return m_height; - } - - virtual TextureFormat format() const override - { - return m_format; - } - - virtual void set_filter(TextureFilter filter) override - { - m_filter = filter; - - gl.BindTexture(GL_TEXTURE_2D, m_id); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); - } - - virtual TextureFilter get_filter() const override - { - return m_filter; - } - - virtual void set_wrap(TextureWrap x, TextureWrap y) override - { - m_wrap_x = x; - m_wrap_y = y; - - gl.BindTexture(GL_TEXTURE_2D, m_id); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (x == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (y == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); - } - - virtual TextureWrap get_wrap_x() const override - { - return m_wrap_x; - } - - virtual TextureWrap get_wrap_y() const override - { - return m_wrap_y; - } - - virtual void set_data(unsigned char* data) override - { - gl.ActiveTexture(GL_TEXTURE0); - gl.BindTexture(GL_TEXTURE_2D, m_id); - gl.TexImage2D(GL_TEXTURE_2D, 0, m_gl_internal_format, m_width, m_height, 0, m_gl_format, m_gl_type, data); - } - - virtual void get_data(unsigned char* data) override - { - gl.ActiveTexture(GL_TEXTURE0); - gl.BindTexture(GL_TEXTURE_2D, m_id); - gl.GetTexImage(GL_TEXTURE_2D, 0, m_gl_internal_format, m_gl_type, data); - } - - virtual bool is_framebuffer() const override - { - return framebuffer_parent; - } - - virtual bool is_valid() const override - { - return m_id > 0; - } - - virtual void dispose() override - { - if (m_id > 0) - { - gl.DeleteTextures(1, &m_id); - m_id = 0; - } - } - - }; - - class OpenGL_FrameBuffer : public FrameBuffer - { - private: - GLuint m_id; - int m_width; - int m_height; - StackVector m_attachments; - - public: - - OpenGL_FrameBuffer(Device* device, int width, int height, const TextureFormat* attachments, int attachmentCount) - { - gl.GenFramebuffers(1, &m_id); - m_width = width; - m_height = height; - - gl.BindFramebuffer(GL_FRAMEBUFFER, m_id); - - for (int i = 0; i < attachmentCount; i++) - { - auto tex = Graphics::create_texture(width, height, attachments[i]); - auto gltex = ((OpenGL_Texture*)tex.get()); - - gltex->framebuffer_parent = true; - m_attachments.push_back(tex); - - if (attachments[i] != TextureFormat::DepthStencil) - { - gl.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, gltex->gl_id(), 0); - } - else - { - gl.FramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, gltex->gl_id(), 0); - } - } - } - - ~OpenGL_FrameBuffer() - { - if (m_id > 0) - { - gl.DeleteFramebuffers(1, &m_id); - m_id = 0; - } - } - - GLuint gl_id() const - { - return m_id; - } - - virtual Attachments& attachments() override - { - return m_attachments; - } - - virtual const Attachments& attachments() const override - { - return m_attachments; - } - - virtual int width() const override - { - return m_width; - } - - virtual int height() const override - { - return m_height; - } - - virtual bool is_valid() const override - { - return m_id > 0; - } - - virtual void dispose() override - { - if (m_id > 0) - { - m_attachments.clear(); - gl.DeleteFramebuffers(1, &m_id); - m_id = 0; - } - } - }; - - class OpenGL_Shader : public Shader - { - private: - GLuint m_id; - Attributes m_attributes; - Uniforms m_uniforms; - - public: - GLint uniforms_loc[BLAH_UNIFORMS] = { 0 }; - - OpenGL_Shader(Device* device, const ShaderData* data) - { - m_id = 0; - - // vertex shader - if (data->vertex == nullptr) - { - Log::error("Vertex Shader is required"); - return; - } - - if (data->fragment == nullptr) - { - Log::error("Fragment Shader is required"); - return; - } - - GLchar log[1024]; - GLsizei log_length = 0; - - GLuint vertex_shader = gl.CreateShader(GL_VERTEX_SHADER); - { - const GLchar* source = (const GLchar*)data->vertex; - gl.ShaderSource(vertex_shader, 1, &source, nullptr); - gl.CompileShader(vertex_shader); - gl.GetShaderInfoLog(vertex_shader, 1024, &log_length, log); - - if (log_length > 0) - { - gl.DeleteShader(vertex_shader); - Log::error(log); - return; - } - } - - GLuint fragment_shader = gl.CreateShader(GL_FRAGMENT_SHADER); - { - const GLchar* source = (const GLchar*)data->fragment; - gl.ShaderSource(fragment_shader, 1, &source, nullptr); - gl.CompileShader(fragment_shader); - gl.GetShaderInfoLog(fragment_shader, 1024, &log_length, log); - - if (log_length > 0) - { - gl.DeleteShader(fragment_shader); - Log::error(log); - return; - } - } - - GLuint id = gl.CreateProgram(); - gl.AttachShader(id, vertex_shader); - gl.AttachShader(id, fragment_shader); - gl.LinkProgram(id); - gl.GetProgramInfoLog(id, 1024, &log_length, log); - - if (log_length > 0) - { - gl.DetachShader(id, vertex_shader); - gl.DetachShader(id, fragment_shader); - gl.DeleteShader(vertex_shader); - gl.DeleteShader(fragment_shader); - - Log::error(log); - return; - } - - // ready to go - m_id = id; - - // get attributes - { - GLint active_attributes = 0; - gl.GetProgramiv(id, GL_ACTIVE_ATTRIBUTES, &active_attributes); - if (active_attributes > BLAH_ATTRIBUTES) - { - Log::warn("Exceeding maximum shader attributes (%i / %i)", active_attributes, BLAH_ATTRIBUTES); - active_attributes = BLAH_ATTRIBUTES; - } - - for (int i = 0; i < active_attributes; i++) - { - GLsizei length; - GLsizei size; - GLenum type; - GLchar name[BLAH_ATTRIBUTE_NAME]; - - gl.GetActiveAttrib(id, i, BLAH_ATTRIBUTE_NAME - 1, &length, &size, &type, name); - name[length] = '\0'; - - ShaderAttribute attr; - attr.name = name; - attr.semantic_name = ""; - attr.semantic_location = 0; - m_attributes.push_back(attr); - } - } - - // get uniforms - { - GLint active_uniforms = 0; - gl.GetProgramiv(id, GL_ACTIVE_UNIFORMS, &active_uniforms); - if (active_uniforms > BLAH_UNIFORMS) - { - Log::warn("Exceeding maximum shader uniforms (%i / %i)", active_uniforms, BLAH_ATTRIBUTES); - active_uniforms = BLAH_UNIFORMS; - } - - for (int i = 0; i < active_uniforms; i++) - { - GLsizei length; - GLsizei size; - GLenum type; - GLchar name[BLAH_UNIFORM_NAME]; - - gl.GetActiveUniform(id, i, BLAH_UNIFORM_NAME - 1, &length, &size, &type, name); - name[length] = '\0'; - - // array names end with "[0]", and we don't want that - for (int n = 0; n < BLAH_UNIFORM_NAME; n++) - if (name[n] == '[') - { - if (name[n + 1] == '0' && name[n + 2] == ']') - { - name[n] = '\0'; - break; - } - } - - ShaderUniform uniform; - uniform.name = name; - uniform.type = UniformType::None; - uniform.array_length = size; - uniforms_loc[i] = gl.GetUniformLocation(id, name); - - if (type == GL_FLOAT) - uniform.type = UniformType::Float; - else if (type == GL_FLOAT_VEC2) - uniform.type = UniformType::Float2; - else if (type == GL_FLOAT_VEC3) - uniform.type = UniformType::Float3; - else if (type == GL_FLOAT_VEC4) - uniform.type = UniformType::Float4; - else if (type == GL_FLOAT_MAT3x2) - uniform.type = UniformType::Mat3x2; - else if (type == GL_FLOAT_MAT4) - uniform.type = UniformType::Mat4x4; - else if (type == GL_SAMPLER_2D) - uniform.type = UniformType::Texture; - else - { - Log::error("Unsupported Uniform Type. Must be either FLOAT, MAT3x2, MAT4, or SAMPLER_2D"); - break; - } - - m_uniforms.push_back(uniform); - } - } - } - - ~OpenGL_Shader() - { - if (m_id > 0) - gl.DeleteProgram(m_id); - m_id = 0; - } - - GLuint gl_id() const - { - return m_id; - } - - virtual Uniforms& uniforms() override - { - return m_uniforms; - } - - virtual const Uniforms& uniforms() const override - { - return m_uniforms; - } - - virtual Attributes& attributes() override - { - return m_attributes; - } - - virtual const Attributes& attributes() const override - { - return m_attributes; - } - - virtual bool is_valid() const override - { - return m_id > 0; - } - - virtual void dispose() override - { - if (m_id > 0) - gl.DeleteProgram(m_id); - m_id = 0; - } - }; - - class OpenGL_Mesh : public Mesh - { - private: - GLuint m_id; - GLuint m_index_buffer; - GLuint m_vertex_buffer; - GLuint m_instance_buffer; - int64_t m_index_count; - int64_t m_vertex_count; - int64_t m_instance_count; - uint16_t m_vertex_size; - uint16_t m_instance_size; - uint8_t m_vertex_attribs_enabled; - uint8_t m_instance_attribs_enabled; - GLuint m_vertex_attribs[BLAH_ATTRIBUTES]; - GLuint m_instance_attribs[BLAH_ATTRIBUTES]; - - public: - - OpenGL_Mesh(Device* device) - { - m_id = 0; - m_index_buffer = 0; - m_vertex_buffer = 0; - m_instance_buffer = 0; - m_index_count = 0; - m_vertex_count = 0; - m_instance_count = 0; - m_vertex_size = 0; - m_instance_size = 0; - m_vertex_attribs_enabled = 0; - m_instance_attribs_enabled = 0; - m_vertex_attribs[0] = 0; - m_instance_attribs[0] = 0; - - gl.GenVertexArrays(1, &m_id); - } - - ~OpenGL_Mesh() - { - if (m_vertex_buffer != 0) - gl.DeleteBuffers(1, &m_vertex_buffer); - if (m_index_buffer != 0) - gl.DeleteBuffers(1, &m_index_buffer); - if (m_instance_buffer != 0) - gl.DeleteBuffers(1, &m_instance_buffer); - if (m_id != 0) - gl.DeleteVertexArrays(1, &m_id); - m_id = 0; - } - - GLuint gl_id() const - { - return m_id; - } - - virtual void vertex_format_internal(const VertexAttribute* attributes, int attribute_count, int stride = -1) override - { - gl.BindVertexArray(m_id); - { - if (m_vertex_buffer == 0) - gl.GenBuffers(1, &(m_vertex_buffer)); - - m_vertex_size = gl_mesh_assign_attributes(m_vertex_buffer, GL_ARRAY_BUFFER, attributes, attribute_count, stride, 0); - } - gl.BindVertexArray(0); - } - - virtual void instance_format_internal(const VertexAttribute* attributes, int attribute_count, int stride = -1) override - { - gl.BindVertexArray(m_id); - { - if (m_instance_buffer == 0) - gl.GenBuffers(1, &(m_instance_buffer)); - - m_instance_size = gl_mesh_assign_attributes(m_instance_buffer, GL_ARRAY_BUFFER, attributes, attribute_count, stride, 1); - } - gl.BindVertexArray(0); - } - - virtual void index_data(const void* indices, int64_t count) override - { - m_index_count = count; - - gl.BindVertexArray(m_id); - { - if (m_index_buffer == 0) - gl.GenBuffers(1, &(m_index_buffer)); - - gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer); - gl.BufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * count, indices, GL_DYNAMIC_DRAW); - } - gl.BindVertexArray(0); - } - - virtual void vertex_data(const void* vertices, int64_t count) override - { - if (m_vertex_buffer == 0 || m_vertex_size <= 0) - { - Log::error("You must assign a Vertex Format before setting Vertex Data"); - } - else - { - m_vertex_count = count; - - gl.BindVertexArray(m_id); - { - gl.BindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer); - gl.BufferData(GL_ARRAY_BUFFER, m_vertex_size * count, vertices, GL_DYNAMIC_DRAW); - } - gl.BindVertexArray(0); - } - } - - virtual void instance_data(const void* instances, int64_t count) override - { - if (m_instance_buffer == 0 || m_instance_size <= 0) - { - Log::error("You must assign an Instance Format before setting Instance Data"); - } - else - { - m_instance_count = count; - - gl.BindVertexArray(m_id); - { - gl.BindBuffer(GL_ARRAY_BUFFER, m_instance_buffer); - gl.BufferData(GL_ARRAY_BUFFER, m_instance_size * count, instances, GL_DYNAMIC_DRAW); - } - gl.BindVertexArray(0); - } - } - - virtual int64_t index_count() const override - { - return m_index_count; - } - - virtual int64_t vertex_count() const override - { - return m_vertex_count; - } - - virtual int64_t instance_count() const override - { - return m_instance_count; - } - - virtual bool is_valid() const override - { - return m_id > 0; - } - - virtual void dispose() override - { - if (m_vertex_buffer != 0) - gl.DeleteBuffers(1, &m_vertex_buffer); - if (m_index_buffer != 0) - gl.DeleteBuffers(1, &m_index_buffer); - if (m_instance_buffer != 0) - gl.DeleteBuffers(1, &m_instance_buffer); - if (m_id != 0) - gl.DeleteVertexArrays(1, &m_id); - m_id = 0; - } - }; - - void Device::startup() - { - valid = true; - - // create gl context - context = Internal::Platform::gl_context_create(); - if (context == nullptr) - { - Log::error("Failed to create OpenGL Context"); - valid = false; - return; - } - Internal::Platform::gl_context_make_current(context); - - // bind opengl functions - #define GL_FUNC(name, ...) gl.name = (GL::name ## Func)(Internal::Platform::gl_get_func("gl" #name)); - GL_FUNCTIONS - #undef GL_FUNC - - // bind debug message callback - if (gl.DebugMessageCallback != nullptr) - { - gl.Enable(GL_DEBUG_OUTPUT); - gl.Enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - gl.DebugMessageCallback(gl_message_callback, nullptr); - } - - // get opengl info - gl.GetIntegerv(0x8CDF, &max_color_attachments); - gl.GetIntegerv(0x80E9, &max_element_indices); - gl.GetIntegerv(0x80E8, &max_element_vertices); - gl.GetIntegerv(0x84E8, &max_renderbuffer_size); - gl.GetIntegerv(0x8D57, &max_samples); - gl.GetIntegerv(0x8872, &max_texture_image_units); - gl.GetIntegerv(0x0D33, &max_texture_size); - - // log - Log::print("OpenGL %s, %s", - gl.GetString(GL_VERSION), - gl.GetString(GL_RENDERER)); - - // don't include row padding - gl.PixelStorei(GL_PACK_ALIGNMENT, 1); - gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1); - - // assign info - info.api = GfxAPI::OpenGL; - info.instancing = true; - info.origin_bottom_left = true; - info.max_texture_size = max_texture_size; - } - - void Device::shutdown() - { - Internal::Platform::gl_context_destroy(context); - context = nullptr; - } - - TextureRef Device::create_texture(int width, int height, TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y, TextureFormat format) - { - return TextureRef(new OpenGL_Texture(this, width, height, filter, wrap_x, wrap_y, format)); - } - - FrameBufferRef Device::create_framebuffer(int width, int height, const TextureFormat* attachments, int attachmentCount) - { - return FrameBufferRef(new OpenGL_FrameBuffer(this, width, height, attachments, attachmentCount)); - } - - ShaderRef Device::create_shader(const ShaderData* data) - { - return ShaderRef(new OpenGL_Shader(this, data)); - } - - MeshRef Device::create_mesh() - { - return MeshRef(new OpenGL_Mesh(this)); - } - - void Device::render(RenderCall* call) - { - // Bind the Target - Point size; - if (!call->target || !call->target->is_valid()) - { - gl.BindFramebuffer(GL_FRAMEBUFFER, 0); - size.x = App::draw_width(); - size.y = App::draw_height(); - } - else - { - auto framebuffer = (OpenGL_FrameBuffer*)call->target.get(); - gl.BindFramebuffer(GL_FRAMEBUFFER, framebuffer->gl_id()); - size.x = call->target->width(); - size.y = call->target->height(); - } - - auto shader_ref = call->material->shader(); - auto shader = (OpenGL_Shader*)shader_ref.get(); - auto mesh = (OpenGL_Mesh*)call->mesh.get(); - - // Use the Shader - // TODO: I don't love how material values are assigned or set here - { - gl.UseProgram(shader->gl_id()); - - // upload uniform values - int texture_slot = 0; - GLint texture_ids[64]; - - auto& uniforms = shader->uniforms(); - for (int i = 0; i < uniforms.size(); i++) - { - auto location = shader->uniforms_loc[i]; - auto& uniform = uniforms[i]; - - // Sampler 2D - if (uniform.type == UniformType::Texture) - { - for (int n = 0; n < uniform.array_length; n++) - { - auto tex = call->material->get_texture(i, n); - - gl.ActiveTexture(GL_TEXTURE0 + texture_slot); - - if (!tex) - { - gl.BindTexture(GL_TEXTURE_2D, 0); - } - else - { - gl.BindTexture(GL_TEXTURE_2D, ((OpenGL_Texture*)tex.get())->gl_id()); - } - - texture_ids[n] = texture_slot; - texture_slot++; - } - - gl.Uniform1iv(location, (GLint)uniform.array_length, &texture_ids[0]); - } - // Float - else if (uniform.type == UniformType::Float) - { - gl.Uniform1fv(location, (GLint)uniform.array_length, (const GLfloat*)call->material->get_value(i)); - } - // Float2 - else if (uniform.type == UniformType::Float2) - { - gl.Uniform2fv(location, (GLint)uniform.array_length, (const GLfloat*)call->material->get_value(i)); - } - // Float3 - else if (uniform.type == UniformType::Float3) - { - gl.Uniform3fv(location, (GLint)uniform.array_length, (const GLfloat*)call->material->get_value(i)); - } - // Float4 - else if (uniform.type == UniformType::Float4) - { - gl.Uniform4fv(location, (GLint)uniform.array_length, (const GLfloat*)call->material->get_value(i)); - } - // Matrix3x2 - else if (uniform.type == UniformType::Mat3x2) - { - gl.UniformMatrix3x2fv(location, (GLint)uniform.array_length, 0, (const GLfloat*)call->material->get_value(i)); - } - // Matrix4x4 - else if (uniform.type == UniformType::Mat4x4) - { - gl.UniformMatrix4fv(location, (GLint)uniform.array_length, 0, (const GLfloat*)call->material->get_value(i)); - } - } - } - - // Blend Mode - { - GLenum colorOp = gl_get_blend_func(call->blend.colorOp); - GLenum alphaOp = gl_get_blend_func(call->blend.alphaOp); - GLenum colorSrc = gl_get_blend_factor(call->blend.colorSrc); - GLenum colorDst = gl_get_blend_factor(call->blend.colorDst); - GLenum alphaSrc = gl_get_blend_factor(call->blend.alphaSrc); - GLenum alphaDst = gl_get_blend_factor(call->blend.alphaDst); - - gl.Enable(GL_BLEND); - gl.BlendEquationSeparate(colorOp, alphaOp); - gl.BlendFuncSeparate(colorSrc, colorDst, alphaSrc, alphaDst); - - gl.ColorMask( - ((int)call->blend.mask & (int)BlendMask::Red), - ((int)call->blend.mask & (int)BlendMask::Green), - ((int)call->blend.mask & (int)BlendMask::Blue), - ((int)call->blend.mask & (int)BlendMask::Alpha)); - - - unsigned char r = call->blend.rgba >> 24; - unsigned char g = call->blend.rgba >> 16; - unsigned char b = call->blend.rgba >> 8; - unsigned char a = call->blend.rgba; - - gl.BlendColor( - r / 255.0f, - g / 255.0f, - b / 255.0f, - a / 255.0f); - } - - // Depth Function - { - if (call->depth == Compare::None) - { - gl.Disable(GL_DEPTH_TEST); - } - else - { - gl.Enable(GL_DEPTH_TEST); - - switch (call->depth) - { - case Compare::None: break; - case Compare::Always: - gl.DepthFunc(GL_ALWAYS); - break; - case Compare::Equal: - gl.DepthFunc(GL_EQUAL); - break; - case Compare::Greater: - gl.DepthFunc(GL_GREATER); - break; - case Compare::GreatorOrEqual: - gl.DepthFunc(GL_GEQUAL); - break; - case Compare::Less: - gl.DepthFunc(GL_LESS); - break; - case Compare::LessOrEqual: - gl.DepthFunc(GL_LEQUAL); - break; - case Compare::Never: - gl.DepthFunc(GL_NEVER); - break; - case Compare::NotEqual: - gl.DepthFunc(GL_NOTEQUAL); - break; - } - } - } - - // Cull Mode - { - if (call->cull == Cull::None) - { - gl.Disable(GL_CULL_FACE); - } - else - { - gl.Enable(GL_CULL_FACE); - - if (call->cull == Cull::Back) - gl.CullFace(GL_BACK); - else if (call->cull == Cull::Front) - gl.CullFace(GL_FRONT); - else - gl.CullFace(GL_FRONT_AND_BACK); - } - } - - // Viewport - { - Rect viewport = call->viewport; - viewport.y = size.y - viewport.y - viewport.h; - - gl.Viewport((GLint)viewport.x, (GLint)viewport.y, (GLint)viewport.w, (GLint)viewport.h); - } - - // Scissor - { - if (!call->has_scissor) - { - gl.Disable(GL_SCISSOR_TEST); - } - else - { - Rect scissor = call->scissor; - scissor.y = size.y - scissor.y - scissor.h; - - if (scissor.w < 0) - scissor.w = 0; - if (scissor.h < 0) - scissor.h = 0; - - gl.Enable(GL_SCISSOR_TEST); - gl.Scissor((GLint)scissor.x, (GLint)scissor.y, (GLint)scissor.w, (GLint)scissor.h); - } - } - - // Draw the Mesh - { - gl.BindVertexArray(mesh->gl_id()); - - if (call->instance_count > 0) - { - gl.DrawElementsInstanced( - GL_TRIANGLES, - (GLint)(call->index_count), - GL_UNSIGNED_INT, - (void*)(sizeof(int) * call->index_start), - (GLint)call->instance_count); - } - else - { - gl.DrawElements( - GL_TRIANGLES, - (GLint)(call->index_count), - GL_UNSIGNED_INT, - (void*)(sizeof(int) * call->index_start)); - } - - gl.BindVertexArray(0); - } - } - - void Device::clear(const FrameBufferRef& target, uint32_t rgba) - { - if (!target || !target->is_valid()) - { - gl.BindFramebuffer(GL_FRAMEBUFFER, 0); - } - else - { - auto framebuffer = (OpenGL_FrameBuffer*)target.get(); - if (framebuffer != nullptr) - gl.BindFramebuffer(GL_FRAMEBUFFER, framebuffer->gl_id()); - } - - unsigned char r = rgba >> 24; - unsigned char g = rgba >> 16; - unsigned char b = rgba >> 8; - unsigned char a = rgba; - - gl.Disable(GL_SCISSOR_TEST); - gl.ClearColor(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); - gl.Clear(GL_COLOR_BUFFER_BIT); - } - - bool supported() - { - return true; - } - - Internal::GraphicsDevice* create() - { - return new OpenGL::Device(); - } - - void destroy(Internal::GraphicsDevice* device) - { - delete device; - } - } - - Internal::GraphicsDeviceInfo Internal::OpenGL_DeviceInfo = { - GfxAPI::OpenGL, - OpenGL::supported, - OpenGL::create, - OpenGL::destroy - }; -} - -#else // BLAH_USE_OPENGL - -namespace Blah -{ - namespace OpenGL - { - bool supported() { return false; } - Internal::GraphicsDevice* create() { return nullptr; } - void destroy(Internal::GraphicsDevice* device) { } - } - - Internal::GraphicsDeviceInfo Internal::OpenGL_DeviceInfo = { - GfxAPI::OpenGL, - OpenGL::supported, - OpenGL::create, - OpenGL::destroy - }; -} - -#endif // BLAH_USE_OPENGL diff --git a/private/blah/internal/input.h b/private/blah/internal/input.h deleted file mode 100644 index d5279e4..0000000 --- a/private/blah/internal/input.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once -#include - -namespace Blah -{ - namespace Internal - { - namespace Input - { - // This is called internally by the app, and initializes the input state - void init(); - - // This is called internally by the app, and updates the input state - void frame(); - - // Call this when the Mouse moves relative to the window - void on_mouse_move(float x, float y); - - // Call this when the Mouse moves relative to the screen - void on_mouse_screen_move(float x, float y); - - // Call this when a Mouse Button is pressed - void on_mouse_down(MouseButton button); - - // Call this when a Mouse Button is released - void on_mouse_up(MouseButton button); - - // Call this when the Mouse Wheel moves - void on_mouse_wheel(Point wheel); - - // Call this when a keyboard key is pressed - void on_key_down(Key key); - - // Call this when a keyboard key is released - void on_key_up(Key key); - - // Call this on Text Input - void on_text_utf8(const char* text); - - // Call this when a Controller is connected. Note that the Name parameter must be kept valid - // until on_controller_disconnect is called with the same index. - void on_controller_connect(int index, const char* name, int isGamepad, int buttonCount, int axisCount); - - // Call this when a controller is disconnected - void on_controller_disconnect(int index); - - // Call this when a controller button is pressed - void on_button_down(int index, int button); - - // Call this when a controller button is released - void on_button_up(int index, int button); - - /// Call this when a controller axis is moved - void on_axis_move(int index, int axis, float value); - } - } -} \ No newline at end of file diff --git a/private/blah/internal/input_backend.h b/private/blah/internal/input_backend.h new file mode 100644 index 0000000..18913b2 --- /dev/null +++ b/private/blah/internal/input_backend.h @@ -0,0 +1,54 @@ +#pragma once +#include + +namespace Blah +{ + namespace InputBackend + { + // This is called internally by the app, and initializes the input state + void init(); + + // This is called internally by the app, and updates the input state + void frame(); + + // Call this when the Mouse moves relative to the window + void on_mouse_move(float x, float y); + + // Call this when the Mouse moves relative to the screen + void on_mouse_screen_move(float x, float y); + + // Call this when a Mouse Button is pressed + void on_mouse_down(MouseButton button); + + // Call this when a Mouse Button is released + void on_mouse_up(MouseButton button); + + // Call this when the Mouse Wheel moves + void on_mouse_wheel(Point wheel); + + // Call this when a keyboard key is pressed + void on_key_down(Key key); + + // Call this when a keyboard key is released + void on_key_up(Key key); + + // Call this on Text Input + void on_text_utf8(const char* text); + + // Call this when a Controller is connected. Note that the Name parameter must be kept valid + // until on_controller_disconnect is called with the same index. + void on_controller_connect(int index, const char* name, int isGamepad, int buttonCount, int axisCount); + + // Call this when a controller is disconnected + void on_controller_disconnect(int index); + + // Call this when a controller button is pressed + void on_button_down(int index, int button); + + // Call this when a controller button is released + void on_button_up(int index, int button); + + /// Call this when a controller axis is moved + void on_axis_move(int index, int axis, float value); + } +} \ No newline at end of file diff --git a/private/blah/internal/platform.h b/private/blah/internal/platform.h deleted file mode 100644 index 63fcfc2..0000000 --- a/private/blah/internal/platform.h +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once -#include -#include -#include - -namespace Blah -{ - struct Config; - enum class FileMode; - - namespace Internal - { - namespace Platform - { - typedef void* FileHandle; - - // Initialize the System - bool init(const Config* config); - - // Called after the on_startup callback, but before the update loop begins - void ready(); - - // Called during shutdown - void shutdown(); - - // The time, in milliseconds, since the Application was started - uint64_t time(); - - // Called every frame - void frame(); - - // Sleeps the current thread - void sleep(int milliseconds); - - // Called to present the window contents - void present(); - - // Gets the Application Window Title in UTF-8 - const char* get_title(); - - // Sets the Application Window Title in UTF-8 - void set_title(const char* title); - - // Gets the Application Window Position, in Screen Coordinates - void get_position(int* x, int* y); - - // Sets the Application Window Position, in Screen Coordinates - void set_position(int x, int y); - - // Sets the Window Fullscreen if enabled is not 0 - void set_fullscreen(bool enabled); - - // Gets the Application Window Size, in Screen Coordinates - void get_size(int* width, int* height); - - // Sets the Application Window Size, in Screen Coordinates - void set_size(int width, int height); - - // Gets the Application Window Drawing Size, in Pixels. This may differ from the Window Size on hi-dpi displays. - void get_draw_size(int* width, int* height); - - // Gets the Desktop Content Scale. Gui should be scaled by this value - float get_content_scale(); - - // Returns the absoluate path to the directory that the application was started from - const char* app_path(); - - // Returns the absolute path to the user directory where save data and settings should be stored - const char* user_path(); - - // Returns true if a file with the given path exists - bool file_exists(const char* path); - - // Returns true if a file with the given path was deleted - bool file_delete(const char* path); - - // Returns true if a directory with the given path was successfully created - bool dir_create(const char* path); - - // Returns true if a directory with the given path exists - bool dir_exists(const char* path); - - // Returns true if a directory with the given path was deleted - bool dir_delete(const char* path); - - // enumerates a directory and appends each file to the given list - void dir_enumerate(Vector& list, const char* path, bool recursive); - - // opens a directory in the OS file explorer / finder - void dir_explore(const char* path); - - // Opens a file and sets the handle. returns true if the file was successfully opened - bool file_open(const char* path, FileHandle* handle, FileMode mode); - - // Returns the length of the file - int64_t file_length(FileHandle file); - - // Returns the Position of the file - int64_t file_position(FileHandle file); - - // Seeks the Position of the file and returns the new position from the start of the file - int64_t file_seek(FileHandle file, int64_t seekTo); - - // Reads a specific number of elements of a given size from the file into ptr - int64_t file_read(FileHandle file, void* ptr, int64_t size); - - // Writes a specific number of elements of the given size from ptr to the file - int64_t file_write(FileHandle file, const void* ptr, int64_t size); - - // Closes a file - void file_close(FileHandle file); - - // OpenGL Methods - void* gl_get_func(const char* name); - void* gl_context_create(); - void gl_context_make_current(void* context); - void gl_context_destroy(void* context); - } - } -} \ No newline at end of file diff --git a/private/blah/internal/platform_backend.h b/private/blah/internal/platform_backend.h new file mode 100644 index 0000000..ebfe734 --- /dev/null +++ b/private/blah/internal/platform_backend.h @@ -0,0 +1,117 @@ +#pragma once +#include +#include +#include + +namespace Blah +{ + struct Config; + enum class FileMode; + + namespace PlatformBackend + { + typedef void* FileHandle; + + // Initialize the System + bool init(const Config* config); + + // Called after the on_startup callback, but before the update loop begins + void ready(); + + // Called during shutdown + void shutdown(); + + // The time, in milliseconds, since the Application was started + uint64_t time(); + + // Called every frame + void frame(); + + // Sleeps the current thread + void sleep(int milliseconds); + + // Called to present the window contents + void present(); + + // Gets the Application Window Title in UTF-8 + const char* get_title(); + + // Sets the Application Window Title in UTF-8 + void set_title(const char* title); + + // Gets the Application Window Position, in Screen Coordinates + void get_position(int* x, int* y); + + // Sets the Application Window Position, in Screen Coordinates + void set_position(int x, int y); + + // Sets the Window Fullscreen if enabled is not 0 + void set_fullscreen(bool enabled); + + // Gets the Application Window Size, in Screen Coordinates + void get_size(int* width, int* height); + + // Sets the Application Window Size, in Screen Coordinates + void set_size(int width, int height); + + // Gets the Application Window Drawing Size, in Pixels. This may differ from the Window Size on hi-dpi displays. + void get_draw_size(int* width, int* height); + + // Gets the Desktop Content Scale. Gui should be scaled by this value + float get_content_scale(); + + // Returns the absoluate path to the directory that the application was started from + const char* app_path(); + + // Returns the absolute path to the user directory where save data and settings should be stored + const char* user_path(); + + // Returns true if a file with the given path exists + bool file_exists(const char* path); + + // Returns true if a file with the given path was deleted + bool file_delete(const char* path); + + // Returns true if a directory with the given path was successfully created + bool dir_create(const char* path); + + // Returns true if a directory with the given path exists + bool dir_exists(const char* path); + + // Returns true if a directory with the given path was deleted + bool dir_delete(const char* path); + + // enumerates a directory and appends each file to the given list + void dir_enumerate(Vector& list, const char* path, bool recursive); + + // opens a directory in the OS file explorer / finder + void dir_explore(const char* path); + + // Opens a file and sets the handle. returns true if the file was successfully opened + bool file_open(const char* path, FileHandle* handle, FileMode mode); + + // Returns the length of the file + int64_t file_length(FileHandle file); + + // Returns the Position of the file + int64_t file_position(FileHandle file); + + // Seeks the Position of the file and returns the new position from the start of the file + int64_t file_seek(FileHandle file, int64_t seekTo); + + // Reads a specific number of elements of a given size from the file into ptr + int64_t file_read(FileHandle file, void* ptr, int64_t size); + + // Writes a specific number of elements of the given size from ptr to the file + int64_t file_write(FileHandle file, const void* ptr, int64_t size); + + // Closes a file + void file_close(FileHandle file); + + // OpenGL Methods + void* gl_get_func(const char* name); + void* gl_context_create(); + void gl_context_make_current(void* context); + void gl_context_destroy(void* context); + } +} \ No newline at end of file diff --git a/private/blah/internal/platform_sdl2.cpp b/private/blah/internal/platform_backend_sdl2.cpp similarity index 75% rename from private/blah/internal/platform_sdl2.cpp rename to private/blah/internal/platform_backend_sdl2.cpp index 2f69c3e..411776a 100644 --- a/private/blah/internal/platform_sdl2.cpp +++ b/private/blah/internal/platform_backend_sdl2.cpp @@ -1,7 +1,8 @@ #ifdef BLAH_USE_SDL2 -#include -#include +#include +#include +#include #include #include #include @@ -26,7 +27,6 @@ namespace fs = std::filesystem; #endif using namespace Blah; -using namespace Internal; namespace { @@ -48,7 +48,7 @@ namespace } } -bool Platform::init(const Config* config) +bool PlatformBackend::init(const Config* config) { // Required to call this for Windows // I'm not sure why SDL2 doesn't do this on Windows automatically? @@ -73,9 +73,13 @@ bool Platform::init(const Config* config) return false; } + int flags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE; + // GL Attributes - if (config->graphics == GfxAPI::OpenGL) + if (GraphicsBackend::renderer() == GraphicsRenderer::OpenGL) { + flags |= SDL_WINDOW_OPENGL; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); @@ -90,11 +94,6 @@ bool Platform::init(const Config* config) SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); } - // set up window flags - int flags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE; - if (config->graphics == GfxAPI::OpenGL) - flags |= SDL_WINDOW_OPENGL; - // create the window window = SDL_CreateWindow(config->name, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, config->width, config->height, flags); if (window == nullptr) @@ -133,14 +132,14 @@ bool Platform::init(const Config* config) return true; } -void Platform::ready() +void PlatformBackend::ready() { // enable V-Sync - if (App::config()->graphics == GfxAPI::OpenGL) + if (GraphicsBackend::renderer() == GraphicsRenderer::OpenGL) SDL_GL_SetSwapInterval(1); } -void Platform::shutdown() +void PlatformBackend::shutdown() { if (window != nullptr) SDL_DestroyWindow(window); @@ -156,12 +155,12 @@ void Platform::shutdown() SDL_Quit(); } -uint64_t Platform::time() +uint64_t PlatformBackend::time() { return (uint64_t)SDL_GetTicks(); } -void Platform::frame() +void PlatformBackend::frame() { // update the mouse every frame { @@ -169,8 +168,8 @@ void Platform::frame() SDL_GetWindowPosition(window, &winX, &winY); SDL_GetGlobalMouseState(&x, &y); - Internal::Input::on_mouse_move((float)(x - winX), (float)(y - winY)); - Internal::Input::on_mouse_screen_move((float)x, (float)y); + InputBackend::on_mouse_move((float)(x - winX), (float)(y - winY)); + InputBackend::on_mouse_screen_move((float)x, (float)y); } // poll normal events @@ -193,7 +192,7 @@ void Platform::frame() btn = MouseButton::Right; else if (event.button.button == SDL_BUTTON_MIDDLE) btn = MouseButton::Middle; - Internal::Input::on_mouse_down(btn); + InputBackend::on_mouse_down(btn); } else if (event.type == SDL_MOUSEBUTTONUP) { @@ -204,26 +203,26 @@ void Platform::frame() btn = MouseButton::Right; else if (event.button.button == SDL_BUTTON_MIDDLE) btn = MouseButton::Middle; - Internal::Input::on_mouse_up(btn); + InputBackend::on_mouse_up(btn); } else if (event.type == SDL_MOUSEWHEEL) { - Internal::Input::on_mouse_wheel(Point(event.wheel.x, event.wheel.y)); + InputBackend::on_mouse_wheel(Point(event.wheel.x, event.wheel.y)); } // Keyboard else if (event.type == SDL_KEYDOWN) { if (event.key.repeat == 0) - Internal::Input::on_key_down((Key)event.key.keysym.scancode); + InputBackend::on_key_down((Key)event.key.keysym.scancode); } else if (event.type == SDL_KEYUP) { if (event.key.repeat == 0) - Internal::Input::on_key_up((Key)event.key.keysym.scancode); + InputBackend::on_key_up((Key)event.key.keysym.scancode); } else if (event.type == SDL_TEXTINPUT) { - Internal::Input::on_text_utf8(event.text.text); + InputBackend::on_text_utf8(event.text.text); } // Joystick Controller else if (event.type == SDL_JOYDEVICEADDED) @@ -237,7 +236,7 @@ void Platform::frame() int button_count = SDL_JoystickNumButtons(ptr); int axis_count = SDL_JoystickNumAxes(ptr); - Internal::Input::on_controller_connect(index, name, 0, button_count, axis_count); + InputBackend::on_controller_connect(index, name, 0, button_count, axis_count); } } else if (event.type == SDL_JOYDEVICEREMOVED) @@ -246,7 +245,7 @@ void Platform::frame() if (SDL_IsGameController(index) == SDL_FALSE) { - Internal::Input::on_controller_disconnect(index); + InputBackend::on_controller_disconnect(index); SDL_JoystickClose(joysticks[index]); } } @@ -254,13 +253,13 @@ void Platform::frame() { Sint32 index = event.jdevice.which; if (SDL_IsGameController(index) == SDL_FALSE) - Internal::Input::on_button_down(index, event.jbutton.button); + InputBackend::on_button_down(index, event.jbutton.button); } else if (event.type == SDL_JOYBUTTONUP) { Sint32 index = event.jdevice.which; if (SDL_IsGameController(index) == SDL_FALSE) - Internal::Input::on_button_up(index, event.jbutton.button); + InputBackend::on_button_up(index, event.jbutton.button); } else if (event.type == SDL_JOYAXISMOTION) { @@ -272,7 +271,7 @@ void Platform::frame() value = event.jaxis.value / 32767.0f; else value = event.jaxis.value / 32768.0f; - Internal::Input::on_axis_move(index, event.jaxis.axis, value); + InputBackend::on_axis_move(index, event.jaxis.axis, value); } } // Gamepad Controller @@ -281,12 +280,12 @@ void Platform::frame() Sint32 index = event.cdevice.which; SDL_GameController* ptr = gamepads[index] = SDL_GameControllerOpen(index); const char* name = SDL_GameControllerName(ptr); - Internal::Input::on_controller_connect(index, name, 1, 15, 6); + InputBackend::on_controller_connect(index, name, 1, 15, 6); } else if (event.type == SDL_CONTROLLERDEVICEREMOVED) { Sint32 index = event.cdevice.which; - Internal::Input::on_controller_disconnect(index); + InputBackend::on_controller_disconnect(index); SDL_GameControllerClose(gamepads[index]); } else if (event.type == SDL_CONTROLLERBUTTONDOWN) @@ -297,7 +296,7 @@ void Platform::frame() if (event.cbutton.button >= 0 && event.cbutton.button < 15) button = event.cbutton.button; // NOTE: These map directly to Engine Buttons enum! - Internal::Input::on_button_down(index, button); + InputBackend::on_button_down(index, button); } else if (event.type == SDL_CONTROLLERBUTTONUP) { @@ -307,7 +306,7 @@ void Platform::frame() if (event.cbutton.button >= 0 && event.cbutton.button < 15) button = event.cbutton.button; // NOTE: These map directly to Engine Buttons enum! - Internal::Input::on_button_up(index, button); + InputBackend::on_button_up(index, button); } else if (event.type == SDL_CONTROLLERAXISMOTION) { @@ -323,20 +322,20 @@ void Platform::frame() else value = event.caxis.value / 32768.0f; - Internal::Input::on_axis_move(index, axis, value); + InputBackend::on_axis_move(index, axis, value); } } } -void Platform::sleep(int milliseconds) +void PlatformBackend::sleep(int milliseconds) { if (milliseconds >= 0) SDL_Delay((uint32_t)milliseconds); } -void Platform::present() +void PlatformBackend::present() { - if (App::config()->graphics == GfxAPI::OpenGL) + if (GraphicsBackend::renderer() == GraphicsRenderer::OpenGL) { SDL_GL_SwapWindow(window); } @@ -350,27 +349,27 @@ void Platform::present() } } -const char* Platform::get_title() +const char* PlatformBackend::get_title() { return nullptr; } -void Platform::set_title(const char* title) +void PlatformBackend::set_title(const char* title) { SDL_SetWindowTitle(window, title); } -void Platform::get_position(int* x, int* y) +void PlatformBackend::get_position(int* x, int* y) { SDL_GetWindowPosition(window, x, y); } -void Platform::set_position(int x, int y) +void PlatformBackend::set_position(int x, int y) { SDL_SetWindowPosition(window, x, y); } -void Platform::set_fullscreen(bool enabled) +void PlatformBackend::set_fullscreen(bool enabled) { if (enabled) SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); @@ -378,36 +377,30 @@ void Platform::set_fullscreen(bool enabled) SDL_SetWindowFullscreen(window, 0); } -void Platform::get_size(int* width, int* height) +void PlatformBackend::get_size(int* width, int* height) { SDL_GetWindowSize(window, width, height); } -void Platform::set_size(int width, int height) +void PlatformBackend::set_size(int width, int height) { SDL_SetWindowSize(window, width, height); } -void Platform::get_draw_size(int* width, int* height) +void PlatformBackend::get_draw_size(int* width, int* height) { auto config = App::config(); - if (config->graphics == GfxAPI::OpenGL) + if (GraphicsBackend::renderer() == GraphicsRenderer::OpenGL) { SDL_GL_GetDrawableSize(window, width, height); } - /* - else if (config->graphics == GfxAPI::Vulkan) - { - SDL_Vulkan_GetDrawableSize(window, width, height); - } - */ else { SDL_GetWindowSize(window, width, height); } } -float Platform::get_content_scale() +float PlatformBackend::get_content_scale() { // TODO: // This is incorrect! but for some reason the scale @@ -435,14 +428,14 @@ float Platform::get_content_scale() // FILE IO -const char* Platform::app_path() +const char* PlatformBackend::app_path() { if (basePath == nullptr) basePath = SDL_GetBasePath(); return basePath; } -const char* Platform::user_path() +const char* PlatformBackend::user_path() { if (userPath == nullptr) { @@ -456,34 +449,34 @@ const char* Platform::user_path() // Windows File System methods #if _WIN32 -bool Platform::file_exists(const char* path) +bool PlatformBackend::file_exists(const char* path) { return fs::is_regular_file(path); } -bool Platform::file_delete(const char* path) +bool PlatformBackend::file_delete(const char* path) { return fs::remove(path); } -bool Platform::dir_create(const char* path) +bool PlatformBackend::dir_create(const char* path) { std::error_code error; return fs::create_directories(path, error); } -bool Platform::dir_exists(const char* path) +bool PlatformBackend::dir_exists(const char* path) { return fs::is_directory(path); } -bool Platform::dir_delete(const char* path) +bool PlatformBackend::dir_delete(const char* path) { BLAH_ERROR("not implemented"); return false; } -void Platform::dir_enumerate(Vector& list, const char* path, bool recursive) +void PlatformBackend::dir_enumerate(Vector& list, const char* path, bool recursive) { if (fs::is_directory(path)) { @@ -500,7 +493,7 @@ void Platform::dir_enumerate(Vector& list, const char* path, bool recu } } -void Platform::dir_explore(const char* path) +void PlatformBackend::dir_explore(const char* path) { ShellExecute(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT); } @@ -508,19 +501,19 @@ void Platform::dir_explore(const char* path) // Non-Windows File System Methods #else -bool Platform::file_exists(const char* path) +bool PlatformBackend::file_exists(const char* path) { struct stat buffer; return (stat(path, &buffer) == 0) && S_ISREG(buffer.st_mode); } -bool Platform::file_delete(const char* path) +bool PlatformBackend::file_delete(const char* path) { BLAH_ERROR("not implemented"); return false; } -bool Platform::dir_create(const char* path) +bool PlatformBackend::dir_create(const char* path) { char tmp[265]; char* p = NULL; @@ -539,19 +532,19 @@ bool Platform::dir_create(const char* path) return mkdir(tmp, S_IRWXU) == 0; } -bool Platform::dir_exists(const char* path) +bool PlatformBackend::dir_exists(const char* path) { struct stat buffer; return (stat(path, &buffer) == 0) && S_ISDIR(buffer.st_mode); } -bool Platform::dir_delete(const char* path) +bool PlatformBackend::dir_delete(const char* path) { BLAH_ERROR("not implemented"); return false; } -void Platform::dir_enumerate(Vector& list, const char* path, bool recursive) +void PlatformBackend::dir_enumerate(Vector& list, const char* path, bool recursive) { DIR* dirp = opendir(path); if (dirp != NULL) @@ -572,61 +565,61 @@ void Platform::dir_enumerate(Vector& list, const char* path, bool recu } } -void Platform::dir_explore(const char* path) +void PlatformBackend::dir_explore(const char* path) { BLAH_ERROR("'dir_explore' Not Implemented"); } #endif -bool Platform::file_open(const char* path, Platform::FileHandle* handle, FileMode mode) +bool PlatformBackend::file_open(const char* path, PlatformBackend::FileHandle* handle, FileMode mode) { const char* sdlMode = "rb"; if (mode == FileMode::Write) sdlMode = "wb"; auto ptr = SDL_RWFromFile(path, sdlMode); - *handle = (Platform::FileHandle)ptr; + *handle = (PlatformBackend::FileHandle)ptr; return ptr != nullptr; } -int64_t Platform::file_length(Platform::FileHandle stream) +int64_t PlatformBackend::file_length(PlatformBackend::FileHandle stream) { return SDL_RWsize((SDL_RWops*)stream); } -int64_t Platform::file_position(Platform::FileHandle stream) +int64_t PlatformBackend::file_position(PlatformBackend::FileHandle stream) { return SDL_RWtell((SDL_RWops*)stream); } -int64_t Platform::file_seek(Platform::FileHandle stream, int64_t seekTo) +int64_t PlatformBackend::file_seek(PlatformBackend::FileHandle stream, int64_t seekTo) { return SDL_RWseek((SDL_RWops*)stream, seekTo, RW_SEEK_SET); } -int64_t Platform::file_read(Platform::FileHandle stream, void* ptr, int64_t length) +int64_t PlatformBackend::file_read(PlatformBackend::FileHandle stream, void* ptr, int64_t length) { return SDL_RWread((SDL_RWops*)stream, ptr, sizeof(char), length); } -int64_t Platform::file_write(Platform::FileHandle stream, const void* ptr, int64_t length) +int64_t PlatformBackend::file_write(PlatformBackend::FileHandle stream, const void* ptr, int64_t length) { return SDL_RWwrite((SDL_RWops*)stream, ptr, sizeof(char), length); } -void Platform::file_close(Platform::FileHandle stream) +void PlatformBackend::file_close(PlatformBackend::FileHandle stream) { if (stream != nullptr) SDL_RWclose((SDL_RWops*)stream); } -void* Platform::gl_get_func(const char* name) +void* PlatformBackend::gl_get_func(const char* name) { return SDL_GL_GetProcAddress(name); } -void* Platform::gl_context_create() +void* PlatformBackend::gl_context_create() { void* pointer = SDL_GL_CreateContext(window); if (pointer == nullptr) @@ -634,12 +627,12 @@ void* Platform::gl_context_create() return pointer; } -void Platform::gl_context_make_current(void* context) +void PlatformBackend::gl_context_make_current(void* context) { SDL_GL_MakeCurrent(window, context); } -void Platform::gl_context_destroy(void* context) +void PlatformBackend::gl_context_destroy(void* context) { SDL_GL_DeleteContext(context); } diff --git a/public/blah/app.cpp b/public/blah/app.cpp index 8b5528c..474b15a 100644 --- a/public/blah/app.cpp +++ b/public/blah/app.cpp @@ -3,9 +3,9 @@ #include #include -#include -#include -#include +#include +#include +#include using namespace Blah; @@ -24,7 +24,6 @@ Config::Config() target_framerate = 60; max_updates = 5; - graphics = GfxAPI::Any; on_startup = nullptr; on_shutdown = nullptr; on_update = nullptr; @@ -50,54 +49,43 @@ bool App::run(const Config* c) Log::print("Starting Up ..."); - // figure out the graphics api - if (app_config.graphics == GfxAPI::Any) - { - app_config.graphics = Internal::Graphics::pick_api(); - if (app_config.graphics == GfxAPI::Any) - { - Log::error("Failed to find a supported graphics api"); - return false; - } - } - // initialize the system - if (!Internal::Platform::init(&app_config)) + if (!PlatformBackend::init(&app_config)) { - Log::error("Failed to initialize system module"); + Log::error("Failed to initialize Platform module"); return false; } // initialize graphics - if (!Internal::Graphics::init(app_config.graphics)) + if (!GraphicsBackend::init()) { - Log::error("Failed to initialize graphics module"); + Log::error("Failed to initialize Graphics module"); return false; } // input - Internal::Input::init(); + InputBackend::init(); // startup if (app_config.on_startup != nullptr) app_config.on_startup(); - uint64_t time_last = Internal::Platform::time(); + uint64_t time_last = PlatformBackend::time(); uint64_t time_accumulator = 0; // display window - Internal::Platform::ready(); + PlatformBackend::ready(); while (!app_is_exiting) { // poll system events - Internal::Platform::frame(); + PlatformBackend::frame(); // update at a fixed timerate // TODO: allow a non-fixed step update? { uint64_t time_target = (uint64_t)((1.0f / app_config.target_framerate) * 1000); - uint64_t time_curr = Internal::Platform::time(); + uint64_t time_curr = PlatformBackend::time(); uint64_t time_diff = time_curr - time_last; time_last = time_curr; time_accumulator += time_diff; @@ -105,9 +93,9 @@ bool App::run(const Config* c) // do not let us run too fast while (time_accumulator < time_target) { - Internal::Platform::sleep((int)(time_target - time_accumulator)); + PlatformBackend::sleep((int)(time_target - time_accumulator)); - time_curr = Internal::Platform::time(); + time_curr = PlatformBackend::time(); time_diff = time_curr - time_last; time_last = time_curr; time_accumulator += time_diff; @@ -139,8 +127,8 @@ bool App::run(const Config* c) Time::previous_elapsed = Time::elapsed; Time::elapsed += Time::delta; - Internal::Input::frame(); - Internal::Graphics::frame(); + InputBackend::frame(); + GraphicsBackend::frame(); if (app_config.on_update != nullptr) app_config.on_update(); @@ -149,13 +137,13 @@ bool App::run(const Config* c) // render { - Internal::Graphics::before_render(); + GraphicsBackend::before_render(); if (app_config.on_render != nullptr) app_config.on_render(); - Internal::Graphics::after_render(); - Internal::Platform::present(); + GraphicsBackend::after_render(); + PlatformBackend::present(); } } @@ -166,8 +154,8 @@ bool App::run(const Config* c) if (app_config.on_shutdown != nullptr) app_config.on_shutdown(); - Internal::Graphics::shutdown(); - Internal::Platform::shutdown(); + GraphicsBackend::shutdown(); + PlatformBackend::shutdown(); // clear static state Log::print("Exited"); @@ -198,48 +186,48 @@ const Config* App::config() const char* App::path() { - return Internal::Platform::app_path(); + return PlatformBackend::app_path(); } const char* App::user_path() { - return Internal::Platform::user_path(); + return PlatformBackend::user_path(); } int App::width() { int w, h; - Internal::Platform::get_size(&w, &h); + PlatformBackend::get_size(&w, &h); return w; } int App::height() { int w, h; - Internal::Platform::get_size(&w, &h); + PlatformBackend::get_size(&w, &h); return h; } int App::draw_width() { int w, h; - Internal::Platform::get_draw_size(&w, &h); + PlatformBackend::get_draw_size(&w, &h); return w; } int App::draw_height() { int w, h; - Internal::Platform::get_draw_size(&w, &h); + PlatformBackend::get_draw_size(&w, &h); return h; } float App::content_scale() { - return Internal::Platform::get_content_scale(); + return PlatformBackend::get_content_scale(); } void App::fullscreen(bool enabled) { - Internal::Platform::set_fullscreen(enabled); + PlatformBackend::set_fullscreen(enabled); } \ No newline at end of file diff --git a/public/blah/app.h b/public/blah/app.h index 9e5be58..77d370c 100644 --- a/public/blah/app.h +++ b/public/blah/app.h @@ -2,13 +2,6 @@ namespace Blah { - enum class GfxAPI - { - Any = -1, - OpenGL, - Count - }; - struct Config { const char* name; @@ -17,8 +10,6 @@ namespace Blah int max_updates; int target_framerate; - GfxAPI graphics; - void (*on_startup)(); void (*on_shutdown)(); void (*on_update)(); diff --git a/public/blah/drawing/batch.cpp b/public/blah/drawing/batch.cpp index 13c4c3a..8932f3b 100644 --- a/public/blah/drawing/batch.cpp +++ b/public/blah/drawing/batch.cpp @@ -135,15 +135,20 @@ Batch::~Batch() dispose(); } -void Batch::push_matrix(const Mat3x2& matrix) +void Batch::push_matrix(const Mat3x2& matrix, bool absolute) { m_matrix_stack.push_back(m_matrix); - m_matrix = matrix * m_matrix; + if (absolute) + m_matrix = matrix; + else + m_matrix = matrix * m_matrix; } -void Batch::pop_matrix() +Mat3x2 Batch::pop_matrix() { + auto was = m_matrix; m_matrix = m_matrix_stack.pop(); + return was; } void Batch::push_scissor(const Rect& scissor) @@ -212,7 +217,7 @@ void Batch::pop_color_mode() void Batch::set_texture(const TextureRef& texture) { - if (m_batch.elements > 0 && texture != m_batch.texture && m_batch.texture && m_batch.texture->is_valid()) + if (m_batch.elements > 0 && texture != m_batch.texture && m_batch.texture) { m_batches.push_back(m_batch); m_batch.offset += m_batch.elements; @@ -222,14 +227,14 @@ void Batch::set_texture(const TextureRef& texture) if (m_batch.texture != texture) { m_batch.texture = texture; - m_batch.flip_vertically = Graphics::info()->origin_bottom_left && texture && texture->is_valid() && texture->is_framebuffer(); + m_batch.flip_vertically = Graphics::info()->origin_bottom_left && texture && texture->is_framebuffer(); } } void Batch::render(const FrameBufferRef& target) { Point size; - if (!target || !target->is_valid()) + if (!target) size = Point(App::draw_width(), App::draw_height()); else size = Point(target->width(), target->height()); @@ -245,7 +250,7 @@ void Batch::render(const FrameBufferRef& target, const Mat4x4& matrix) // define defaults { - if (!m_mesh || !m_mesh->is_valid()) + if (!m_mesh) { m_mesh = Graphics::create_mesh(); m_mesh->vertex_format(attributes, 4, sizeof(Vertex)); @@ -281,7 +286,7 @@ void Batch::render(const FrameBufferRef& target, const Mat4x4& matrix) void Batch::render_single_batch(RenderCall& call, const DrawBatch& b, const Mat4x4& matrix) { call.material = b.material; - if (!call.material || !call.material->is_valid()) + if (!call.material) call.material = m_default_material; call.material->set_texture(texture_uniform, b.texture, 0); @@ -635,6 +640,11 @@ void Batch::semi_circle_line(Vec2 center, float start_radians, float end_radians } void Batch::circle(const Vec2 center, float radius, int steps, Color color) +{ + circle(center, radius, steps, color, color); +} + +void Batch::circle(const Vec2 center, float radius, int steps, Color center_color, Color outer_color) { Vec2 last = Vec2(center.x + radius, center.y); @@ -643,7 +653,7 @@ void Batch::circle(const Vec2 center, float radius, int steps, Color color) const auto radians = (i / (float)steps) * Calc::TAU; const auto next = Vec2(center.x + Calc::cos(radians) * radius, center.y + Calc::sin(radians) * radius); - tri(last, next, center, color); + tri(last, next, center, outer_color, outer_color, center_color); last = next; } @@ -761,7 +771,7 @@ void Batch::tex() void Batch::tex(const Subtexture& sub, const Vec2& pos, Color color) { - if (!sub.texture || !sub.texture->is_valid()) + if (!sub.texture) { PUSH_QUAD( pos.x + sub.draw_coords[0].x, pos.y + sub.draw_coords[0].y, @@ -794,7 +804,7 @@ void Batch::tex(const Subtexture& sub, const Vec2& pos, const Vec2& origin, cons { push_matrix(Mat3x2::create_transform(pos, origin, scale, rotation)); - if (!sub.texture || !sub.texture->is_valid()) + if (!sub.texture) { PUSH_QUAD( sub.draw_coords[0].x, sub.draw_coords[0].y, diff --git a/public/blah/drawing/batch.h b/public/blah/drawing/batch.h index 990407b..8efec60 100644 --- a/public/blah/drawing/batch.h +++ b/public/blah/drawing/batch.h @@ -44,8 +44,8 @@ namespace Blah Batch& operator=(const Batch& other) = delete; ~Batch(); - void push_matrix(const Mat3x2& matrix); - void pop_matrix(); + void push_matrix(const Mat3x2& matrix, bool absolute = false); + Mat3x2 pop_matrix(); void push_scissor(const Rect& scissor); void pop_scissor(); void push_blend(const BlendMode& blend); @@ -90,6 +90,7 @@ namespace Blah void semi_circle_line(Vec2 center, float start_radians, float end_radians, float radius, int steps, float t, Color color); void circle(const Vec2 center, float radius, int steps, Color color); + void circle(const Vec2 center, float radius, int steps, Color center_color, Color outer_color); void circle_line(const Vec2 center, float raidus, float t, int steps, Color color); void quad(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec2& pos3, Color color); diff --git a/public/blah/drawing/subtexture.cpp b/public/blah/drawing/subtexture.cpp index f148e7a..0d4d3ef 100644 --- a/public/blah/drawing/subtexture.cpp +++ b/public/blah/drawing/subtexture.cpp @@ -24,7 +24,7 @@ void Subtexture::update() draw_coords[3].x = -frame.x; draw_coords[3].y = -frame.y + source.h; - if (texture && texture->is_valid()) + if (texture) { float uvx = 1.0f / (float)texture->width(); float uvy = 1.0f / (float)texture->height(); diff --git a/public/blah/filesystem.cpp b/public/blah/filesystem.cpp index 2aef2b2..e6eb4ad 100644 --- a/public/blah/filesystem.cpp +++ b/public/blah/filesystem.cpp @@ -1,31 +1,31 @@ #include -#include +#include using namespace Blah; bool File::exists(const FilePath& path) { - return Internal::Platform::file_exists(path.cstr()); + return PlatformBackend::file_exists(path.cstr()); } bool File::remove(const FilePath& path) { - return Internal::Platform::file_delete(path.cstr()); + return PlatformBackend::file_delete(path.cstr()); } bool Directory::create(const FilePath& path) { - return Internal::Platform::dir_create(path.cstr()); + return PlatformBackend::dir_create(path.cstr()); } bool Directory::exists(const FilePath& path) { - return Internal::Platform::dir_exists(path.cstr()); + return PlatformBackend::dir_exists(path.cstr()); } bool Directory::remove(const FilePath& path) { - return Internal::Platform::dir_delete(path.cstr()); + return PlatformBackend::dir_delete(path.cstr()); } Vector Directory::enumerate(const FilePath& path, bool recursive) @@ -33,7 +33,7 @@ Vector Directory::enumerate(const FilePath& path, bool recursive) Vector list; // get files - Internal::Platform::dir_enumerate(list, path.cstr(), recursive); + PlatformBackend::dir_enumerate(list, path.cstr(), recursive); // normalize path names for (auto& it : list) @@ -44,7 +44,7 @@ Vector Directory::enumerate(const FilePath& path, bool recursive) void Directory::explore(const FilePath& path) { - Internal::Platform::dir_explore(path); + PlatformBackend::dir_explore(path); } FilePath Path::get_file_name(const FilePath& path) diff --git a/public/blah/graphics/framebuffer.h b/public/blah/graphics/framebuffer.h index dddc7cd..05cfd42 100644 --- a/public/blah/graphics/framebuffer.h +++ b/public/blah/graphics/framebuffer.h @@ -19,17 +19,17 @@ namespace Blah // Gets the list of Attachments from the FrameBuffer virtual const Attachments& attachments() const = 0; + // Gets the Attachment at a given index from the FrameBuffer + virtual TextureRef& attachment(int index) = 0; + + // Gets the Attachment at a given index from the FrameBuffer + virtual const TextureRef& attachment(int index) const = 0; + // Gets the width of the FrameBuffer virtual int width() const = 0; // Gets the height of the FrameBuffer virtual int height() const = 0; - - // Returns true if the FrameBuffer is valid - virtual bool is_valid() const = 0; - - // Destroys the given FrameBuffer - virtual void dispose() = 0; }; typedef std::shared_ptr FrameBufferRef; diff --git a/public/blah/graphics/graphics.cpp b/public/blah/graphics/graphics.cpp index 36c3b7b..e2c862a 100644 --- a/public/blah/graphics/graphics.cpp +++ b/public/blah/graphics/graphics.cpp @@ -5,27 +5,12 @@ #include #include #include -#include +#include #include #include using namespace Blah; -namespace -{ - // active graphics device - Internal::GraphicsDevice* device; - - // active graphics device info - Internal::GraphicsDeviceInfo* device_info; - - // list of possible device info - Internal::GraphicsDeviceInfo* device_options[] = - { - &Internal::OpenGL_DeviceInfo - }; -} - const BlendMode BlendMode::Normal = BlendMode( BlendOp::Add, BlendFactor::One, @@ -37,74 +22,25 @@ const BlendMode BlendMode::Normal = BlendMode( 0xffffffff ); -GfxAPI Internal::Graphics::pick_api() -{ - for (int i = 0; i < (int)GfxAPI::Count; i++) - { - if (device_options[i]->supported()) - return device_options[i]->api; - } - - return GfxAPI::Any; -} - -bool Internal::Graphics::init(GfxAPI api) -{ - for (int i = 0; i < (int)GfxAPI::Count; i++) - { - if (device_options[i]->api == api) - { - device_info = device_options[i]; - device = device_info->create(); - if (device != nullptr) - { - device->startup(); - if (device->valid) - break; - - device_info->destroy(device); - device = nullptr; - } - } - } - - return device != nullptr && device->valid; -} +const BlendMode BlendMode::Subtract = BlendMode( + BlendOp::ReverseSubtract, + BlendFactor::One, + BlendFactor::One, + BlendOp::Add, + BlendFactor::One, + BlendFactor::One, + BlendMask::RGBA, + 0xffffffff +); const GraphicsInfo* Graphics::info() { - if (device == nullptr || !device->valid) - return nullptr; - return &device->info; + return GraphicsBackend::info(); } -void Internal::Graphics::shutdown() +GraphicsRenderer Graphics::renderer() { - if (device != nullptr && device_info != nullptr) - { - device->shutdown(); - device_info->destroy(device); - device = nullptr; - device_info = nullptr; - } -} - -void Internal::Graphics::frame() -{ - if (device != nullptr && device->valid) - device->update(); -} - -void Internal::Graphics::before_render() -{ - if (device != nullptr && device->valid) - device->before_render(); -} - -void Internal::Graphics::after_render() -{ - if (device != nullptr && device->valid) - device->after_render(); + return GraphicsBackend::renderer(); } TextureRef Graphics::create_texture(const Image& image) @@ -125,9 +61,8 @@ TextureRef Graphics::create_texture(int width, int height, TextureFormat format) { BLAH_ASSERT(width > 0 && height > 0, "Texture width and height must be larger than 0"); BLAH_ASSERT((int)format > (int)TextureFormat::None && (int)format < (int)TextureFormat::Count, "Invalid texture format"); - BLAH_ASSERT(device != nullptr && device->valid, "The graphics device has not been created"); - return device->create_texture(width, height, TextureFilter::Linear, TextureWrap::Repeat, TextureWrap::Repeat, format); + return GraphicsBackend::create_texture(width, height, TextureFilter::Linear, TextureWrap::Repeat, TextureWrap::Repeat, format); } TextureRef Graphics::create_texture(Stream& stream) @@ -171,31 +106,27 @@ FrameBufferRef Graphics::create_framebuffer(int width, int height, const Texture BLAH_ASSERT(attachment_count > 0, "At least one attachment must be provided"); for (int i = 0; i < attachment_count; i++) BLAH_ASSERT((int)attachments[i] > (int)TextureFormat::None && (int)attachments[i] < (int)TextureFormat::Count, "Invalid texture format"); - BLAH_ASSERT(device != nullptr && device->valid, "The graphics device has not been created"); - return device->create_framebuffer(width, height, attachments, attachment_count); + return GraphicsBackend::create_framebuffer(width, height, attachments, attachment_count); } ShaderRef Graphics::create_shader(const ShaderData* data) { - BLAH_ASSERT(device != nullptr && device->valid, "The graphics device has not been created"); - return device->create_shader(data); + return GraphicsBackend::create_shader(data); } MaterialRef Graphics::create_material(const ShaderRef& shader) { - BLAH_ASSERT(device != nullptr && device->valid, "The graphics device has not been created"); - BLAH_ASSERT(shader && shader->is_valid(), "The provided shader is invalid"); + BLAH_ASSERT(shader, "The provided shader is invalid"); // TODO: - // use a pool for Materials + // use a pool for Materials? return MaterialRef(new Material(shader)); } MeshRef Graphics::create_mesh() { - BLAH_ASSERT(device != nullptr && device->valid, "Graphics device has not been created"); - return device->create_mesh(); + return GraphicsBackend::create_mesh(); } RenderCall::RenderCall() @@ -217,36 +148,27 @@ RenderCall::RenderCall() void Graphics::render(const RenderCall& render_call) { - BLAH_ASSERT(device != nullptr && device->valid, "Graphics device has not been created"); - // Validate Material - if (!render_call.material || !render_call.material->is_valid()) + if (!render_call.material) { Log::warn("Trying to draw with an invalid Material"); return; } // Validate Shader - if (!render_call.material->shader() || !render_call.material->shader()->is_valid()) + if (!render_call.material->shader()) { Log::warn("Trying to draw with an invalid Shader"); return; } // Validate Mesh - if (!render_call.mesh || !render_call.mesh->is_valid()) + if (!render_call.mesh) { Log::warn("Trying to draw with an invalid Mesh"); return; } - // Validate FrameBuffer - if (render_call.target && !render_call.target->is_valid()) - { - Log::warn("Trying to draw with an invalid FrameBuffer"); - return; - } - // copy call RenderCall call = render_call; @@ -330,11 +252,10 @@ void Graphics::render(const RenderCall& render_call) call.scissor.h = 0; } - device->render(&call); + GraphicsBackend::render(&call); } void Graphics::clear(const FrameBufferRef& target, uint32_t rgba) { - BLAH_ASSERT(device != nullptr && device->valid, "Graphics device has not been created"); - device->clear(target, rgba); + GraphicsBackend::clear(target, rgba); } \ No newline at end of file diff --git a/public/blah/graphics/graphics.h b/public/blah/graphics/graphics.h index 1f777fb..c4a39e3 100644 --- a/public/blah/graphics/graphics.h +++ b/public/blah/graphics/graphics.h @@ -32,9 +32,17 @@ namespace Blah class Mesh; typedef std::shared_ptr MeshRef; + enum class GraphicsRenderer + { + None = -1, + OpenGL, + D3D11, + Metal, + Count + }; + struct GraphicsInfo { - GfxAPI api = GfxAPI::Any; bool instancing = false; bool origin_bottom_left = false; int max_texture_size = 0; @@ -174,6 +182,7 @@ namespace Blah inline bool operator!=(const BlendMode& rhs) const { return !(*this == rhs); } static const BlendMode Normal; + static const BlendMode Subtract; }; enum class UniformType @@ -300,6 +309,9 @@ namespace Blah // Gets graphics information from the graphics device const GraphicsInfo* info(); + // Gets the Renderer implementation type + GraphicsRenderer renderer(); + // Creates a new Texture. // If the Texture creation fails, it will return an invalid TextureRef. TextureRef create_texture(const Image& image); diff --git a/public/blah/graphics/material.cpp b/public/blah/graphics/material.cpp index b14c84f..86ee593 100644 --- a/public/blah/graphics/material.cpp +++ b/public/blah/graphics/material.cpp @@ -28,16 +28,8 @@ namespace Material::Material(const ShaderRef& shader) { + BLAH_ASSERT(shader, "Material is being created with an invalid shader"); m_shader = shader; - m_data = nullptr; - m_disposed = false; - - // invalid shader - if (!m_shader || !m_shader->is_valid()) - { - m_disposed = true; - return; - } Uniforms uniforms = shader->uniforms(); StackVector float_offsets; @@ -59,16 +51,9 @@ Material::Material(const ShaderRef& shader) float_size += calc_uniform_size(uniform); } - m_data = new float[float_size]; - memset(m_data, 0, sizeof(float) * float_size); - + m_data.expand(float_size); for (auto& it : float_offsets) - m_floats.push_back(m_data + it); -} - -Material::~Material() -{ - dispose(); + m_floats.push_back(m_data.begin() + it); } const ShaderRef Material::shader() const @@ -78,8 +63,7 @@ const ShaderRef Material::shader() const void Material::set_texture(const char* name, const TextureRef& texture, int index) { - BLAH_ASSERT(!m_disposed, "Material has been disposed"); - BLAH_ASSERT(m_shader && m_shader->is_valid(), "Material Shader is invalid"); + BLAH_ASSERT(m_shader, "Material Shader is invalid"); if (m_textures.size() > 0) { @@ -106,8 +90,7 @@ void Material::set_texture(const char* name, const TextureRef& texture, int inde TextureRef Material::get_texture(const char* name, int index) const { - BLAH_ASSERT(!m_disposed, "Material has been disposed"); - BLAH_ASSERT(m_shader && m_shader->is_valid(), "Material Shader is invalid"); + BLAH_ASSERT(m_shader, "Material Shader is invalid"); int offset = 0; for (auto& uniform : m_shader->uniforms()) @@ -129,8 +112,7 @@ TextureRef Material::get_texture(const char* name, int index) const TextureRef Material::get_texture(int slot, int index) const { - BLAH_ASSERT(!m_disposed, "Material has been disposed"); - BLAH_ASSERT(m_shader && m_shader->is_valid(), "Material Shader is invalid"); + BLAH_ASSERT(m_shader, "Material Shader is invalid"); int offset = 0; int s = 0; @@ -155,8 +137,7 @@ TextureRef Material::get_texture(int slot, int index) const void Material::set_value(const char* name, const float* value, int64_t length) { - BLAH_ASSERT(!m_disposed, "Material has been disposed"); - BLAH_ASSERT(m_shader && m_shader->is_valid(), "Material Shader is invalid"); + BLAH_ASSERT(m_shader, "Material Shader is invalid"); BLAH_ASSERT(length >= 0, "Length must be >= 0"); int index = 0; @@ -186,8 +167,7 @@ void Material::set_value(const char* name, const float* value, int64_t length) const float* Material::get_value(const char* name, int64_t* length) const { - BLAH_ASSERT(!m_disposed, "Material has been disposed"); - BLAH_ASSERT(m_shader && m_shader->is_valid(), "Material Shader is invalid"); + BLAH_ASSERT(m_shader, "Material Shader is invalid"); int index = 0; for (auto& uniform : m_shader->uniforms()) @@ -212,8 +192,7 @@ const float* Material::get_value(const char* name, int64_t* length) const const float* Material::get_value(int slot, int64_t* length) const { - BLAH_ASSERT(!m_disposed, "Material has been disposed"); - BLAH_ASSERT(m_shader && m_shader->is_valid(), "Material Shader is invalid"); + BLAH_ASSERT(m_shader, "Material Shader is invalid"); int index = 0; int s = 0; @@ -233,21 +212,7 @@ const float* Material::get_value(int slot, int64_t* length) const s++; } + Log::warn("No Uniform [%i] exists", slot); *length = 0; return nullptr; - Log::warn("No Uniform [%i] exists", slot); -} - -bool Material::is_valid() const -{ - return !m_disposed && m_shader && m_shader->is_valid(); -} - -void Material::dispose() -{ - delete[] m_data; - m_data = nullptr; - m_shader.reset(); - m_textures.clear(); - m_floats.clear(); } \ No newline at end of file diff --git a/public/blah/graphics/material.h b/public/blah/graphics/material.h index caec404..4aa80f0 100644 --- a/public/blah/graphics/material.h +++ b/public/blah/graphics/material.h @@ -10,8 +10,6 @@ namespace Blah { public: Material(const ShaderRef& shader); - ~Material(); - Material(const Material& src) = delete; Material(Material&& src) = delete; Material& operator=(const Material& src) = delete; @@ -48,18 +46,11 @@ namespace Blah // is a float2, and there are 4 elements, the length should be 8. const float* get_value(int slot, int64_t* length = nullptr) const; - // Returns true if the Material is valid - bool is_valid() const; - - // Destroys the Material - void dispose(); - private: ShaderRef m_shader; Vector m_textures; Vector m_floats; - float* m_data; - bool m_disposed; + Vector m_data; }; typedef std::shared_ptr MaterialRef; diff --git a/public/blah/graphics/mesh.h b/public/blah/graphics/mesh.h index e8296b1..b94f0a6 100644 --- a/public/blah/graphics/mesh.h +++ b/public/blah/graphics/mesh.h @@ -36,12 +36,6 @@ namespace Blah // Gets the instance count of the Mesh virtual int64_t instance_count() const = 0; - // Returns true if the Mesh is valid - virtual bool is_valid() const = 0; - - // Destroys the given Mesh - virtual void dispose() = 0; - protected: virtual void vertex_format_internal(const VertexAttribute* attributes, int count, int stride) = 0; virtual void instance_format_internal(const VertexAttribute* attributes, int count, int stride) = 0; diff --git a/public/blah/graphics/shader.h b/public/blah/graphics/shader.h index 1deeaef..8ecd1fe 100644 --- a/public/blah/graphics/shader.h +++ b/public/blah/graphics/shader.h @@ -24,12 +24,6 @@ namespace Blah // Gets a list of Shader Attributes from Shader virtual const Attributes& attributes() const = 0; - - // Returns true if the Shader is valid - virtual bool is_valid() const = 0; - - // Destroys the given Shader - virtual void dispose() = 0; }; typedef std::shared_ptr ShaderRef; diff --git a/public/blah/graphics/texture.h b/public/blah/graphics/texture.h index 197b127..ac1fb71 100644 --- a/public/blah/graphics/texture.h +++ b/public/blah/graphics/texture.h @@ -45,12 +45,6 @@ namespace Blah // Returns true if the Texture is part of a FrameBuffer virtual bool is_framebuffer() const = 0; - - // Returns true if the Texture - virtual bool is_valid() const = 0; - - // Destroys the given Texture - virtual void dispose() = 0; }; typedef std::shared_ptr TextureRef; diff --git a/public/blah/input/input.cpp b/public/blah/input/input.cpp index 5def06f..418fcc5 100644 --- a/public/blah/input/input.cpp +++ b/public/blah/input/input.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include using namespace Blah; @@ -17,7 +17,7 @@ namespace ControllerState g_empty_controller; } -void Internal::Input::init() +void InputBackend::init() { g_empty_controller.name = "Disconnected"; for (int i = 0; i < Blah::Input::max_controllers; i++) @@ -28,7 +28,7 @@ void Internal::Input::init() g_next_state = g_empty_state; } -void Internal::Input::frame() +void InputBackend::frame() { // cycle states g_last_state = g_curr_state; @@ -68,7 +68,7 @@ void Internal::Input::frame() } } -void Internal::Input::on_mouse_move(float x, float y) +void InputBackend::on_mouse_move(float x, float y) { g_next_state.mouse.position.x = x; g_next_state.mouse.position.y = y; @@ -80,13 +80,13 @@ void Internal::Input::on_mouse_move(float x, float y) g_next_state.mouse.draw_position.y = (y / (float)size.y) * draw.y; } -void Internal::Input::on_mouse_screen_move(float x, float y) +void InputBackend::on_mouse_screen_move(float x, float y) { g_next_state.mouse.screen_position.x = x; g_next_state.mouse.screen_position.y = y; } -void Internal::Input::on_mouse_down(MouseButton button) +void InputBackend::on_mouse_down(MouseButton button) { int i = (int)button; if (i >= 0 && i < Blah::Input::max_mouse_buttons) @@ -97,7 +97,7 @@ void Internal::Input::on_mouse_down(MouseButton button) } } -void Internal::Input::on_mouse_up(MouseButton button) +void InputBackend::on_mouse_up(MouseButton button) { int i = (int)button; if (i >= 0 && i < Blah::Input::max_mouse_buttons) @@ -107,7 +107,7 @@ void Internal::Input::on_mouse_up(MouseButton button) } } -void Internal::Input::on_key_down(Key key) +void InputBackend::on_key_down(Key key) { int i = (int)key; if (i >= 0 && i < Blah::Input::max_keyboard_keys) @@ -118,12 +118,12 @@ void Internal::Input::on_key_down(Key key) } } -void Internal::Input::on_mouse_wheel(Point wheel) +void InputBackend::on_mouse_wheel(Point wheel) { g_next_state.mouse.wheel = wheel; } -void Internal::Input::on_key_up(Key key) +void InputBackend::on_key_up(Key key) { int i = (int)key; if (i >= 0 && i < Blah::Input::max_keyboard_keys) @@ -133,12 +133,12 @@ void Internal::Input::on_key_up(Key key) } } -void Internal::Input::on_text_utf8(const char* text) +void InputBackend::on_text_utf8(const char* text) { strncat(g_next_state.keyboard.text, text, Blah::Input::max_text_input); } -void Internal::Input::on_controller_connect(int index, const char* name, int is_gamepad, int button_count, int axis_count) +void InputBackend::on_controller_connect(int index, const char* name, int is_gamepad, int button_count, int axis_count) { if (index < Blah::Input::max_controllers) { @@ -152,13 +152,13 @@ void Internal::Input::on_controller_connect(int index, const char* name, int is_ } } -void Internal::Input::on_controller_disconnect(int index) +void InputBackend::on_controller_disconnect(int index) { if (index < Blah::Input::max_controllers) g_next_state.controllers[index] = g_empty_controller; } -void Internal::Input::on_button_down(int index, int button) +void InputBackend::on_button_down(int index, int button) { if (index < Blah::Input::max_controllers && button < Blah::Input::max_controller_buttons && @@ -171,7 +171,7 @@ void Internal::Input::on_button_down(int index, int button) } } -void Internal::Input::on_button_up(int index, int button) +void InputBackend::on_button_up(int index, int button) { if (index < Blah::Input::max_controllers && button < Blah::Input::max_controller_buttons && @@ -183,7 +183,7 @@ void Internal::Input::on_button_up(int index, int button) } } -void Internal::Input::on_axis_move(int index, int axis, float value) +void InputBackend::on_axis_move(int index, int axis, float value) { if (index < Blah::Input::max_controllers && axis < Blah::Input::max_controller_axis && diff --git a/public/blah/streams/filestream.cpp b/public/blah/streams/filestream.cpp index c0114bd..822f7ba 100644 --- a/public/blah/streams/filestream.cpp +++ b/public/blah/streams/filestream.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -14,7 +14,7 @@ FileStream::FileStream() FileStream::FileStream(const char* path, FileMode mode) : m_mode(mode) { - if (!Internal::Platform::file_open(path, &m_handle, mode)) + if (!PlatformBackend::file_open(path, &m_handle, mode)) m_handle = nullptr; } @@ -36,7 +36,7 @@ FileStream& FileStream::operator=(FileStream&& src) noexcept FileStream::~FileStream() { if (m_handle != nullptr) - Internal::Platform::file_close(m_handle); + PlatformBackend::file_close(m_handle); } int64_t FileStream::length() const @@ -44,7 +44,7 @@ int64_t FileStream::length() const if (m_handle == nullptr) return 0; - return Internal::Platform::file_length(m_handle); + return PlatformBackend::file_length(m_handle); } int64_t FileStream::position() const @@ -52,7 +52,7 @@ int64_t FileStream::position() const if (m_handle == nullptr) return 0; - return Internal::Platform::file_position(m_handle); + return PlatformBackend::file_position(m_handle); } int64_t FileStream::seek(int64_t seek_to) @@ -60,7 +60,7 @@ int64_t FileStream::seek(int64_t seek_to) if (m_handle == nullptr) return 0; - return Internal::Platform::file_seek(m_handle, seek_to); + return PlatformBackend::file_seek(m_handle, seek_to); } int64_t FileStream::read_into(void* ptr, int64_t length) @@ -71,7 +71,7 @@ int64_t FileStream::read_into(void* ptr, int64_t length) return 0; } - return Internal::Platform::file_read(m_handle, ptr, length); + return PlatformBackend::file_read(m_handle, ptr, length); } int64_t FileStream::write_from(const void* ptr, int64_t length) @@ -85,13 +85,13 @@ int64_t FileStream::write_from(const void* ptr, int64_t length) return 0; } - return Internal::Platform::file_write(m_handle, ptr, length); + return PlatformBackend::file_write(m_handle, ptr, length); } void FileStream::close() { if (m_handle != nullptr) - Internal::Platform::file_close(m_handle); + PlatformBackend::file_close(m_handle); m_handle = nullptr; m_mode = FileMode::None; } \ No newline at end of file diff --git a/public/blah/streams/stream.cpp b/public/blah/streams/stream.cpp index 883c844..682b0a6 100644 --- a/public/blah/streams/stream.cpp +++ b/public/blah/streams/stream.cpp @@ -1,6 +1,5 @@ #include #include -#include #include using namespace Blah;