diff --git a/components/sdlutil/sdlcursormanager.cpp b/components/sdlutil/sdlcursormanager.cpp index bf265dc7e..1747c9b94 100644 --- a/components/sdlutil/sdlcursormanager.cpp +++ b/components/sdlutil/sdlcursormanager.cpp @@ -25,15 +25,14 @@ USE_GRAPHICSWINDOW() #endif -#if OSG_VERSION_GREATER_OR_EQUAL(3, 5, 8) || defined(__APPLE__) -#define OPENMW_USE_SOFTWARE_CURSOR_DECOMPRESSION 1 -#else -#define OPENMW_USE_SOFTWARE_CURSOR_DECOMPRESSION 0 -#endif - -#if !OPENMW_USE_SOFTWARE_CURSOR_DECOMPRESSION -namespace +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: @@ -90,10 +89,8 @@ namespace osg::ref_ptr _gc; }; - osg::ref_ptr decompress (osg::ref_ptr source, float rotDegrees) + SDLUtil::SurfaceUniquePtr hardwareDecompress (osg::ref_ptr source, float rotDegrees) { - // TODO: use software decompression once S3TC patent expires - int width = source->s(); int height = source->t(); @@ -152,11 +149,55 @@ namespace source->releaseGLObjects(); texture->releaseGLObjects(); - return resultImage; + return SDLUtil::imageToSurface(resultImage, true); + } + + SDLUtil::SurfaceUniquePtr softwareDecompress (osg::ref_ptr source, float rotDegrees) + { + int width = source->s(); + int height = source->t(); + bool useAlpha = source->isImageTranslucent(); + + osg::ref_ptr 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; ssetColor(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, NULL, NULL, -rotDegrees, NULL, SDL_FLIP_VERTICAL); + + SDL_DestroyTexture(cursorTexture); + SDL_FreeSurface(cursorSurface); + SDL_DestroyRenderer(renderer); + + return SDLUtil::SurfaceUniquePtr(targetSurface, SDL_FreeSurface); } } -#endif namespace SDLUtil { @@ -220,77 +261,32 @@ namespace SDLUtil #endif } -#if OPENMW_USE_SOFTWARE_CURSOR_DECOMPRESSION - SurfaceUniquePtr decompress(osg::Image* source, int rotDegrees) - { - int width = source->s(); - int height = source->t(); - bool useAlpha = source->isImageTranslucent(); - - osg::ref_ptr 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; ssetColor(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, NULL, NULL, -rotDegrees, NULL, SDL_FLIP_VERTICAL); - - SDL_DestroyTexture(cursorTexture); - SDL_FreeSurface(cursorSurface); - SDL_DestroyRenderer(renderer); - - return SurfaceUniquePtr(targetSurface, SDL_FreeSurface); - } -#endif - 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; -#if !OPENMW_USE_SOFTWARE_CURSOR_DECOMPRESSION - osg::ref_ptr decompressed; + static bool forceSoftwareDecompression = (getenv("OPENMW_DECOMPRESS_TEXTURES") != 0); + + SurfaceUniquePtr (*decompressionFunction)(osg::ref_ptr, float); + if (forceSoftwareDecompression || CursorDecompression::DXTCSupported) { + decompressionFunction = CursorDecompression::softwareDecompress; + } else { + decompressionFunction = CursorDecompression::hardwareDecompress; + } try { - decompressed = decompress(image, static_cast(rotDegrees)); + auto surface = decompressionFunction(image, static_cast(rotDegrees)); + + //set the cursor and store it for later + SDL_Cursor* curs = SDL_CreateColorCursor(surface.get(), hotspot_x, hotspot_y); + + mCursorMap.insert(CursorMap::value_type(std::string(name), curs)); } catch (std::exception& e) { std::cerr << e.what() << std::endl; std::cerr <<"Using default cursor."<