aboutsummaryrefslogtreecommitdiff
path: root/backends/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'backends/graphics')
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp63
-rw-r--r--backends/graphics/opengl/opengl-graphics.h8
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp23
3 files changed, 93 insertions, 1 deletions
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index e3c56dccca..00e8dc358e 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -29,6 +29,7 @@
#include "common/textconsole.h"
#include "common/translation.h"
#include "common/algorithm.h"
+#include "common/file.h"
#ifdef USE_OSD
#include "common/tokenizer.h"
#include "common/rect.h"
@@ -849,6 +850,11 @@ void OpenGLGraphicsManager::notifyContextChange(const Graphics::PixelFormat &def
GLCALL(glEnable(GL_TEXTURE_2D));
+ // We use a "pack" alignment (when reading from textures) to 4 here,
+ // since the only place where we really use it is the BMP screenshot
+ // code and that requires the same alignment too.
+ GLCALL(glPixelStorei(GL_PACK_ALIGNMENT, 4));
+
// Query information needed by textures.
Texture::queryTextureInformation();
@@ -1082,4 +1088,61 @@ const Graphics::Font *OpenGLGraphicsManager::getFontOSD() {
}
#endif
+void OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const {
+ const uint width = _outputScreenWidth;
+ const uint height = _outputScreenHeight;
+
+ // A line of a BMP image must have a size divisible by 4.
+ // We calculate the padding bytes needed here.
+ // Since we use a 3 byte per pixel mode, we can use width % 4 here, since
+ // it is equal to 4 - (width * 3) % 4. (4 - (width * Bpp) % 4, is the
+ // usual way of computing the padding bytes required).
+ const uint linePaddingSize = width % 4;
+ const uint lineSize = width * 3 + linePaddingSize;
+
+ // Allocate memory for screenshot
+ uint8 *pixels = new uint8[lineSize * height];
+
+ // Get pixel data from OpenGL buffer
+ GLCALL(glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels));
+
+ // BMP stores as BGR. Since we can't assume that GL_BGR is supported we
+ // will swap the components from the RGB we read to BGR on our own.
+ for (uint y = height; y-- > 0;) {
+ uint8 *line = pixels + y * lineSize;
+
+ for (uint x = width; x > 0; --x, line += 3) {
+ SWAP(line[0], line[2]);
+ }
+ }
+
+ // Open file
+ Common::DumpFile out;
+ out.open(filename);
+
+ // Write BMP header
+ out.writeByte('B');
+ out.writeByte('M');
+ out.writeUint32LE(height * lineSize + 54);
+ out.writeUint32LE(0);
+ out.writeUint32LE(54);
+ out.writeUint32LE(40);
+ out.writeUint32LE(width);
+ out.writeUint32LE(height);
+ out.writeUint16LE(1);
+ out.writeUint16LE(24);
+ out.writeUint32LE(0);
+ out.writeUint32LE(0);
+ out.writeUint32LE(0);
+ out.writeUint32LE(0);
+ out.writeUint32LE(0);
+ out.writeUint32LE(0);
+
+ // Write pixel data to BMP
+ out.write(pixels, lineSize * height);
+
+ // Free allocated memory
+ delete[] pixels;
+}
+
} // End of namespace OpenGL
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index 67ad5aa067..ebfe38fb60 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -247,6 +247,14 @@ protected:
*/
virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) = 0;
+ /**
+ * Save a screenshot of the full display as BMP to the given file. This
+ * uses Common::DumpFile for writing the screenshot.
+ *
+ * @param filename The output filename.
+ */
+ void saveScreenshot(const Common::String &filename) const;
+
private:
//
// OpenGL utilities
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index a1a3e8590a..925237b75e 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -355,6 +355,26 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
#endif
return true;
}
+
+ if (event.kbd.keycode == Common::KEYCODE_s) {
+ // Alt-s creates a screenshot
+ Common::String filename;
+
+ for (int n = 0;; n++) {
+ SDL_RWops *file;
+
+ filename = Common::String::format("scummvm%05d.bmp", n);
+ file = SDL_RWFromFile(filename.c_str(), "r");
+ if (!file)
+ break;
+ SDL_RWclose(file);
+ }
+
+ saveScreenshot(filename.c_str());
+ debug("Saved screenshot '%s'", filename.c_str());
+
+ return true;
+ }
} else if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) {
if ( event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS
|| event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS) {
@@ -502,7 +522,8 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) {
if (event.kbd.hasFlags(Common::KBD_ALT)) {
return event.kbd.keycode == Common::KEYCODE_RETURN
- || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER;
+ || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER
+ || event.kbd.keycode == Common::KEYCODE_s;
} else if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) {
return event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS
|| event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS