From b2f5f56063fe41adbb7c8fceddc3741e784df36c Mon Sep 17 00:00:00 2001 From: Frank DeMarco Date: Sun, 21 Jul 2019 03:13:19 -0400 Subject: [PATCH] - store video stashes in linked lists - cube face textures demo - only dispatch events to active nodes - only update animation if containing object is active --- demo/Demo.cpp | 44 ++++-- demo/Demo.hpp | 2 + demo/Makefile | 4 +- demo/config.json | 4 +- src/Animation.cpp | 2 +- src/Animation.hpp | 3 + src/Configuration.cpp | 1 + src/Delegate.cpp | 5 +- src/Delegate.hpp | 4 +- src/Display.cpp | 30 +++- src/Game.cpp | 308 +++++++++++++++++++++++------------------- src/Game.hpp | 6 +- src/Node.cpp | 5 + src/Node.hpp | 3 +- src/Recorder.cpp | 99 ++++++++------ src/Recorder.hpp | 7 +- 16 files changed, 316 insertions(+), 211 deletions(-) diff --git a/demo/Demo.cpp b/demo/Demo.cpp index d4d17f7..302955b 100644 --- a/demo/Demo.cpp +++ b/demo/Demo.cpp @@ -1,9 +1,10 @@ /*** reset, pause, auto reset, analog d-pad, gamepad config, any key, confirm exit - game, screen wipes, screen offset, screen scale, networking + game, screen wipes, screen offset, screen scale, networking, post processing :) SWEATY HANDS :) OILY SNACKS :) AND BAD HYGIENE :) *surf wizard* + *Exxiit* eXIt ***/ @@ -73,9 +74,9 @@ GLuint get_gl_texture_from_surface(SDL_Surface *surface, GLint mipmap_filter) glBindTexture(GL_TEXTURE_2D, id); GLenum format; #if SDL_BYTEORDER == SDL_BIG_ENDIAN - format = GL_RGBA; -#else format = GL_BGRA; +#else + format = GL_RGBA; #endif glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, format, GL_UNSIGNED_BYTE, surface->pixels); @@ -142,7 +143,8 @@ void Mushroom::update() Demo::Demo() { - Mix_Music *music = Mix_LoadMUS("resource/Field.mp3"); + // Mix_Music *music = Mix_LoadMUS("resource/Field.mp3"); + Mix_Music *music = Mix_LoadMUS("/home/frank/WATERMELON-clean.mp3"); Mix_PlayMusic(music, -1); load_gl_context(); delegate.subscribe(&Demo::respond, this); @@ -219,10 +221,19 @@ void Demo::load_gl_context() 100.0f); view = glm::lookAt( glm::vec3(4, 3, 3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); - SDL_Surface *surface = rotateSurface90Degrees(IMG_Load("resource/tile.png"), 2); + SDL_Surface* surface = zoomSurface( + rotateSurface90Degrees(IMG_Load("resource/tile.png"), 2), 1, -1, SMOOTHING_OFF); SDL_Log("tile.png bytes per pixel %i", surface->format->BytesPerPixel); space_texture_id = get_gl_texture_from_surface(surface, GL_LINEAR); SDL_FreeSurface(surface); + std::vector paths = sfw::glob("/home/frank/projects/public/games/rov/face03/[0-9]+\\-.+\\.png"); + for (fs::path path : paths) + { + surface = zoomSurface(rotateSurface90Degrees(IMG_Load(path.c_str()), 2), -1, 1, SMOOTHING_OFF); + SDL_Log("loading %s", path.c_str()); + face_ids.push_back(get_gl_texture_from_surface(surface, GL_LINEAR)); + SDL_FreeSurface(surface); + } std::array framerate_indicator_uv = { { {0, 1}, {1, 1}, {0, 0}, @@ -296,8 +307,8 @@ void Demo::load_gl_context() link_shader(flat_program); mvp_id = glGetUniformLocation(world_program, "MVP"); // GLuint sampler_uniform_id = glGetUniformLocation(world_program, "myTextureSampler"); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, space_texture_id); + // glActiveTexture(GL_TEXTURE0); + // glBindTexture(GL_TEXTURE_2D, space_texture_id); // glUniform1i(sampler_uniform_id, 0); glDepthFunc(GL_LESS); frame_count_timestamp = SDL_GetTicks(); @@ -399,7 +410,9 @@ void Demo::update() { // glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); // glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), diamond, GL_STATIC_DRAW); - glClearColor(.7, .7, .5, 1); + // glColorMask(false, false, false, true); + // glClearColor(.7, .7, .5, 1); + glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glUseProgram(flat_program); @@ -417,18 +430,27 @@ void Demo::update() glDrawArrays(GL_TRIANGLES, 42, 6); } // printf("%s\n", glm::to_string(model).c_str()); - model = glm::rotate(model, .0005f * frame_length, glm::vec3(0.0f, 1.0f, 0.0f)); + float rotation = .0005f * frame_length; + model = glm::rotate(model, rotation, glm::vec3(0.0f, 1.0f, 0.0f)); mvp = projection * view * model; glEnable(GL_DEPTH_TEST); glUseProgram(world_program); glUniformMatrix4fv(mvp_id, 1, GL_FALSE, &mvp[0][0]); - glBindTexture(GL_TEXTURE_2D, space_texture_id); glEnableVertexAttribArray(1); glDisableVertexAttribArray(2); glVertexAttrib3f(2, 1, 1, 1); - glDrawArrays(GL_TRIANGLES, 0, 36); + for (int ii = 0; ii < 6; ii++) + { + glBindTexture(GL_TEXTURE_2D, face_ids[ii]); + glDrawArrays(GL_TRIANGLES, ii * 6, 6); + } //glFlush(); SDL_GL_SwapWindow(window); + // if (amount_rotated < 3.14f * 2) + // { + // recorder.capture_screen(); + // } + amount_rotated += rotation; } else { diff --git a/demo/Demo.hpp b/demo/Demo.hpp index 704878a..bb873ef 100644 --- a/demo/Demo.hpp +++ b/demo/Demo.hpp @@ -63,6 +63,8 @@ struct Demo : Game glm::mat4 projection, view, model = glm::mat4(1.0f), mvp; Mushroom mushroom = Mushroom(this); Sprite grass = Sprite(this, "resource/Field.png"); + std::vector face_ids; + float amount_rotated; Demo(); void load_sdl_context(); diff --git a/demo/Makefile b/demo/Makefile index f864ff1..5cd6d32 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -40,8 +40,8 @@ $(SFW_SRC_DIR)Sprite.o: $(addprefix $(SFW_SRC_DIR),Game.*pp Location.*pp Node.*p $(SFW_SRC_DIR)Game.o: $(addprefix $(SFW_SRC_DIR),Sprite.*pp Configuration.*pp Delegate.*pp Display.*pp \ Recorder.*pp Node.*pp Input.*pp) $(SFW_SRC_DIR)Node.o: $(addprefix $(SFW_SRC_DIR),Game.*pp Configuration.*pp Delegate.*pp) -$(SFW_SRC_DIR)Animation.o: $(addprefix $(SFW_SRC_DIR),Timer.*pp) -$(SFW_SRC_DIR)Recorder.o: $(addprefix $(SFW_SRC_DIR),extension.*pp Node.*pp Delegate.*pp Animation.*pp) +$(SFW_SRC_DIR)Animation.o: $(addprefix $(SFW_SRC_DIR),Node.*pp Timer.*pp) +$(SFW_SRC_DIR)Recorder.o: $(addprefix $(SFW_SRC_DIR),extension.*pp Node.*pp Delegate.*pp Animation.*pp Display.*pp) $(SFW_SRC_DIR)Input.o: $(addprefix $(SFW_SRC_DIR),Delegate.*pp Node.*pp) $(SFW_SRC_DIR)Configuration.o: $(addprefix $(SFW_SRC_DIR),Node.*pp) $(SFW_SRC_DIR)Delegate.o: $(addprefix $(SFW_SRC_DIR),Node.*pp) diff --git a/demo/config.json b/demo/config.json index 031c4ad..4f72cc3 100644 --- a/demo/config.json +++ b/demo/config.json @@ -20,7 +20,9 @@ }, "recording": { + "enabled": true, "write-mp4": true, - "video-frame-length": 33.334 + "video-frame-length": 16.667, + "max-video-memory": 2000 } } diff --git a/src/Animation.cpp b/src/Animation.cpp index 59dcda0..a3b0c8c 100644 --- a/src/Animation.cpp +++ b/src/Animation.cpp @@ -47,7 +47,7 @@ void Animation::reset() void Animation::update() { timer.update(); - if (playing and not paused) + if (playing and not paused and containing_object->is_active()) { if (delay > 0) { diff --git a/src/Animation.hpp b/src/Animation.hpp index df87a61..520d435 100644 --- a/src/Animation.hpp +++ b/src/Animation.hpp @@ -5,6 +5,7 @@ #include #include +#include "Node.hpp" #include "Timer.hpp" typedef std::function callback; @@ -16,6 +17,7 @@ struct Animation int previous_step_time = 0, overflow = 0, count = 0; float delay = 0, frame_length; callback step; + Node* containing_object; Timer timer = Timer(); template @@ -23,6 +25,7 @@ struct Animation { step = std::bind(f, o); timer.toggle(false); + containing_object = static_cast(o); } void set_frame_length(float); diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 29b1624..d994e3e 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -34,6 +34,7 @@ void Configuration::set_defaults() {"fps", 60} }; sys_config["recording"] = { + {"enabled", false}, {"screenshot-prefix", "screenshot-"}, {"screenshot-extension", ".png"}, {"screenshot-zfill", 5}, diff --git a/src/Delegate.cpp b/src/Delegate.cpp index f23ef52..17b8f61 100644 --- a/src/Delegate.cpp +++ b/src/Delegate.cpp @@ -24,7 +24,10 @@ void Delegate::dispatch() { for (Subscriber s : iter->second) { - s.f(event); + if (s.o->is_active()) + { + s.f(event); + } } } } diff --git a/src/Delegate.hpp b/src/Delegate.hpp index b668896..12a2302 100644 --- a/src/Delegate.hpp +++ b/src/Delegate.hpp @@ -15,7 +15,7 @@ struct Subscriber { std::function f; - void* o; + Node* o; }; struct Delegate : Node @@ -34,7 +34,7 @@ struct Delegate : Node template void subscribe(void(T::*f)(SDL_Event&), T* o, int type = command_event_type) { - add_subscriber({std::bind(f, o, std::placeholders::_1), o}, type); + add_subscriber({std::bind(f, o, std::placeholders::_1), static_cast(o)}, type); } template diff --git a/src/Display.cpp b/src/Display.cpp index b39c580..77adf86 100644 --- a/src/Display.cpp +++ b/src/Display.cpp @@ -16,19 +16,25 @@ void Display::get_screen_pixels(unsigned char* pixels, int w, int h, int x, int { GLenum format; #if SDL_BYTEORDER == SDL_BIG_ENDIAN - format = GL_RGBA; -#else format = GL_BGRA; +#else + format = GL_RGBA; #endif + glReadBuffer(GL_FRONT); glReadPixels(x, y, w, h, format, GL_UNSIGNED_BYTE, pixels); + // SDL_Log("(%i, %i, %i) (%i, %i, %i, %i)", + // glCheckFramebufferStatus(GL_FRAMEBUFFER), + // glCheckFramebufferStatus(GL_READ_FRAMEBUFFER), + // glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER), + // pixels[0], pixels[1], pixels[2], pixels[3]); } else { Uint32 format; #if SDL_BYTEORDER == SDL_BIG_ENDIAN - format = SDL_PIXELFORMAT_ABGR8888; -#else format = SDL_PIXELFORMAT_ARGB8888; +#else + format = SDL_PIXELFORMAT_ABGR8888; #endif SDL_RenderReadPixels( get_root()->renderer, NULL, format, pixels, bpp / 8 * w); @@ -51,16 +57,28 @@ SDL_Surface* Display::get_screen_surface_from_pixels( { glm::ivec2 size = get_window_size(); SDL_Surface* surface; + Uint32 rmask, gmask, bmask, amask; +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + rmask = 0xff000000; + gmask = 0x00ff0000; + bmask = 0x0000ff00; + amask = 0x000000ff; +#else + rmask = 0x000000ff; + gmask = 0x0000ff00; + bmask = 0x00ff0000; + amask = 0xff000000; +#endif if (flip) { SDL_Surface* pixel_surface = SDL_CreateRGBSurfaceFrom( - pixels, size.x, size.y, bpp, bpp / 8 * size.x, 0, 0, 0, 0); + pixels, size.x, size.y, bpp, bpp / 8 * size.x, rmask, gmask, bmask, amask); surface = zoomSurface(pixel_surface, 1, -1, SMOOTHING_OFF); SDL_FreeSurface(pixel_surface); } else { - surface = SDL_CreateRGBSurface(0, size.x, size.y, bpp, 0, 0, 0, 0); + surface = SDL_CreateRGBSurface(0, size.x, size.y, bpp, rmask, gmask, bmask, amask); std::memcpy(surface->pixels, pixels, bpp / 8 * size.x * size.y); } return surface; diff --git a/src/Game.cpp b/src/Game.cpp index f4388dc..1723e09 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -13,7 +13,7 @@ Game::Game() delegate.subscribe(&Game::handle_quit_event, this, SDL_QUIT); SDL_Log("GLEW %s", glewGetString(GLEW_VERSION)); putenv("SDL_VIDEO_X11_LEGACY_FULLSCREEN=0"); - putenv("SDL_VIDEO_CENTERED=0"); + // putenv("SDL_VIDEO_CENTERED=0"); SDL_version version; SDL_GetVersion(&version); SDL_Log("SDL %d.%d.%d", version.major, version.minor, version.patch); @@ -31,9 +31,14 @@ Game::Game() // SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); print_gl_attributes(); std::vector window_size = get_configuration()["display"]["dimensions"]; - window = SDL_CreateWindow("TARE control", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + window = SDL_CreateWindow("TARE control", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_size[0], window_size[1], SDL_WINDOW_OPENGL); if (window == NULL) { @@ -74,9 +79,9 @@ Game::Game() SDL_GetAudioDeviceName(ii, SDL_TRUE)); } #if SDL_BYTEORDER == SDL_BIG_ENDIAN - SDL_Log("big endian, using GL_RGBA and SDL_PIXELFORMAT_ABGR8888"); + SDL_Log("big endian"); #else - SDL_Log("little endian, using GL_BGRA and SDL_PIXELFORMAT_ARGB8888"); + SDL_Log("little endian"); #endif last_frame_timestamp = SDL_GetTicks(); } @@ -133,6 +138,7 @@ void Game::load_sdl_context() info.max_texture_height); } is_gl_context = false; + log_display_mode(); } void Game::load_gl_context() @@ -162,6 +168,7 @@ void Game::load_gl_context() glGetString(GL_VERSION), glGetString(GL_RENDERER), glGetString(GL_SHADING_LANGUAGE_VERSION)); is_gl_context = true; + log_display_mode(); } GLuint Game::create_gl_texture() @@ -172,7 +179,7 @@ GLuint Game::create_gl_texture() return id; } -bool Game::log_gl_errors() +bool Game::log_gl_errors(std::string suffix) { GLenum error; bool error_logged = false; @@ -184,186 +191,213 @@ bool Game::log_gl_errors() SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, "GL_INVALID_ENUM, an unacceptable value is specified for an " - "enumerated argument"); + "enumerated argument %s", suffix.c_str()); } else if (error == GL_INVALID_VALUE) { SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, - "GL_INVALID_VALUE, a numeric argument is out of range"); + "GL_INVALID_VALUE, a numeric argument is out of range %s", suffix.c_str()); } else if (error == GL_INVALID_OPERATION) { SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, "GL_INVALID_OPERATION, the specified operation is not allowed " - "in the current state"); + "in the current state %s", suffix.c_str()); } else if (error == GL_INVALID_FRAMEBUFFER_OPERATION) { SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, "GL_INVALID_FRAMEBUFFER_OPERATION, the framebuffer object is " - "not complete"); + "not complete %s", suffix.c_str()); } else if (error == GL_OUT_OF_MEMORY) { SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, "GL_OUT_OF_MEMORY, there is not enough memory left to execute " - "the command"); + "the command %s", suffix.c_str()); } else if (error == GL_STACK_UNDERFLOW) { SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, "GL_STACK_UNDERFLOW, an attempt has been made to perform an " - "operation that would cause an internal stack to underflow."); + "operation that would cause an internal stack to underflow. %s", suffix.c_str()); } else if (error == GL_STACK_OVERFLOW) { SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, "GL_STACK_OVERFLOW, an attempt has been made to perform an " - "operation that would cause an internal stack to overflow."); + "operation that would cause an internal stack to overflow. %s", suffix.c_str()); } } return error_logged; } +// from SDL_GetCurrentDisplayMode.html +void Game::log_display_mode() +{ + SDL_DisplayMode current; + for (int ii = 0; ii < SDL_GetNumVideoDisplays(); ii++) + { + int mode = SDL_GetCurrentDisplayMode(ii, ¤t); + if (mode != 0) + { + SDL_Log("Could not get display mode for video display #%d: %s", ii, + SDL_GetError()); + } + else + { + SDL_Log("Display #%d: display mode is %dx%dpx @ %dhz %s", ii, + current.w, current.h, current.refresh_rate, + get_pixel_format_string(current.format).c_str()); + } + } +} + void Game::log_surface_format(SDL_Surface* surface, std::string preface) { SDL_PixelFormat* format = surface->format; - std::string pixel_format; - if (format->format == SDL_PIXELFORMAT_UNKNOWN) - { - pixel_format = "SDL_PIXELFORMAT_UNKNOWN"; - } - else if (format->format == SDL_PIXELFORMAT_INDEX1LSB) - { - pixel_format = "SDL_PIXELFORMAT_INDEX1LSB"; - } - else if (format->format == SDL_PIXELFORMAT_INDEX1MSB) - { - pixel_format = "SDL_PIXELFORMAT_INDEX1MSB"; - } - else if (format->format == SDL_PIXELFORMAT_INDEX4LSB) - { - pixel_format = "SDL_PIXELFORMAT_INDEX4LSB"; - } - else if (format->format == SDL_PIXELFORMAT_INDEX4MSB) - { - pixel_format = "SDL_PIXELFORMAT_INDEX4MSB"; - } - else if (format->format == SDL_PIXELFORMAT_INDEX8) - { - pixel_format = "SDL_PIXELFORMAT_INDEX8"; - } - else if (format->format == SDL_PIXELFORMAT_RGB332) - { - pixel_format = "SDL_PIXELFORMAT_RGB332"; - } - else if (format->format == SDL_PIXELFORMAT_RGB444) - { - pixel_format = "SDL_PIXELFORMAT_RGB444"; - } - else if (format->format == SDL_PIXELFORMAT_RGB555) - { - pixel_format = "SDL_PIXELFORMAT_RGB555"; - } - else if (format->format == SDL_PIXELFORMAT_BGR555) - { - pixel_format = "SDL_PIXELFORMAT_BGR555"; - } - else if (format->format == SDL_PIXELFORMAT_ARGB4444) - { - pixel_format = "SDL_PIXELFORMAT_ARGB4444"; - } - else if (format->format == SDL_PIXELFORMAT_RGBA4444) - { - pixel_format = "SDL_PIXELFORMAT_RGBA4444"; - } - else if (format->format == SDL_PIXELFORMAT_ABGR4444) - { - pixel_format = "SDL_PIXELFORMAT_ABGR4444"; - } - else if (format->format == SDL_PIXELFORMAT_BGRA4444) - { - pixel_format = "SDL_PIXELFORMAT_BGRA4444"; - } - else if (format->format == SDL_PIXELFORMAT_ARGB1555) - { - pixel_format = "SDL_PIXELFORMAT_ARGB1555"; - } - else if (format->format == SDL_PIXELFORMAT_RGBA5551) - { - pixel_format = "SDL_PIXELFORMAT_RGBA5551"; - } - else if (format->format == SDL_PIXELFORMAT_ABGR1555) - { - pixel_format = "SDL_PIXELFORMAT_ABGR1555"; - } - else if (format->format == SDL_PIXELFORMAT_BGRA5551) - { - pixel_format = "SDL_PIXELFORMAT_BGRA5551"; - } - else if (format->format == SDL_PIXELFORMAT_RGB565) - { - pixel_format = "SDL_PIXELFORMAT_RGB565"; - } - else if (format->format == SDL_PIXELFORMAT_BGR565) - { - pixel_format = "SDL_PIXELFORMAT_BGR565"; - } - else if (format->format == SDL_PIXELFORMAT_RGB24) - { - pixel_format = "SDL_PIXELFORMAT_RGB24"; - } - else if (format->format == SDL_PIXELFORMAT_BGR24) - { - pixel_format = "SDL_PIXELFORMAT_BGR24"; - } - else if (format->format == SDL_PIXELFORMAT_RGB888) - { - pixel_format = "SDL_PIXELFORMAT_RGB888"; - } - else if (format->format == SDL_PIXELFORMAT_RGBX8888) - { - pixel_format = "SDL_PIXELFORMAT_RGBX8888"; - } - else if (format->format == SDL_PIXELFORMAT_BGR888) - { - pixel_format = "SDL_PIXELFORMAT_BGR888"; - } - else if (format->format == SDL_PIXELFORMAT_BGRX8888) - { - pixel_format = "SDL_PIXELFORMAT_BGRX8888"; - } - else if (format->format == SDL_PIXELFORMAT_ARGB8888) - { - pixel_format = "SDL_PIXELFORMAT_ARGB8888"; - } - else if (format->format == SDL_PIXELFORMAT_RGBA8888) - { - pixel_format = "SDL_PIXELFORMAT_RGBA8888"; - } - else if (format->format == SDL_PIXELFORMAT_ABGR8888) - { - pixel_format = "SDL_PIXELFORMAT_ABGR8888"; - } - else if (format->format == SDL_PIXELFORMAT_BGRA8888) - { - pixel_format = "SDL_PIXELFORMAT_BGRA8888"; - } - else if (format->format == SDL_PIXELFORMAT_ARGB2101010) - { - pixel_format = "SDL_PIXELFORMAT_ARGB2101010"; - } + std::string pixel_format = get_pixel_format_string(format->format); SDL_Log("%s bpp: %i mask: %i %i %i %i format: %s", preface.c_str(), format->BytesPerPixel, format->Rmask, format->Gmask, format->Bmask, format->Amask, pixel_format.c_str()); } +std::string Game::get_pixel_format_string(Uint32 format) +{ + std::string pixel_format; + if (format == SDL_PIXELFORMAT_UNKNOWN) + { + pixel_format = "SDL_PIXELFORMAT_UNKNOWN"; + } + else if (format == SDL_PIXELFORMAT_INDEX1LSB) + { + pixel_format = "SDL_PIXELFORMAT_INDEX1LSB"; + } + else if (format == SDL_PIXELFORMAT_INDEX1MSB) + { + pixel_format = "SDL_PIXELFORMAT_INDEX1MSB"; + } + else if (format == SDL_PIXELFORMAT_INDEX4LSB) + { + pixel_format = "SDL_PIXELFORMAT_INDEX4LSB"; + } + else if (format == SDL_PIXELFORMAT_INDEX4MSB) + { + pixel_format = "SDL_PIXELFORMAT_INDEX4MSB"; + } + else if (format == SDL_PIXELFORMAT_INDEX8) + { + pixel_format = "SDL_PIXELFORMAT_INDEX8"; + } + else if (format == SDL_PIXELFORMAT_RGB332) + { + pixel_format = "SDL_PIXELFORMAT_RGB332"; + } + else if (format == SDL_PIXELFORMAT_RGB444) + { + pixel_format = "SDL_PIXELFORMAT_RGB444"; + } + else if (format == SDL_PIXELFORMAT_RGB555) + { + pixel_format = "SDL_PIXELFORMAT_RGB555"; + } + else if (format == SDL_PIXELFORMAT_BGR555) + { + pixel_format = "SDL_PIXELFORMAT_BGR555"; + } + else if (format == SDL_PIXELFORMAT_ARGB4444) + { + pixel_format = "SDL_PIXELFORMAT_ARGB4444"; + } + else if (format == SDL_PIXELFORMAT_RGBA4444) + { + pixel_format = "SDL_PIXELFORMAT_RGBA4444"; + } + else if (format == SDL_PIXELFORMAT_ABGR4444) + { + pixel_format = "SDL_PIXELFORMAT_ABGR4444"; + } + else if (format == SDL_PIXELFORMAT_BGRA4444) + { + pixel_format = "SDL_PIXELFORMAT_BGRA4444"; + } + else if (format == SDL_PIXELFORMAT_ARGB1555) + { + pixel_format = "SDL_PIXELFORMAT_ARGB1555"; + } + else if (format == SDL_PIXELFORMAT_RGBA5551) + { + pixel_format = "SDL_PIXELFORMAT_RGBA5551"; + } + else if (format == SDL_PIXELFORMAT_ABGR1555) + { + pixel_format = "SDL_PIXELFORMAT_ABGR1555"; + } + else if (format == SDL_PIXELFORMAT_BGRA5551) + { + pixel_format = "SDL_PIXELFORMAT_BGRA5551"; + } + else if (format == SDL_PIXELFORMAT_RGB565) + { + pixel_format = "SDL_PIXELFORMAT_RGB565"; + } + else if (format == SDL_PIXELFORMAT_BGR565) + { + pixel_format = "SDL_PIXELFORMAT_BGR565"; + } + else if (format == SDL_PIXELFORMAT_RGB24) + { + pixel_format = "SDL_PIXELFORMAT_RGB24"; + } + else if (format == SDL_PIXELFORMAT_BGR24) + { + pixel_format = "SDL_PIXELFORMAT_BGR24"; + } + else if (format == SDL_PIXELFORMAT_RGB888) + { + pixel_format = "SDL_PIXELFORMAT_RGB888"; + } + else if (format == SDL_PIXELFORMAT_RGBX8888) + { + pixel_format = "SDL_PIXELFORMAT_RGBX8888"; + } + else if (format == SDL_PIXELFORMAT_BGR888) + { + pixel_format = "SDL_PIXELFORMAT_BGR888"; + } + else if (format == SDL_PIXELFORMAT_BGRX8888) + { + pixel_format = "SDL_PIXELFORMAT_BGRX8888"; + } + else if (format == SDL_PIXELFORMAT_ARGB8888) + { + pixel_format = "SDL_PIXELFORMAT_ARGB8888"; + } + else if (format == SDL_PIXELFORMAT_RGBA8888) + { + pixel_format = "SDL_PIXELFORMAT_RGBA8888"; + } + else if (format == SDL_PIXELFORMAT_ABGR8888) + { + pixel_format = "SDL_PIXELFORMAT_ABGR8888"; + } + else if (format == SDL_PIXELFORMAT_BGRA8888) + { + pixel_format = "SDL_PIXELFORMAT_BGRA8888"; + } + else if (format == SDL_PIXELFORMAT_ARGB2101010) + { + pixel_format = "SDL_PIXELFORMAT_ARGB2101010"; + } + return pixel_format; +} + void Game::run() { while (not done) diff --git a/src/Game.hpp b/src/Game.hpp index 09e858b..0935d40 100644 --- a/src/Game.hpp +++ b/src/Game.hpp @@ -46,7 +46,7 @@ struct Game : Node int frame_time_overflow = 0, framerate, ticks, last_frame_timestamp, frame_count_timestamp, last_frame_length; float frame_length; - bool done = false, show_framerate = false, is_gl_context = true; + bool done = false, show_framerate = true, is_gl_context = true; Configuration configuration = Configuration(this); Delegate delegate = Delegate(this); Display display = Display(this); @@ -61,8 +61,10 @@ struct Game : Node void load_sdl_context(); void load_gl_context(); GLuint create_gl_texture(); - bool log_gl_errors(); + bool log_gl_errors(std::string); + void log_display_mode(); void log_surface_format(SDL_Surface*, std::string = "surface"); + std::string get_pixel_format_string(Uint32); void run(); void flag_to_end(); virtual void update() {}; diff --git a/src/Node.cpp b/src/Node.cpp index 9c67ccf..883c12d 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -32,6 +32,11 @@ void Node::deactivate() active = false; } +bool Node::is_active() +{ + return active; +} + nlohmann::json& Node::get_configuration() { return get_root()->configuration.config; diff --git a/src/Node.hpp b/src/Node.hpp index 6fe7ce6..645731c 100644 --- a/src/Node.hpp +++ b/src/Node.hpp @@ -20,10 +20,11 @@ struct Node bool active = false; Node(); - Node(Node*, bool = false); + Node(Node*, bool = true); virtual ~Node(); void activate(); void deactivate(); + bool is_active(); Game* get_root(); nlohmann::json& get_configuration(); Delegate& get_delegate(); diff --git a/src/Recorder.cpp b/src/Recorder.cpp index 3151ef4..425a0ae 100644 --- a/src/Recorder.cpp +++ b/src/Recorder.cpp @@ -7,7 +7,10 @@ Recorder::Recorder(Node* parent) : Node(parent) get_delegate().subscribe(&Recorder::respond, this); animation.play(); Mix_SetPostMix(&process_audio, this); - video_stashes.reserve(100); + if (not get_configuration()["recording"]["enabled"]) + { + deactivate(); + } } float Recorder::get_frame_length() @@ -87,9 +90,7 @@ void Recorder::grab_stash() void Recorder::write_most_recent_frames() { make_directory(); - write_stash_frames(&most_recent_stash.pixel_buffers, - &most_recent_stash.flipped, - most_recent_stash.frame_offset); + write_stash_frames(&most_recent_stash); open_audio_file(); while (not most_recent_stash.audio_buffers.empty()) { @@ -136,7 +137,7 @@ void Recorder::open_audio_file() void Recorder::add_frame() { glm::ivec2 size = get_display().get_window_size(); - int bytes = 32 / 8 * size.x * size.y; + int bytes = Display::bpp / 8 * size.x * size.y; unsigned char* pixels = new unsigned char[bytes]; get_display().get_screen_pixels(pixels, size.x, size.y); int max_length = get_configuration()["recording"]["max-stash-length"]; @@ -157,14 +158,29 @@ void Recorder::add_frame() video_stashes.back().flipped.push_back(get_root()->is_gl_context); if (video_stashes.back().pixel_buffers.size() * get_frame_length() > max_length) { - std::function*, std::vector*, int)> f = - std::bind(&Recorder::write_stash_frames, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3); - std::thread writing(f, &video_stashes.back().pixel_buffers, - &video_stashes.back().flipped, - video_stashes.back().frame_offset); + std::function f = + std::bind(&Recorder::write_stash_frames, this, std::placeholders::_1); + std::thread writing(f, &video_stashes.back()); writing.detach(); + // int frame_offset = video_stashes.back().frame_offset; + // std::vector pixel_buffers = video_stashes.back().pixel_buffers; + // std::vector flipped = video_stashes.back().flipped; + // for (int ii = frame_offset; ii < pixel_buffers.size() + frame_offset; ii++) + // { + // SDL_Surface* frame = get_display().get_screen_surface_from_pixels( + // pixel_buffers[ii - frame_offset], flipped[ii - frame_offset]); + // std::stringstream name; + // name << sfw::pad(ii, 5) << ".png"; + // fs::path path = current_video_directory / name.str(); + // SDL_Log("%s (%i, %i) (%i, %i, %i, %i)", path.c_str(), frame->w, frame->h, + // ((unsigned char*) frame->pixels)[0], ((unsigned char*) frame->pixels)[1], + // ((unsigned char*) frame->pixels)[2], ((unsigned char*) frame->pixels)[3]); + // IMG_SavePNG(frame, path.string().c_str()); + // } + // end_recording(); + // write_stash_frames(video_stashes.back().pixel_buffers, + // video_stashes.back().flipped, + // video_stashes.back().frame_offset); video_stashes.push_back( Stash(video_stashes.back().frame_offset + video_stashes.back().pixel_buffers.size())); @@ -212,31 +228,27 @@ void Recorder::make_directory() current_video_directory = directory; } -void Recorder::write_stash_frames( - std::vector* pixel_buffers, std::vector* flipped, - int frame_offset) +void Recorder::write_stash_frames(Stash* stash) { - SDL_Log("Writing stash offset %i to %s...", frame_offset, current_video_directory.c_str()); + SDL_Log("Writing stash offset %i to %s...", stash->frame_offset, current_video_directory.c_str()); SDL_Surface* frame; GifWriter gif_writer; int gif_frame_length = get_configuration()["recording"]["gif-frame-length"]; fs::path gif_path = sfw::get_next_file_name( current_video_directory, 3, "gif-", ".gif"); float elapsed = 0, last_gif_write = 0, gif_write_overflow = 0; - SDL_Log("Pixel buffers size %zu", pixel_buffers->size()); - for (int ii = frame_offset; not pixel_buffers->empty(); ii++) + for (int ii = stash->frame_offset; not stash->pixel_buffers.empty(); ii++) { frame = get_display().get_screen_surface_from_pixels( - pixel_buffers->front(), flipped->front()); - get_root()->log_surface_format(frame, "got"); + stash->pixel_buffers.front(), stash->flipped.front()); std::stringstream name; name << sfw::pad(ii, 5) << ".png"; fs::path path = current_video_directory / name.str(); IMG_SavePNG(frame, path.string().c_str()); - if (ii == frame_offset or + if (ii == stash->frame_offset or elapsed - last_gif_write + gif_write_overflow >= gif_frame_length) { - if (ii == frame_offset) + if (ii == stash->frame_offset) { GifBegin(&gif_writer, gif_path.string().c_str(), frame->w, frame->h, gif_frame_length / 10); @@ -252,9 +264,9 @@ void Recorder::write_stash_frames( frame->w, frame->h, gif_frame_length / 10); } elapsed += get_frame_length(); - delete[] pixel_buffers->front(); - pixel_buffers->erase(pixel_buffers->begin()); - flipped->erase(flipped->begin()); + delete[] stash->pixel_buffers.front(); + stash->pixel_buffers.erase(stash->pixel_buffers.begin()); + stash->flipped.erase(stash->flipped.begin()); SDL_FreeSurface(frame); } GifEnd(&gif_writer); @@ -291,9 +303,7 @@ void Recorder::end_recording() void Recorder::finish_writing_video() { - write_stash_frames( - &video_stashes.back().pixel_buffers, &video_stashes.back().flipped, - video_stashes.back().frame_offset); + write_stash_frames(&video_stashes.back()); int count; while (true) { @@ -352,21 +362,24 @@ void Recorder::update() void process_audio(void* user_data, Uint8* stream, int len) { Recorder* recorder = static_cast(user_data); - int max_length = recorder->get_configuration()["recording"]["max-stash-length"]; - float length = recorder->get_frame_length() * recorder->current_stash.pixel_buffers.size(); - if (length > max_length) + if (recorder->is_active()) { - delete[] recorder->current_stash.audio_buffers.front(); - recorder->current_stash.audio_buffers.erase(recorder->current_stash.audio_buffers.begin()); - recorder->current_stash.audio_buffer_lengths.erase( - recorder->current_stash.audio_buffer_lengths.begin()); - } - Uint8* stream_copy = new Uint8[len]; - std::memcpy(stream_copy, stream, len); - recorder->current_stash.audio_buffers.push_back(stream_copy); - recorder->current_stash.audio_buffer_lengths.push_back(len); - if (recorder->is_recording) - { - recorder->write_audio(stream_copy, len); + int max_length = recorder->get_configuration()["recording"]["max-stash-length"]; + float length = recorder->get_frame_length() * recorder->current_stash.pixel_buffers.size(); + if (length > max_length) + { + delete[] recorder->current_stash.audio_buffers.front(); + recorder->current_stash.audio_buffers.erase(recorder->current_stash.audio_buffers.begin()); + recorder->current_stash.audio_buffer_lengths.erase( + recorder->current_stash.audio_buffer_lengths.begin()); + } + Uint8* stream_copy = new Uint8[len]; + std::memcpy(stream_copy, stream, len); + recorder->current_stash.audio_buffers.push_back(stream_copy); + recorder->current_stash.audio_buffer_lengths.push_back(len); + if (recorder->is_recording) + { + recorder->write_audio(stream_copy, len); + } } } diff --git a/src/Recorder.hpp b/src/Recorder.hpp index a0214a4..4b214e0 100644 --- a/src/Recorder.hpp +++ b/src/Recorder.hpp @@ -36,8 +36,8 @@ struct Recorder : Node Stash current_stash = Stash(); Stash most_recent_stash; - std::vector in_game_stashes; - std::vector video_stashes; + std::list in_game_stashes; + std::list video_stashes; fs::path current_video_directory, current_audio_path; Animation animation = Animation(&Recorder::add_frame, this); bool is_recording = false, writing_recording = false, writing_most_recent = false; @@ -54,8 +54,7 @@ struct Recorder : Node void add_frame(); int get_memory_size(); void make_directory(); - void write_stash_frames( - std::vector*, std::vector*, int); + void write_stash_frames(Stash*); void keep_stash(); void end_recording(); void finish_writing_video();