7
7
8
8
#include < SDL_mouse.h>
9
9
#include < SDL_endian.h>
10
+ #include < SDL_render.h>
11
+ #include < SDL_hints.h>
10
12
11
13
#include < osg/GraphicsContext>
12
14
#include < osg/Geometry>
13
15
#include < osg/Texture2D>
14
16
#include < osg/TexMat>
17
+ #include < osg/Version>
15
18
#include < osgViewer/GraphicsWindow>
16
19
17
20
#include " imagetosurface.hpp"
22
25
USE_GRAPHICSWINDOW ()
23
26
#endif
24
27
25
- namespace
28
+ namespace CursorDecompression
26
29
{
30
+ // macOS builds use the OSG fork that includes DXTC commit
31
+ #if OSG_VERSION_GREATER_OR_EQUAL(3, 5, 8) || defined(__APPLE__)
32
+ static const bool DXTCSupported = true ;
33
+ #else
34
+ static const bool DXTCSupported = false ;
35
+ #endif
27
36
28
37
class MyGraphicsContext {
29
38
public:
@@ -80,10 +89,8 @@ namespace
80
89
osg::ref_ptr<osg::GraphicsContext> _gc;
81
90
};
82
91
83
- osg::ref_ptr<osg::Image> decompress (osg::ref_ptr<osg::Image> source, float rotDegrees)
92
+ SDLUtil::SurfaceUniquePtr hardwareDecompress (osg::ref_ptr<osg::Image> source, float rotDegrees)
84
93
{
85
- // TODO: use software decompression once S3TC patent expires
86
-
87
94
int width = source->s ();
88
95
int height = source->t ();
89
96
@@ -132,17 +139,6 @@ namespace
132
139
133
140
osg::ref_ptr<osg::Geometry> geom;
134
141
135
- #if defined(__APPLE__)
136
- // Extra flip needed on OS X systems due to a driver bug
137
- const char * envval = getenv (" OPENMW_CURSOR_WORKAROUND" );
138
- bool workaround = !envval || envval == std::string (" 1" );
139
- std::string vendorString = (const char *)glGetString (GL_VENDOR);
140
- if (!envval)
141
- workaround = vendorString.find (" Intel" ) != std::string::npos || vendorString.find (" ATI" ) != std::string::npos || vendorString.find (" AMD" ) != std::string::npos;
142
- if (workaround)
143
- geom = osg::createTexturedQuadGeometry (osg::Vec3 (-1 ,1 ,0 ), osg::Vec3 (2 ,0 ,0 ), osg::Vec3 (0 ,-2 ,0 ));
144
- else
145
- #endif
146
142
geom = osg::createTexturedQuadGeometry (osg::Vec3 (-1 ,-1 ,0 ), osg::Vec3 (2 ,0 ,0 ), osg::Vec3 (0 ,2 ,0 ));
147
143
148
144
geom->drawImplementation (renderInfo);
@@ -153,7 +149,52 @@ namespace
153
149
source->releaseGLObjects ();
154
150
texture->releaseGLObjects ();
155
151
156
- return resultImage;
152
+ return SDLUtil::imageToSurface (resultImage, true );
153
+ }
154
+
155
+ SDLUtil::SurfaceUniquePtr softwareDecompress (osg::ref_ptr<osg::Image> source, float rotDegrees)
156
+ {
157
+ int width = source->s ();
158
+ int height = source->t ();
159
+ bool useAlpha = source->isImageTranslucent ();
160
+
161
+ osg::ref_ptr<osg::Image> decompressedImage = new osg::Image;
162
+ decompressedImage->setFileName (source->getFileName ());
163
+ decompressedImage->allocateImage (width, height, 1 , useAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE);
164
+ for (int s=0 ; s<width; ++s)
165
+ for (int t=0 ; t<height; ++t)
166
+ decompressedImage->setColor (source->getColor (s,t,0 ), s,t,0 );
167
+
168
+ Uint32 redMask = 0x000000ff ;
169
+ Uint32 greenMask = 0x0000ff00 ;
170
+ Uint32 blueMask = 0x00ff0000 ;
171
+ Uint32 alphaMask = useAlpha ? 0xff000000 : 0 ;
172
+
173
+ SDL_Surface *cursorSurface = SDL_CreateRGBSurfaceFrom (decompressedImage->data (),
174
+ width,
175
+ height,
176
+ decompressedImage->getPixelSizeInBits (),
177
+ decompressedImage->getRowSizeInBytes (),
178
+ redMask,
179
+ greenMask,
180
+ blueMask,
181
+ alphaMask);
182
+
183
+ SDL_Surface *targetSurface = SDL_CreateRGBSurface (0 , width, height, 32 , redMask, greenMask, blueMask, alphaMask);
184
+ SDL_Renderer *renderer = SDL_CreateSoftwareRenderer (targetSurface);
185
+
186
+ SDL_RenderClear (renderer);
187
+
188
+ SDL_SetHint (SDL_HINT_RENDER_SCALE_QUALITY, " 1" );
189
+ SDL_Texture *cursorTexture = SDL_CreateTextureFromSurface (renderer, cursorSurface);
190
+
191
+ SDL_RenderCopyEx (renderer, cursorTexture, NULL , NULL , -rotDegrees, NULL , SDL_FLIP_VERTICAL);
192
+
193
+ SDL_DestroyTexture (cursorTexture);
194
+ SDL_FreeSurface (cursorSurface);
195
+ SDL_DestroyRenderer (renderer);
196
+
197
+ return SDLUtil::SurfaceUniquePtr (targetSurface, SDL_FreeSurface);
157
198
}
158
199
159
200
}
@@ -222,27 +263,30 @@ namespace SDLUtil
222
263
223
264
void SDLCursorManager::_createCursorFromResource (const std::string& name, int rotDegrees, osg::Image* image, Uint8 hotspot_x, Uint8 hotspot_y)
224
265
{
225
- osg::ref_ptr<osg::Image> decompressed;
226
-
227
266
if (mCursorMap .find (name) != mCursorMap .end ())
228
267
return ;
229
268
269
+ static bool forceSoftwareDecompression = (getenv (" OPENMW_DECOMPRESS_TEXTURES" ) != 0 );
270
+
271
+ SurfaceUniquePtr (*decompressionFunction)(osg::ref_ptr<osg::Image>, float );
272
+ if (forceSoftwareDecompression || CursorDecompression::DXTCSupported) {
273
+ decompressionFunction = CursorDecompression::softwareDecompress;
274
+ } else {
275
+ decompressionFunction = CursorDecompression::hardwareDecompress;
276
+ }
277
+
230
278
try {
231
- decompressed = decompress (image, static_cast <float >(rotDegrees));
279
+ auto surface = decompressionFunction (image, static_cast <float >(rotDegrees));
280
+
281
+ // set the cursor and store it for later
282
+ SDL_Cursor* curs = SDL_CreateColorCursor (surface.get (), hotspot_x, hotspot_y);
283
+
284
+ mCursorMap .insert (CursorMap::value_type (std::string (name), curs));
232
285
} catch (std::exception & e) {
233
286
std::cerr << e.what () << std::endl;
234
287
std::cerr <<" Using default cursor." <<std::endl;
235
288
return ;
236
289
}
237
-
238
- SDL_Surface* surf = SDLUtil::imageToSurface (decompressed, true );
239
-
240
- // set the cursor and store it for later
241
- SDL_Cursor* curs = SDL_CreateColorCursor (surf, hotspot_x, hotspot_y);
242
- mCursorMap .insert (CursorMap::value_type (std::string (name), curs));
243
-
244
- // clean up
245
- SDL_FreeSurface (surf);
246
290
}
247
291
248
292
}
0 commit comments