Initial commit
This commit is contained in:
48
backends/graphics/opengl/pipelines/clut8.cpp
Normal file
48
backends/graphics/opengl/pipelines/clut8.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "backends/graphics/opengl/pipelines/clut8.h"
|
||||
#include "backends/graphics/opengl/shader.h"
|
||||
#include "backends/graphics/opengl/framebuffer.h"
|
||||
#include "graphics/opengl/debug.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
CLUT8LookUpPipeline::CLUT8LookUpPipeline()
|
||||
: ShaderPipeline(ShaderMan.query(ShaderManager::kCLUT8LookUp)), _paletteTexture(nullptr) {
|
||||
}
|
||||
|
||||
void CLUT8LookUpPipeline::drawTextureInternal(const Texture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
|
||||
assert(isActive());
|
||||
|
||||
// Set the palette texture.
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE1));
|
||||
if (_paletteTexture) {
|
||||
_paletteTexture->bind();
|
||||
}
|
||||
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE0));
|
||||
ShaderPipeline::drawTextureInternal(texture, coordinates, texcoords);
|
||||
}
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
} // End of namespace OpenGL
|
||||
46
backends/graphics/opengl/pipelines/clut8.h
Normal file
46
backends/graphics/opengl/pipelines/clut8.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_CLUT8_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_PIPELINES_CLUT8_H
|
||||
|
||||
#include "backends/graphics/opengl/pipelines/shader.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
class CLUT8LookUpPipeline : public ShaderPipeline {
|
||||
public:
|
||||
CLUT8LookUpPipeline();
|
||||
|
||||
void setPaletteTexture(const Texture *paletteTexture) { _paletteTexture = paletteTexture; }
|
||||
|
||||
protected:
|
||||
void drawTextureInternal(const Texture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
|
||||
|
||||
private:
|
||||
const Texture *_paletteTexture;
|
||||
};
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
||||
88
backends/graphics/opengl/pipelines/fixed.cpp
Normal file
88
backends/graphics/opengl/pipelines/fixed.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "backends/graphics/opengl/pipelines/fixed.h"
|
||||
#include "graphics/opengl/debug.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
#if !USE_FORCED_GLES2
|
||||
void FixedPipeline::activateInternal() {
|
||||
Pipeline::activateInternal();
|
||||
|
||||
// Disable 3D properties.
|
||||
GL_CALL(glDisable(GL_CULL_FACE));
|
||||
GL_CALL(glDisable(GL_DEPTH_TEST));
|
||||
GL_CALL(glDisable(GL_DITHER));
|
||||
|
||||
GL_CALL(glDisable(GL_LIGHTING));
|
||||
GL_CALL(glDisable(GL_FOG));
|
||||
GL_CALL(glShadeModel(GL_FLAT));
|
||||
GL_CALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST));
|
||||
|
||||
GL_CALL(glEnableClientState(GL_VERTEX_ARRAY));
|
||||
GL_CALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
if (OpenGLContext.multitextureSupported) {
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE0));
|
||||
}
|
||||
#endif
|
||||
GL_CALL(glEnable(GL_TEXTURE_2D));
|
||||
GL_CALL(glColor4f(_r, _g, _b, _a));
|
||||
}
|
||||
|
||||
void FixedPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
|
||||
_r = r;
|
||||
_g = g;
|
||||
_b = b;
|
||||
_a = a;
|
||||
|
||||
if (isActive()) {
|
||||
GL_CALL(glColor4f(r, g, b, a));
|
||||
}
|
||||
}
|
||||
|
||||
void FixedPipeline::drawTextureInternal(const Texture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
|
||||
assert(isActive());
|
||||
|
||||
texture.bind();
|
||||
|
||||
GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords));
|
||||
GL_CALL(glVertexPointer(2, GL_FLOAT, 0, coordinates));
|
||||
GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
|
||||
void FixedPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix) {
|
||||
assert(isActive());
|
||||
|
||||
GL_CALL(glMatrixMode(GL_PROJECTION));
|
||||
GL_CALL(glLoadMatrixf(projectionMatrix.getData()));
|
||||
|
||||
GL_CALL(glMatrixMode(GL_MODELVIEW));
|
||||
GL_CALL(glLoadIdentity());
|
||||
|
||||
GL_CALL(glMatrixMode(GL_TEXTURE));
|
||||
GL_CALL(glLoadIdentity());
|
||||
}
|
||||
#endif // !USE_FORCED_GLES2
|
||||
|
||||
} // End of namespace OpenGL
|
||||
48
backends/graphics/opengl/pipelines/fixed.h
Normal file
48
backends/graphics/opengl/pipelines/fixed.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_FIXED_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_PIPELINES_FIXED_H
|
||||
|
||||
#include "backends/graphics/opengl/pipelines/pipeline.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
#if !USE_FORCED_GLES2
|
||||
class FixedPipeline : public Pipeline {
|
||||
public:
|
||||
FixedPipeline() : _r(0.f), _g(0.f), _b(0.f), _a(0.f) {}
|
||||
|
||||
void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) override;
|
||||
|
||||
void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
|
||||
|
||||
protected:
|
||||
void activateInternal() override;
|
||||
void drawTextureInternal(const Texture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
|
||||
|
||||
GLfloat _r, _g, _b, _a;
|
||||
};
|
||||
#endif // !USE_FORCED_GLES2
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
||||
1075
backends/graphics/opengl/pipelines/libretro.cpp
Normal file
1075
backends/graphics/opengl/pipelines/libretro.cpp
Normal file
File diff suppressed because it is too large
Load Diff
277
backends/graphics/opengl/pipelines/libretro.h
Normal file
277
backends/graphics/opengl/pipelines/libretro.h
Normal file
@@ -0,0 +1,277 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_LIBRETRO_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_PIPELINES_LIBRETRO_H
|
||||
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
#include "backends/graphics/opengl/pipelines/shader.h"
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/fs.h"
|
||||
|
||||
namespace Graphics {
|
||||
struct Surface;
|
||||
}
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
namespace LibRetro {
|
||||
struct ShaderPreset;
|
||||
struct ShaderPass;
|
||||
} // End of namespace LibRetro
|
||||
|
||||
class TextureTarget;
|
||||
class LibRetroTextureTarget;
|
||||
|
||||
/**
|
||||
* Pipeline implementation using Libretro shader presets.
|
||||
*/
|
||||
class LibRetroPipeline : public Pipeline {
|
||||
public:
|
||||
LibRetroPipeline();
|
||||
~LibRetroPipeline() override;
|
||||
|
||||
void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) override;
|
||||
void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
|
||||
|
||||
bool open(const Common::Path &shaderPath, Common::SearchSet &archSet);
|
||||
void close();
|
||||
|
||||
/* Called by OpenGLGraphicsManager */
|
||||
void enableLinearFiltering(bool enabled) { _linearFiltering = enabled; }
|
||||
void setRotation(Common::RotationMode rotation) { if (_rotation != rotation) { _rotation = rotation; setPipelineState(); } }
|
||||
/* Called by OpenGLGraphicsManager to setup the internal objects sizes */
|
||||
void setDisplaySizes(uint inputWidth, uint inputHeight, const Common::Rect &outputRect);
|
||||
/* Called by OpenGLGraphicsManager to indicate that next draws need to be scaled. */
|
||||
void beginScaling();
|
||||
/* Called by OpenGLGraphicsManager to indicate that next draws don't need to be scaled.
|
||||
* This must be called to execute scaling. */
|
||||
void finishScaling();
|
||||
bool isAnimated() const { return _isAnimated; }
|
||||
|
||||
static bool isSupportedByContext() {
|
||||
return OpenGLContext.shadersSupported
|
||||
&& OpenGLContext.multitextureSupported
|
||||
&& OpenGLContext.framebufferObjectSupported;
|
||||
}
|
||||
private:
|
||||
void activateInternal() override;
|
||||
void deactivateInternal() override;
|
||||
void drawTextureInternal(const Texture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
|
||||
|
||||
bool loadTextures(Common::SearchSet &archSet);
|
||||
bool loadPasses(Common::SearchSet &archSet);
|
||||
|
||||
void setPipelineState();
|
||||
bool setupFBOs();
|
||||
void setupPassUniforms(const uint id);
|
||||
void setShaderTexUniforms(const Common::String &prefix, Shader *shader, const Texture &texture);
|
||||
|
||||
/* Pipelines used to draw all layers
|
||||
* First before the scaler then after it to draw on screen
|
||||
*/
|
||||
ShaderPipeline _inputPipeline;
|
||||
ShaderPipeline _outputPipeline;
|
||||
bool _needsScaling;
|
||||
|
||||
const LibRetro::ShaderPreset *_shaderPreset;
|
||||
|
||||
uint _inputWidth;
|
||||
uint _inputHeight;
|
||||
Common::Rect _outputRect;
|
||||
|
||||
bool _linearFiltering;
|
||||
Common::RotationMode _rotation;
|
||||
|
||||
/* Determines if preset depends on frameCount or from previous frames */
|
||||
bool _isAnimated;
|
||||
uint _frameCount;
|
||||
|
||||
Common::Array<LibRetroTextureTarget> _inputTargets;
|
||||
uint _currentTarget;
|
||||
|
||||
struct LibRetroTexture {
|
||||
LibRetroTexture() : textureData(nullptr), glTexture(nullptr) {}
|
||||
LibRetroTexture(Graphics::Surface *tD, Texture *glTex) : textureData(tD), glTexture(glTex) {}
|
||||
|
||||
Common::String id;
|
||||
Graphics::Surface *textureData;
|
||||
Texture *glTexture;
|
||||
};
|
||||
LibRetroTexture loadTexture(const Common::Path &fileName, Common::Archive *container, Common::SearchSet &archSet);
|
||||
|
||||
typedef Common::Array<LibRetroTexture> TextureArray;
|
||||
TextureArray _textures;
|
||||
|
||||
struct Pass {
|
||||
Pass()
|
||||
: shaderPass(nullptr), shader(nullptr), target(nullptr), texCoords(), texSamplers(),
|
||||
inputTexture(nullptr), vertexCoord(), hasFrameCount(false), prevCount(0) {}
|
||||
Pass(const LibRetro::ShaderPass *sP, Shader *s, TextureTarget *t)
|
||||
: shaderPass(sP), shader(s), target(t), texCoords(), texSamplers(),
|
||||
inputTexture(nullptr), vertexCoord(), hasFrameCount(false), prevCount(0) {}
|
||||
|
||||
const LibRetro::ShaderPass *shaderPass;
|
||||
Shader *shader;
|
||||
TextureTarget *target;
|
||||
|
||||
/**
|
||||
* Description of texture coordinates bound to attribute.
|
||||
*/
|
||||
struct TexCoordAttribute {
|
||||
/**
|
||||
* Attribute name to bind data to.
|
||||
*/
|
||||
Common::String name;
|
||||
|
||||
enum Type {
|
||||
/**
|
||||
* 'index' denotes the 'index'th shader texture's coordinates.
|
||||
*/
|
||||
kTypeTexture,
|
||||
|
||||
/**
|
||||
* 'index' denotes the texture coordinates given to pass 'index'.
|
||||
*/
|
||||
kTypePass,
|
||||
|
||||
/**
|
||||
* 'index' denotes the texture coordinates of the 'index'th previous frame.
|
||||
*/
|
||||
kTypePrev
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the attribute.
|
||||
*/
|
||||
Type type;
|
||||
|
||||
/**
|
||||
* Index for the texture coordinates to use.
|
||||
*/
|
||||
uint index;
|
||||
|
||||
TexCoordAttribute() : name(), type(), index() {}
|
||||
TexCoordAttribute(const Common::String &n, Type t, uint i) : name(n), type(t), index(i) {}
|
||||
};
|
||||
|
||||
typedef Common::Array<TexCoordAttribute> TexCoordAttributeArray;
|
||||
TexCoordAttributeArray texCoords;
|
||||
|
||||
/**
|
||||
* Build the 'texCoords' array.
|
||||
*
|
||||
* @param id Identifier of the current pass.
|
||||
*/
|
||||
void buildTexCoords(const uint id, const Common::StringArray &aliases);
|
||||
|
||||
void addTexCoord(const Common::String &prefix, const TexCoordAttribute::Type type, const uint index);
|
||||
|
||||
/**
|
||||
* Description of a texture sampler.
|
||||
*/
|
||||
struct TextureSampler {
|
||||
/**
|
||||
* Texture unit to use.
|
||||
*/
|
||||
uint unit;
|
||||
|
||||
enum Type {
|
||||
/**
|
||||
* 'index' denotes the 'index'th shader texture.
|
||||
*/
|
||||
kTypeTexture,
|
||||
|
||||
/**
|
||||
* 'index' denotes the input to pass 'index'.
|
||||
*/
|
||||
kTypePass,
|
||||
|
||||
/**
|
||||
* 'index' denotes the input of the 'index'th previous frame.
|
||||
*/
|
||||
kTypePrev
|
||||
};
|
||||
|
||||
/**
|
||||
* Source type of the texture to bind.
|
||||
*/
|
||||
Type type;
|
||||
|
||||
/**
|
||||
* Index of the texture.
|
||||
*/
|
||||
uint index;
|
||||
|
||||
TextureSampler() : unit(), type(), index() {}
|
||||
TextureSampler(uint u, Type t, uint i) : unit(u), type(t), index(i) {}
|
||||
};
|
||||
|
||||
typedef Common::Array<TextureSampler> TextureSamplerArray;
|
||||
TextureSamplerArray texSamplers;
|
||||
|
||||
/**
|
||||
* Build the 'texSamplers' array.
|
||||
*
|
||||
* @param id Identifier of the current pass.
|
||||
* @param textures Array of shader textures available.
|
||||
*/
|
||||
void buildTexSamplers(const uint id, const TextureArray &textures, const Common::StringArray &aliases);
|
||||
|
||||
bool addTexSampler(const Common::String &name, uint *unit, const TextureSampler::Type type, const uint index, const bool prefixIsId = false);
|
||||
|
||||
/**
|
||||
* Input texture of the pass.
|
||||
*/
|
||||
const Texture *inputTexture;
|
||||
|
||||
/**
|
||||
* Vertex coordinates used for drawing.
|
||||
*/
|
||||
GLfloat vertexCoord[2*4];
|
||||
|
||||
/**
|
||||
* Whether the shader has a FrameCount uniform or not
|
||||
* Allows to speed up if it is not here
|
||||
*/
|
||||
bool hasFrameCount;
|
||||
|
||||
/**
|
||||
* The number of previous frames this pass needs
|
||||
*/
|
||||
uint prevCount;
|
||||
};
|
||||
|
||||
typedef Common::Array<Pass> PassArray;
|
||||
PassArray _passes;
|
||||
|
||||
void renderPass(const Pass &pass);
|
||||
void renderPassSetupCoordinates(const Pass &pass);
|
||||
void renderPassSetupTextures(const Pass &pass);
|
||||
};
|
||||
|
||||
} // End of namespace OpenGL
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
#endif
|
||||
573
backends/graphics/opengl/pipelines/libretro/parser.cpp
Normal file
573
backends/graphics/opengl/pipelines/libretro/parser.cpp
Normal file
@@ -0,0 +1,573 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
#include "backends/graphics/opengl/pipelines/libretro/parser.h"
|
||||
|
||||
#include "common/file.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/algorithm.h"
|
||||
#include "common/tokenizer.h"
|
||||
#include "common/ptr.h"
|
||||
#include "common/util.h"
|
||||
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace OpenGL {
|
||||
namespace LibRetro {
|
||||
|
||||
class PresetParser {
|
||||
public:
|
||||
ShaderPreset *parseStream(Common::SeekableReadStream &stream);
|
||||
|
||||
const Common::String &getErrorDesc() const { return _errorDesc; }
|
||||
private:
|
||||
bool parsePreset(Common::SeekableReadStream &stream);
|
||||
bool lookUpValue(const Common::String &key, Common::String *value);
|
||||
bool lookUpValue(const Common::String &key, bool *value);
|
||||
bool lookUpValue(const Common::String &key, uint *value);
|
||||
bool lookUpValue(const Common::String &key, float *value);
|
||||
bool lookUpValue(const Common::String &key, FilteringMode *value, const FilteringMode defaultValue);
|
||||
bool lookUpValue(const Common::String &key, ScaleType *value, const ScaleType defaultValue);
|
||||
bool lookUpValueScale(const Common::String &key, float *floatValue, uint *uintValue, const ScaleType scaleType);
|
||||
bool lookUpValue(const Common::String &key, WrapMode *value, const WrapMode defaultValue);
|
||||
|
||||
template<typename T, typename DefaultT>
|
||||
bool lookUpValue(const Common::String &key, T *value, const DefaultT &defaultValue) {
|
||||
if (_entries.contains(key)) {
|
||||
return lookUpValue(key, value);
|
||||
} else {
|
||||
*value = defaultValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool parseTextures();
|
||||
bool parseTexture(const Common::String &id);
|
||||
|
||||
bool parsePasses();
|
||||
bool parsePass(const uint id, const bool isLast);
|
||||
bool parsePassScaleType(const uint id, const bool isLast, ShaderPass *pass);
|
||||
bool parsePassScale(const uint id, ShaderPass *pass);
|
||||
bool computeDefaultScale(const Common::String &key, float *floatValue, uint *uintValue, const ScaleType scaleType);
|
||||
|
||||
bool parseParameters();
|
||||
|
||||
typedef Common::HashMap<Common::String, Common::String> StringMap;
|
||||
StringMap _entries;
|
||||
|
||||
Common::String _errorDesc;
|
||||
|
||||
Common::ScopedPtr<ShaderPreset> _shader;
|
||||
};
|
||||
|
||||
ShaderPreset *PresetParser::parseStream(Common::SeekableReadStream &stream) {
|
||||
_errorDesc.clear();
|
||||
_entries.clear();
|
||||
|
||||
if (!parsePreset(stream)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
_shader.reset(new ShaderPreset);
|
||||
if (!parseTextures()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!parsePasses()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!parseParameters()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return _shader.release();
|
||||
}
|
||||
|
||||
bool PresetParser::parsePreset(Common::SeekableReadStream &stream) {
|
||||
while (!stream.eos()) {
|
||||
Common::String line = stream.readLine();
|
||||
if (stream.err()) {
|
||||
_errorDesc = "Read error";
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t sharpPos = line.findFirstOf('#');
|
||||
if (sharpPos != line.npos) {
|
||||
// Remove the end of line
|
||||
line.erase(sharpPos);
|
||||
}
|
||||
|
||||
if (line.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool empty = true;
|
||||
for (uint i = 0; i < line.size(); i++) {
|
||||
if (!Common::isSpace(line[i])) {
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty)
|
||||
continue;
|
||||
|
||||
// Split line into key, value pair.
|
||||
Common::String::const_iterator equalIter = Common::find(line.begin(), line.end(), '=');
|
||||
if (equalIter == line.end()) {
|
||||
_errorDesc = "Could not find '=' in line '" + line + '\'';
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::String key(line.begin(), equalIter);
|
||||
Common::String value(equalIter + 1);
|
||||
|
||||
key.trim();
|
||||
value.trim();
|
||||
|
||||
// Check whether the value is put in quotation marks. This might be
|
||||
// useful when a path contains a whitespace. But Libretro's is not
|
||||
// mentioning any exact format, but one example for 'textures'
|
||||
// indicates quotes are supported in this place.
|
||||
if (!value.empty() && value[0] == '"') {
|
||||
if (value.size() < 2 || value.lastChar() != '"') {
|
||||
_errorDesc = "Unmatched '\"' for value in line '" + line + '\'';
|
||||
}
|
||||
|
||||
value.deleteLastChar();
|
||||
value.deleteChar(0);
|
||||
}
|
||||
|
||||
_entries[key] = value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PresetParser::lookUpValue(const Common::String &key, Common::String *value) {
|
||||
StringMap::const_iterator iter = _entries.find(key);
|
||||
if (iter != _entries.end()) {
|
||||
*value = iter->_value;
|
||||
return true;
|
||||
} else {
|
||||
_errorDesc = "Missing key '" + key + "'";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PresetParser::lookUpValue(const Common::String &key, bool *value) {
|
||||
StringMap::const_iterator iter = _entries.find(key);
|
||||
if (iter != _entries.end()) {
|
||||
if (Common::parseBool(iter->_value, *value)) {
|
||||
return true;
|
||||
} else {
|
||||
_errorDesc = "Invalid boolean value for key '" + key + "': '" + iter->_value + '\'';
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
_errorDesc = "Missing key '" + key + "'";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PresetParser::lookUpValue(const Common::String &key, uint *value) {
|
||||
StringMap::const_iterator iter = _entries.find(key);
|
||||
if (iter != _entries.end()) {
|
||||
char *endptr;
|
||||
const unsigned long uintVal = strtoul(iter->_value.c_str(), &endptr, 0);
|
||||
// Original libretro is quite laxist with int values and only checks errno
|
||||
// This means that as long as there is some number at start, parsing won't fail
|
||||
if (endptr == iter->_value.c_str() || uintVal >= UINT_MAX) {
|
||||
_errorDesc = "Invalid unsigned integer value for key '" + key + "': '" + iter->_value + '\'';
|
||||
return false;
|
||||
} else {
|
||||
if (*endptr != '\0') {
|
||||
warning("Possibly invalid unsigned integer value for key '%s': '%s'", key.c_str(), iter->_value.c_str());
|
||||
}
|
||||
*value = uintVal;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
_errorDesc = "Missing key '" + key + "'";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PresetParser::lookUpValue(const Common::String &key, float *value) {
|
||||
StringMap::const_iterator iter = _entries.find(key);
|
||||
if (iter != _entries.end()) {
|
||||
char *endptr;
|
||||
const double doubleVal = strtod(iter->_value.c_str(), &endptr);
|
||||
if (*endptr != '\0') {
|
||||
_errorDesc = "Invalid float value for key '" + key + "': '" + iter->_value + '\'';
|
||||
return false;
|
||||
} else {
|
||||
*value = doubleVal;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
_errorDesc = "Missing key '" + key + "'";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PresetParser::lookUpValue(const Common::String &key, FilteringMode *value, const FilteringMode defaultValue) {
|
||||
StringMap::const_iterator iter = _entries.find(key);
|
||||
if (iter != _entries.end()) {
|
||||
bool isLinear;
|
||||
if (Common::parseBool(iter->_value, isLinear)) {
|
||||
*value = isLinear ? kFilteringModeLinear : kFilteringModeNearest;
|
||||
return true;
|
||||
} else {
|
||||
_errorDesc = "Invalid filtering mode for key '" + key + "': '" + iter->_value + '\'';
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
*value = defaultValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool PresetParser::lookUpValue(const Common::String &key, ScaleType *value, const ScaleType defaultValue) {
|
||||
StringMap::const_iterator iter = _entries.find(key);
|
||||
if (iter != _entries.end()) {
|
||||
if (iter->_value == "source") {
|
||||
*value = kScaleTypeSource;
|
||||
return true;
|
||||
} else if (iter->_value == "viewport") {
|
||||
*value = kScaleTypeViewport;
|
||||
return true;
|
||||
} else if (iter->_value == "absolute") {
|
||||
*value = kScaleTypeAbsolute;
|
||||
return true;
|
||||
} else {
|
||||
_errorDesc = "Invalid scale type for key '" + key + "': '" + iter->_value + '\'';
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
*value = defaultValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool PresetParser::lookUpValueScale(const Common::String &key, float *floatValue, uint *uintValue, const ScaleType scaleType) {
|
||||
switch (scaleType) {
|
||||
case kScaleTypeSource:
|
||||
case kScaleTypeViewport:
|
||||
return lookUpValue(key, floatValue, 1.0f);
|
||||
|
||||
case kScaleTypeAbsolute:
|
||||
return lookUpValue(key, uintValue);
|
||||
|
||||
case kScaleTypeFull:
|
||||
return true;
|
||||
|
||||
default:
|
||||
_errorDesc = "Internal Error: Invalid scale type";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PresetParser::lookUpValue(const Common::String &key, WrapMode *value, const WrapMode defaultValue) {
|
||||
StringMap::const_iterator iter = _entries.find(key);
|
||||
if (iter != _entries.end()) {
|
||||
if (iter->_value == "clamp_to_border") {
|
||||
*value = kWrapModeBorder;
|
||||
return true;
|
||||
} else if (iter->_value == "clamp_to_edge") {
|
||||
*value = kWrapModeEdge;
|
||||
return true;
|
||||
} else if (iter->_value == "repeat") {
|
||||
*value = kWrapModeRepeat;
|
||||
return true;
|
||||
} else if (iter->_value == "mirrored_repeat") {
|
||||
*value = kWrapModeMirroredRepeat;
|
||||
return true;
|
||||
} else {
|
||||
_errorDesc = "Invalid wrap mode for key '" + key + "': '" + iter->_value + '\'';
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
*value = defaultValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool PresetParser::parseTextures() {
|
||||
Common::String textures;
|
||||
if (!lookUpValue("textures", &textures)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse all texture information from preset.
|
||||
Common::StringTokenizer tokenizer(textures, ";");
|
||||
while (!tokenizer.empty()) {
|
||||
if (!parseTexture(tokenizer.nextToken())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PresetParser::parseTexture(const Common::String &id) {
|
||||
Common::String fileName;
|
||||
if (!lookUpValue(id, &fileName)) {
|
||||
_errorDesc = "No file name specified for texture '" + id + '\'';
|
||||
return false;
|
||||
}
|
||||
|
||||
FilteringMode filteringMode;
|
||||
if (!lookUpValue(id + "_linear", &filteringMode, kFilteringModeLinear)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WrapMode wrapMode;
|
||||
if (!lookUpValue(id + "_wrap_mode", &wrapMode, kWrapModeBorder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_shader->textures.push_back(ShaderTexture(id, fileName, filteringMode, wrapMode));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PresetParser::parsePasses() {
|
||||
uint numShaders;
|
||||
if (!lookUpValue("shaders", &numShaders)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint shaderPass = 0; shaderPass < numShaders; ++shaderPass) {
|
||||
if (!parsePass(shaderPass, shaderPass == numShaders - 1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define passKey(x) Common::String::format(x "%u", id)
|
||||
bool PresetParser::parsePass(const uint id, const bool isLast) {
|
||||
ShaderPass pass;
|
||||
|
||||
if (!lookUpValue(passKey("shader"), &pass.fileName)) {
|
||||
_errorDesc = Common::String::format("No file name specified for pass '%u'", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lookUpValue(passKey("alias"), &pass.alias)) {
|
||||
_errorDesc.clear();
|
||||
pass.alias.clear();
|
||||
}
|
||||
|
||||
if (!lookUpValue(passKey("filter_linear"), &pass.filteringMode, kFilteringModeUnspecified)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lookUpValue(passKey("wrap_mode"), &pass.wrapMode, kWrapModeBorder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lookUpValue(passKey("mipmap_input"), &pass.mipmapInput, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lookUpValue(passKey("float_framebuffer"), &pass.floatFBO, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lookUpValue(passKey("srgb_framebuffer"), &pass.srgbFBO, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lookUpValue(passKey("frame_count_mod"), &pass.frameCountMod, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parsePassScaleType(id, isLast, &pass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parsePassScale(id, &pass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_shader->passes.push_back(pass);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PresetParser::parsePassScaleType(const uint id, const bool isLast, ShaderPass *pass) {
|
||||
// Parse scale type for the pass.
|
||||
//
|
||||
// This is a little more complicated because it is possible to specify the
|
||||
// scale type per axis. However, a generic scale type overrides the axis
|
||||
// scale types.
|
||||
//
|
||||
// Additionally, the default value for the passes vary. The last pass
|
||||
// defaults to use full size, all other default to source scaling.
|
||||
|
||||
const ScaleType defaultScaleType = isLast ? kScaleTypeFull : kScaleTypeSource;
|
||||
|
||||
if (!lookUpValue(passKey("scale_type_x"), &pass->scaleTypeX, defaultScaleType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lookUpValue(passKey("scale_type_y"), &pass->scaleTypeY, defaultScaleType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScaleType scale_type;
|
||||
// Small trick here: lookUpValue never returns kScaleTypeFull
|
||||
if (!lookUpValue(passKey("scale_type"), &scale_type, kScaleTypeFull)) {
|
||||
return false;
|
||||
} else if (scale_type != kScaleTypeFull) {
|
||||
pass->scaleTypeY = pass->scaleTypeX = scale_type;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PresetParser::parsePassScale(const uint id, ShaderPass *pass) {
|
||||
// Parse actual scale value for the pass.
|
||||
//
|
||||
// Like for the scale type, 'scale' overrides 'scale_x'/'scale_y'.
|
||||
if (_entries.contains(passKey("scale"))) {
|
||||
if (!lookUpValueScale(passKey("scale"), &pass->scaleXFloat, &pass->scaleXUint, pass->scaleTypeX)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lookUpValueScale(passKey("scale"), &pass->scaleYFloat, &pass->scaleYUint, pass->scaleTypeY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_entries.contains(passKey("scale_x"))) {
|
||||
if (!lookUpValueScale(passKey("scale_x"), &pass->scaleXFloat, &pass->scaleXUint, pass->scaleTypeX)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!computeDefaultScale(passKey("scale_x"), &pass->scaleXFloat, &pass->scaleXUint, pass->scaleTypeX)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_entries.contains(passKey("scale_y"))) {
|
||||
if (!lookUpValueScale(passKey("scale_y"), &pass->scaleYFloat, &pass->scaleYUint, pass->scaleTypeY)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!computeDefaultScale(passKey("scale_y"), &pass->scaleYFloat, &pass->scaleYUint, pass->scaleTypeY)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#undef passKey
|
||||
|
||||
bool PresetParser::computeDefaultScale(const Common::String &key, float *floatValue, uint *uintValue, const ScaleType scaleType) {
|
||||
switch (scaleType) {
|
||||
case kScaleTypeSource:
|
||||
case kScaleTypeViewport:
|
||||
*floatValue = 1.0f;
|
||||
return true;
|
||||
|
||||
case kScaleTypeAbsolute:
|
||||
_errorDesc = "No value specified for scale '" + key + '\'';
|
||||
return false;
|
||||
|
||||
case kScaleTypeFull:
|
||||
return true;
|
||||
|
||||
default:
|
||||
_errorDesc = "Internal Error: Invalid scale type";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PresetParser::parseParameters() {
|
||||
Common::String parameters;
|
||||
if (!lookUpValue("parameters", ¶meters)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse all texture information from preset.
|
||||
Common::StringTokenizer tokenizer(parameters, ";");
|
||||
while (!tokenizer.empty()) {
|
||||
Common::String key = tokenizer.nextToken();
|
||||
if (_entries.contains(key)) {
|
||||
float value;
|
||||
if (!lookUpValue(key, &value)) {
|
||||
return false;
|
||||
}
|
||||
_shader->parameters[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ShaderPreset *parsePreset(const Common::Path &shaderPreset, Common::SearchSet &archSet) {
|
||||
Common::SeekableReadStream *stream;
|
||||
Common::Archive *container = nullptr;
|
||||
Common::Path basePath;
|
||||
|
||||
// First try SearchMan, then fallback to filesystem
|
||||
if (archSet.hasFile(shaderPreset)) {
|
||||
Common::ArchiveMemberPtr member = archSet.getMember(shaderPreset, &container);
|
||||
stream = member->createReadStream();
|
||||
basePath = shaderPreset.getParent();
|
||||
} else {
|
||||
Common::FSNode fsnode(shaderPreset);
|
||||
if (!fsnode.exists() || !fsnode.isReadable() || fsnode.isDirectory()
|
||||
|| !(stream = fsnode.createReadStream())) {
|
||||
warning("LibRetro Preset Parsing: Invalid file path '%s'", shaderPreset.toString(Common::Path::kNativeSeparator).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
basePath = fsnode.getParent().getPath();
|
||||
}
|
||||
|
||||
PresetParser parser;
|
||||
ShaderPreset *shader = parser.parseStream(*stream);
|
||||
|
||||
delete stream;
|
||||
|
||||
if (!shader) {
|
||||
warning("LibRetro Preset Parsing: Error while parsing file '%s': %s", shaderPreset.toString().c_str(), parser.getErrorDesc().c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
shader->container = container;
|
||||
shader->basePath = basePath;
|
||||
return shader;
|
||||
}
|
||||
|
||||
} // End of namespace LibRetro
|
||||
} // End of namespace OpenGL
|
||||
#endif // !USE_FORCED_GLES
|
||||
39
backends/graphics/opengl/pipelines/libretro/parser.h
Normal file
39
backends/graphics/opengl/pipelines/libretro/parser.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_LIBRETRO_PARSER_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_PIPELINES_LIBRETRO_PARSER_H
|
||||
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
#include "backends/graphics/opengl/pipelines/libretro/types.h"
|
||||
|
||||
namespace OpenGL {
|
||||
namespace LibRetro {
|
||||
|
||||
ShaderPreset *parsePreset(const Common::Path &shaderPreset, Common::SearchSet &archSet);
|
||||
|
||||
} // End of namespace LibRetro
|
||||
} // End of namespace OpenGL
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
#endif
|
||||
132
backends/graphics/opengl/pipelines/libretro/types.h
Normal file
132
backends/graphics/opengl/pipelines/libretro/types.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_LIBRETRO_TYPES_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_PIPELINES_LIBRETRO_TYPES_H
|
||||
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
#include "graphics/opengl/texture.h"
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
#include "common/str.h"
|
||||
#include "common/array.h"
|
||||
#include "common/fs.h"
|
||||
|
||||
namespace OpenGL {
|
||||
namespace LibRetro {
|
||||
|
||||
typedef Common::HashMap<Common::String, float, Common::CaseSensitiveString_Hash, Common::CaseSensitiveString_EqualTo> UniformsMap;
|
||||
|
||||
enum FilteringMode {
|
||||
kFilteringModeUnspecified,
|
||||
kFilteringModeNearest,
|
||||
kFilteringModeLinear
|
||||
};
|
||||
|
||||
struct ShaderTexture {
|
||||
ShaderTexture() : id(), fileName(), filteringMode(kFilteringModeUnspecified) {}
|
||||
ShaderTexture(const Common::String &i, const Common::String &fN, FilteringMode fM, WrapMode wM)
|
||||
: id(i), fileName(fN), filteringMode(fM), wrapMode(wM) {}
|
||||
|
||||
Common::String id;
|
||||
Common::String fileName;
|
||||
FilteringMode filteringMode;
|
||||
WrapMode wrapMode;
|
||||
};
|
||||
|
||||
enum ScaleType {
|
||||
kScaleTypeSource,
|
||||
kScaleTypeViewport,
|
||||
kScaleTypeAbsolute,
|
||||
kScaleTypeFull
|
||||
};
|
||||
|
||||
inline void applyScale(const ScaleType type,
|
||||
const float source, const float viewport,
|
||||
const float scaleFloat, const uint scaleUint,
|
||||
float *output) {
|
||||
switch (type) {
|
||||
case kScaleTypeSource:
|
||||
*output = source * scaleFloat;
|
||||
break;
|
||||
|
||||
case kScaleTypeViewport:
|
||||
*output = viewport * scaleFloat;
|
||||
break;
|
||||
|
||||
case kScaleTypeAbsolute:
|
||||
*output = scaleUint;
|
||||
break;
|
||||
|
||||
case kScaleTypeFull:
|
||||
*output = viewport;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ShaderPass {
|
||||
Common::String fileName;
|
||||
Common::String alias;
|
||||
|
||||
FilteringMode filteringMode;
|
||||
WrapMode wrapMode;
|
||||
bool mipmapInput;
|
||||
|
||||
bool floatFBO;
|
||||
bool srgbFBO;
|
||||
|
||||
uint frameCountMod;
|
||||
|
||||
ScaleType scaleTypeX;
|
||||
ScaleType scaleTypeY;
|
||||
|
||||
float scaleXFloat;
|
||||
float scaleYFloat;
|
||||
|
||||
uint scaleXUint;
|
||||
uint scaleYUint;
|
||||
|
||||
void applyScale(const float sourceW, const float sourceH,
|
||||
const float viewportW, const float viewportH,
|
||||
float *outputW, float *outputH) const {
|
||||
OpenGL::LibRetro::applyScale(scaleTypeX, sourceW, viewportW, scaleXFloat, scaleXUint, outputW);
|
||||
OpenGL::LibRetro::applyScale(scaleTypeY, sourceH, viewportH, scaleYFloat, scaleYUint, outputH);
|
||||
}
|
||||
};
|
||||
|
||||
struct ShaderPreset {
|
||||
Common::Archive *container;
|
||||
Common::Path basePath;
|
||||
|
||||
typedef Common::Array<ShaderTexture> TextureArray;
|
||||
TextureArray textures;
|
||||
|
||||
typedef Common::Array<ShaderPass> PassArray;
|
||||
PassArray passes;
|
||||
|
||||
UniformsMap parameters;
|
||||
};
|
||||
|
||||
} // End of namespace LibRetro
|
||||
} // End of namespace OpenGL
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
#endif
|
||||
81
backends/graphics/opengl/pipelines/pipeline.cpp
Normal file
81
backends/graphics/opengl/pipelines/pipeline.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "backends/graphics/opengl/pipelines/pipeline.h"
|
||||
#include "backends/graphics/opengl/framebuffer.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
Pipeline *Pipeline::activePipeline = nullptr;
|
||||
|
||||
Pipeline::Pipeline()
|
||||
: _activeFramebuffer(nullptr) {
|
||||
}
|
||||
|
||||
void Pipeline::activate() {
|
||||
if (activePipeline == this) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (activePipeline) {
|
||||
activePipeline->deactivate();
|
||||
}
|
||||
|
||||
activePipeline = this;
|
||||
|
||||
activateInternal();
|
||||
}
|
||||
|
||||
void Pipeline::activateInternal() {
|
||||
if (_activeFramebuffer) {
|
||||
_activeFramebuffer->activate(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Pipeline::deactivate() {
|
||||
assert(isActive());
|
||||
|
||||
deactivateInternal();
|
||||
|
||||
activePipeline = nullptr;
|
||||
}
|
||||
|
||||
void Pipeline::deactivateInternal() {
|
||||
if (_activeFramebuffer) {
|
||||
_activeFramebuffer->deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
Framebuffer *Pipeline::setFramebuffer(Framebuffer *framebuffer) {
|
||||
Framebuffer *oldFramebuffer = _activeFramebuffer;
|
||||
if (isActive() && oldFramebuffer) {
|
||||
oldFramebuffer->deactivate();
|
||||
}
|
||||
|
||||
_activeFramebuffer = framebuffer;
|
||||
if (isActive() && _activeFramebuffer) {
|
||||
_activeFramebuffer->activate(this);
|
||||
}
|
||||
|
||||
return oldFramebuffer;
|
||||
}
|
||||
|
||||
} // End of namespace OpenGL
|
||||
167
backends/graphics/opengl/pipelines/pipeline.h
Normal file
167
backends/graphics/opengl/pipelines/pipeline.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_PIPELINE_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_PIPELINES_PIPELINE_H
|
||||
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
#include "graphics/opengl/texture.h"
|
||||
|
||||
#include "math/matrix4.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
class Framebuffer;
|
||||
|
||||
/**
|
||||
* Interface for OpenGL pipeline functionality.
|
||||
*
|
||||
* This encapsulates differences in various rendering pipelines used for
|
||||
* OpenGL, OpenGL ES 1, and OpenGL ES 2.
|
||||
*/
|
||||
class Pipeline {
|
||||
public:
|
||||
/**
|
||||
* Deactivate any pipeline.
|
||||
*/
|
||||
static void disable() { if (activePipeline) activePipeline->deactivate(); }
|
||||
|
||||
Pipeline();
|
||||
virtual ~Pipeline() { if (isActive()) deactivate(); }
|
||||
|
||||
/**
|
||||
* Activate the pipeline.
|
||||
*
|
||||
* This sets the OpenGL state to make use of drawing with the given
|
||||
* OpenGL pipeline.
|
||||
*/
|
||||
void activate();
|
||||
|
||||
/**
|
||||
* Deactivate the pipeline.
|
||||
*/
|
||||
void deactivate();
|
||||
|
||||
/**
|
||||
* Set framebuffer to render to.
|
||||
*
|
||||
* Client is responsible for any memory management related to framebuffer.
|
||||
*
|
||||
* @param framebuffer Framebuffer to activate.
|
||||
* @return Formerly active framebuffer.
|
||||
*/
|
||||
Framebuffer *setFramebuffer(Framebuffer *framebuffer);
|
||||
|
||||
/**
|
||||
* Set modulation color.
|
||||
*
|
||||
* @param r Red component in [0,1].
|
||||
* @param g Green component in [0,1].
|
||||
* @param b Blue component in [0,1].
|
||||
* @param a Alpha component in [0,1].
|
||||
*/
|
||||
virtual void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) = 0;
|
||||
|
||||
/**
|
||||
* Draw a texture rectangle to the currently active framebuffer.
|
||||
*
|
||||
* @param texture Texture to use for drawing.
|
||||
* @param coordinates x1, y1, x2, y2 coordinates where to draw the texture.
|
||||
*/
|
||||
inline void drawTexture(const Texture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
|
||||
drawTextureInternal(texture, coordinates, texcoords);
|
||||
}
|
||||
|
||||
inline void drawTexture(const Texture &texture, const GLfloat *coordinates) {
|
||||
drawTextureInternal(texture, coordinates, texture.getTexCoords());
|
||||
}
|
||||
|
||||
inline void drawTexture(const Texture &texture, GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
|
||||
const GLfloat coordinates[4*2] = {
|
||||
x, y,
|
||||
x + w, y,
|
||||
x, y + h,
|
||||
x + w, y + h
|
||||
};
|
||||
drawTextureInternal(texture, coordinates, texture.getTexCoords());
|
||||
}
|
||||
|
||||
inline void drawTexture(const Texture &texture, GLfloat x, GLfloat y, GLfloat w, GLfloat h, const Common::Rect &clip) {
|
||||
const GLfloat coordinates[4*2] = {
|
||||
x, y,
|
||||
x + w, y,
|
||||
x, y + h,
|
||||
x + w, y + h
|
||||
};
|
||||
|
||||
const uint tw = texture.getWidth(),
|
||||
th = texture.getHeight();
|
||||
|
||||
if (tw == 0 || th == 0) {
|
||||
// Nothing to display
|
||||
return;
|
||||
}
|
||||
|
||||
const GLfloat texcoords[4*2] = {
|
||||
(float)clip.left / tw, (float)clip.top / th,
|
||||
(float)clip.right / tw, (float)clip.top / th,
|
||||
(float)clip.left / tw, (float)clip.bottom / th,
|
||||
(float)clip.right / tw, (float)clip.bottom / th
|
||||
};
|
||||
|
||||
drawTextureInternal(texture, coordinates, texcoords);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the projection matrix.
|
||||
*
|
||||
* This is intended to be only ever be used by Framebuffer subclasses.
|
||||
*/
|
||||
virtual void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Activate the pipeline.
|
||||
*
|
||||
* This sets the OpenGL state to make use of drawing with the given
|
||||
* OpenGL pipeline.
|
||||
*/
|
||||
virtual void activateInternal();
|
||||
|
||||
/**
|
||||
* Deactivate the pipeline.
|
||||
*/
|
||||
virtual void deactivateInternal();
|
||||
|
||||
virtual void drawTextureInternal(const Texture &texture, const GLfloat *coordinates, const GLfloat *texcoords) = 0;
|
||||
|
||||
bool isActive() const { return activePipeline == this; }
|
||||
|
||||
Framebuffer *_activeFramebuffer;
|
||||
|
||||
private:
|
||||
/** Currently active rendering pipeline. */
|
||||
static Pipeline *activePipeline;
|
||||
};
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
||||
110
backends/graphics/opengl/pipelines/shader.cpp
Normal file
110
backends/graphics/opengl/pipelines/shader.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "backends/graphics/opengl/pipelines/shader.h"
|
||||
#include "backends/graphics/opengl/shader.h"
|
||||
#include "backends/graphics/opengl/framebuffer.h"
|
||||
#include "graphics/opengl/debug.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
// A 4 elements with 2 components vector of floats
|
||||
static const int kCoordinatesSize = 4 * 2 * sizeof(float);
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
ShaderPipeline::ShaderPipeline(Shader *shader)
|
||||
: _activeShader(shader), _colorAttributes(), _colorDirty(true) {
|
||||
// Use the same VBO for vertices and texcoords as we modify them at the same time
|
||||
_coordsVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, kCoordinatesSize, nullptr, GL_STATIC_DRAW);
|
||||
_activeShader->enableVertexAttribute("position", _coordsVBO, 2, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
_texcoordsVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, kCoordinatesSize, nullptr, GL_STATIC_DRAW);
|
||||
_activeShader->enableVertexAttribute("texCoordIn", _texcoordsVBO, 2, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
_colorVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(_colorAttributes), nullptr, GL_DYNAMIC_DRAW);
|
||||
_activeShader->enableVertexAttribute("blendColorIn", _colorVBO, 4, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
}
|
||||
|
||||
ShaderPipeline::~ShaderPipeline() {
|
||||
delete _activeShader;
|
||||
|
||||
OpenGL::Shader::freeBuffer(_coordsVBO);
|
||||
OpenGL::Shader::freeBuffer(_texcoordsVBO);
|
||||
OpenGL::Shader::freeBuffer(_colorVBO);
|
||||
}
|
||||
|
||||
void ShaderPipeline::activateInternal() {
|
||||
Pipeline::activateInternal();
|
||||
|
||||
// Disable 3D properties.
|
||||
GL_CALL(glDisable(GL_CULL_FACE));
|
||||
GL_CALL(glDisable(GL_DEPTH_TEST));
|
||||
GL_CALL(glDisable(GL_DITHER));
|
||||
|
||||
if (OpenGLContext.multitextureSupported) {
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE0));
|
||||
}
|
||||
|
||||
_activeShader->use();
|
||||
}
|
||||
|
||||
void ShaderPipeline::deactivateInternal() {
|
||||
_activeShader->unbind();
|
||||
|
||||
Pipeline::deactivateInternal();
|
||||
}
|
||||
|
||||
void ShaderPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
|
||||
GLfloat *dst = _colorAttributes;
|
||||
for (uint i = 0; i < 4; ++i) {
|
||||
*dst++ = r;
|
||||
*dst++ = g;
|
||||
*dst++ = b;
|
||||
*dst++ = a;
|
||||
}
|
||||
_colorDirty = true;
|
||||
}
|
||||
|
||||
void ShaderPipeline::drawTextureInternal(const Texture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
|
||||
assert(isActive());
|
||||
|
||||
texture.bind();
|
||||
|
||||
if (_colorDirty) {
|
||||
GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, _colorVBO));
|
||||
GL_CALL(glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(_colorAttributes), _colorAttributes));
|
||||
_colorDirty = false;
|
||||
}
|
||||
GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, _coordsVBO));
|
||||
GL_CALL(glBufferData(GL_ARRAY_BUFFER, kCoordinatesSize, coordinates, GL_STATIC_DRAW));
|
||||
GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, _texcoordsVBO));
|
||||
GL_CALL(glBufferData(GL_ARRAY_BUFFER, kCoordinatesSize, texcoords, GL_STATIC_DRAW));
|
||||
GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
|
||||
GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
|
||||
void ShaderPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix) {
|
||||
assert(isActive());
|
||||
|
||||
_activeShader->setUniform("projection", projectionMatrix);
|
||||
}
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
} // End of namespace OpenGL
|
||||
59
backends/graphics/opengl/pipelines/shader.h
Normal file
59
backends/graphics/opengl/pipelines/shader.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_SHADER_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_PIPELINES_SHADER_H
|
||||
|
||||
#include "backends/graphics/opengl/pipelines/pipeline.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
class Shader;
|
||||
|
||||
class ShaderPipeline : public Pipeline {
|
||||
public:
|
||||
ShaderPipeline(Shader *shader);
|
||||
~ShaderPipeline() override;
|
||||
|
||||
void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) override;
|
||||
|
||||
void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
|
||||
|
||||
protected:
|
||||
void activateInternal() override;
|
||||
void deactivateInternal() override;
|
||||
void drawTextureInternal(const Texture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
|
||||
|
||||
GLuint _coordsVBO;
|
||||
GLuint _texcoordsVBO;
|
||||
GLuint _colorVBO;
|
||||
|
||||
GLfloat _colorAttributes[4*4];
|
||||
bool _colorDirty;
|
||||
|
||||
Shader *const _activeShader;
|
||||
};
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user