diff --git a/CMakeLists.txt b/CMakeLists.txt index 66966e7756..e40ce41ff6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,9 @@ endif () if (DISABLE_OPENGL) add_definitions(-DDISABLE_OPENGL) +else (DISABLE_OPENGL) + # Makes OpenGL function get queried in run-time rather than linked-in + add_definitions(-DOPENGL_NO_LINK) endif (DISABLE_OPENGL) if (DISABLE_NETWORK) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index e4cd72b85b..6a0f0dad32 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -117,6 +117,18 @@ D41B73EF1C2101890080A7B9 /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B73EE1C2101890080A7B9 /* libcurl.tbd */; }; D41B741D1C210A7A0080A7B9 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B741C1C210A7A0080A7B9 /* libiconv.tbd */; }; D41B74731C2125E50080A7B9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D41B74721C2125E50080A7B9 /* Assets.xcassets */; }; + D43407D61D0E14BE00C2B3D4 /* CopyFramebufferShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D43407C01D0E14BE00C2B3D4 /* CopyFramebufferShader.cpp */; }; + D43407D71D0E14BE00C2B3D4 /* DrawImageMaskedShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D43407C21D0E14BE00C2B3D4 /* DrawImageMaskedShader.cpp */; }; + D43407D81D0E14BE00C2B3D4 /* DrawImageShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D43407C41D0E14BE00C2B3D4 /* DrawImageShader.cpp */; }; + D43407D91D0E14BE00C2B3D4 /* DrawLineShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D43407C61D0E14BE00C2B3D4 /* DrawLineShader.cpp */; }; + D43407DA1D0E14BE00C2B3D4 /* FillRectShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D43407C81D0E14BE00C2B3D4 /* FillRectShader.cpp */; }; + D43407DB1D0E14BE00C2B3D4 /* OpenGLAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D43407CB1D0E14BE00C2B3D4 /* OpenGLAPI.cpp */; }; + D43407DC1D0E14BE00C2B3D4 /* OpenGLDrawingEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D43407CD1D0E14BE00C2B3D4 /* OpenGLDrawingEngine.cpp */; }; + D43407DD1D0E14BE00C2B3D4 /* OpenGLFramebuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D43407CE1D0E14BE00C2B3D4 /* OpenGLFramebuffer.cpp */; }; + D43407DE1D0E14BE00C2B3D4 /* OpenGLShaderProgram.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D43407D01D0E14BE00C2B3D4 /* OpenGLShaderProgram.cpp */; }; + D43407DF1D0E14BE00C2B3D4 /* SwapFramebuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D43407D21D0E14BE00C2B3D4 /* SwapFramebuffer.cpp */; }; + D43407E01D0E14BE00C2B3D4 /* TextureCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D43407D41D0E14BE00C2B3D4 /* TextureCache.cpp */; }; + D43407E21D0E14CE00C2B3D4 /* shaders in Resources */ = {isa = PBXBuildFile; fileRef = D43407E11D0E14CE00C2B3D4 /* shaders */; }; D44271F51CC81B3200D84D28 /* addresses.c in Sources */ = {isa = PBXBuildFile; fileRef = D44270CD1CC81B3200D84D28 /* addresses.c */; }; D44271F61CC81B3200D84D28 /* audio.c in Sources */ = {isa = PBXBuildFile; fileRef = D44270D01CC81B3200D84D28 /* audio.c */; }; D44271F71CC81B3200D84D28 /* mixer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D44270D21CC81B3200D84D28 /* mixer.cpp */; }; @@ -307,10 +319,8 @@ D45A395D1CF300AF00659A24 /* libSDL2_ttf.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38B71CF3006400659A24 /* libSDL2_ttf.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; D45A395E1CF300AF00659A24 /* libSDL2.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38B81CF3006400659A24 /* libSDL2.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; D45A395F1CF300AF00659A24 /* libspeexdsp.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38B91CF3006400659A24 /* libspeexdsp.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; - D45F046B1D07733900CBA2BA /* OpenGLAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D45F04691D07733900CBA2BA /* OpenGLAPI.cpp */; }; D47304D51C4FF8250015C0EA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D47304D41C4FF8250015C0EA /* libz.tbd */; }; D48A8D831D00272F00649DA7 /* TcpSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D48A8D811D00272F00649DA7 /* TcpSocket.cpp */; }; - D49766821D03B9FE002222CD /* OpenGLDrawingEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D49766801D03B9FE002222CD /* OpenGLDrawingEngine.cpp */; }; D49766831D03B9FE002222CD /* SoftwareDrawingEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D49766811D03B9FE002222CD /* SoftwareDrawingEngine.cpp */; }; D49766861D03BAA5002222CD /* NewDrawing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D49766841D03BAA5002222CD /* NewDrawing.cpp */; }; D49766891D03BABB002222CD /* rain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D49766871D03BABB002222CD /* rain.cpp */; }; @@ -468,6 +478,29 @@ D41B73EE1C2101890080A7B9 /* libcurl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.tbd; path = usr/lib/libcurl.tbd; sourceTree = SDKROOT; }; D41B741C1C210A7A0080A7B9 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; D41B74721C2125E50080A7B9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = distribution/osx/Assets.xcassets; sourceTree = SOURCE_ROOT; }; + D43407C01D0E14BE00C2B3D4 /* CopyFramebufferShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CopyFramebufferShader.cpp; sourceTree = ""; }; + D43407C11D0E14BE00C2B3D4 /* CopyFramebufferShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyFramebufferShader.h; sourceTree = ""; }; + D43407C21D0E14BE00C2B3D4 /* DrawImageMaskedShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DrawImageMaskedShader.cpp; sourceTree = ""; }; + D43407C31D0E14BE00C2B3D4 /* DrawImageMaskedShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawImageMaskedShader.h; sourceTree = ""; }; + D43407C41D0E14BE00C2B3D4 /* DrawImageShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DrawImageShader.cpp; sourceTree = ""; }; + D43407C51D0E14BE00C2B3D4 /* DrawImageShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawImageShader.h; sourceTree = ""; }; + D43407C61D0E14BE00C2B3D4 /* DrawLineShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DrawLineShader.cpp; sourceTree = ""; }; + D43407C71D0E14BE00C2B3D4 /* DrawLineShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawLineShader.h; sourceTree = ""; }; + D43407C81D0E14BE00C2B3D4 /* FillRectShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FillRectShader.cpp; sourceTree = ""; }; + D43407C91D0E14BE00C2B3D4 /* FillRectShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FillRectShader.h; sourceTree = ""; }; + D43407CA1D0E14BE00C2B3D4 /* GLSLTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLSLTypes.h; sourceTree = ""; }; + D43407CB1D0E14BE00C2B3D4 /* OpenGLAPI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpenGLAPI.cpp; sourceTree = ""; }; + D43407CC1D0E14BE00C2B3D4 /* OpenGLAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenGLAPI.h; sourceTree = ""; }; + D43407CD1D0E14BE00C2B3D4 /* OpenGLDrawingEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpenGLDrawingEngine.cpp; sourceTree = ""; }; + D43407CE1D0E14BE00C2B3D4 /* OpenGLFramebuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpenGLFramebuffer.cpp; sourceTree = ""; }; + D43407CF1D0E14BE00C2B3D4 /* OpenGLFramebuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenGLFramebuffer.h; sourceTree = ""; }; + D43407D01D0E14BE00C2B3D4 /* OpenGLShaderProgram.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpenGLShaderProgram.cpp; sourceTree = ""; }; + D43407D11D0E14BE00C2B3D4 /* OpenGLShaderProgram.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenGLShaderProgram.h; sourceTree = ""; }; + D43407D21D0E14BE00C2B3D4 /* SwapFramebuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SwapFramebuffer.cpp; sourceTree = ""; }; + D43407D31D0E14BE00C2B3D4 /* SwapFramebuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SwapFramebuffer.h; sourceTree = ""; }; + D43407D41D0E14BE00C2B3D4 /* TextureCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureCache.cpp; sourceTree = ""; }; + D43407D51D0E14BE00C2B3D4 /* TextureCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCache.h; sourceTree = ""; }; + D43407E11D0E14CE00C2B3D4 /* shaders */ = {isa = PBXFileReference; lastKnownFileType = folder; name = shaders; path = data/shaders; sourceTree = SOURCE_ROOT; }; D44270CD1CC81B3200D84D28 /* addresses.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = addresses.c; path = src/addresses.c; sourceTree = ""; }; D44270CE1CC81B3200D84D28 /* addresses.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = addresses.h; path = src/addresses.h; sourceTree = ""; }; D44270D01CC81B3200D84D28 /* audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = audio.c; sourceTree = ""; }; @@ -900,13 +933,10 @@ D45A39561CF3007A00659A24 /* speex_resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speex_resampler.h; sourceTree = ""; }; D45A39571CF3007A00659A24 /* speexdsp_config_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speexdsp_config_types.h; sourceTree = ""; }; D45A39581CF3007A00659A24 /* speexdsp_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speexdsp_types.h; sourceTree = ""; }; - D45F04691D07733900CBA2BA /* OpenGLAPI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpenGLAPI.cpp; sourceTree = ""; }; - D45F046A1D07733900CBA2BA /* OpenGLAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenGLAPI.h; sourceTree = ""; }; D47304D41C4FF8250015C0EA /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; D4895D321C23EFDD000CD788 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = distribution/osx/Info.plist; sourceTree = SOURCE_ROOT; }; D48A8D811D00272F00649DA7 /* TcpSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TcpSocket.cpp; sourceTree = ""; }; D48A8D821D00272F00649DA7 /* TcpSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TcpSocket.h; sourceTree = ""; }; - D49766801D03B9FE002222CD /* OpenGLDrawingEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpenGLDrawingEngine.cpp; sourceTree = ""; }; D49766811D03B9FE002222CD /* SoftwareDrawingEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SoftwareDrawingEngine.cpp; sourceTree = ""; }; D49766841D03BAA5002222CD /* NewDrawing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewDrawing.cpp; sourceTree = ""; }; D49766851D03BAA5002222CD /* NewDrawing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewDrawing.h; sourceTree = ""; }; @@ -1201,6 +1231,35 @@ path = libxc; sourceTree = ""; }; + D43407BF1D0E14BE00C2B3D4 /* opengl */ = { + isa = PBXGroup; + children = ( + D43407C01D0E14BE00C2B3D4 /* CopyFramebufferShader.cpp */, + D43407C11D0E14BE00C2B3D4 /* CopyFramebufferShader.h */, + D43407C21D0E14BE00C2B3D4 /* DrawImageMaskedShader.cpp */, + D43407C31D0E14BE00C2B3D4 /* DrawImageMaskedShader.h */, + D43407C41D0E14BE00C2B3D4 /* DrawImageShader.cpp */, + D43407C51D0E14BE00C2B3D4 /* DrawImageShader.h */, + D43407C61D0E14BE00C2B3D4 /* DrawLineShader.cpp */, + D43407C71D0E14BE00C2B3D4 /* DrawLineShader.h */, + D43407C81D0E14BE00C2B3D4 /* FillRectShader.cpp */, + D43407C91D0E14BE00C2B3D4 /* FillRectShader.h */, + D43407CA1D0E14BE00C2B3D4 /* GLSLTypes.h */, + D43407CB1D0E14BE00C2B3D4 /* OpenGLAPI.cpp */, + D43407CC1D0E14BE00C2B3D4 /* OpenGLAPI.h */, + D43407CD1D0E14BE00C2B3D4 /* OpenGLDrawingEngine.cpp */, + D43407CE1D0E14BE00C2B3D4 /* OpenGLFramebuffer.cpp */, + D43407CF1D0E14BE00C2B3D4 /* OpenGLFramebuffer.h */, + D43407D01D0E14BE00C2B3D4 /* OpenGLShaderProgram.cpp */, + D43407D11D0E14BE00C2B3D4 /* OpenGLShaderProgram.h */, + D43407D21D0E14BE00C2B3D4 /* SwapFramebuffer.cpp */, + D43407D31D0E14BE00C2B3D4 /* SwapFramebuffer.h */, + D43407D41D0E14BE00C2B3D4 /* TextureCache.cpp */, + D43407D51D0E14BE00C2B3D4 /* TextureCache.h */, + ); + path = opengl; + sourceTree = ""; + }; D44270CF1CC81B3200D84D28 /* audio */ = { isa = PBXGroup; children = ( @@ -1761,9 +1820,7 @@ D497667F1D03B9FE002222CD /* engines */ = { isa = PBXGroup; children = ( - D45F04691D07733900CBA2BA /* OpenGLAPI.cpp */, - D45F046A1D07733900CBA2BA /* OpenGLAPI.h */, - D49766801D03B9FE002222CD /* OpenGLDrawingEngine.cpp */, + D43407BF1D0E14BE00C2B3D4 /* opengl */, D49766811D03B9FE002222CD /* SoftwareDrawingEngine.cpp */, ); path = engines; @@ -1804,6 +1861,7 @@ children = ( D4EC48E31C2637710024B507 /* g2.dat */, D4EC48E41C2637710024B507 /* language */, + D43407E11D0E14CE00C2B3D4 /* shaders */, D4EC48E51C2637710024B507 /* title */, ); name = data; @@ -1913,6 +1971,7 @@ D41B74731C2125E50080A7B9 /* Assets.xcassets in Resources */, D4EC48E61C2637710024B507 /* g2.dat in Resources */, D4EC48E71C2637710024B507 /* language in Resources */, + D43407E21D0E14CE00C2B3D4 /* shaders in Resources */, D45A38BB1CF3006400659A24 /* engines in Resources */, D4EC48E81C2637710024B507 /* title in Resources */, ); @@ -2062,6 +2121,7 @@ C686F9421CDBC3B7009F9BFC /* magic_carpet.c in Sources */, D44272021CC81B3200D84D28 /* Json.cpp in Sources */, D44272591CC81B3200D84D28 /* dropdown.c in Sources */, + D43407DF1D0E14BE00C2B3D4 /* SwapFramebuffer.cpp in Sources */, C686F8AF1CDBC37E009F9BFC /* map_element.c in Sources */, D44272081CC81B3200D84D28 /* diagnostic.c in Sources */, D44272A51CC81B3200D84D28 /* particle.c in Sources */, @@ -2082,6 +2142,7 @@ D442725A1CC81B3200D84D28 /* editor_bottom_toolbar.c in Sources */, D442729D1CC81B3200D84D28 /* footpath.c in Sources */, D44272501CC81B3200D84D28 /* title.c in Sources */, + D43407DD1D0E14BE00C2B3D4 /* OpenGLFramebuffer.cpp in Sources */, D442721D1CC81B3200D84D28 /* screenshot.c in Sources */, D44272381CC81B3200D84D28 /* openrct2.c in Sources */, C686F92C1CDBC3B7009F9BFC /* circus_show.c in Sources */, @@ -2090,7 +2151,6 @@ C686F9321CDBC3B7009F9BFC /* haunted_house.c in Sources */, D442720A1CC81B3200D84D28 /* drawing_fast.cpp in Sources */, C686F9521CDBC3B7009F9BFC /* river_rapids.c in Sources */, - D45F046B1D07733900CBA2BA /* OpenGLAPI.cpp in Sources */, 008BF72C1CDAA5C30019A2AD /* track_design.c in Sources */, C61FB7241CF86356004CE991 /* NetworkUser.cpp in Sources */, D44272191CC81B3200D84D28 /* colour.c in Sources */, @@ -2116,8 +2176,10 @@ C686F93C1CDBC3B7009F9BFC /* misc.c in Sources */, D442723A1CC81B3200D84D28 /* staff.c in Sources */, D44272931CC81B3200D84D28 /* top_toolbar.c in Sources */, + D43407DA1D0E14BE00C2B3D4 /* FillRectShader.cpp in Sources */, D44271F61CC81B3200D84D28 /* audio.c in Sources */, D442728A1CC81B3200D84D28 /* tile_inspector.c in Sources */, + D43407D91D0E14BE00C2B3D4 /* DrawLineShader.cpp in Sources */, C686F9411CDBC3B7009F9BFC /* launched_freefall.c in Sources */, D44272571CC81B3200D84D28 /* clear_scenery.c in Sources */, D442727D1CC81B3200D84D28 /* ride_list.c in Sources */, @@ -2185,6 +2247,7 @@ D442725B1CC81B3200D84D28 /* editor_inventions_list.c in Sources */, D44272311CC81B3200D84D28 /* news_item.c in Sources */, D44272011CC81B3200D84D28 /* Guard.cpp in Sources */, + D43407E01D0E14BE00C2B3D4 /* TextureCache.cpp in Sources */, D44272951CC81B3200D84D28 /* track_manage.c in Sources */, D44272851CC81B3200D84D28 /* staff.c in Sources */, D442725F1CC81B3200D84D28 /* editor_scenario_options.c in Sources */, @@ -2207,14 +2270,15 @@ D44272031CC81B3200D84D28 /* Path.cpp in Sources */, C686F9301CDBC3B7009F9BFC /* flying_saucers.c in Sources */, D44272401CC81B3200D84D28 /* windows.c in Sources */, - D49766821D03B9FE002222CD /* OpenGLDrawingEngine.cpp in Sources */, D44272881CC81B3200D84D28 /* text_input.c in Sources */, D442720F1CC81B3200D84D28 /* scrolling_text.c in Sources */, D44271F51CC81B3200D84D28 /* addresses.c in Sources */, D44272041CC81B3200D84D28 /* Stopwatch.cpp in Sources */, + D43407D81D0E14BE00C2B3D4 /* DrawImageShader.cpp in Sources */, 007A05D01CFB2C8B00F419C3 /* NetworkGroup.cpp in Sources */, C686F9491CDBC3B7009F9BFC /* chairlift.c in Sources */, C686F9501CDBC3B7009F9BFC /* log_flume.c in Sources */, + D43407D61D0E14BE00C2B3D4 /* CopyFramebufferShader.cpp in Sources */, D44272241CC81B3200D84D28 /* intro.c in Sources */, D44272631CC81B3200D84D28 /* game_bottom_toolbar.c in Sources */, 008BF72A1CDAA5C30019A2AD /* track_design_index.c in Sources */, @@ -2227,6 +2291,7 @@ C686F9311CDBC3B7009F9BFC /* ghost_train.c in Sources */, D44272821CC81B3200D84D28 /* shortcut_key_change.c in Sources */, D442722A1CC81B3200D84D28 /* localisation.c in Sources */, + D43407D71D0E14BE00C2B3D4 /* DrawImageMaskedShader.cpp in Sources */, D44272731CC81B3200D84D28 /* new_ride.c in Sources */, D442721A1CC81B3200D84D28 /* console.c in Sources */, D44271FB1CC81B3200D84D28 /* ScreenshotCommands.cpp in Sources */, @@ -2238,6 +2303,8 @@ C686F9351CDBC3B7009F9BFC /* mini_golf.c in Sources */, D44272541CC81B3200D84D28 /* banner.c in Sources */, D44272A31CC81B3200D84D28 /* money_effect.c in Sources */, + D43407DE1D0E14BE00C2B3D4 /* OpenGLShaderProgram.cpp in Sources */, + D43407DC1D0E14BE00C2B3D4 /* OpenGLDrawingEngine.cpp in Sources */, D44272761CC81B3200D84D28 /* options.c in Sources */, C686F93D1CDBC3B7009F9BFC /* shop.c in Sources */, C686F8AD1CDBC37E009F9BFC /* entrance.c in Sources */, @@ -2282,6 +2349,7 @@ D44272301CC81B3200D84D28 /* marketing.c in Sources */, D44272321CC81B3200D84D28 /* research.c in Sources */, D442725D1CC81B3200D84D28 /* editor_object_selection.c in Sources */, + D43407DB1D0E14BE00C2B3D4 /* OpenGLAPI.cpp in Sources */, D44272981CC81B3200D84D28 /* water.c in Sources */, D442726C1CC81B3200D84D28 /* map_tooltip.c in Sources */, C686F9281CDBC3B7009F9BFC /* wild_mouse.c in Sources */, @@ -2328,7 +2396,6 @@ GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", OPENGL_NO_LINK, - DISABLE_OPENGL ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -2371,10 +2438,7 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - OPENGL_NO_LINK, - DISABLE_OPENGL - ); + GCC_PREPROCESSOR_DEFINITIONS = OPENGL_NO_LINK; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; diff --git a/data/shaders/copyframebuffer.frag b/data/shaders/copyframebuffer.frag new file mode 100644 index 0000000000..65071fff10 --- /dev/null +++ b/data/shaders/copyframebuffer.frag @@ -0,0 +1,13 @@ +#version 330 + +uniform sampler2D uTexture; + +in vec2 fPosition; +in vec2 fTextureCoordinate; + +layout (location = 0) out vec4 oColour; + +void main() +{ + oColour = texture(uTexture, fTextureCoordinate); +} diff --git a/data/shaders/copyframebuffer.vert b/data/shaders/copyframebuffer.vert new file mode 100644 index 0000000000..577ec0ef2b --- /dev/null +++ b/data/shaders/copyframebuffer.vert @@ -0,0 +1,42 @@ +#version 330 + +uniform ivec2 uScreenSize; +uniform ivec4 uBounds; +uniform ivec4 uTextureCoordinates; + +in int vIndex; + +out vec2 fPosition; +out vec2 fTextureCoordinate; + +void main() +{ + vec2 pos; + switch (vIndex) { + case 0: + pos = uBounds.xy; + fTextureCoordinate = uTextureCoordinates.xy; + break; + case 1: + pos = uBounds.zy; + fTextureCoordinate = uTextureCoordinates.zy; + break; + case 2: + pos = uBounds.zw; + fTextureCoordinate = uTextureCoordinates.zw; + break; + case 3: + pos = uBounds.xw; + fTextureCoordinate = uTextureCoordinates.xw; + break; + } + + fPosition = pos; + + // Transform screen coordinates to viewport + pos.x = (pos.x * (2.0 / uScreenSize.x)) - 1.0; + pos.y = (pos.y * (2.0 / uScreenSize.y)) - 1.0; + pos.y *= -1; + + gl_Position = vec4(pos, 0.0, 1.0); +} diff --git a/data/shaders/drawimage.frag b/data/shaders/drawimage.frag new file mode 100644 index 0000000000..a18e81433d --- /dev/null +++ b/data/shaders/drawimage.frag @@ -0,0 +1,30 @@ +#version 330 + +uniform ivec4 uClip; +uniform int uFlags; +uniform vec4 uColour; +uniform sampler2D uTexture; + +in vec2 fPosition; +in vec2 fTextureCoordinate; + +layout (location = 0) out vec4 oColour; + +void main() +{ + if (fPosition.x < uClip.x || fPosition.x > uClip.z || + fPosition.y < uClip.y || fPosition.y > uClip.w) + { + discard; + } + + vec4 texel = texture(uTexture, fTextureCoordinate); + if ((uFlags & 1) != 0) + { + oColour = vec4(uColour.rgb, uColour.a * texel.a); + } + else + { + oColour = texel; + } +} diff --git a/data/shaders/drawimage.vert b/data/shaders/drawimage.vert new file mode 100644 index 0000000000..577ec0ef2b --- /dev/null +++ b/data/shaders/drawimage.vert @@ -0,0 +1,42 @@ +#version 330 + +uniform ivec2 uScreenSize; +uniform ivec4 uBounds; +uniform ivec4 uTextureCoordinates; + +in int vIndex; + +out vec2 fPosition; +out vec2 fTextureCoordinate; + +void main() +{ + vec2 pos; + switch (vIndex) { + case 0: + pos = uBounds.xy; + fTextureCoordinate = uTextureCoordinates.xy; + break; + case 1: + pos = uBounds.zy; + fTextureCoordinate = uTextureCoordinates.zy; + break; + case 2: + pos = uBounds.zw; + fTextureCoordinate = uTextureCoordinates.zw; + break; + case 3: + pos = uBounds.xw; + fTextureCoordinate = uTextureCoordinates.xw; + break; + } + + fPosition = pos; + + // Transform screen coordinates to viewport + pos.x = (pos.x * (2.0 / uScreenSize.x)) - 1.0; + pos.y = (pos.y * (2.0 / uScreenSize.y)) - 1.0; + pos.y *= -1; + + gl_Position = vec4(pos, 0.0, 1.0); +} diff --git a/data/shaders/drawimagemasked.frag b/data/shaders/drawimagemasked.frag new file mode 100644 index 0000000000..7910547ed6 --- /dev/null +++ b/data/shaders/drawimagemasked.frag @@ -0,0 +1,23 @@ +#version 330 + +uniform ivec4 uClip; +uniform sampler2D uTextureMask; +uniform sampler2D uTextureColour; + +in vec2 fPosition; +in vec2 fTextureCoordinate; + +layout (location = 0) out vec4 oColour; + +void main() +{ + if (fPosition.x < uClip.x || fPosition.x > uClip.z || + fPosition.y < uClip.y || fPosition.y > uClip.w) + { + discard; + } + + vec4 mask = texture(uTextureMask, fTextureCoordinate); + vec4 colour = texture(uTextureColour, fTextureCoordinate); + oColour = colour * mask; +} diff --git a/data/shaders/drawimagemasked.vert b/data/shaders/drawimagemasked.vert new file mode 100644 index 0000000000..4cd77cc1bc --- /dev/null +++ b/data/shaders/drawimagemasked.vert @@ -0,0 +1,41 @@ +#version 330 + +uniform ivec2 uScreenSize; +uniform ivec4 uBounds; + +in int vIndex; + +out vec2 fPosition; +out vec2 fTextureCoordinate; + +void main() +{ + vec2 pos; + switch (vIndex) { + case 0: + pos = uBounds.xy; + fTextureCoordinate = vec2(0, 0); + break; + case 1: + pos = uBounds.zy; + fTextureCoordinate = vec2(1, 0); + break; + case 2: + pos = uBounds.zw; + fTextureCoordinate = vec2(1, 1); + break; + case 3: + pos = uBounds.xw; + fTextureCoordinate = vec2(0, 1); + break; + } + + fPosition = pos; + + // Transform screen coordinates to viewport + pos.x = (pos.x * (2.0 / uScreenSize.x)) - 1.0; + pos.y = (pos.y * (2.0 / uScreenSize.y)) - 1.0; + pos.y *= -1; + + gl_Position = vec4(pos, 0.0, 1.0); +} diff --git a/data/shaders/drawline.frag b/data/shaders/drawline.frag new file mode 100644 index 0000000000..3e1ef5f151 --- /dev/null +++ b/data/shaders/drawline.frag @@ -0,0 +1,20 @@ +#version 330 + +uniform ivec2 uScreenSize; +uniform ivec4 uClip; +uniform vec4 uColour; + +in vec2 fPosition; + +layout (location = 0) out vec4 oColour; + +void main() +{ + if (fPosition.x < uClip.x || fPosition.x > uClip.z || + fPosition.y < uClip.y || fPosition.y > uClip.w) + { + discard; + } + + oColour = uColour; +} diff --git a/data/shaders/drawline.vert b/data/shaders/drawline.vert new file mode 100644 index 0000000000..5bfb974472 --- /dev/null +++ b/data/shaders/drawline.vert @@ -0,0 +1,30 @@ +#version 330 + +uniform ivec2 uScreenSize; +uniform ivec4 uBounds; + +in int vIndex; + +out vec2 fPosition; + +void main() +{ + vec2 pos; + if (vIndex == 0) + { + pos = uBounds.xy; + } + else + { + pos = uBounds.zw; + } + + fPosition = pos; + + // Transform screen coordinates to viewport + pos.x = (pos.x * (2.0 / uScreenSize.x)) - 1.0; + pos.y = (pos.y * (2.0 / uScreenSize.y)) - 1.0; + pos.y *= -1; + + gl_Position = vec4(pos, 0.0, 1.0); +} diff --git a/data/shaders/fillrect.frag b/data/shaders/fillrect.frag new file mode 100644 index 0000000000..7860eaba2f --- /dev/null +++ b/data/shaders/fillrect.frag @@ -0,0 +1,61 @@ +#version 330 + +uniform ivec2 uScreenSize; +uniform ivec4 uClip; +uniform int uFlags; +uniform vec4 uColour[2]; +uniform sampler2D uSourceFramebuffer; +uniform ivec4 uBounds; + +in vec2 fPosition; + +layout (location = 0) out vec4 oColour; + +float getluma(vec3 colour) +{ + return (colour.r * 0.2126) + + (colour.g * 0.7152) + + (colour.b * 0.0722); +} + +void main() +{ + if (fPosition.x < uClip.x || fPosition.x > uClip.z || + fPosition.y < uClip.y || fPosition.y > uClip.w) + { + discard; + } + + vec4 targetColour; + int posSum = int(fPosition.x) + int(fPosition.y); + if ((posSum % 2) == 0) + { + targetColour = uColour[0]; + } + else + { + targetColour = uColour[1]; + } + + if ((uFlags & 1) != 0) + { + vec2 textureCoordinates = (fPosition / vec2(uScreenSize)) * vec2(1, -1); + vec4 sourceColour = texture(uSourceFramebuffer, textureCoordinates); + + float luma = getluma(sourceColour.rgb); + sourceColour = vec4(vec3(luma), 1); + + if (luma < 0.5) + { + oColour = 2.0 * sourceColour * targetColour; + } + else + { + oColour = 1.0 - 2.0 * (1.0 - sourceColour) * (1.0 - targetColour); + } + } + else + { + oColour = targetColour; + } +} diff --git a/data/shaders/fillrect.vert b/data/shaders/fillrect.vert new file mode 100644 index 0000000000..066225c359 --- /dev/null +++ b/data/shaders/fillrect.vert @@ -0,0 +1,36 @@ +#version 330 + +uniform ivec2 uScreenSize; +uniform ivec4 uBounds; + +in int vIndex; + +out vec2 fPosition; + +void main() +{ + vec2 pos; + switch (vIndex) { + case 0: + pos = uBounds.xy; + break; + case 1: + pos = uBounds.zy; + break; + case 2: + pos = uBounds.zw; + break; + case 3: + pos = uBounds.xw; + break; + } + + fPosition = pos; + + // Transform screen coordinates to viewport + pos.x = (pos.x * (2.0 / uScreenSize.x)) - 1.0; + pos.y = (pos.y * (2.0 / uScreenSize.y)) - 1.0; + pos.y *= -1; + + gl_Position = vec4(pos, 0.0, 1.0); +} diff --git a/openrct2.vcxproj b/openrct2.vcxproj index 7dbb67b984..ec0c401011 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -16,6 +16,16 @@ + + + + + + + + + + @@ -42,8 +52,17 @@ - - + + + + + + + + + + + @@ -338,6 +357,17 @@ + + + + + + + + + + + @@ -494,7 +524,7 @@ Level3 Disabled true - $(OpenRCT2_DEFINES);DEBUG;DISABLE_OPENGL;OPENGL_NO_LINK;_CRT_SECURE_NO_WARNINGS;_USE_MATH_DEFINES;CURL_STATICLIB;SDL_MAIN_HANDLED;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) + $(OpenRCT2_DEFINES);DEBUG;OPENGL_NO_LINK;_CRT_SECURE_NO_WARNINGS;_USE_MATH_DEFINES;CURL_STATICLIB;SDL_MAIN_HANDLED;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded true $(IntDir)\%(RelativeDir) @@ -521,7 +551,7 @@ 4013 false - $(OpenRCT2_DEFINES);DISABLE_OPENGL;OPENGL_NO_LINK;_CRT_SECURE_NO_WARNINGS;_USE_MATH_DEFINES;CURL_STATICLIB;SDL_MAIN_HANDLED;%(PreprocessorDefinitions) + $(OpenRCT2_DEFINES);OPENGL_NO_LINK;_CRT_SECURE_NO_WARNINGS;_USE_MATH_DEFINES;CURL_STATICLIB;SDL_MAIN_HANDLED;%(PreprocessorDefinitions) $(IntDir)\%(RelativeDir) true Speed diff --git a/scripts/ps/build.ps1 b/scripts/ps/build.ps1 index 3fba811aed..3a908184e2 100644 --- a/scripts/ps/build.ps1 +++ b/scripts/ps/build.ps1 @@ -37,6 +37,7 @@ function Build-Data() # Create symlinks Symlink-or-Copy "$binDataPath\language" "$dataPath\language" > $null + Symlink-or-Copy "$binDataPath\shaders" "$dataPath\shaders" > $null Symlink-or-Copy "$binDataPath\title" "$dataPath\title" > $null return 0 diff --git a/src/drawing/IDrawingContext.h b/src/drawing/IDrawingContext.h index 9fecefbe6f..5c83258fcb 100644 --- a/src/drawing/IDrawingContext.h +++ b/src/drawing/IDrawingContext.h @@ -30,6 +30,7 @@ interface IDrawingContext virtual void FillRect(uint32 colour, sint32 left, sint32 top, sint32 right, sint32 bottom) abstract; virtual void DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2) abstract; virtual void DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour) abstract; - virtual void DrawSpritePaletteSet(uint32 image, sint32 x, sint32 y, uint8 * palette, uint8 * unknown) abstract; virtual void DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) abstract; + virtual void DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour) abstract; + virtual void DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette) abstract; }; diff --git a/src/drawing/NewDrawing.cpp b/src/drawing/NewDrawing.cpp index 3e0b9795e5..b3dd0b00a0 100644 --- a/src/drawing/NewDrawing.cpp +++ b/src/drawing/NewDrawing.cpp @@ -209,12 +209,12 @@ extern "C" } } - void FASTCALL gfx_draw_sprite_palette_set(rct_drawpixelinfo * dpi, int image, int x, int y, uint8 * palette, uint8 * unknown) + void FASTCALL gfx_draw_glpyh(rct_drawpixelinfo * dpi, int image, int x, int y, uint8 * palette) { if (_drawingEngine != nullptr) { IDrawingContext * dc = _drawingEngine->GetDrawingContext(dpi); - dc->DrawSpritePaletteSet(image, x, y, palette, unknown); + dc->DrawGlyph(image, x, y, palette); } } @@ -227,6 +227,15 @@ extern "C" } } + void FASTCALL gfx_draw_sprite_solid(rct_drawpixelinfo * dpi, int image, int x, int y, uint8 colour) + { + if (_drawingEngine != nullptr) + { + IDrawingContext * dc = _drawingEngine->GetDrawingContext(dpi); + dc->DrawSpriteSolid(image, x, y, colour); + } + } + int screenshot_dump() { if (_drawingEngine != nullptr) diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h index 9e4f311611..4cd3576b28 100644 --- a/src/drawing/drawing.h +++ b/src/drawing/drawing.h @@ -146,8 +146,9 @@ rct_g1_element* gfx_get_g1_element(int image_id); void sub_68371D(); void FASTCALL gfx_rle_sprite_to_buffer(const uint8* RESTRICT source_bits_pointer, uint8* RESTRICT dest_bits_pointer, const uint8* RESTRICT palette_pointer, const rct_drawpixelinfo * RESTRICT dpi, int image_type, int source_y_start, int height, int source_x_start, int width); void FASTCALL gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 tertiary_colour); -void FASTCALL gfx_draw_sprite_palette_set(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8* palette_pointer, uint8* unknown_pointer); +void FASTCALL gfx_draw_glpyh(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8 * palette); void FASTCALL gfx_draw_sprite_raw_masked(rct_drawpixelinfo *dpi, int x, int y, int maskImage, int colourImage); +void FASTCALL gfx_draw_sprite_solid(rct_drawpixelinfo * dpi, int image, int x, int y, uint8 colour); void FASTCALL gfx_draw_sprite_software(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 tertiary_colour); void FASTCALL gfx_draw_sprite_palette_set_software(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8* palette_pointer, uint8* unknown_pointer); diff --git a/src/drawing/engines/OpenGLAPI.h b/src/drawing/engines/OpenGLAPI.h deleted file mode 100644 index 30191c7400..0000000000 --- a/src/drawing/engines/OpenGLAPI.h +++ /dev/null @@ -1,142 +0,0 @@ -#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers -/***************************************************************************** - * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. - * - * OpenRCT2 is the work of many authors, a full list can be found in contributors.md - * For more information, visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 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. - * - * A full copy of the GNU General Public License can be found in licence.txt - *****************************************************************************/ -#pragma endregion - -#pragma once - -#if OPENGL_NO_LINK - -// BEGIN [Do not define 1.1 function signatures] -#define glBegin __static__glBegin -#define glBindTexture __static__glBindTexture -#define glBlendFunc __static__glBlendFunc -#define glClear __static__glClear -#define glClearColor __static__glClearColor -#define glColor3f __static__glColor3f -#define glColor4f __static__glColor4f -#define glDeleteTextures __static__glDeleteTextures -#define glDisable __static__glDisable -#define glEnable __static__glEnable -#define glEnd __static__glEnd -#define glGenTextures __static__glGenTextures -#define glLoadIdentity __static__glLoadIdentity -#define glMatrixMode __static__glMatrixMode -#define glOrtho __static__glOrtho -#define glScalef __static__glScalef -#define glTexCoord2f __static__glTexCoord2f -#define glTexImage2D __static__glTexImage2D -#define glTexParameteri __static__glTexParameteri -#define glTranslatef __static__glTranslatef -#define glVertex2i __static__glVertex2i -#define glViewport __static__glViewport - -#endif - -#include - -#if OPENGL_NO_LINK - -// END [Do not define 1.1 function signatures] -#undef glBegin -#undef glBindTexture -#undef glBlendFunc -#undef glClear -#undef glClearColor -#undef glColor3f -#undef glColor4f -#undef glDeleteTextures -#undef glDisable -#undef glEnable -#undef glEnd -#undef glGenTextures -#undef glLoadIdentity -#undef glMatrixMode -#undef glOrtho -#undef glScalef -#undef glTexCoord2f -#undef glTexImage2D -#undef glTexParameteri -#undef glTranslatef -#undef glVertex2i -#undef glViewport - -// 1.1 function signatures -typedef void (APIENTRYP PFNGLBEGINPROC )(GLenum mode); -typedef void (APIENTRYP PFNGLBINDTEXTUREPROC )(GLenum target, GLuint texture); -typedef void (APIENTRYP PFNGLBLENDFUNCPROC )(GLenum sfactor, GLenum dfactor); -typedef void (APIENTRYP PFNGLCLEARPROC )(GLbitfield mask); -typedef void (APIENTRYP PFNGLCLEARCOLORPROC )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -typedef void (APIENTRYP PFNGLCOLOR3FPROC )(GLfloat red, GLfloat green, GLfloat blue); -typedef void (APIENTRYP PFNGLCOLOR4FPROC )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -typedef void (APIENTRYP PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint *textures); -typedef void (APIENTRYP PFNGLDISABLEPROC )(GLenum cap); -typedef void (APIENTRYP PFNGLENABLEPROC )(GLenum cap); -typedef void (APIENTRYP PFNGLENDPROC )(void); -typedef void (APIENTRYP PFNGLGENTEXTURESPROC )(GLsizei n, GLuint *textures); -typedef void (APIENTRYP PFNGLLOADIDENTITYPROC )(void); -typedef void (APIENTRYP PFNGLMATRIXMODEPROC )(GLenum mode); -typedef void (APIENTRYP PFNGLORTHOPROC )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val); -typedef void (APIENTRYP PFNGLSCALEFPROC )(GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLTEXCOORD2FPROC )(GLfloat s, GLfloat t); -typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC )(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC )(GLenum target, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLTRANSLATEFPROC )(GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLVERTEX2IPROC )(GLint x, GLint y); -typedef void (APIENTRYP PFNGLVIEWPORTPROC )(GLint x, GLint y, GLsizei width, GLsizei height); - -#ifdef NO_EXTERN_GLAPI - // Defines the function pointers - #define GLAPI_DECL - #define GLAPI_SET = nullptr -#else - // Defines the functions as "extern" - #define GLAPI_DECL extern - #define GLAPI_SET -#endif - -// 1.1 function pointers -GLAPI_DECL PFNGLBEGINPROC glBegin GLAPI_SET; -GLAPI_DECL PFNGLBINDTEXTUREPROC glBindTexture GLAPI_SET; -GLAPI_DECL PFNGLBLENDFUNCPROC glBlendFunc GLAPI_SET; -GLAPI_DECL PFNGLCLEARPROC glClear GLAPI_SET; -GLAPI_DECL PFNGLCLEARCOLORPROC glClearColor GLAPI_SET; -GLAPI_DECL PFNGLCOLOR3FPROC glColor3f GLAPI_SET; -GLAPI_DECL PFNGLCOLOR4FPROC glColor4f GLAPI_SET; -GLAPI_DECL PFNGLDELETETEXTURESPROC glDeleteTextures GLAPI_SET; -GLAPI_DECL PFNGLDISABLEPROC glDisable GLAPI_SET; -GLAPI_DECL PFNGLENABLEPROC glEnable GLAPI_SET; -GLAPI_DECL PFNGLENDPROC glEnd GLAPI_SET; -GLAPI_DECL PFNGLGENTEXTURESPROC glGenTextures GLAPI_SET; -GLAPI_DECL PFNGLLOADIDENTITYPROC glLoadIdentity GLAPI_SET; -GLAPI_DECL PFNGLMATRIXMODEPROC glMatrixMode GLAPI_SET; -GLAPI_DECL PFNGLORTHOPROC glOrtho GLAPI_SET; -GLAPI_DECL PFNGLSCALEFPROC glScalef GLAPI_SET; -GLAPI_DECL PFNGLTEXCOORD2FPROC glTexCoord2f GLAPI_SET; -GLAPI_DECL PFNGLTEXIMAGE2DPROC glTexImage2D GLAPI_SET; -GLAPI_DECL PFNGLTEXPARAMETERIPROC glTexParameteri GLAPI_SET; -GLAPI_DECL PFNGLTRANSLATEFPROC glTranslatef GLAPI_SET; -GLAPI_DECL PFNGLVERTEX2IPROC glVertex2i GLAPI_SET; -GLAPI_DECL PFNGLVIEWPORTPROC glViewport GLAPI_SET; - -// 2.0+ function pointers -GLAPI_DECL PFNGLCREATESHADERPROC glCreateShader GLAPI_SET; -GLAPI_DECL PFNGLDELETESHADERPROC glDeleteShader GLAPI_SET; - -#endif /* OPENGL_NO_LINK */ - -namespace OpenGLAPI -{ - bool Initialise(); -} diff --git a/src/drawing/engines/OpenGLDrawingEngine.cpp b/src/drawing/engines/OpenGLDrawingEngine.cpp deleted file mode 100644 index 06781286b6..0000000000 --- a/src/drawing/engines/OpenGLDrawingEngine.cpp +++ /dev/null @@ -1,638 +0,0 @@ -#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers -/***************************************************************************** - * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. - * - * OpenRCT2 is the work of many authors, a full list can be found in contributors.md - * For more information, visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 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. - * - * A full copy of the GNU General Public License can be found in licence.txt - *****************************************************************************/ -#pragma endregion - -#ifdef DISABLE_OPENGL - -#include "../IDrawingEngine.h" - -IDrawingEngine * DrawingEngineFactory::CreateOpenGL() -{ - return nullptr; -} - -#else - -#include -#include -#include - -#include "OpenGLAPI.h" - -#include "../../core/Exception.hpp" -#include "../../core/Math.hpp" -#include "../../core/Memory.hpp" -#include "../IDrawingContext.h" -#include "../IDrawingEngine.h" -#include "../Rain.h" - -extern "C" -{ - #include "../../config.h" - #include "../../interface/window.h" - #include "../../intro.h" - #include "../drawing.h" -} - -class OpenGLDrawingEngine; - -struct vec2f -{ - union { float x; float s; float r; }; - union { float y; float t; float g; }; -}; - -struct vec4f -{ - union { float x; float s; float r; }; - union { float y; float t; float g; }; - union { float z; float p; float b; }; - union { float w; float q; float a; }; -}; - -class OpenGLDrawingContext : public IDrawingContext -{ -private: - OpenGLDrawingEngine * _engine; - rct_drawpixelinfo * _dpi; - - sint32 _offsetX; - sint32 _offsetY; - sint32 _clipLeft; - sint32 _clipTop; - sint32 _clipRight; - sint32 _clipBottom; - - std::vector _textures; - std::unordered_map _imageTextureMap; - -public: - OpenGLDrawingContext(OpenGLDrawingEngine * engine); - ~OpenGLDrawingContext() override; - - IDrawingEngine * GetEngine() override; - - void Clear(uint32 colour) override; - void FillRect(uint32 colour, sint32 x, sint32 y, sint32 w, sint32 h) override; - void DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2) override; - void DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour) override; - void DrawSpritePaletteSet(uint32 image, sint32 x, sint32 y, uint8 * palette, uint8 * unknown) override; - void DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) override; - - void SetDPI(rct_drawpixelinfo * dpi); - void InvalidateImage(uint32 image); - -private: - GLuint GetOrLoadImageTexture(uint32 image); - GLuint LoadImageTexture(uint32 image); - void * GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32 * outWidth, uint32 * outHeight); - void FreeTextures(); -}; - -class OpenGLDrawingEngine : public IDrawingEngine -{ -private: - SDL_Window * _window = nullptr; - SDL_GLContext _context; - - uint32 _width = 0; - uint32 _height = 0; - uint32 _pitch = 0; - size_t _bitsSize = 0; - uint8 * _bits = nullptr; - - rct_drawpixelinfo _bitsDPI = { 0 }; - - OpenGLDrawingContext * _drawingContext; - -public: - SDL_Color Palette[256]; - vec4f GLPalette[256]; - - OpenGLDrawingEngine() - { - _drawingContext = new OpenGLDrawingContext(this); - } - - ~OpenGLDrawingEngine() override - { - delete _drawingContext; - delete [] _bits; - - SDL_GL_DeleteContext(_context); - } - - void Initialise(SDL_Window * window) override - { - _window = window; - - _context = SDL_GL_CreateContext(_window); - SDL_GL_MakeCurrent(_window, _context); - - if (!OpenGLAPI::Initialise()) - { - throw Exception("Unable to initialise OpenGL."); - } - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - void Resize(uint32 width, uint32 height) override - { - ConfigureBits(width, height, width); - - glViewport(0, 0, (GLsizei)width, (GLsizei)height); - } - - void SetPalette(SDL_Color * palette) override - { - for (int i = 0; i < 256; i++) - { - SDL_Color colour = palette[i]; - Palette[i] = colour; - GLPalette[i] = { colour.r / 255.0f, - colour.g / 255.0f, - colour.b / 255.0f, - colour.a / 255.0f }; - } - } - - void Invalidate(sint32 left, sint32 top, sint32 right, sint32 bottom) override - { - } - - void Draw() override - { - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - - glMatrixMode(GL_PROJECTION_MATRIX); - glLoadIdentity(); - glOrtho(0, _width, _height, 0, -1.0, 1.0); - - glMatrixMode(GL_MODELVIEW_MATRIX); - glLoadIdentity(); - glScalef(1, -1.0f, 0); - glTranslatef(-1.0f, -1.0f, 0); - glScalef(2.0f / _width, 2.0f / _height, 0); - - if (gIntroState != INTRO_STATE_NONE) { - intro_draw(&_bitsDPI); - } else { - window_update_all_viewports(); - window_draw_all(&_bitsDPI, 0, 0, _width, _height); - window_update_all(); - - gfx_draw_pickedup_peep(&_bitsDPI); - - rct2_draw(&_bitsDPI); - } - Display(); - } - - sint32 Screenshot() override - { - // Not implemented - return -1; - } - - void CopyRect(sint32 x, sint32 y, sint32 width, sint32 height, sint32 dx, sint32 dy) override - { - // Not applicable for this engine - } - - IDrawingContext * GetDrawingContext(rct_drawpixelinfo * dpi) override - { - _drawingContext->SetDPI(dpi); - return _drawingContext; - } - - rct_drawpixelinfo * GetDrawingPixelInfo() override - { - return &_bitsDPI; - } - - DRAWING_ENGINE_FLAGS GetFlags() override - { - return DEF_NONE; - } - - void InvalidateImage(uint32 image) override - { - _drawingContext->InvalidateImage(image); - } - - rct_drawpixelinfo * GetDPI() - { - return &_bitsDPI; - } - -private: - - void ConfigureBits(uint32 width, uint32 height, uint32 pitch) - { - size_t newBitsSize = pitch * height; - uint8 * newBits = new uint8[newBitsSize]; - if (_bits == nullptr) - { - Memory::Set(newBits, 0, newBitsSize); - } - else - { - if (_pitch == pitch) - { - Memory::Copy(newBits, _bits, Math::Min(_bitsSize, newBitsSize)); - } - else - { - uint8 * src = _bits; - uint8 * dst = newBits; - - uint32 minWidth = Math::Min(_width, width); - uint32 minHeight = Math::Min(_height, height); - for (uint32 y = 0; y < minHeight; y++) - { - Memory::Copy(dst, src, minWidth); - if (pitch - minWidth > 0) - { - Memory::Set(dst + minWidth, 0, pitch - minWidth); - } - src += _pitch; - dst += pitch; - } - } - delete [] _bits; - } - - _bits = newBits; - _bitsSize = newBitsSize; - _width = width; - _height = height; - _pitch = pitch; - - rct_drawpixelinfo * dpi = &_bitsDPI; - dpi->bits = _bits; - dpi->x = 0; - dpi->y = 0; - dpi->width = width; - dpi->height = height; - dpi->pitch = _pitch - width; - } - - void Display() - { - SDL_GL_SwapWindow(_window); - } -}; - -IDrawingEngine * DrawingEngineFactory::CreateOpenGL() -{ - return new OpenGLDrawingEngine(); -} - -OpenGLDrawingContext::OpenGLDrawingContext(OpenGLDrawingEngine * engine) -{ - _engine = engine; -} - -OpenGLDrawingContext::~OpenGLDrawingContext() -{ - -} - -IDrawingEngine * OpenGLDrawingContext::GetEngine() -{ - return _engine; -} - -void OpenGLDrawingContext::Clear(uint32 colour) -{ - FillRect(colour, _clipLeft, _clipTop, _clipRight, _clipBottom); -} - -void OpenGLDrawingContext::FillRect(uint32 colour, sint32 left, sint32 top, sint32 right, sint32 bottom) -{ - vec4f paletteColour = _engine->GLPalette[colour & 0xFF]; - - if (left > right) - { - left ^= right; - right ^= left; - left ^= right; - } - if (top > bottom) - { - top ^= bottom; - bottom ^= top; - top ^= bottom; - } - - left += _offsetX; - top += _offsetY; - right += _offsetX; - bottom += _offsetY; - - left = Math::Max(left, _clipLeft); - top = Math::Max(top, _clipTop); - right = Math::Min(right, _clipRight); - bottom = Math::Min(bottom, _clipBottom); - - if (right < left || bottom < top) - { - return; - } - - glDisable(GL_TEXTURE_2D); - - if (colour & 0x2000000) - { - glColor4f(paletteColour.r, paletteColour.g, paletteColour.b, 0.4f); - } - else - { - glColor3f(paletteColour.r, paletteColour.g, paletteColour.b); - } - - glBegin(GL_QUADS); - glVertex2i(left, top); - glVertex2i(left, bottom + 1); - glVertex2i(right + 1, bottom + 1); - glVertex2i(right + 1, top); - glEnd(); -} - -void OpenGLDrawingContext::DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2) -{ - vec4f paletteColour = _engine->GLPalette[colour & 0xFF]; - glColor3f(paletteColour.r, paletteColour.g, paletteColour.b); - glBegin(GL_LINES); - glVertex2i(x1, y1); - glVertex2i(x2, y2); - glEnd(); -} - -void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour) -{ - int g1Id = image & 0x7FFFF; - rct_g1_element * g1Element = gfx_get_g1_element(g1Id); - - if (_dpi->zoom_level != 0) - { - if (g1Element->flags & (1 << 4)) - { - rct_drawpixelinfo zoomedDPI; - zoomedDPI.bits = _dpi->bits; - zoomedDPI.x = _dpi->x >> 1; - zoomedDPI.y = _dpi->y >> 1; - zoomedDPI.height = _dpi->height >> 1; - zoomedDPI.width = _dpi->width >> 1; - zoomedDPI.pitch = _dpi->pitch; - zoomedDPI.zoom_level = _dpi->zoom_level - 1; - SetDPI(&zoomedDPI); - DrawSprite((image << 28) | (g1Id - g1Element->zoomed_offset), x >> 1, y >> 1, tertiaryColour); - return; - } - if (g1Element->flags & (1 << 5)) - { - return; - } - } - - GLuint texture = GetOrLoadImageTexture(image); - - sint32 drawOffsetX = g1Element->x_offset; - sint32 drawOffsetY = g1Element->y_offset; - sint32 drawWidth = (uint16)g1Element->width >> _dpi->zoom_level; - sint32 drawHeight = (uint16)g1Element->height >> _dpi->zoom_level; - - sint32 left = x + drawOffsetX; - sint32 top = y + drawOffsetY; - sint32 right = left + drawWidth; - sint32 bottom = top + drawHeight; - // FillRect(g1Id & 0xFF, left, top, right, bottom); - - if (left > right) - { - left ^= right; - right ^= left; - left ^= right; - } - if (top > bottom) - { - top ^= bottom; - bottom ^= top; - top ^= bottom; - } - - left += _offsetX; - top += _offsetY; - right += _offsetX; - bottom += _offsetY; - - vec2f texCoords[4] = { { 0, 0 }, - { 0, 1 }, - { 1, 1 }, - { 1, 0 } }; - - sint32 leftChop = _clipLeft - left; - if (leftChop > 0) - { - left += leftChop; - texCoords[0].x = - texCoords[1].x = (float)leftChop / g1Element->width; - } - - sint32 rightChop = right - _clipRight; - if (rightChop > 0) - { - right -= rightChop; - texCoords[2].x = - texCoords[3].x = 1.0f - ((float)rightChop / g1Element->width); - } - - sint32 topChop = _clipTop - top; - if (topChop > 0) - { - top += topChop; - texCoords[0].y = - texCoords[3].y = (float)topChop / g1Element->height; - } - - sint32 bottomChop = bottom - _clipBottom; - if (bottomChop > 0) - { - bottom -= bottomChop; - texCoords[1].y = - texCoords[2].y = 1.0f - ((float)bottomChop / g1Element->height); - } - - if (right < left || bottom < top) - { - return; - } - - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, texture); - glColor3f(1, 1, 1); - glBegin(GL_QUADS); - glTexCoord2f(texCoords[0].s, texCoords[0].t); - glVertex2i(left, top); - glTexCoord2f(texCoords[1].s, texCoords[1].t); - glVertex2i(left, bottom); - glTexCoord2f(texCoords[2].s, texCoords[2].t); - glVertex2i(right, bottom); - glTexCoord2f(texCoords[3].s, texCoords[3].t); - glVertex2i(right, top); - glEnd(); -} - -void OpenGLDrawingContext::DrawSpritePaletteSet(uint32 image, sint32 x, sint32 y, uint8 * palette, uint8 * unknown) -{ - DrawSprite(image, x, y, 0); -} - -void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) -{ -} - -void OpenGLDrawingContext::SetDPI(rct_drawpixelinfo * dpi) -{ - rct_drawpixelinfo * screenDPI = _engine->GetDPI(); - size_t bitsSize = (size_t)screenDPI->height * (size_t)(screenDPI->width + screenDPI->pitch); - size_t bitsOffset = (size_t)(dpi->bits - screenDPI->bits); - - assert(bitsOffset < bitsSize); - - _clipLeft = bitsOffset % (screenDPI->width + screenDPI->pitch); - _clipTop = bitsOffset / (screenDPI->width + screenDPI->pitch); - - _clipRight = _clipLeft + dpi->width; - _clipBottom = _clipTop + dpi->height; - _offsetX = _clipLeft - dpi->x; - _offsetY = _clipTop - dpi->y; - - _dpi = dpi; -} - -GLuint OpenGLDrawingContext::GetOrLoadImageTexture(uint32 image) -{ - auto kvp = _imageTextureMap.find(image); - if (kvp != _imageTextureMap.end()) - { - return kvp->second; - } - - GLuint texture = LoadImageTexture(image); - _textures.push_back(texture); - _imageTextureMap[image] = texture; - - // if ((_textures.size() % 100) == 0) - // { - // printf("Textures: %d\n", _textures.size()); - // } - - return texture; -} - -GLuint OpenGLDrawingContext::LoadImageTexture(uint32 image) -{ - GLuint texture; - glGenTextures(1, &texture); - - uint32 width, height; - void * pixels32 = GetImageAsARGB(image, 0, &width, &height); - - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels32); - - delete [] (uint8 *) pixels32; - - return texture; -} - -void * OpenGLDrawingContext::GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32 * outWidth, uint32 * outHeight) -{ - int g1Id = image & 0x7FFFF; - rct_g1_element * g1Element = gfx_get_g1_element(g1Id); - - uint32 width = (uint32)g1Element->width; - uint32 height = (uint32)g1Element->height; - - size_t numPixels = width * height; - uint8 * pixels8 = new uint8[numPixels]; - Memory::Set(pixels8, 0, numPixels); - - rct_drawpixelinfo dpi; - dpi.bits = pixels8; - dpi.pitch = 0; - dpi.x = 0; - dpi.y = 0; - dpi.width = width; - dpi.height = height; - dpi.zoom_level = 0; - gfx_draw_sprite_software(&dpi, image, -g1Element->x_offset, -g1Element->y_offset, tertiaryColour); - - uint8 * pixels32 = new uint8[width * height * 4]; - uint8 * src = pixels8; - uint8 * dst = pixels32; - for (size_t i = 0; i < numPixels; i++) - { - uint8 paletteIndex = *src++; - if (paletteIndex == 0) - { - // Transparent - *dst++ = 0; - *dst++ = 0; - *dst++ = 0; - *dst++ = 0; - } - else - { - SDL_Color colour = _engine->Palette[paletteIndex]; - *dst++ = colour.r; - *dst++ = colour.g; - *dst++ = colour.b; - *dst++ = 255; - } - } - - delete[] pixels8; - - *outWidth = width; - *outHeight = height; - return pixels32; -} - -void OpenGLDrawingContext::InvalidateImage(uint32 image) -{ - auto kvp = _imageTextureMap.find(image); - if (kvp != _imageTextureMap.end()) - { - GLuint texture = kvp->second; - glDeleteTextures(1, &texture); - - _imageTextureMap.erase(kvp); - } -} - -void OpenGLDrawingContext::FreeTextures() -{ - glDeleteTextures(_textures.size(), _textures.data()); -} - -#endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/SoftwareDrawingEngine.cpp b/src/drawing/engines/SoftwareDrawingEngine.cpp index 7efa5b3ceb..6bf113c305 100644 --- a/src/drawing/engines/SoftwareDrawingEngine.cpp +++ b/src/drawing/engines/SoftwareDrawingEngine.cpp @@ -170,8 +170,9 @@ public: void FillRect(uint32 colour, sint32 x, sint32 y, sint32 w, sint32 h) override; void DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2) override; void DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour) override; - void DrawSpritePaletteSet(uint32 image, sint32 x, sint32 y, uint8 * palette, uint8 * unknown) override; void DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) override; + void DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour) override; + void DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette) override; void SetDPI(rct_drawpixelinfo * dpi); }; @@ -1006,16 +1007,27 @@ void SoftwareDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 gfx_draw_sprite_software(_dpi, image, x, y, tertiaryColour); } -void SoftwareDrawingContext::DrawSpritePaletteSet(uint32 image, sint32 x, sint32 y, uint8 * palette, uint8 * unknown) -{ - gfx_draw_sprite_palette_set_software(_dpi, image, x, y, palette, unknown); -} - void SoftwareDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) { gfx_draw_sprite_raw_masked_software(_dpi, x, y, maskImage, colourImage); } +void SoftwareDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour) +{ + uint8 palette[256]; + memset(palette, colour, 256); + palette[0] = 0; + + RCT2_GLOBAL(0x00EDF81C, uint32) = 0x20000000; + image &= 0x7FFFF; + gfx_draw_sprite_palette_set_software(_dpi, image | 0x20000000, x, y, palette, nullptr); +} + +void SoftwareDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette) +{ + gfx_draw_sprite_palette_set_software(_dpi, image, x, y, palette, nullptr); +} + void SoftwareDrawingContext::SetDPI(rct_drawpixelinfo * dpi) { _dpi = dpi; diff --git a/src/drawing/engines/opengl/CopyFramebufferShader.cpp b/src/drawing/engines/opengl/CopyFramebufferShader.cpp new file mode 100644 index 0000000000..a5520099a5 --- /dev/null +++ b/src/drawing/engines/opengl/CopyFramebufferShader.cpp @@ -0,0 +1,83 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#ifndef DISABLE_OPENGL + +#include "CopyFramebufferShader.h" + +CopyFramebufferShader::CopyFramebufferShader() : OpenGLShaderProgram("copyframebuffer") +{ + GetLocations(); + + glGenBuffers(1, &_vbo); + glGenVertexArrays(1, &_vao); + + vec2i vertices[] = { 0, 1, 2, 3 }; + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glBindVertexArray(_vao); + glEnableVertexAttribArray(vIndex); + glVertexAttribIPointer(vIndex, 1, GL_INT, 0, nullptr); + + Use(); + SetTextureCoordinates(0, 0, 1, 1); + glUniform1i(uTexture, 0); +} + +CopyFramebufferShader::~CopyFramebufferShader() +{ + glDeleteBuffers(1, &_vbo); + glDeleteVertexArrays(1, &_vao); +} + +void CopyFramebufferShader::GetLocations() +{ + uScreenSize = GetUniformLocation("uScreenSize"); + uBounds = GetUniformLocation("uBounds"); + uTextureCoordinates = GetUniformLocation("uTextureCoordinates"); + uTexture = GetUniformLocation("uTexture"); + + vIndex = GetAttributeLocation("vIndex"); +} + +void CopyFramebufferShader::SetScreenSize(sint32 width, sint32 height) +{ + glUniform2i(uScreenSize, width, height); +} + +void CopyFramebufferShader::SetBounds(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + glUniform4i(uBounds, left, top, right, bottom); +} + +void CopyFramebufferShader::SetTextureCoordinates(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + glUniform4i(uTextureCoordinates, left, top, right, bottom); +} + +void CopyFramebufferShader::SetTexture(GLuint texture) +{ + OpenGLAPI::SetTexture2D(0, texture); +} + +void CopyFramebufferShader::Draw() +{ + glBindVertexArray(_vao); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +} + +#endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/opengl/CopyFramebufferShader.h b/src/drawing/engines/opengl/CopyFramebufferShader.h new file mode 100644 index 0000000000..2ba4cb3887 --- /dev/null +++ b/src/drawing/engines/opengl/CopyFramebufferShader.h @@ -0,0 +1,48 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "GLSLTypes.h" +#include "OpenGLShaderProgram.h" + +class CopyFramebufferShader : public OpenGLShaderProgram +{ +private: + GLuint uScreenSize; + GLuint uBounds; + GLuint uTextureCoordinates; + GLuint uTexture; + + GLuint vIndex; + + GLuint _vbo; + GLuint _vao; + +public: + CopyFramebufferShader(); + ~CopyFramebufferShader() override; + + void SetScreenSize(sint32 width, sint32 height); + void SetBounds(sint32 left, sint32 top, sint32 right, sint32 bottom); + void SetTextureCoordinates(sint32 left, sint32 top, sint32 right, sint32 bottom); + void SetTexture(GLuint texture); + + void Draw(); + +private: + void GetLocations(); +}; diff --git a/src/drawing/engines/opengl/DrawImageMaskedShader.cpp b/src/drawing/engines/opengl/DrawImageMaskedShader.cpp new file mode 100644 index 0000000000..3566c02cfc --- /dev/null +++ b/src/drawing/engines/opengl/DrawImageMaskedShader.cpp @@ -0,0 +1,93 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#ifndef DISABLE_OPENGL + +#include "DrawImageMaskedShader.h" + +DrawImageMaskedShader::DrawImageMaskedShader() : OpenGLShaderProgram("drawimagemasked") +{ + GetLocations(); + + glGenBuffers(1, &_vbo); + glGenVertexArrays(1, &_vao); + + vec2i vertices[] = { 0, 1, 2, 3 }; + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glBindVertexArray(_vao); + glEnableVertexAttribArray(vIndex); + glVertexAttribIPointer(vIndex, 1, GL_INT, 0, 0); + + Use(); + glUniform1i(uTextureMask, 0); + glUniform1i(uTextureColour, 1); +} + +DrawImageMaskedShader::~DrawImageMaskedShader() +{ + glDeleteBuffers(1, &_vbo); + glDeleteVertexArrays(1, &_vao); + + glBindVertexArray(_vao); +} + +void DrawImageMaskedShader::GetLocations() +{ + uScreenSize = GetUniformLocation("uScreenSize"); + uClip = GetUniformLocation("uClip"); + uBounds = GetUniformLocation("uBounds"); + uTextureMask = GetUniformLocation("uTextureMask"); + uTextureColour = GetUniformLocation("uTextureColour"); + + vIndex = GetAttributeLocation("vIndex"); +} + +void DrawImageMaskedShader::SetScreenSize(sint32 width, sint32 height) +{ + glUniform2i(uScreenSize, width, height); +} + +void DrawImageMaskedShader::SetClip(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + glUniform4i(uClip, left, top, right, bottom); +} + +void DrawImageMaskedShader::SetBounds(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + glUniform4i(uBounds, left, top, right, bottom); +} + +void DrawImageMaskedShader::SetTextureMask(GLuint texture) +{ + OpenGLAPI::SetTexture2D(0, texture); +} + +void DrawImageMaskedShader::SetTextureColour(GLuint texture) +{ + OpenGLAPI::SetTexture2D(1, texture); +} + +void DrawImageMaskedShader::Draw(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + SetBounds(left, top, right, bottom); + + glBindVertexArray(_vao); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +} + +#endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/opengl/DrawImageMaskedShader.h b/src/drawing/engines/opengl/DrawImageMaskedShader.h new file mode 100644 index 0000000000..f1081b4a5c --- /dev/null +++ b/src/drawing/engines/opengl/DrawImageMaskedShader.h @@ -0,0 +1,49 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "GLSLTypes.h" +#include "OpenGLShaderProgram.h" + +class DrawImageMaskedShader : public OpenGLShaderProgram +{ +private: + GLuint uScreenSize; + GLuint uClip; + GLuint uBounds; + GLuint uTextureMask; + GLuint uTextureColour; + + GLuint vIndex; + + GLuint _vbo; + GLuint _vao; + +public: + DrawImageMaskedShader(); + ~DrawImageMaskedShader() override; + + void SetScreenSize(sint32 width, sint32 height); + void SetClip(sint32 left, sint32 top, sint32 right, sint32 bottom); + void SetBounds(sint32 left, sint32 top, sint32 right, sint32 bottom); + void SetTextureMask(GLuint texture); + void SetTextureColour(GLuint texture); + void Draw(sint32 left, sint32 top, sint32 right, sint32 bottom); + +private: + void GetLocations(); +}; diff --git a/src/drawing/engines/opengl/DrawImageShader.cpp b/src/drawing/engines/opengl/DrawImageShader.cpp new file mode 100644 index 0000000000..d8000fe5ce --- /dev/null +++ b/src/drawing/engines/opengl/DrawImageShader.cpp @@ -0,0 +1,106 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#ifndef DISABLE_OPENGL + +#include "DrawImageShader.h" + +DrawImageShader::DrawImageShader() : OpenGLShaderProgram("drawimage") +{ + GetLocations(); + + glGenBuffers(1, &_vbo); + glGenVertexArrays(1, &_vao); + + vec2i vertices[] = { 0, 1, 2, 3 }; + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glBindVertexArray(_vao); + glEnableVertexAttribArray(vIndex); + glVertexAttribIPointer(vIndex, 1, GL_INT, 0, nullptr); + + Use(); + SetFlags(0); + SetTextureCoordinates(0, 0, 1, 1); + glUniform1i(uTexture, 0); +} + +DrawImageShader::~DrawImageShader() +{ + glDeleteBuffers(1, &_vbo); + glDeleteVertexArrays(1, &_vao); + + glBindVertexArray(_vao); +} + +void DrawImageShader::GetLocations() +{ + uScreenSize = GetUniformLocation("uScreenSize"); + uClip = GetUniformLocation("uClip"); + uBounds = GetUniformLocation("uBounds"); + uTextureCoordinates = GetUniformLocation("uTextureCoordinates"); + uTexture = GetUniformLocation("uTexture"); + uColour = GetUniformLocation("uColour"); + uFlags = GetUniformLocation("uFlags"); + + vIndex = GetAttributeLocation("vIndex"); +} + +void DrawImageShader::SetScreenSize(sint32 width, sint32 height) +{ + glUniform2i(uScreenSize, width, height); +} + +void DrawImageShader::SetClip(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + glUniform4i(uClip, left, top, right, bottom); +} + +void DrawImageShader::SetBounds(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + glUniform4i(uBounds, left, top, right, bottom); +} + +void DrawImageShader::SetTextureCoordinates(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + glUniform4i(uTextureCoordinates, left, top, right, bottom); +} + +void DrawImageShader::SetTexture(GLuint texture) +{ + OpenGLAPI::SetTexture2D(0, texture); +} + +void DrawImageShader::SetColour(vec4f colour) +{ + glUniform4f(uColour, colour.r, colour.g, colour.b, colour.a); +} + +void DrawImageShader::SetFlags(uint32 flags) +{ + glUniform1i(uFlags, flags); +} + +void DrawImageShader::Draw(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + SetBounds(left, top, right, bottom); + + glBindVertexArray(_vao); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +} + +#endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/opengl/DrawImageShader.h b/src/drawing/engines/opengl/DrawImageShader.h new file mode 100644 index 0000000000..8c9b2756b0 --- /dev/null +++ b/src/drawing/engines/opengl/DrawImageShader.h @@ -0,0 +1,54 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "GLSLTypes.h" +#include "OpenGLShaderProgram.h" + +class DrawImageShader : public OpenGLShaderProgram +{ +private: + GLuint uScreenSize; + GLuint uClip; + GLuint uBounds; + GLuint uTextureCoordinates; + GLuint uTexture; + GLuint uColour; + GLuint uFlags; + + GLuint vIndex; + + GLuint _vbo; + GLuint _vao; + +public: + DrawImageShader(); + ~DrawImageShader() override; + + void SetScreenSize(sint32 width, sint32 height); + void SetClip(sint32 left, sint32 top, sint32 right, sint32 bottom); + void SetBounds(sint32 left, sint32 top, sint32 right, sint32 bottom); + void SetTextureCoordinates(sint32 left, sint32 top, sint32 right, sint32 bottom); + void SetTexture(GLuint texture); + void SetColour(vec4f colour); + void SetFlags(uint32 flags); + + void Draw(sint32 left, sint32 top, sint32 right, sint32 bottom); + +private: + void GetLocations(); +}; diff --git a/src/drawing/engines/opengl/DrawLineShader.cpp b/src/drawing/engines/opengl/DrawLineShader.cpp new file mode 100644 index 0000000000..5f220ee6c9 --- /dev/null +++ b/src/drawing/engines/opengl/DrawLineShader.cpp @@ -0,0 +1,86 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#ifndef DISABLE_OPENGL + +#include "DrawLineShader.h" +#include "OpenGLFramebuffer.h" + +DrawLineShader::DrawLineShader() : OpenGLShaderProgram("drawline") +{ + GetLocations(); + + glGenBuffers(1, &_vbo); + glGenVertexArrays(1, &_vao); + + vec2i vertices[] = { 0, 1 }; + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glBindVertexArray(_vao); + glEnableVertexAttribArray(vIndex); + glVertexAttribIPointer(vIndex, 1, GL_INT, 0, nullptr); + + Use(); +} + +DrawLineShader::~DrawLineShader() +{ + glDeleteBuffers(1, &_vbo); + glDeleteVertexArrays(1, &_vao); + + glBindVertexArray(_vao); +} + +void DrawLineShader::GetLocations() +{ + uScreenSize = GetUniformLocation("uScreenSize"); + uClip = GetUniformLocation("uClip"); + uBounds = GetUniformLocation("uBounds"); + uColour = GetUniformLocation("uColour"); + + vIndex = GetAttributeLocation("vIndex"); +} + +void DrawLineShader::SetScreenSize(sint32 width, sint32 height) +{ + glUniform2i(uScreenSize, width, height); +} + +void DrawLineShader::SetClip(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + glUniform4i(uClip, left, top, right, bottom); +} + +void DrawLineShader::SetBounds(sint32 x0, sint32 y0, sint32 x1, sint32 y1) +{ + glUniform4i(uBounds, x0, y0, x1, y1); +} + +void DrawLineShader::SetColour(vec4f colour) +{ + glUniform4f(uColour, colour.r, colour.g, colour.b, colour.a); +} + +void DrawLineShader::Draw(sint32 x0, sint32 y0, sint32 x1, sint32 y1) +{ + SetBounds(x0, y0, x1, y1); + + glBindVertexArray(_vao); + glDrawArrays(GL_LINES, 0, 2); +} + +#endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/opengl/DrawLineShader.h b/src/drawing/engines/opengl/DrawLineShader.h new file mode 100644 index 0000000000..f8473b8dd9 --- /dev/null +++ b/src/drawing/engines/opengl/DrawLineShader.h @@ -0,0 +1,48 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "GLSLTypes.h" +#include "OpenGLShaderProgram.h" + +class DrawLineShader : public OpenGLShaderProgram +{ +private: + GLuint uScreenSize; + GLuint uClip; + GLuint uBounds; + GLuint uColour; + + GLuint vIndex; + + GLuint _vbo; + GLuint _vao; + +public: + DrawLineShader(); + ~DrawLineShader() override; + + void SetScreenSize(sint32 width, sint32 height); + void SetClip(sint32 left, sint32 top, sint32 right, sint32 bottom); + void SetBounds(sint32 x0, sint32 y0, sint32 x1, sint32 y1); + void SetColour(vec4f colour); + + void Draw(sint32 x0, sint32 y0, sint32 x1, sint32 y1); + +private: + void GetLocations(); +}; diff --git a/src/drawing/engines/opengl/FillRectShader.cpp b/src/drawing/engines/opengl/FillRectShader.cpp new file mode 100644 index 0000000000..9c02a00148 --- /dev/null +++ b/src/drawing/engines/opengl/FillRectShader.cpp @@ -0,0 +1,101 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#ifndef DISABLE_OPENGL + +#include "FillRectShader.h" +#include "OpenGLFramebuffer.h" + +FillRectShader::FillRectShader() : OpenGLShaderProgram("fillrect") +{ + GetLocations(); + + glGenBuffers(1, &_vbo); + glGenVertexArrays(1, &_vao); + + vec2i vertices[] = { 0, 1, 2, 3 }; + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glBindVertexArray(_vao); + glEnableVertexAttribArray(vIndex); + glVertexAttribIPointer(vIndex, 1, GL_INT, 0, 0); + + Use(); + SetFlags(0); + glUniform1i(uSourceFramebuffer, 0); +} + +FillRectShader::~FillRectShader() +{ + glDeleteBuffers(1, &_vbo); + glDeleteVertexArrays(1, &_vao); + + glBindVertexArray(_vao); +} + +void FillRectShader::GetLocations() +{ + uScreenSize = GetUniformLocation("uScreenSize"); + uClip = GetUniformLocation("uClip"); + uBounds = GetUniformLocation("uBounds"); + uFlags = GetUniformLocation("uFlags"); + uColour[0] = GetUniformLocation("uColour[0]"); + uColour[1] = GetUniformLocation("uColour[1]"); + uSourceFramebuffer = GetUniformLocation("uSourceFramebuffer"); + + vIndex = GetAttributeLocation("vIndex"); +} + +void FillRectShader::SetScreenSize(sint32 width, sint32 height) +{ + glUniform2i(uScreenSize, width, height); +} + +void FillRectShader::SetClip(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + glUniform4i(uClip, left, top, right, bottom); +} + +void FillRectShader::SetBounds(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + glUniform4i(uBounds, left, top, right, bottom); +} + +void FillRectShader::SetFlags(uint32 flags) +{ + glUniform1i(uFlags, flags); +} + +void FillRectShader::SetColour(int index, vec4f colour) +{ + glUniform4f(uColour[index], colour.r, colour.g, colour.b, colour.a); +} + +void FillRectShader::SetSourceFramebuffer(GLuint texture) +{ + OpenGLAPI::SetTexture2D(0, texture); +} + +void FillRectShader::Draw(sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + SetBounds(left, top, right, bottom); + + glBindVertexArray(_vao); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +} + +#endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/opengl/FillRectShader.h b/src/drawing/engines/opengl/FillRectShader.h new file mode 100644 index 0000000000..d96c33c705 --- /dev/null +++ b/src/drawing/engines/opengl/FillRectShader.h @@ -0,0 +1,54 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "GLSLTypes.h" +#include "OpenGLShaderProgram.h" + +class OpenGLFramebuffer; + +class FillRectShader : public OpenGLShaderProgram +{ +private: + GLuint uScreenSize; + GLuint uClip; + GLuint uBounds; + GLuint uFlags; + GLuint uColour[2]; + GLuint uSourceFramebuffer; + + GLuint vIndex; + + GLuint _vbo; + GLuint _vao; + +public: + FillRectShader(); + ~FillRectShader() override; + + void SetScreenSize(sint32 width, sint32 height); + void SetClip(sint32 left, sint32 top, sint32 right, sint32 bottom); + void SetBounds(sint32 left, sint32 top, sint32 right, sint32 bottom); + void SetFlags(uint32 flags); + void SetColour(int index, vec4f colour); + void SetSourceFramebuffer(GLuint texture); + + void Draw(sint32 left, sint32 top, sint32 right, sint32 bottom); + +private: + void GetLocations(); +}; diff --git a/src/drawing/engines/opengl/GLSLTypes.h b/src/drawing/engines/opengl/GLSLTypes.h new file mode 100644 index 0000000000..301bfe5389 --- /dev/null +++ b/src/drawing/engines/opengl/GLSLTypes.h @@ -0,0 +1,58 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../../../common.h" + +#pragma pack(push, 1) + +struct vec2i +{ + union { sint32 x; sint32 s; sint32 r; }; + union { sint32 y; sint32 t; sint32 g; }; +}; + +struct vec2f +{ + union { float x; float s; float r; }; + union { float y; float t; float g; }; +}; + +struct vec3f +{ + union { float x; float s; float r; }; + union { float y; float t; float g; }; + union { float z; float p; float b; }; +}; + +struct vec4i +{ + union { sint32 x; sint32 s; sint32 r; }; + union { sint32 y; sint32 t; sint32 g; }; + union { sint32 z; sint32 p; sint32 b; }; + union { sint32 w; sint32 q; sint32 a; }; +}; + +struct vec4f +{ + union { float x; float s; float r; }; + union { float y; float t; float g; }; + union { float z; float p; float b; }; + union { float w; float q; float a; }; +}; + +#pragma pack(pop) diff --git a/src/drawing/engines/OpenGLAPI.cpp b/src/drawing/engines/opengl/OpenGLAPI.cpp similarity index 55% rename from src/drawing/engines/OpenGLAPI.cpp rename to src/drawing/engines/opengl/OpenGLAPI.cpp index 9be06343ce..af07c6c566 100644 --- a/src/drawing/engines/OpenGLAPI.cpp +++ b/src/drawing/engines/opengl/OpenGLAPI.cpp @@ -23,7 +23,7 @@ #include -#include "../../core/Console.hpp" +#include "../../../core/Console.hpp" template static inline bool SetProc(T * func, const char * name) @@ -49,38 +49,82 @@ static inline bool SetProc(T * func, const char * name) static const char * TryLoadAllProcAddresses() { // 1.1 functions + SetupOpenGLFunction(glActiveTexture); SetupOpenGLFunction(glBegin); SetupOpenGLFunction(glBindTexture); SetupOpenGLFunction(glBlendFunc); SetupOpenGLFunction(glClear); SetupOpenGLFunction(glClearColor); - SetupOpenGLFunction(glColor3f); - SetupOpenGLFunction(glColor4f); + SetupOpenGLFunction(glCullFace); SetupOpenGLFunction(glDeleteTextures); SetupOpenGLFunction(glDisable); + SetupOpenGLFunction(glDrawArrays); SetupOpenGLFunction(glEnable); SetupOpenGLFunction(glEnd); SetupOpenGLFunction(glGenTextures); - SetupOpenGLFunction(glLoadIdentity); - SetupOpenGLFunction(glMatrixMode); - SetupOpenGLFunction(glOrtho); - SetupOpenGLFunction(glScalef); - SetupOpenGLFunction(glTexCoord2f); + SetupOpenGLFunction(glGetError); + SetupOpenGLFunction(glReadPixels); SetupOpenGLFunction(glTexImage2D); SetupOpenGLFunction(glTexParameteri); - SetupOpenGLFunction(glTranslatef); - SetupOpenGLFunction(glVertex2i); SetupOpenGLFunction(glViewport); // 2.0+ functions + SetupOpenGLFunction(glAttachShader); + SetupOpenGLFunction(glBindBuffer); + SetupOpenGLFunction(glBindFragDataLocation); + SetupOpenGLFunction(glBindFramebuffer); + SetupOpenGLFunction(glBindVertexArray); + SetupOpenGLFunction(glBufferData); + SetupOpenGLFunction(glCompileShader); + SetupOpenGLFunction(glCreateProgram); SetupOpenGLFunction(glCreateShader); + SetupOpenGLFunction(glDeleteBuffers); + SetupOpenGLFunction(glDeleteFramebuffers); + SetupOpenGLFunction(glDeleteProgram); SetupOpenGLFunction(glDeleteShader); + SetupOpenGLFunction(glDeleteVertexArrays); + SetupOpenGLFunction(glDetachShader); + SetupOpenGLFunction(glEnableVertexAttribArray); + SetupOpenGLFunction(glFramebufferTexture2D); + SetupOpenGLFunction(glGetAttribLocation); + SetupOpenGLFunction(glGenBuffers); + SetupOpenGLFunction(glGenFramebuffers); + SetupOpenGLFunction(glGetProgramInfoLog); + SetupOpenGLFunction(glGetProgramiv); + SetupOpenGLFunction(glGetShaderInfoLog); + SetupOpenGLFunction(glGetShaderiv); + SetupOpenGLFunction(glGetUniformLocation); + SetupOpenGLFunction(glGenVertexArrays); + SetupOpenGLFunction(glLinkProgram); + SetupOpenGLFunction(glShaderSource); + SetupOpenGLFunction(glUniform1i); + SetupOpenGLFunction(glUniform2i); + SetupOpenGLFunction(glUniform4f); + SetupOpenGLFunction(glUniform4i); + SetupOpenGLFunction(glUseProgram); + SetupOpenGLFunction(glVertexAttribIPointer); + SetupOpenGLFunction(glVertexAttribPointer); return nullptr; } #endif /* #if OPENGL_NO_LINK */ +namespace OpenGLState +{ + uint16 ActiveTexture = UINT16_MAX; + GLuint CurrentProgram = UINT32_MAX; +} + +void OpenGLAPI::SetTexture2D(uint16 index, GLuint texture) +{ + if (OpenGLState::ActiveTexture != index) + { + glActiveTexture(GL_TEXTURE0 + index); + } + glBindTexture(GL_TEXTURE_2D, texture); +} + bool OpenGLAPI::Initialise() { #ifdef OPENGL_NO_LINK diff --git a/src/drawing/engines/opengl/OpenGLAPI.h b/src/drawing/engines/opengl/OpenGLAPI.h new file mode 100644 index 0000000000..8ee1713f64 --- /dev/null +++ b/src/drawing/engines/opengl/OpenGLAPI.h @@ -0,0 +1,177 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../../../common.h" + +#if OPENGL_NO_LINK + +// BEGIN [Do not define 1.1 function signatures] +#define glActiveTexture __static__glActiveTexture +#define glBegin __static__glBegin +#define glBindTexture __static__glBindTexture +#define glBlendFunc __static__glBlendFunc +#define glClear __static__glClear +#define glClearColor __static__glClearColor +#define glCullFace __static__glCullFace +#define glDeleteTextures __static__glDeleteTextures +#define glDisable __static__glDisable +#define glDrawArrays __static__glDrawArrays +#define glEnable __static__glEnable +#define glEnd __static__glEnd +#define glGenTextures __static__glGenTextures +#define glGetError __static__glGetError +#define glReadPixels __static__glReadPixels +#define glTexImage2D __static__glTexImage2D +#define glTexParameteri __static__glTexParameteri +#define glViewport __static__glViewport + +#endif + +#include + +#if OPENGL_NO_LINK + +// END [Do not define 1.1 function signatures] +#undef glActiveTexture +#undef glBegin +#undef glBindTexture +#undef glBlendFunc +#undef glClear +#undef glClearColor +#undef glCullFace +#undef glDeleteTextures +#undef glDisable +#undef glDrawArrays +#undef glEnable +#undef glEnd +#undef glGenTextures +#undef glGetError +#undef glReadPixels +#undef glTexImage2D +#undef glTexParameteri +#undef glViewport + +// 1.1 function signatures +typedef void (APIENTRYP PFNGLBEGINPROC )(GLenum mode); +typedef void (APIENTRYP PFNGLBINDTEXTUREPROC )(GLenum target, GLuint texture); +typedef void (APIENTRYP PFNGLBLENDFUNCPROC )(GLenum sfactor, GLenum dfactor); +typedef void (APIENTRYP PFNGLCLEARPROC )(GLbitfield mask); +typedef void (APIENTRYP PFNGLCLEARCOLORPROC )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (APIENTRYP PFNGLCULLFACEPROC )(GLenum mode); +typedef void (APIENTRYP PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint *textures); +typedef void (APIENTRYP PFNGLDISABLEPROC )(GLenum cap); +typedef void (APIENTRYP PFNGLDRAWARRAYSPROC )(GLenum mode, GLint first, GLsizei count); +typedef void (APIENTRYP PFNGLENABLEPROC )(GLenum cap); +typedef void (APIENTRYP PFNGLENDPROC )(void); +typedef GLenum (APIENTRYP PFNGLGETERRORPROC )(void); +typedef void (APIENTRYP PFNGLGENTEXTURESPROC )(GLsizei n, GLuint *textures); +typedef void (APIENTRYP PFNGLREADPIXELSPROC )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid * pixels); +typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC )(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC )(GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLVIEWPORTPROC )(GLint x, GLint y, GLsizei width, GLsizei height); + +#ifdef NO_EXTERN_GLAPI + // Defines the function pointers + #define GLAPI_DECL + #define GLAPI_SET = nullptr +#else + // Defines the functions as "extern" + #define GLAPI_DECL extern + #define GLAPI_SET +#endif + +// 1.1 function pointers +GLAPI_DECL PFNGLACTIVETEXTUREPROC glActiveTexture GLAPI_SET; +GLAPI_DECL PFNGLBEGINPROC glBegin GLAPI_SET; +GLAPI_DECL PFNGLBINDTEXTUREPROC glBindTexture GLAPI_SET; +GLAPI_DECL PFNGLBLENDFUNCPROC glBlendFunc GLAPI_SET; +GLAPI_DECL PFNGLCLEARPROC glClear GLAPI_SET; +GLAPI_DECL PFNGLCLEARCOLORPROC glClearColor GLAPI_SET; +GLAPI_DECL PFNGLCULLFACEPROC glCullFace GLAPI_SET; +GLAPI_DECL PFNGLDELETETEXTURESPROC glDeleteTextures GLAPI_SET; +GLAPI_DECL PFNGLDISABLEPROC glDisable GLAPI_SET; +GLAPI_DECL PFNGLDRAWARRAYSPROC glDrawArrays GLAPI_SET; +GLAPI_DECL PFNGLENABLEPROC glEnable GLAPI_SET; +GLAPI_DECL PFNGLENDPROC glEnd GLAPI_SET; +GLAPI_DECL PFNGLGENTEXTURESPROC glGenTextures GLAPI_SET; +GLAPI_DECL PFNGLGETERRORPROC glGetError GLAPI_SET; +GLAPI_DECL PFNGLREADPIXELSPROC glReadPixels GLAPI_SET; +GLAPI_DECL PFNGLTEXIMAGE2DPROC glTexImage2D GLAPI_SET; +GLAPI_DECL PFNGLTEXPARAMETERIPROC glTexParameteri GLAPI_SET; +GLAPI_DECL PFNGLVIEWPORTPROC glViewport GLAPI_SET; + +// 2.0+ function pointers +GLAPI_DECL PFNGLATTACHSHADERPROC glAttachShader GLAPI_SET; +GLAPI_DECL PFNGLBINDBUFFERPROC glBindBuffer GLAPI_SET; +GLAPI_DECL PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation GLAPI_SET; +GLAPI_DECL PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer GLAPI_SET; +GLAPI_DECL PFNGLBINDVERTEXARRAYPROC glBindVertexArray GLAPI_SET; +GLAPI_DECL PFNGLBUFFERDATAPROC glBufferData GLAPI_SET; +GLAPI_DECL PFNGLCOMPILESHADERPROC glCompileShader GLAPI_SET; +GLAPI_DECL PFNGLCREATEPROGRAMPROC glCreateProgram GLAPI_SET; +GLAPI_DECL PFNGLCREATESHADERPROC glCreateShader GLAPI_SET; +GLAPI_DECL PFNGLDELETEBUFFERSPROC glDeleteBuffers GLAPI_SET; +GLAPI_DECL PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers GLAPI_SET; +GLAPI_DECL PFNGLDELETEPROGRAMPROC glDeleteProgram GLAPI_SET; +GLAPI_DECL PFNGLDELETESHADERPROC glDeleteShader GLAPI_SET; +GLAPI_DECL PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays GLAPI_SET; +GLAPI_DECL PFNGLDETACHSHADERPROC glDetachShader GLAPI_SET; +GLAPI_DECL PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray GLAPI_SET; +GLAPI_DECL PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D GLAPI_SET; +GLAPI_DECL PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation GLAPI_SET; +GLAPI_DECL PFNGLGENBUFFERSPROC glGenBuffers GLAPI_SET; +GLAPI_DECL PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers GLAPI_SET; +GLAPI_DECL PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog GLAPI_SET; +GLAPI_DECL PFNGLGETPROGRAMIVPROC glGetProgramiv GLAPI_SET; +GLAPI_DECL PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog GLAPI_SET; +GLAPI_DECL PFNGLGETSHADERIVPROC glGetShaderiv GLAPI_SET; +GLAPI_DECL PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation GLAPI_SET; +GLAPI_DECL PFNGLGENVERTEXARRAYSPROC glGenVertexArrays GLAPI_SET; +GLAPI_DECL PFNGLLINKPROGRAMPROC glLinkProgram GLAPI_SET; +GLAPI_DECL PFNGLSHADERSOURCEPROC glShaderSource GLAPI_SET; +GLAPI_DECL PFNGLUNIFORM1IPROC glUniform1i GLAPI_SET; +GLAPI_DECL PFNGLUNIFORM2IPROC glUniform2i GLAPI_SET; +GLAPI_DECL PFNGLUNIFORM4FPROC glUniform4f GLAPI_SET; +GLAPI_DECL PFNGLUNIFORM4IPROC glUniform4i GLAPI_SET; +GLAPI_DECL PFNGLUSEPROGRAMPROC glUseProgram GLAPI_SET; +GLAPI_DECL PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer GLAPI_SET; +GLAPI_DECL PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer GLAPI_SET; + +#endif /* OPENGL_NO_LINK */ + +inline void CheckGLError() +{ + GLenum error = glGetError(); + while (error != GL_NO_ERROR) + { + log_error("OpenGL Error 0x%04X", error); + error = glGetError(); + } +} + +namespace OpenGLAPI +{ + bool Initialise(); + void SetTexture2D(uint16 index, GLuint texture); +} + +namespace OpenGLState +{ + extern uint16 ActiveTexture; + extern GLuint CurrentProgram; +} diff --git a/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp new file mode 100644 index 0000000000..a9f7c6f239 --- /dev/null +++ b/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -0,0 +1,770 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#ifdef DISABLE_OPENGL + +#include "../../IDrawingEngine.h" + +IDrawingEngine * DrawingEngineFactory::CreateOpenGL() +{ + return nullptr; +} + +#else + +#include +#include +#include + +#include "GLSLTypes.h" +#include "OpenGLAPI.h" +#include "OpenGLFramebuffer.h" +#include "CopyFramebufferShader.h" +#include "DrawImageShader.h" +#include "DrawImageMaskedShader.h" +#include "DrawLineShader.h" +#include "FillRectShader.h" +#include "SwapFramebuffer.h" +#include "TextureCache.h" + +#include "../../../core/Console.hpp" +#include "../../../core/Exception.hpp" +#include "../../../core/Math.hpp" +#include "../../../core/Memory.hpp" +#include "../../IDrawingContext.h" +#include "../../IDrawingEngine.h" +#include "../../Rain.h" + +extern "C" +{ + #include "../../../config.h" + #include "../../../interface/screenshot.h" + #include "../../../interface/window.h" + #include "../../../intro.h" + #include "../../drawing.h" +} + +static const vec3f TransparentColourTable[144 - 44] = +{ + { 0.7f, 0.8f, 0.8f }, // 44 + { 0.7f, 0.8f, 0.8f }, + { 0.3f, 0.4f, 0.4f }, + { 0.2f, 0.3f, 0.3f }, + { 0.1f, 0.2f, 0.2f }, + { 0.4f, 0.5f, 0.5f }, + { 0.3f, 0.4f, 0.4f }, + { 0.4f, 0.5f, 0.5f }, + { 0.4f, 0.5f, 0.5f }, + { 0.3f, 0.4f, 0.4f }, + { 0.6f, 0.7f, 0.7f }, + { 0.3f, 0.5f, 0.9f }, + { 0.1f, 0.3f, 0.8f }, + { 0.5f, 0.7f, 0.9f }, + { 0.6f, 0.2f, 0.2f }, + { 0.5f, 0.1f, 0.1f }, + { 0.8f, 0.4f, 0.4f }, + { 0.3f, 0.5f, 0.4f }, + { 0.2f, 0.4f, 0.2f }, + { 0.5f, 0.7f, 0.5f }, + { 0.5f, 0.5f, 0.7f }, + { 0.3f, 0.3f, 0.5f }, + { 0.6f, 0.6f, 0.8f }, + { 0.5f, 0.5f, 0.2f }, + { 0.4f, 0.4f, 0.1f }, + { 0.7f, 0.7f, 0.4f }, + { 0.7f, 0.5f, 0.3f }, + { 0.6f, 0.4f, 0.2f }, + { 0.8f, 0.7f, 0.4f }, + { 0.8f, 0.7f, 0.1f }, + { 0.7f, 0.4f, 0.0f }, + { 1.0f, 0.9f, 0.2f }, + { 0.4f, 0.6f, 0.2f }, + { 0.3f, 0.4f, 0.2f }, + { 0.5f, 0.7f, 0.3f }, + { 0.5f, 0.6f, 0.4f }, + { 0.4f, 0.4f, 0.3f }, + { 0.7f, 0.8f, 0.5f }, + { 0.3f, 0.7f, 0.2f }, + { 0.2f, 0.6f, 0.0f }, + { 0.4f, 0.8f, 0.3f }, + { 0.8f, 0.5f, 0.4f }, + { 0.7f, 0.4f, 0.3f }, + { 0.9f, 0.7f, 0.5f }, + { 0.5f, 0.3f, 0.7f }, + { 0.4f, 0.2f, 0.6f }, + { 0.7f, 0.5f, 0.8f }, + { 0.9f, 0.0f, 0.0f }, + { 0.7f, 0.0f, 0.0f }, + { 1.0f, 0.3f, 0.3f }, + { 1.0f, 0.4f, 0.1f }, + { 0.9f, 0.3f, 0.0f }, + { 1.0f, 0.6f, 0.3f }, + { 0.2f, 0.6f, 0.6f }, + { 0.0f, 0.4f, 0.4f }, + { 0.4f, 0.7f, 0.7f }, + { 0.9f, 0.2f, 0.6f }, + { 0.6f, 0.1f, 0.4f }, + { 1.0f, 0.5f, 0.7f }, + { 0.6f, 0.5f, 0.4f }, + { 0.4f, 0.3f, 0.2f }, + { 0.7f, 0.7f, 0.6f }, + { 0.9f, 0.6f, 0.6f }, + { 0.8f, 0.5f, 0.5f }, + { 1.0f, 0.7f, 0.7f }, + { 0.7f, 0.8f, 0.8f }, + { 0.5f, 0.6f, 0.6f }, + { 0.9f, 1.0f, 1.0f }, + { 0.2f, 0.3f, 0.3f }, + { 0.4f, 0.5f, 0.5f }, + { 0.7f, 0.8f, 0.8f }, + { 0.2f, 0.3f, 0.5f }, + { 0.5f, 0.5f, 0.7f }, + { 0.5f, 0.3f, 0.7f }, + { 0.1f, 0.3f, 0.7f }, + { 0.3f, 0.5f, 0.9f }, + { 0.6f, 0.8f, 1.0f }, + { 0.2f, 0.6f, 0.6f }, + { 0.5f, 0.8f, 0.8f }, + { 0.1f, 0.5f, 0.0f }, + { 0.3f, 0.5f, 0.4f }, + { 0.4f, 0.6f, 0.2f }, + { 0.3f, 0.7f, 0.2f }, + { 0.5f, 0.6f, 0.4f }, + { 0.5f, 0.5f, 0.2f }, + { 1.0f, 0.9f, 0.2f }, + { 0.8f, 0.7f, 0.1f }, + { 0.6f, 0.3f, 0.0f }, + { 1.0f, 0.4f, 0.1f }, + { 0.7f, 0.3f, 0.0f }, + { 0.7f, 0.5f, 0.3f }, + { 0.5f, 0.3f, 0.1f }, + { 0.5f, 0.4f, 0.3f }, + { 0.8f, 0.5f, 0.4f }, + { 0.6f, 0.2f, 0.2f }, + { 0.6f, 0.0f, 0.0f }, + { 0.9f, 0.0f, 0.0f }, + { 0.6f, 0.1f, 0.3f }, + { 0.9f, 0.2f, 0.6f }, + { 0.9f, 0.6f, 0.6f }, +}; + +class OpenGLDrawingEngine; + +class OpenGLDrawingContext : public IDrawingContext +{ +private: + OpenGLDrawingEngine * _engine; + rct_drawpixelinfo * _dpi; + + DrawImageShader * _drawImageShader = nullptr; + DrawImageMaskedShader * _drawImageMaskedShader = nullptr; + DrawLineShader * _drawLineShader = nullptr; + FillRectShader * _fillRectShader = nullptr; + + TextureCache * _textureCache = nullptr; + + sint32 _offsetX; + sint32 _offsetY; + sint32 _clipLeft; + sint32 _clipTop; + sint32 _clipRight; + sint32 _clipBottom; + +public: + explicit OpenGLDrawingContext(OpenGLDrawingEngine * engine); + ~OpenGLDrawingContext() override; + + IDrawingEngine * GetEngine() override; + TextureCache * GetTextureCache() const { return _textureCache; } + + void Initialise(); + void Resize(sint32 width, sint32 height); + + void Clear(uint32 colour) override; + void FillRect(uint32 colour, sint32 x, sint32 y, sint32 w, sint32 h) override; + void DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2) override; + void DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour) override; + void DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) override; + void DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour) override; + void DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette) override; + + void SetDPI(rct_drawpixelinfo * dpi); +}; + +class OpenGLDrawingEngine : public IDrawingEngine +{ +private: + SDL_Window * _window = nullptr; + SDL_GLContext _context; + + uint32 _width = 0; + uint32 _height = 0; + uint32 _pitch = 0; + size_t _bitsSize = 0; + uint8 * _bits = nullptr; + + rct_drawpixelinfo _bitsDPI = { 0 }; + + OpenGLDrawingContext * _drawingContext; + + CopyFramebufferShader * _copyFramebufferShader = nullptr; + OpenGLFramebuffer * _screenFramebuffer = nullptr; + SwapFramebuffer * _swapFramebuffer = nullptr; + +public: + SDL_Color Palette[256]; + vec4f GLPalette[256]; + + OpenGLDrawingEngine() + { + _drawingContext = new OpenGLDrawingContext(this); + } + + ~OpenGLDrawingEngine() override + { + delete _copyFramebufferShader; + + delete _drawingContext; + delete [] _bits; + + SDL_GL_DeleteContext(_context); + } + + void Initialise(SDL_Window * window) override + { + _window = window; + + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + _context = SDL_GL_CreateContext(_window); + SDL_GL_MakeCurrent(_window, _context); + + if (!OpenGLAPI::Initialise()) + { + throw Exception("Unable to initialise OpenGL."); + } + + _drawingContext->Initialise(); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // Do not draw the unseen side of the primitives + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + + _copyFramebufferShader = new CopyFramebufferShader(); + } + + void Resize(uint32 width, uint32 height) override + { + ConfigureBits(width, height, width); + ConfigureCanvas(); + _drawingContext->Resize(width, height); + } + + void SetPalette(SDL_Color * palette) override + { + for (int i = 0; i < 256; i++) + { + SDL_Color colour = palette[i]; + colour.a = i == 0 ? 0 : 255; + + Palette[i] = colour; + GLPalette[i] = { colour.r / 255.0f, + colour.g / 255.0f, + colour.b / 255.0f, + colour.a / 255.0f }; + } + _drawingContext->GetTextureCache() + ->SetPalette(Palette); + } + + void Invalidate(sint32 left, sint32 top, sint32 right, sint32 bottom) override + { + } + + void Draw() override + { + assert(_screenFramebuffer != nullptr); + assert(_swapFramebuffer != nullptr); + + _swapFramebuffer->Bind(); + + if (gIntroState != INTRO_STATE_NONE) { + intro_draw(&_bitsDPI); + } else { + window_update_all_viewports(); + window_draw_all(&_bitsDPI, 0, 0, _width, _height); + window_update_all(); + + gfx_draw_pickedup_peep(&_bitsDPI); + + _swapFramebuffer->SwapCopy(); + + rct2_draw(&_bitsDPI); + } + + // Scale up to window + _screenFramebuffer->Bind(); + + sint32 width = _screenFramebuffer->GetWidth(); + sint32 height = _screenFramebuffer->GetHeight(); + _copyFramebufferShader->Use(); + _copyFramebufferShader->SetTexture(_swapFramebuffer->GetTargetFramebuffer() + ->GetTexture()); + _copyFramebufferShader->Draw(); + + CheckGLError(); + Display(); + } + + sint32 Screenshot() override + { + const OpenGLFramebuffer * framebuffer = _swapFramebuffer->GetTargetFramebuffer(); + framebuffer->Bind(); + void * pixels = framebuffer->GetPixels(); + + int result = screenshot_dump_png_32bpp(_width, _height, pixels); + Memory::Free(pixels); + return result; + } + + void CopyRect(sint32 x, sint32 y, sint32 width, sint32 height, sint32 dx, sint32 dy) override + { + // Not applicable for this engine + } + + IDrawingContext * GetDrawingContext(rct_drawpixelinfo * dpi) override + { + _drawingContext->SetDPI(dpi); + return _drawingContext; + } + + rct_drawpixelinfo * GetDrawingPixelInfo() override + { + return &_bitsDPI; + } + + DRAWING_ENGINE_FLAGS GetFlags() override + { + return DEF_NONE; + } + + void InvalidateImage(uint32 image) override + { + _drawingContext->GetTextureCache() + ->InvalidateImage(image); + } + + rct_drawpixelinfo * GetDPI() + { + return &_bitsDPI; + } + + GLuint SwapCopyReturningSourceTexture() + { + _swapFramebuffer->SwapCopy(); + return _swapFramebuffer->GetSourceTexture(); + } + +private: + void ConfigureBits(uint32 width, uint32 height, uint32 pitch) + { + size_t newBitsSize = pitch * height; + uint8 * newBits = new uint8[newBitsSize]; + if (_bits == nullptr) + { + Memory::Set(newBits, 0, newBitsSize); + } + else + { + if (_pitch == pitch) + { + Memory::Copy(newBits, _bits, Math::Min(_bitsSize, newBitsSize)); + } + else + { + uint8 * src = _bits; + uint8 * dst = newBits; + + uint32 minWidth = Math::Min(_width, width); + uint32 minHeight = Math::Min(_height, height); + for (uint32 y = 0; y < minHeight; y++) + { + Memory::Copy(dst, src, minWidth); + if (pitch - minWidth > 0) + { + Memory::Set(dst + minWidth, 0, pitch - minWidth); + } + src += _pitch; + dst += pitch; + } + } + delete [] _bits; + } + + _bits = newBits; + _bitsSize = newBitsSize; + _width = width; + _height = height; + _pitch = pitch; + + rct_drawpixelinfo * dpi = &_bitsDPI; + dpi->bits = _bits; + dpi->x = 0; + dpi->y = 0; + dpi->width = width; + dpi->height = height; + dpi->pitch = _pitch - width; + } + + void ConfigureCanvas() + { + // Re-create screen framebuffer + delete _screenFramebuffer; + _screenFramebuffer = new OpenGLFramebuffer(_window); + + // Re-create canvas framebuffer + delete _swapFramebuffer; + _swapFramebuffer = new SwapFramebuffer(_width, _height); + + _copyFramebufferShader->Use(); + _copyFramebufferShader->SetScreenSize(_width, _height); + _copyFramebufferShader->SetBounds(0, 0, _width, _height); + _copyFramebufferShader->SetTextureCoordinates(0, 1, 1, 0); + } + + void Display() + { + SDL_GL_SwapWindow(_window); + } +}; + +IDrawingEngine * DrawingEngineFactory::CreateOpenGL() +{ + return new OpenGLDrawingEngine(); +} + +OpenGLDrawingContext::OpenGLDrawingContext(OpenGLDrawingEngine * engine) +{ + _engine = engine; + _textureCache = new TextureCache(); +} + +OpenGLDrawingContext::~OpenGLDrawingContext() +{ + delete _drawImageShader; + delete _drawImageMaskedShader; + delete _drawLineShader; + delete _fillRectShader; + + delete _textureCache; +} + +IDrawingEngine * OpenGLDrawingContext::GetEngine() +{ + return _engine; +} + +void OpenGLDrawingContext::Initialise() +{ + _drawImageShader = new DrawImageShader(); + _drawImageMaskedShader = new DrawImageMaskedShader(); + _drawLineShader = new DrawLineShader(); + _fillRectShader = new FillRectShader(); +} + +void OpenGLDrawingContext::Resize(sint32 width, sint32 height) +{ + _drawImageShader->Use(); + _drawImageShader->SetScreenSize(width, height); + _drawImageMaskedShader->Use(); + _drawImageMaskedShader->SetScreenSize(width, height); + _drawLineShader->Use(); + _drawLineShader->SetScreenSize(width, height); + _fillRectShader->Use(); + _fillRectShader->SetScreenSize(width, height); +} + +void OpenGLDrawingContext::Clear(uint32 colour) +{ + FillRect(colour, _clipLeft - _offsetX, _clipTop - _offsetY, _clipRight, _clipBottom); +} + +void OpenGLDrawingContext::FillRect(uint32 colour, sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + left += _offsetX; + top += _offsetY; + right += _offsetX; + bottom += _offsetY; + + vec4f paletteColour[2]; + paletteColour[0] = _engine->GLPalette[(colour >> 0) & 0xFF]; + paletteColour[1] = paletteColour[0]; + if (colour & 0x1000000) + { + paletteColour[1].a = 0; + + _fillRectShader->Use(); + _fillRectShader->SetFlags(0); + } + else if (colour & 0x2000000) + { + uint8 tableIndex = colour & 0xFF; + if (tableIndex < 44) return; + if (tableIndex >= 144) return; + tableIndex -= 44; + + vec3f transformColour = TransparentColourTable[tableIndex]; + paletteColour[0].r = transformColour.r; + paletteColour[0].g = transformColour.g; + paletteColour[0].b = transformColour.b; + paletteColour[0].a = 1; + paletteColour[1] = paletteColour[0]; + + GLuint srcTexture = _engine->SwapCopyReturningSourceTexture(); + _fillRectShader->Use(); + _fillRectShader->SetFlags(1); + _fillRectShader->SetSourceFramebuffer(srcTexture); + } + else + { + _fillRectShader->Use(); + _fillRectShader->SetFlags(0); + } + + _fillRectShader->SetColour(0, paletteColour[0]); + _fillRectShader->SetColour(1, paletteColour[1]); + _fillRectShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); + _fillRectShader->Draw(left, top, right + 1, bottom + 1); +} + +void OpenGLDrawingContext::DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2) +{ + x1 += _offsetX; + y1 += _offsetY; + x2 += _offsetX; + y2 += _offsetY; + + vec4f paletteColour = _engine->GLPalette[colour & 0xFF]; + + _drawLineShader->Use(); + _drawLineShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); + _drawLineShader->SetColour(paletteColour); + _drawLineShader->Draw(x1, y1, x2, y2); +} + +void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour) +{ + int g1Id = image & 0x7FFFF; + rct_g1_element * g1Element = gfx_get_g1_element(g1Id); + + if (_dpi->zoom_level != 0) + { + if (g1Element->flags & (1 << 4)) + { + rct_drawpixelinfo zoomedDPI; + zoomedDPI.bits = _dpi->bits; + zoomedDPI.x = _dpi->x >> 1; + zoomedDPI.y = _dpi->y >> 1; + zoomedDPI.height = _dpi->height >> 1; + zoomedDPI.width = _dpi->width >> 1; + zoomedDPI.pitch = _dpi->pitch; + zoomedDPI.zoom_level = _dpi->zoom_level - 1; + SetDPI(&zoomedDPI); + DrawSprite((image << 28) | (g1Id - g1Element->zoomed_offset), x >> 1, y >> 1, tertiaryColour); + return; + } + if (g1Element->flags & (1 << 5)) + { + return; + } + } + + GLuint texture = _textureCache->GetOrLoadImageTexture(image); + + sint32 drawOffsetX = g1Element->x_offset; + sint32 drawOffsetY = g1Element->y_offset; + sint32 drawWidth = (uint16)g1Element->width >> _dpi->zoom_level; + sint32 drawHeight = (uint16)g1Element->height >> _dpi->zoom_level; + + sint32 left = x + drawOffsetX; + sint32 top = y + drawOffsetY; + sint32 right = left + drawWidth; + sint32 bottom = top + drawHeight; + + if (left > right) + { + std::swap(left, right); + } + if (top > bottom) + { + std::swap(top, bottom); + } + + left += _offsetX; + top += _offsetY; + right += _offsetX; + bottom += _offsetY; + + _drawImageShader->Use(); + _drawImageShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); + _drawImageShader->SetTexture(texture); + _drawImageShader->Draw(left, top, right, bottom); +} + +void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) +{ + rct_g1_element * g1ElementMask = gfx_get_g1_element(maskImage & 0x7FFFF); + rct_g1_element * g1ElementColour = gfx_get_g1_element(colourImage & 0x7FFFF); + + GLuint textureMask = _textureCache->GetOrLoadImageTexture(maskImage); + GLuint textureColour = _textureCache->GetOrLoadImageTexture(colourImage); + + sint32 drawOffsetX = g1ElementMask->x_offset; + sint32 drawOffsetY = g1ElementMask->y_offset; + sint32 drawWidth = Math::Min(g1ElementMask->width, g1ElementColour->width); + sint32 drawHeight = Math::Min(g1ElementMask->height, g1ElementColour->height); + + sint32 left = x + drawOffsetX; + sint32 top = y + drawOffsetY; + sint32 right = left + drawWidth; + sint32 bottom = top + drawHeight; + + if (left > right) + { + std::swap(left, right); + } + if (top > bottom) + { + std::swap(top, bottom); + } + + left += _offsetX; + top += _offsetY; + right += _offsetX; + bottom += _offsetY; + + _drawImageMaskedShader->Use(); + _drawImageMaskedShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); + _drawImageMaskedShader->SetTextureMask(textureMask); + _drawImageMaskedShader->SetTextureColour(textureColour); + _drawImageMaskedShader->Draw(left, top, right, bottom); +} + +void OpenGLDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour) +{ + vec4f paletteColour = _engine->GLPalette[colour & 0xFF]; + + int g1Id = image & 0x7FFFF; + rct_g1_element * g1Element = gfx_get_g1_element(g1Id); + + GLuint texture = _textureCache->GetOrLoadImageTexture(image); + + sint32 drawOffsetX = g1Element->x_offset; + sint32 drawOffsetY = g1Element->y_offset; + sint32 drawWidth = (uint16)g1Element->width; + sint32 drawHeight = (uint16)g1Element->height; + + sint32 left = x + drawOffsetX; + sint32 top = y + drawOffsetY; + sint32 right = left + drawWidth; + sint32 bottom = top + drawHeight; + + if (left > right) + { + std::swap(left, right); + } + if (top > bottom) + { + std::swap(top, bottom); + } + + left += _offsetX; + top += _offsetY; + right += _offsetX; + bottom += _offsetY; + + _drawImageShader->Use(); + _drawImageShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); + _drawImageShader->SetTexture(texture); + _drawImageShader->SetFlags(1); + _drawImageShader->SetColour(paletteColour); + _drawImageShader->Draw(left, top, right, bottom); + _drawImageShader->SetFlags(0); +} + +void OpenGLDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette) +{ + int g1Id = image & 0x7FFFF; + rct_g1_element * g1Element = gfx_get_g1_element(g1Id); + + GLuint texture = _textureCache->GetOrLoadGlyphTexture(image, palette); + + sint32 drawOffsetX = g1Element->x_offset; + sint32 drawOffsetY = g1Element->y_offset; + sint32 drawWidth = (uint16)g1Element->width; + sint32 drawHeight = (uint16)g1Element->height; + + sint32 left = x + drawOffsetX; + sint32 top = y + drawOffsetY; + sint32 right = left + drawWidth; + sint32 bottom = top + drawHeight; + + if (left > right) + { + std::swap(left, right); + } + if (top > bottom) + { + std::swap(top, bottom); + } + + left += _offsetX; + top += _offsetY; + right += _offsetX; + bottom += _offsetY; + + _drawImageShader->Use(); + _drawImageShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); + _drawImageShader->SetTexture(texture); + _drawImageShader->Draw(left, top, right, bottom); + _drawImageShader->SetFlags(0); +} + +void OpenGLDrawingContext::SetDPI(rct_drawpixelinfo * dpi) +{ + rct_drawpixelinfo * screenDPI = _engine->GetDPI(); + size_t bitsSize = (size_t)screenDPI->height * (size_t)(screenDPI->width + screenDPI->pitch); + size_t bitsOffset = (size_t)(dpi->bits - screenDPI->bits); + + assert(bitsOffset < bitsSize); + + _clipLeft = bitsOffset % (screenDPI->width + screenDPI->pitch); + _clipTop = bitsOffset / (screenDPI->width + screenDPI->pitch); + + _clipRight = _clipLeft + dpi->width; + _clipBottom = _clipTop + dpi->height; + _offsetX = _clipLeft - dpi->x; + _offsetY = _clipTop - dpi->y; + + _dpi = dpi; +} + +#endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/opengl/OpenGLFramebuffer.cpp b/src/drawing/engines/opengl/OpenGLFramebuffer.cpp new file mode 100644 index 0000000000..f60ce7d384 --- /dev/null +++ b/src/drawing/engines/opengl/OpenGLFramebuffer.cpp @@ -0,0 +1,84 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#ifndef DISABLE_OPENGL + +#include +#include "../../../core/Memory.hpp" +#include "OpenGLFramebuffer.h" + +constexpr GLuint BACKBUFFER_ID = 0; + +OpenGLFramebuffer::OpenGLFramebuffer(SDL_Window * window) +{ + _id = BACKBUFFER_ID; + _texture = 0; + SDL_GetWindowSize(window, &_width, &_height); +} + +OpenGLFramebuffer::OpenGLFramebuffer(sint32 width, sint32 height) +{ + _width = width; + _height = height; + + glGenTextures(1, &_texture); + glBindTexture(GL_TEXTURE_2D, _texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glGenFramebuffers(1, &_id); + glBindFramebuffer(GL_FRAMEBUFFER, _id); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0); +} + +OpenGLFramebuffer::~OpenGLFramebuffer() +{ + if (_id != BACKBUFFER_ID) + { + glDeleteTextures(1, &_texture); + glDeleteFramebuffers(1, &_id); + } +} + +void OpenGLFramebuffer::Bind() const +{ + glBindFramebuffer(GL_FRAMEBUFFER, _id); + glViewport(0, 0, (GLsizei)_width, (GLsizei)_height); +} + +void * OpenGLFramebuffer::GetPixels() const +{ + void * pixels = Memory::Allocate(_width * _height * 4); + glReadPixels(0, 0, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Flip pixels vertically + void * flippedPixels = Memory::Allocate(_width * _height * 4); + size_t stride = _width * 4; + uint8 * src = (uint8 *)pixels + ((_height - 1) * stride); + uint8 * dst = (uint8 *)flippedPixels; + for (sint32 y = 0; y < _height; y++) + { + Memory::Copy(dst, src, stride); + src -= stride; + dst += stride; + } + Memory::Free(pixels); + + return flippedPixels; +} + +#endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/opengl/OpenGLFramebuffer.h b/src/drawing/engines/opengl/OpenGLFramebuffer.h new file mode 100644 index 0000000000..9e5c5054d3 --- /dev/null +++ b/src/drawing/engines/opengl/OpenGLFramebuffer.h @@ -0,0 +1,43 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../../../common.h" +#include "OpenGLAPI.h" + +struct SDL_Window; + +class OpenGLFramebuffer +{ +private: + GLuint _id; + GLuint _texture; + sint32 _width; + sint32 _height; + +public: + explicit OpenGLFramebuffer(SDL_Window * window); + OpenGLFramebuffer(sint32 width, sint32 height); + ~OpenGLFramebuffer(); + + GLuint GetWidth() const { return _width; } + GLuint GetHeight() const { return _height; } + GLuint GetTexture() const { return _texture; } + + void Bind() const; + void * GetPixels() const; +}; diff --git a/src/drawing/engines/opengl/OpenGLShaderProgram.cpp b/src/drawing/engines/opengl/OpenGLShaderProgram.cpp new file mode 100644 index 0000000000..606df1e4b9 --- /dev/null +++ b/src/drawing/engines/opengl/OpenGLShaderProgram.cpp @@ -0,0 +1,167 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#ifndef DISABLE_OPENGL + +#include "../../../core/Console.hpp" +#include "../../../core/Exception.hpp" +#include "../../../core/FileStream.hpp" +#include "../../../core/Memory.hpp" +#include "../../../core/Path.hpp" +#include "../../../core/String.hpp" +#include "OpenGLShaderProgram.h" + +extern "C" +{ + #include "../../../platform/platform.h" +} + +OpenGLShader::OpenGLShader(const char * name, GLenum type) +{ + _type = type; + + utf8 path[MAX_PATH]; + GetPath(path, sizeof(path), name); + char * sourceCode = ReadSourceCode(path); + + _id = glCreateShader(type); + glShaderSource(_id, 1, (const GLchar**)&sourceCode, nullptr); + glCompileShader(_id); + + Memory::Free(sourceCode); + + GLint status; + glGetShaderiv(_id, GL_COMPILE_STATUS, &status); + if (status != GL_TRUE) + { + char buffer[512]; + glGetShaderInfoLog(_id, sizeof(buffer), nullptr, buffer); + glDeleteShader(_id); + + Console::Error::WriteFormat("Error compiling %s\n", path); + Console::Error::WriteLine(buffer); + + throw Exception("Error compiling shader."); + } +} + +OpenGLShader::~OpenGLShader() +{ + glDeleteShader(_id); +} + +GLuint OpenGLShader::GetShaderId() +{ + return _id; +} + +void OpenGLShader::GetPath(char * buffer, size_t bufferSize, const char * name) +{ + platform_get_openrct_data_path(buffer); + Path::Append(buffer, bufferSize, "shaders"); + Path::Append(buffer, bufferSize, name); + if (_type == GL_VERTEX_SHADER) + { + String::Append(buffer, bufferSize, ".vert"); + } + else + { + String::Append(buffer, bufferSize, ".frag"); + } +} + +char * OpenGLShader::ReadSourceCode(const utf8 * path) +{ + auto fs = FileStream(path, FILE_MODE_OPEN); + + uint64 fileLength = fs.GetLength(); + if (fileLength > MaxSourceSize) + { + throw IOException("Shader source too large."); + } + + utf8 * fileData = Memory::Allocate((size_t)fileLength + 1); + fs.Read(fileData, fileLength); + fileData[fileLength] = '\0'; + return fileData; +} + +OpenGLShaderProgram::OpenGLShaderProgram(const char * name) +{ + _vertexShader = new OpenGLShader(name, GL_VERTEX_SHADER); + _fragmentShader = new OpenGLShader(name, GL_FRAGMENT_SHADER); + + _id = glCreateProgram(); + glAttachShader(_id, _vertexShader->GetShaderId()); + glAttachShader(_id, _fragmentShader->GetShaderId()); + + if (!Link()) + { + char buffer[512]; + GLsizei length; + glGetProgramInfoLog(_id, sizeof(buffer), &length, buffer); + + Console::Error::WriteFormat("Error linking %s\n", name); + Console::Error::WriteLine(buffer); + + throw Exception("Failed to link OpenGL shader."); + } +} + +OpenGLShaderProgram::~OpenGLShaderProgram() +{ + if (_vertexShader != nullptr) + { + glDetachShader(_id, _vertexShader->GetShaderId()); + delete _vertexShader; + } + if (_fragmentShader != nullptr) + { + glDetachShader(_id, _fragmentShader->GetShaderId()); + delete _fragmentShader; + } + glDeleteProgram(_id); +} + +GLuint OpenGLShaderProgram::GetAttributeLocation(const char * name) +{ + return glGetAttribLocation(_id, name); +} + +GLuint OpenGLShaderProgram::GetUniformLocation(const char * name) +{ + return glGetUniformLocation(_id, name); +} + +void OpenGLShaderProgram::Use() +{ + if (OpenGLState::CurrentProgram != _id) + { + OpenGLState::CurrentProgram = _id; + glUseProgram(_id); + } +} + +bool OpenGLShaderProgram::Link() +{ + glLinkProgram(_id); + + GLint linkStatus; + glGetProgramiv(_id, GL_LINK_STATUS, &linkStatus); + return linkStatus == GL_TRUE; +} + +#endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/opengl/OpenGLShaderProgram.h b/src/drawing/engines/opengl/OpenGLShaderProgram.h new file mode 100644 index 0000000000..e2a19ac8f2 --- /dev/null +++ b/src/drawing/engines/opengl/OpenGLShaderProgram.h @@ -0,0 +1,59 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../../../common.h" +#include "OpenGLAPI.h" + +class OpenGLShader +{ +private: + static constexpr uint64 MaxSourceSize = 8 * 1024 * 1024; // 8 MiB + + GLenum _type; + GLuint _id = 0; + +public: + OpenGLShader(const char * name, GLenum type); + virtual ~OpenGLShader(); + + GLuint GetShaderId(); + +private: + void GetPath(char * buffer, size_t bufferSize, const char * name); + static char * ReadSourceCode(const utf8 * path); +}; + +class OpenGLShaderProgram +{ +private: + GLuint _id = 0; + OpenGLShader * _vertexShader = nullptr; + OpenGLShader * _fragmentShader = nullptr; + +public: + OpenGLShaderProgram(const char * name); + virtual ~OpenGLShaderProgram(); + + GLuint GetAttributeLocation(const char * name); + GLuint GetUniformLocation(const char * name); + void Use(); + +private: + bool Link(); +}; + diff --git a/src/drawing/engines/opengl/SwapFramebuffer.cpp b/src/drawing/engines/opengl/SwapFramebuffer.cpp new file mode 100644 index 0000000000..259733f241 --- /dev/null +++ b/src/drawing/engines/opengl/SwapFramebuffer.cpp @@ -0,0 +1,68 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#ifndef DISABLE_OPENGL + +#include "CopyFramebufferShader.h" +#include "OpenGLFramebuffer.h" +#include "SwapFramebuffer.h" + +SwapFramebuffer::SwapFramebuffer(sint32 width, sint32 height) +{ + _width = width; + _height = height; + _targetFramebufferIndex = 0; + _framebuffer[0] = new OpenGLFramebuffer(width, height); + _framebuffer[1] = new OpenGLFramebuffer(width, height); + _targetFramebuffer = _framebuffer[0]; + + _copyFramebufferShader = new CopyFramebufferShader(); + _copyFramebufferShader->Use(); + _copyFramebufferShader->SetScreenSize(_width, _height); + _copyFramebufferShader->SetBounds(0, 0, _width, _height); + _copyFramebufferShader->SetTextureCoordinates(0, 1, 1, 0); +} + +SwapFramebuffer::~SwapFramebuffer() +{ + delete _framebuffer[0]; + delete _framebuffer[1]; + delete _copyFramebufferShader; +} + +GLuint SwapFramebuffer::GetSourceTexture() const +{ + return _sourceFramebuffer->GetTexture(); +} + +void SwapFramebuffer::SwapCopy() +{ + _sourceFramebuffer = _targetFramebuffer; + _targetFramebufferIndex = (_targetFramebufferIndex + 1) & 1; + _targetFramebuffer = _framebuffer[_targetFramebufferIndex]; + _targetFramebuffer->Bind(); + + _copyFramebufferShader->Use(); + _copyFramebufferShader->SetTexture(GetSourceTexture()); + _copyFramebufferShader->Draw(); +} + +void SwapFramebuffer::Bind() +{ + _targetFramebuffer->Bind(); +} + +#endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/opengl/SwapFramebuffer.h b/src/drawing/engines/opengl/SwapFramebuffer.h new file mode 100644 index 0000000000..68b638cd53 --- /dev/null +++ b/src/drawing/engines/opengl/SwapFramebuffer.h @@ -0,0 +1,70 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../../../common.h" +#include "OpenGLAPI.h" + +class CopyFramebufferShader; +class OpenGLFramebuffer; + +/** + * Class to maintain two different framebuffers where the active framebuffer + * will swap between the two, copying the other's pixels in the process for + * performing pre-processing filters. + * + * When you need to bind the current frame to a shader, call SwapCopy and + * then bind the value of GetSourceTexture to your shader. + */ +class SwapFramebuffer +{ +private: + sint32 _width; + sint32 _height; + uint8 _targetFramebufferIndex; + OpenGLFramebuffer * _targetFramebuffer; + OpenGLFramebuffer * _sourceFramebuffer; + OpenGLFramebuffer * _framebuffer[2]; + + CopyFramebufferShader * _copyFramebufferShader = nullptr; + +public: + SwapFramebuffer(sint32 width, sint32 height); + ~SwapFramebuffer(); + + /** + * Gets the current target framebuffer. + */ + const OpenGLFramebuffer * GetTargetFramebuffer() const { return _targetFramebuffer; } + + /** + * Gets the texture ID for the source framebuffer. + */ + GLuint GetSourceTexture() const; + + /** + * Swaps the target framebuffer, binds it and then draws the previous + * framebuffer resulting in the two buffers matching and ready for + * pre-processing. + */ + void SwapCopy(); + + /** + * Binds the current target framebuffer. + */ + void Bind(); +}; diff --git a/src/drawing/engines/opengl/TextureCache.cpp b/src/drawing/engines/opengl/TextureCache.cpp new file mode 100644 index 0000000000..10d80e261e --- /dev/null +++ b/src/drawing/engines/opengl/TextureCache.cpp @@ -0,0 +1,228 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#ifndef DISABLE_OPENGL + +#include +#include "../../../core/Memory.hpp" +#include "TextureCache.h" + +extern "C" +{ + #include "../../drawing.h" +} + +TextureCache::TextureCache() +{ +} + +TextureCache::~TextureCache() +{ + FreeTextures(); +} + +void TextureCache::SetPalette(const SDL_Color * palette) +{ + Memory::CopyArray(_palette, palette, 256); +} + +void TextureCache::InvalidateImage(uint32 image) +{ + auto kvp = _imageTextureMap.find(image); + if (kvp != _imageTextureMap.end()) + { + GLuint texture = kvp->second; + glDeleteTextures(1, &texture); + + _imageTextureMap.erase(kvp); + } +} + +GLuint TextureCache::GetOrLoadImageTexture(uint32 image) +{ + auto kvp = _imageTextureMap.find(image); + if (kvp != _imageTextureMap.end()) + { + return kvp->second; + } + + GLuint texture = LoadImageTexture(image); + _imageTextureMap[image] = texture; + + return texture; +} + +GLuint TextureCache::GetOrLoadGlyphTexture(uint32 image, uint8 * palette) +{ + GlyphId glyphId; + glyphId.Image = image; + Memory::Copy(&glyphId.Palette, palette, sizeof(glyphId.Palette)); + + auto kvp = _glyphTextureMap.find(glyphId); + if (kvp != _glyphTextureMap.end()) + { + return kvp->second; + } + + GLuint texture = LoadGlyphTexture(image, palette); + _glyphTextureMap[glyphId] = texture; + + return texture; +} + +GLuint TextureCache::LoadImageTexture(uint32 image) +{ + GLuint texture; + glGenTextures(1, &texture); + + uint32 width, height; + void * pixels32 = GetImageAsARGB(image, 0, &width, &height); + + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels32); + + Memory::Free(pixels32); + + return texture; +} + +GLuint TextureCache::LoadGlyphTexture(uint32 image, uint8 * palette) +{ + GLuint texture; + glGenTextures(1, &texture); + + uint32 width, height; + void * pixels32 = GetGlyphAsARGB(image, palette, &width, &height); + + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels32); + + Memory::Free(pixels32); + + return texture; +} + +void * TextureCache::GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32 * outWidth, uint32 * outHeight) +{ + rct_g1_element * g1Element = gfx_get_g1_element(image & 0x7FFFF); + sint32 width = g1Element->width; + sint32 height = g1Element->height; + + rct_drawpixelinfo * dpi = CreateDPI(width, height); + gfx_draw_sprite_software(dpi, image, -g1Element->x_offset, -g1Element->y_offset, tertiaryColour); + void * pixels32 = ConvertDPIto32bpp(dpi); + DeleteDPI(dpi); + + *outWidth = width; + *outHeight = height; + return pixels32; +} + +void * TextureCache::GetGlyphAsARGB(uint32 image, uint8 * palette, uint32 * outWidth, uint32 * outHeight) +{ + rct_g1_element * g1Element = gfx_get_g1_element(image & 0x7FFFF); + sint32 width = g1Element->width; + sint32 height = g1Element->height; + + rct_drawpixelinfo * dpi = CreateDPI(width, height); + gfx_draw_sprite_palette_set_software(dpi, image, -g1Element->x_offset, -g1Element->y_offset, palette, nullptr); + void * pixels32 = ConvertDPIto32bpp(dpi); + DeleteDPI(dpi); + + *outWidth = width; + *outHeight = height; + return pixels32; +} + +void * TextureCache::ConvertDPIto32bpp(const rct_drawpixelinfo * dpi) +{ + size_t numPixels = dpi->width * dpi->height; + uint8 * pixels32 = Memory::Allocate(numPixels * 4); + uint8 * src = dpi->bits; + uint8 * dst = pixels32; + for (size_t i = 0; i < numPixels; i++) + { + uint8 paletteIndex = *src++; + if (paletteIndex == 0) + { + // Transparent + *dst++ = 0; + *dst++ = 0; + *dst++ = 0; + *dst++ = 0; + } + else + { + SDL_Color colour = _palette[paletteIndex]; + *dst++ = colour.r; + *dst++ = colour.g; + *dst++ = colour.b; + *dst++ = colour.a; + } + } + return pixels32; +} + +void TextureCache::FreeTextures() +{ + // Free images + size_t numTextures = _imageTextureMap.size(); + auto textures = std::vector(numTextures); + for (auto kvp : _imageTextureMap) + { + textures.push_back(kvp.second); + } + glDeleteTextures(textures.size(), textures.data()); + + // Free glyphs + numTextures = _glyphTextureMap.size(); + textures.clear(); + textures.reserve(numTextures); + for (auto kvp : _glyphTextureMap) + { + textures.push_back(kvp.second); + } + glDeleteTextures(textures.size(), textures.data()); +} + +rct_drawpixelinfo * TextureCache::CreateDPI(sint32 width, sint32 height) +{ + size_t numPixels = width * height; + uint8 * pixels8 = Memory::Allocate(numPixels); + Memory::Set(pixels8, 0, numPixels); + + rct_drawpixelinfo * dpi = new rct_drawpixelinfo(); + dpi->bits = pixels8; + dpi->pitch = 0; + dpi->x = 0; + dpi->y = 0; + dpi->width = width; + dpi->height = height; + dpi->zoom_level = 0; + return dpi; +} + +void TextureCache::DeleteDPI(rct_drawpixelinfo* dpi) +{ + Memory::Free(dpi->bits); + delete dpi; +} + +#endif /* DISABLE_OPENGL */ diff --git a/src/drawing/engines/opengl/TextureCache.h b/src/drawing/engines/opengl/TextureCache.h new file mode 100644 index 0000000000..3f5e36673c --- /dev/null +++ b/src/drawing/engines/opengl/TextureCache.h @@ -0,0 +1,78 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include +#include +#include "../../../common.h" +#include "OpenGLAPI.h" + +struct rct_drawpixelinfo; + +struct GlyphId +{ + uint32 Image; + uint64 Palette; + + struct Hash + { + size_t operator()(const GlyphId &k) const + { + size_t hash = 0x3154A85E; + hash = k.Image * 7; + hash += (k.Palette & 0xFFFFFFFF) * 13; + hash += (k.Palette >> 32) * 23; + return hash; + } + }; + + struct Equal + { + bool operator()(const GlyphId &lhs, const GlyphId &rhs) const + { + return lhs.Image == rhs.Image && + lhs.Palette == rhs.Palette; + } + }; +}; + +class TextureCache +{ +private: + std::unordered_map _imageTextureMap; + std::unordered_map _glyphTextureMap; + SDL_Color _palette[256]; + +public: + TextureCache(); + ~TextureCache(); + void SetPalette(const SDL_Color * palette); + void InvalidateImage(uint32 image); + GLuint GetOrLoadImageTexture(uint32 image); + GLuint GetOrLoadGlyphTexture(uint32 image, uint8 * palette); + +private: + GLuint LoadImageTexture(uint32 image); + GLuint LoadGlyphTexture(uint32 image, uint8 * palette); + void * GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32 * outWidth, uint32 * outHeight); + void * GetGlyphAsARGB(uint32 image, uint8 * palette, uint32 * outWidth, uint32 * outHeight); + void * ConvertDPIto32bpp(const rct_drawpixelinfo * dpi); + void FreeTextures(); + + static rct_drawpixelinfo * CreateDPI(sint32 width, sint32 height); + static void DeleteDPI(rct_drawpixelinfo * dpi); +}; diff --git a/src/drawing/sprite.c b/src/drawing/sprite.c index 3fb9dfed32..f04cd9a5cf 100644 --- a/src/drawing/sprite.c +++ b/src/drawing/sprite.c @@ -383,7 +383,7 @@ void FASTCALL gfx_draw_sprite_palette_set_software(rct_drawpixelinfo *dpi, int i .pitch = dpi->pitch, .zoom_level = dpi->zoom_level - 1 }; - gfx_draw_sprite_palette_set(&zoomed_dpi, (image_type << 28) | (image_element - g1_source->zoomed_offset), x >> 1, y >> 1, palette_pointer, unknown_pointer); + gfx_draw_sprite_palette_set_software(&zoomed_dpi, (image_type << 28) | (image_element - g1_source->zoomed_offset), x >> 1, y >> 1, palette_pointer, unknown_pointer); return; } diff --git a/src/drawing/string.c b/src/drawing/string.c index 12ee28304a..bf50c33535 100644 --- a/src/drawing/string.c +++ b/src/drawing/string.c @@ -924,7 +924,7 @@ static void ttf_draw_character_sprite(rct_drawpixelinfo *dpi, int codepoint, tex if (info->flags & TEXT_DRAW_FLAG_Y_OFFSET_EFFECT) { y += *info->y_offset++; } - gfx_draw_sprite_palette_set(dpi, sprite, x, y, info->palette, NULL); + gfx_draw_glpyh(dpi, sprite, x, y, info->palette); } info->x += characterWidth; diff --git a/src/image_io.c b/src/image_io.c index f897a20c88..b1909308b0 100644 --- a/src/image_io.c +++ b/src/image_io.c @@ -171,6 +171,67 @@ bool image_io_png_write(const rct_drawpixelinfo *dpi, const rct_palette *palette return true; } +static void image_io_png_warning(png_structp png_ptr, const char *b) +{ + log_warning(b); +} + +static void image_io_png_error(png_structp png_ptr, const char *b) +{ + log_error(b); +} + +bool image_io_png_write_32bpp(sint32 width, sint32 height, const void *pixels, const utf8 *path) +{ + // Setup PNG + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, image_io_png_error, image_io_png_warning); + if (png_ptr == NULL) { + return false; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + return false; + } + + // Open file for writing + SDL_RWops *file = SDL_RWFromFile(path, "wb"); + if (file == NULL) { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + return false; + } + png_set_write_fn(png_ptr, file, my_png_write_data, my_png_flush); + + // Set error handler + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + SDL_RWclose(file); + return false; + } + + // Write header + png_set_IHDR( + png_ptr, info_ptr, width, height, 8, + PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT + ); + png_write_info(png_ptr, info_ptr); + + // Write pixels + uint8 *bits = (uint8*)pixels; + for (int y = 0; y < height; y++) { + png_write_row(png_ptr, (png_byte *)bits); + bits += width * 4; + } + + // Finish + png_write_end(png_ptr, NULL); + SDL_RWclose(file); + + png_destroy_write_struct(&png_ptr, &info_ptr); + return true; +} + static void my_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { SDL_RWops *file = (SDL_RWops*)png_get_io_ptr(png_ptr); diff --git a/src/image_io.h b/src/image_io.h index 6e920963fc..82a45a91b4 100644 --- a/src/image_io.h +++ b/src/image_io.h @@ -23,5 +23,6 @@ bool image_io_png_read(uint8 **pixels, uint32 *width, uint32 *height, const utf8 *path); bool image_io_png_write(const rct_drawpixelinfo *dpi, const rct_palette *palette, const utf8 *path); +bool image_io_png_write_32bpp(sint32 width, sint32 height, const void *pixels, const utf8 *path); #endif diff --git a/src/interface/screenshot.c b/src/interface/screenshot.c index 7ba9a5bc02..19ed7ff9bd 100644 --- a/src/interface/screenshot.c +++ b/src/interface/screenshot.c @@ -115,6 +115,22 @@ int screenshot_dump_png(rct_drawpixelinfo *dpi) } } +int screenshot_dump_png_32bpp(sint32 width, sint32 height, const void *pixels) +{ + // Get a free screenshot path + int index; + char path[MAX_PATH] = ""; + if ((index = screenshot_get_next_path(path)) == -1) { + return -1; + } + + if (image_io_png_write_32bpp(width, height, pixels, path)) { + return index; + } else { + return -1; + } +} + void screenshot_giant() { int originalRotation = get_current_rotation(); diff --git a/src/interface/screenshot.h b/src/interface/screenshot.h index 5b14a788d8..f29d54515c 100644 --- a/src/interface/screenshot.h +++ b/src/interface/screenshot.h @@ -22,6 +22,7 @@ void screenshot_check(); int screenshot_dump(); int screenshot_dump_png(rct_drawpixelinfo *dpi); +int screenshot_dump_png_32bpp(sint32 width, sint32 height, const void *pixels); void screenshot_giant(); int cmdline_for_screenshot(const char **argv, int argc); diff --git a/src/interface/widget.c b/src/interface/widget.c index eac3ecc77b..f1298846bc 100644 --- a/src/interface/widget.c +++ b/src/interface/widget.c @@ -859,23 +859,12 @@ static void widget_draw_image(rct_drawpixelinfo *dpi, rct_window *w, int widgetI // Draw greyed out (light border bottom right shadow) colour = w->colours[widget->colour]; colour = ColourMapA[colour & 0x7F].lighter; - - uint8 palette[256]; - memset(palette, colour, 256); - palette[0] = 0; - - RCT2_GLOBAL(0x00EDF81C, uint32) = 0x20000000; - image &= 0x7FFFF; - gfx_draw_sprite_palette_set(dpi, image | 0x20000000, l + 1, t + 1, palette, NULL); + gfx_draw_sprite_solid(dpi, image, l + 1, t + 1, colour); // Draw greyed out (dark) colour = w->colours[widget->colour]; colour = ColourMapA[colour & 0x7F].mid_light; - memset(palette, colour, 256); - palette[0] = 0; - - RCT2_GLOBAL(0x00EDF81C, uint32) = 0x20000000; - gfx_draw_sprite_palette_set(dpi, image | 0x20000000, l, t, palette, NULL); + gfx_draw_sprite_solid(dpi, image, l, t, colour); } else { if (image & 0x80000000) { // ?