#5534 remove OSG 3.4 support and require at least 3.6.5 support

This commit is contained in:
psi29a 2022-08-09 21:07:28 +00:00
parent bb9884c024
commit b551e69b6f
14 changed files with 59 additions and 348 deletions

View file

@ -1,8 +1,6 @@
#include "sdlcursormanager.hpp"
#include <cassert>
#include <stdexcept>
#include <cstdlib>
#include <SDL_mouse.h>
#include <SDL_endian.h>
@ -26,180 +24,6 @@
USE_GRAPHICSWINDOW()
#endif
namespace CursorDecompression
{
// macOS builds use the OSG fork that includes DXTC commit
#if OSG_VERSION_GREATER_OR_EQUAL(3, 5, 8) || defined(__APPLE__)
static const bool DXTCSupported = true;
#else
static const bool DXTCSupported = false;
#endif
class MyGraphicsContext {
public:
MyGraphicsContext(int w, int h)
{
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->x = 0;
traits->y = 0;
traits->width = w;
traits->height = h;
traits->red = 8;
traits->green = 8;
traits->blue = 8;
traits->alpha = 8;
traits->windowDecoration = false;
traits->doubleBuffer = false;
traits->sharedContext = nullptr;
traits->pbuffer = true;
osg::GraphicsContext::ScreenIdentifier si;
si.readDISPLAY();
if (si.displayNum<0) si.displayNum = 0;
traits->displayNum = si.displayNum;
traits->screenNum = si.screenNum;
traits->hostName = si.hostName;
_gc = osg::GraphicsContext::createGraphicsContext(traits.get());
if (!_gc)
{
Log(Debug::Warning) << "Failed to create pbuffer, failing back to normal graphics window.";
traits->pbuffer = false;
_gc = osg::GraphicsContext::createGraphicsContext(traits.get());
if (!_gc)
throw std::runtime_error("Failed to create graphics context for image decompression");
}
if (_gc.valid())
{
_gc->realize();
_gc->makeCurrent();
}
}
osg::ref_ptr<osg::GraphicsContext> getContext()
{
return _gc;
}
bool valid() const { return _gc.valid() && _gc->isRealized(); }
private:
osg::ref_ptr<osg::GraphicsContext> _gc;
};
SDLUtil::SurfaceUniquePtr hardwareDecompress (osg::ref_ptr<osg::Image> source, float rotDegrees)
{
int width = source->s();
int height = source->t();
MyGraphicsContext context(width, height);
osg::ref_ptr<osg::State> state = context.getContext()->getState();
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
texture->setImage(source);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER);
texture->setBorderColor(osg::Vec4f(0.f, 0.f, 0.f, 0.f));
osg::ref_ptr<osg::TexMat> texmat = new osg::TexMat;
osg::Matrix texRot (osg::Matrix::identity());
float theta ( osg::DegreesToRadians(-rotDegrees) );
float cosTheta = std::cos(theta);
float sinTheta = std::sin(theta);
texRot(0,0) = cosTheta;
texRot(1,0) = -sinTheta;
texRot(0,1) = sinTheta;
texRot(1,1) = cosTheta;
// Offset center of rotation to center of texture
texRot(3,0) = 0.5f + ( (-0.5f * cosTheta) - (-0.5f * sinTheta) );
texRot(3,1) = 0.5f + ( (-0.5f * sinTheta) + (-0.5f * cosTheta) );
texmat->setMatrix(texRot);
state->applyTextureAttribute(0, texmat);
osg::ref_ptr<osg::RefMatrix> identity (new osg::RefMatrix(osg::Matrix::identity()));
state->applyModelViewMatrix(identity);
state->applyProjectionMatrix(identity);
state->applyMode(GL_TEXTURE_2D, true);
state->applyTextureAttribute(0, texture);
osg::ref_ptr<osg::Image> resultImage = new osg::Image;
resultImage->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
osg::RenderInfo renderInfo;
renderInfo.setState(state);
glViewport(0, 0, width, height);
osg::ref_ptr<osg::Geometry> geom;
geom = osg::createTexturedQuadGeometry(osg::Vec3(-1,-1,0), osg::Vec3(2,0,0), osg::Vec3(0,2,0));
geom->drawImplementation(renderInfo);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, resultImage->data());
geom->releaseGLObjects();
source->releaseGLObjects();
texture->releaseGLObjects();
return SDLUtil::imageToSurface(resultImage, true);
}
SDLUtil::SurfaceUniquePtr softwareDecompress (osg::ref_ptr<osg::Image> source, float rotDegrees)
{
int width = source->s();
int height = source->t();
bool useAlpha = source->isImageTranslucent();
osg::ref_ptr<osg::Image> decompressedImage = new osg::Image;
decompressedImage->setFileName(source->getFileName());
decompressedImage->allocateImage(width, height, 1, useAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE);
for (int s=0; s<width; ++s)
for (int t=0; t<height; ++t)
decompressedImage->setColor(source->getColor(s,t,0), s,t,0);
Uint32 redMask = 0x000000ff;
Uint32 greenMask = 0x0000ff00;
Uint32 blueMask = 0x00ff0000;
Uint32 alphaMask = useAlpha ? 0xff000000 : 0;
SDL_Surface *cursorSurface = SDL_CreateRGBSurfaceFrom(decompressedImage->data(),
width,
height,
decompressedImage->getPixelSizeInBits(),
decompressedImage->getRowSizeInBytes(),
redMask,
greenMask,
blueMask,
alphaMask);
SDL_Surface *targetSurface = SDL_CreateRGBSurface(0, width, height, 32, redMask, greenMask, blueMask, alphaMask);
SDL_Renderer *renderer = SDL_CreateSoftwareRenderer(targetSurface);
SDL_RenderClear(renderer);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
SDL_Texture *cursorTexture = SDL_CreateTextureFromSurface(renderer, cursorSurface);
SDL_RenderCopyEx(renderer, cursorTexture, nullptr, nullptr, -rotDegrees, nullptr, SDL_FLIP_VERTICAL);
SDL_DestroyTexture(cursorTexture);
SDL_FreeSurface(cursorSurface);
SDL_DestroyRenderer(renderer);
return SDLUtil::SurfaceUniquePtr(targetSurface, SDL_FreeSurface);
}
}
namespace SDLUtil
{
@ -262,22 +86,58 @@ namespace SDLUtil
#endif
}
SDLUtil::SurfaceUniquePtr decompress(osg::ref_ptr<osg::Image> source, float rotDegrees)
{
int width = source->s();
int height = source->t();
bool useAlpha = source->isImageTranslucent();
osg::ref_ptr<osg::Image> decompressedImage = new osg::Image;
decompressedImage->setFileName(source->getFileName());
decompressedImage->allocateImage(width, height, 1, useAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE);
for (int s=0; s<width; ++s)
for (int t=0; t<height; ++t)
decompressedImage->setColor(source->getColor(s,t,0), s,t,0);
Uint32 redMask = 0x000000ff;
Uint32 greenMask = 0x0000ff00;
Uint32 blueMask = 0x00ff0000;
Uint32 alphaMask = useAlpha ? 0xff000000 : 0;
SDL_Surface *cursorSurface = SDL_CreateRGBSurfaceFrom(decompressedImage->data(),
width,
height,
decompressedImage->getPixelSizeInBits(),
decompressedImage->getRowSizeInBytes(),
redMask,
greenMask,
blueMask,
alphaMask);
SDL_Surface *targetSurface = SDL_CreateRGBSurface(0, width, height, 32, redMask, greenMask, blueMask, alphaMask);
SDL_Renderer *renderer = SDL_CreateSoftwareRenderer(targetSurface);
SDL_RenderClear(renderer);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
SDL_Texture *cursorTexture = SDL_CreateTextureFromSurface(renderer, cursorSurface);
SDL_RenderCopyEx(renderer, cursorTexture, nullptr, nullptr, -rotDegrees, nullptr, SDL_FLIP_VERTICAL);
SDL_DestroyTexture(cursorTexture);
SDL_FreeSurface(cursorSurface);
SDL_DestroyRenderer(renderer);
return SDLUtil::SurfaceUniquePtr(targetSurface, SDL_FreeSurface);
}
void SDLCursorManager::_createCursorFromResource(const std::string& name, int rotDegrees, osg::Image* image, Uint8 hotspot_x, Uint8 hotspot_y)
{
if (mCursorMap.find(name) != mCursorMap.end())
return;
static bool forceSoftwareDecompression = (getenv("OPENMW_DECOMPRESS_TEXTURES") != nullptr);
SurfaceUniquePtr (*decompressionFunction)(osg::ref_ptr<osg::Image>, float);
if (forceSoftwareDecompression || CursorDecompression::DXTCSupported) {
decompressionFunction = CursorDecompression::softwareDecompress;
} else {
decompressionFunction = CursorDecompression::hardwareDecompress;
}
try {
auto surface = decompressionFunction(image, static_cast<float>(rotDegrees));
auto surface = decompress(image, static_cast<float>(rotDegrees));
//set the cursor and store it for later
SDL_Cursor* curs = SDL_CreateColorCursor(surface.get(), hotspot_x, hotspot_y);