From db358049b97ca40a0f0c58fc7f109abff9c3b6e2 Mon Sep 17 00:00:00 2001 From: rogerman Date: Mon, 24 Mar 2014 18:19:11 +0000 Subject: [PATCH] Cocoa Port: - Do a huge refactor of the display code. - Add support for shader-based filters. - New feature: The display pipeline has been separated into three parts - Source --> Pixel Scale --> Output. Different sets of filters may be applied to each part of the pipeline. - Add the following source filters: Deposterize - Add the following output filters: Bicubic (B-Spline), Bicubic (Mitchell-Netravali), Lanczos2, Lanczos3. - Add shader-based equivalents to the following pixel scalers: Nearest 2x, Scanline, EPX, EPX+, Super Eagle, 2xSaI, Super 2xSaI. These will be used instead of the CPU-based scalers if "Run filters on GPU if possible" is enabled (default is enabled). - Remove the following pixel scalers from the UI: Nearest 1.5x, Nearest+ 1.5x, Bilinear 2x, EPX 1.5x, EPX+ 1.5x. The reasoning behind this is because these pixel scalers aren't necessary due to the automatic sizing of display view to window. Also, the new output filters make it so that running similar pixel scalers along with an output filter will always yield superior results. --- desmume/src/cocoa/DefaultUserPrefs.plist | 4 + desmume/src/cocoa/OGLDisplayOutput.cpp | 2504 +++++++-- desmume/src/cocoa/OGLDisplayOutput.h | 291 +- desmume/src/cocoa/cocoa_globals.h | 2 +- desmume/src/cocoa/cocoa_output.h | 5 +- desmume/src/cocoa/cocoa_output.mm | 25 +- .../English.lproj/MainMenu.strings | Bin 316320 -> 321358 bytes .../translations/English.lproj/MainMenu.xib | 4669 +++++++++-------- .../userinterface/DisplayWindowController.h | 34 +- .../userinterface/DisplayWindowController.mm | 401 +- .../src/cocoa/userinterface/appDelegate.mm | 22 +- 11 files changed, 5181 insertions(+), 2776 deletions(-) diff --git a/desmume/src/cocoa/DefaultUserPrefs.plist b/desmume/src/cocoa/DefaultUserPrefs.plist index 101d8a702..072fcb44e 100644 --- a/desmume/src/cocoa/DefaultUserPrefs.plist +++ b/desmume/src/cocoa/DefaultUserPrefs.plist @@ -12,8 +12,12 @@ CoreControl_SpeedScalar 1 + DisplayView_Deposterize + DisplayView_Mode 2 + DisplayView_OutputFilter + 1 DisplayView_Rotation 0 DisplayView_ShowHUD diff --git a/desmume/src/cocoa/OGLDisplayOutput.cpp b/desmume/src/cocoa/OGLDisplayOutput.cpp index d0cae6392..7368021c5 100644 --- a/desmume/src/cocoa/OGLDisplayOutput.cpp +++ b/desmume/src/cocoa/OGLDisplayOutput.cpp @@ -22,7 +22,7 @@ // VERTEX SHADER FOR DISPLAY OUTPUT -static const char *vertexProgram_100 = {"\ +static const char *Sample1x1OutputVertShader_100 = {"\ attribute vec2 inPosition; \n\ attribute vec2 inTexCoord0; \n\ \n\ @@ -30,7 +30,7 @@ static const char *vertexProgram_100 = {"\ uniform float scalar; \n\ uniform float angleDegrees; \n\ \n\ - varying vec2 vtxTexCoord; \n\ + varying vec2 texCoord[1]; \n\ \n\ void main() \n\ { \n\ @@ -45,20 +45,947 @@ static const char *vertexProgram_100 = {"\ mat2 scale = mat2( vec2(scalar, 0.0), \n\ vec2( 0.0, scalar)); \n\ \n\ - vtxTexCoord = inTexCoord0; \n\ - gl_Position = vec4(projection * rotation * scale * inPosition, 1.0, 1.0); \n\ + texCoord[0] = inTexCoord0; \n\ + gl_Position = vec4(projection * rotation * scale * inPosition, 0.0, 1.0);\n\ } \n\ "}; -// FRAGMENT SHADER FOR DISPLAY OUTPUT -static const char *fragmentProgram_100 = {"\ - varying vec2 vtxTexCoord; \n\ - uniform sampler2D tex; \n\ +static const char *BicubicSample4x4Output_VertShader_110 = {"\ + //---------------------------------------\n\ + // Input Pixel Mapping: 06|07|08|09\n\ + // 05|00|01|10\n\ + // 04|03|02|11\n\ + // 15|14|13|12\n\ \n\ - void main() \n\ - { \n\ - gl_FragColor = texture2D(tex, vtxTexCoord); \n\ - } \n\ + attribute vec2 inPosition;\n\ + attribute vec2 inTexCoord0;\n\ + \n\ + uniform vec2 viewSize; \n\ + uniform float scalar; \n\ + uniform float angleDegrees; \n\ + \n\ + varying vec2 texCoord[16];\n\ + \n\ + void main()\n\ + {\n\ + float angleRadians = radians(angleDegrees); \n\ + \n\ + mat2 projection = mat2( vec2(2.0/viewSize.x, 0.0), \n\ + vec2( 0.0, 2.0/viewSize.y)); \n\ + \n\ + mat2 rotation = mat2( vec2(cos(angleRadians), -sin(angleRadians)), \n\ + vec2(sin(angleRadians), cos(angleRadians))); \n\ + \n\ + mat2 scale = mat2( vec2(scalar, 0.0), \n\ + vec2( 0.0, scalar)); \n\ + \n\ + vec2 xystart = floor(inTexCoord0 - 0.5) + 0.5;\n\ + \n\ + texCoord[ 6] = xystart + vec2(-1.0,-1.0);\n\ + texCoord[ 7] = xystart + vec2( 0.0,-1.0);\n\ + texCoord[ 8] = xystart + vec2( 1.0,-1.0);\n\ + texCoord[ 9] = xystart + vec2( 2.0,-1.0);\n\ + \n\ + texCoord[ 5] = xystart + vec2(-1.0, 0.0);\n\ + texCoord[ 0] = xystart + vec2( 0.0, 0.0); // Center pixel\n\ + texCoord[ 1] = xystart + vec2( 1.0, 0.0);\n\ + texCoord[10] = xystart + vec2( 2.0, 0.0);\n\ + \n\ + texCoord[ 4] = xystart + vec2(-1.0, 1.0);\n\ + texCoord[ 3] = xystart + vec2( 0.0, 1.0);\n\ + texCoord[ 2] = xystart + vec2( 1.0, 1.0);\n\ + texCoord[11] = xystart + vec2( 2.0, 1.0);\n\ + \n\ + texCoord[15] = xystart + vec2(-1.0, 2.0);\n\ + texCoord[14] = xystart + vec2( 0.0, 2.0);\n\ + texCoord[13] = xystart + vec2( 1.0, 2.0);\n\ + texCoord[12] = xystart + vec2( 2.0, 2.0);\n\ + \n\ + gl_Position = vec4(projection * rotation * scale * inPosition, 0.0, 1.0);\n\ + }\n\ +"}; + +// FRAGMENT SHADER FOR DISPLAY OUTPUT +static const char *PassthroughOutputFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[1];\n\ + uniform sampler2DRect tex;\n\ + \n\ + void main()\n\ + {\n\ + gl_FragColor = texture2DRect(tex, texCoord[0]);\n\ + }\n\ +"}; + +// VERTEX SHADER FOR VIDEO FILTERS +static const char *Sample1x1_VertShader_110 = {"\ + // For reference, the pixels are mapped as follows:\n\ + // Start at center pixel 0 (p0), and circle around it\n\ + // in a clockwise fashion, starting from the right.\n\ + //---------------------------------------\n\ + // Input Pixel Mapping: 20|21|22|23|24\n\ + // 19|06|07|08|09\n\ + // 18|05|00|01|10\n\ + // 17|04|03|02|11\n\ + // 16|15|14|13|12\n\ + \n\ + attribute vec2 inPosition;\n\ + attribute vec2 inTexCoord0;\n\ + varying vec2 texCoord[1];\n\ + \n\ + void main()\n\ + {\n\ + texCoord[0] = inTexCoord0;\n\ + gl_Position = vec4(inPosition, 0.0, 1.0);\n\ + }\n\ +"}; + +static const char *Sample2x2_VertShader_110 = {"\ + //---------------------------------------\n\ + // Input Pixel Mapping: 00|01\n\ + // 03|02\n\ + \n\ + attribute vec2 inPosition;\n\ + attribute vec2 inTexCoord0;\n\ + varying vec2 texCoord[4];\n\ + \n\ + void main()\n\ + {\n\ + texCoord[0] = inTexCoord0 + vec2( 0.0, 0.0); // Center pixel\n\ + texCoord[1] = inTexCoord0 + vec2( 1.0, 0.0);\n\ + texCoord[3] = inTexCoord0 + vec2( 0.0, 1.0);\n\ + texCoord[2] = inTexCoord0 + vec2( 1.0, 1.0);\n\ + \n\ + gl_Position = vec4(inPosition, 0.0, 1.0);\n\ + }\n\ +"}; + +static const char *Sample3x3_VertShader_110 = {"\ + //---------------------------------------\n\ + // Input Pixel Mapping: 06|07|08\n\ + // 05|00|01\n\ + // 04|03|02\n\ + \n\ + attribute vec2 inPosition;\n\ + attribute vec2 inTexCoord0;\n\ + varying vec2 texCoord[9];\n\ + \n\ + void main()\n\ + {\n\ + texCoord[6] = inTexCoord0 + vec2(-1.0,-1.0);\n\ + texCoord[7] = inTexCoord0 + vec2( 0.0,-1.0);\n\ + texCoord[8] = inTexCoord0 + vec2( 1.0,-1.0);\n\ + \n\ + texCoord[5] = inTexCoord0 + vec2(-1.0, 0.0);\n\ + texCoord[0] = inTexCoord0 + vec2( 0.0, 0.0); // Center pixel\n\ + texCoord[1] = inTexCoord0 + vec2( 1.0, 0.0);\n\ + \n\ + texCoord[4] = inTexCoord0 + vec2(-1.0, 1.0);\n\ + texCoord[3] = inTexCoord0 + vec2( 0.0, 1.0);\n\ + texCoord[2] = inTexCoord0 + vec2( 1.0, 1.0);\n\ + \n\ + gl_Position = vec4(inPosition, 0.0, 1.0);\n\ + }\n\ +"}; + +static const char *Sample4x4_VertShader_110 = {"\ + //---------------------------------------\n\ + // Input Pixel Mapping: 06|07|08|09\n\ + // 05|00|01|10\n\ + // 04|03|02|11\n\ + // 15|14|13|12\n\ + \n\ + attribute vec2 inPosition;\n\ + attribute vec2 inTexCoord0;\n\ + varying vec2 texCoord[16];\n\ + \n\ + void main()\n\ + {\n\ + texCoord[ 6] = inTexCoord0 + vec2(-1.0,-1.0);\n\ + texCoord[ 7] = inTexCoord0 + vec2( 0.0,-1.0);\n\ + texCoord[ 8] = inTexCoord0 + vec2( 1.0,-1.0);\n\ + texCoord[ 9] = inTexCoord0 + vec2( 2.0,-1.0);\n\ + \n\ + texCoord[ 5] = inTexCoord0 + vec2(-1.0, 0.0);\n\ + texCoord[ 0] = inTexCoord0 + vec2( 0.0, 0.0); // Center pixel\n\ + texCoord[ 1] = inTexCoord0 + vec2( 1.0, 0.0);\n\ + texCoord[10] = inTexCoord0 + vec2( 2.0, 0.0);\n\ + \n\ + texCoord[ 4] = inTexCoord0 + vec2(-1.0, 1.0);\n\ + texCoord[ 3] = inTexCoord0 + vec2( 0.0, 1.0);\n\ + texCoord[ 2] = inTexCoord0 + vec2( 1.0, 1.0);\n\ + texCoord[11] = inTexCoord0 + vec2( 2.0, 1.0);\n\ + \n\ + texCoord[15] = inTexCoord0 + vec2(-1.0, 2.0);\n\ + texCoord[14] = inTexCoord0 + vec2( 0.0, 2.0);\n\ + texCoord[13] = inTexCoord0 + vec2( 1.0, 2.0);\n\ + texCoord[12] = inTexCoord0 + vec2( 2.0, 2.0);\n\ + \n\ + gl_Position = vec4(inPosition, 0.0, 1.0);\n\ + }\n\ +"}; + +// FRAGMENT SHADER PASSTHROUGH FOR FILTERS +static const char *PassthroughFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[1];\n\ + uniform sampler2DRect tex;\n\ + \n\ + void main()\n\ + {\n\ + gl_FragColor = texture2DRect(tex, texCoord[0]);\n\ + }\n\ +"}; + +// FRAGMENT SHADER FOR DEPOSTERIZATION +static const char *FilterDeposterizeFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[9];\n\ + uniform sampler2DRect tex;\n\ + \n\ + vec4 InterpLTE(vec4 pixA, vec4 pixB, vec4 threshold)\n\ + {\n\ + vec4 interpPix = mix(pixA, pixB, 0.5);\n\ + vec4 pixCompare = vec4( lessThanEqual(abs(pixB - pixA), threshold) );\n\ + \n\ + return mix(pixA, interpPix, pixCompare);\n\ + }\n\ + \n\ + //---------------------------------------\n\ + // Input Pixel Mapping: --|07|--\n\ + // 05|00|01\n\ + // --|03|--\n\ + //\n\ + // Output Pixel Mapping: A\n\ + \n\ + void main()\n\ + {\n\ + const vec4 threshold = vec4(0.0355);\n\ + vec4 pU = texture2DRect(tex, texCoord[7]);\n\ + vec4 pL = texture2DRect(tex, texCoord[5]);\n\ + vec4 pC = texture2DRect(tex, texCoord[0]); // Center pixel\n\ + vec4 pR = texture2DRect(tex, texCoord[1]);\n\ + vec4 pD = texture2DRect(tex, texCoord[3]);\n\ + \n\ + vec4 tempL = InterpLTE(pC, pL, threshold);\n\ + vec4 tempR = InterpLTE(pC, pR, threshold);\n\ + vec4 tempU = InterpLTE(pC, pU, threshold);\n\ + vec4 tempD = InterpLTE(pC, pD, threshold);\n\ + \n\ + gl_FragColor = mix( mix(tempL, tempR, 0.5), mix(tempU, tempD, 0.5), 0.5 );\n\ + }\n\ +"}; + +static const char *FilterBicubicBSplineFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[16];\n\ + uniform sampler2DRect tex;\n\ + \n\ + vec4 WeightBSpline(float f)\n\ + {\n\ + return vec4(pow((1.0 - f), 3.0) / 6.0,\n\ + (4.0 - 6.0*f*f + 3.0*f*f*f) / 6.0,\n\ + (1.0 + 3.0*f + 3.0*f*f - 3.0*f*f*f) / 6.0,\n\ + f*f*f / 6.0);\n\ + }\n\ + \n\ + //---------------------------------------\n\ + // Input Pixel Mapping: 06|07|08|09\n\ + // 05|00|01|10\n\ + // 04|03|02|11\n\ + // 15|14|13|12\n\ + \n\ + void main()\n\ + {\n\ + vec2 f = fract(texCoord[0]);\n\ + vec4 wx = WeightBSpline(f.x);\n\ + vec4 wy = WeightBSpline(f.y);\n\ + \n\ + // Normalize weights\n\ + wx /= dot(wx, vec4(1.0));\n\ + wy /= dot(wy, vec4(1.0));\n\ + \n\ + gl_FragColor = (texture2DRect(tex, texCoord[ 6]) * wx.r\n\ + + texture2DRect(tex, texCoord[ 7]) * wx.g\n\ + + texture2DRect(tex, texCoord[ 8]) * wx.b\n\ + + texture2DRect(tex, texCoord[ 9]) * wx.a) * wy.r\n\ + + (texture2DRect(tex, texCoord[ 5]) * wx.r\n\ + + texture2DRect(tex, texCoord[ 0]) * wx.g\n\ + + texture2DRect(tex, texCoord[ 1]) * wx.b\n\ + + texture2DRect(tex, texCoord[10]) * wx.a) * wy.g\n\ + + (texture2DRect(tex, texCoord[ 4]) * wx.r\n\ + + texture2DRect(tex, texCoord[ 3]) * wx.g\n\ + + texture2DRect(tex, texCoord[ 2]) * wx.b\n\ + + texture2DRect(tex, texCoord[11]) * wx.a) * wy.b\n\ + + (texture2DRect(tex, texCoord[15]) * wx.r\n\ + + texture2DRect(tex, texCoord[14]) * wx.g\n\ + + texture2DRect(tex, texCoord[13]) * wx.b\n\ + + texture2DRect(tex, texCoord[12]) * wx.a) * wy.a;\n\ + }\n\ +"}; + +static const char *FilterBicubicBSplineFastFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[1];\n\ + uniform sampler2DRect tex;\n\ + \n\ + void main()\n\ + {\n\ + vec2 texCenterPosition = floor(texCoord[0] - 0.5) + 0.5;\n\ + vec2 f = abs(texCoord[0] - texCenterPosition);\n\ + \n\ + vec2 w0 = pow((1.0 - f), vec2(3.0, 3.0)) / 6.0;\n\ + vec2 w1 = (4.0 - 6.0*f*f + 3.0*f*f*f) / 6.0;\n\ + vec2 w3 = f*f*f / 6.0;\n\ + vec2 w2 = 1.0 - w0 - w1 - w3;\n\ + \n\ + vec2 s0 = w0 + w1;\n\ + vec2 s1 = w2 + w3;\n\ + \n\ + vec2 t0 = texCenterPosition - 1.0 + (w1 / s0);\n\ + vec2 t1 = texCenterPosition + 1.0 + (w3 / s1);\n\ + \n\ + gl_FragColor = (texture2DRect(tex, vec2(t0.x, t0.y)) * s0.x +\n\ + texture2DRect(tex, vec2(t1.x, t0.y)) * s1.x) * s0.y +\n\ + (texture2DRect(tex, vec2(t0.x, t1.y)) * s0.x +\n\ + texture2DRect(tex, vec2(t1.x, t1.y)) * s1.x) * s1.y;\n\ + }\n\ +"}; + +static const char *FilterBicubicMitchellNetravaliFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[16];\n\ + uniform sampler2DRect tex;\n\ + \n\ + vec4 WeightMitchellNetravali(float f)\n\ + {\n\ + return vec4((1.0 - 9.0*f + 15.0*f*f - 7.0*f*f*f) / 18.0,\n\ + (16.0 - 36.0*f*f + 21.0*f*f*f) / 18.0,\n\ + (1.0 + 9.0*f + 27.0*f*f - 21.0*f*f*f) / 18.0,\n\ + (7.0*f*f*f - 6.0*f*f) / 18.0);\n\ + }\n\ + \n\ + //---------------------------------------\n\ + // Input Pixel Mapping: 06|07|08|09\n\ + // 05|00|01|10\n\ + // 04|03|02|11\n\ + // 15|14|13|12\n\ + \n\ + void main()\n\ + {\n\ + vec2 f = fract(texCoord[0]);\n\ + vec4 wx = WeightMitchellNetravali(f.x);\n\ + vec4 wy = WeightMitchellNetravali(f.y);\n\ + \n\ + // Normalize weights\n\ + wx /= dot(wx, vec4(1.0));\n\ + wy /= dot(wy, vec4(1.0));\n\ + \n\ + gl_FragColor = (texture2DRect(tex, texCoord[ 6]) * wx.r\n\ + + texture2DRect(tex, texCoord[ 7]) * wx.g\n\ + + texture2DRect(tex, texCoord[ 8]) * wx.b\n\ + + texture2DRect(tex, texCoord[ 9]) * wx.a) * wy.r\n\ + + (texture2DRect(tex, texCoord[ 5]) * wx.r\n\ + + texture2DRect(tex, texCoord[ 0]) * wx.g\n\ + + texture2DRect(tex, texCoord[ 1]) * wx.b\n\ + + texture2DRect(tex, texCoord[10]) * wx.a) * wy.g\n\ + + (texture2DRect(tex, texCoord[ 4]) * wx.r\n\ + + texture2DRect(tex, texCoord[ 3]) * wx.g\n\ + + texture2DRect(tex, texCoord[ 2]) * wx.b\n\ + + texture2DRect(tex, texCoord[11]) * wx.a) * wy.b\n\ + + (texture2DRect(tex, texCoord[15]) * wx.r\n\ + + texture2DRect(tex, texCoord[14]) * wx.g\n\ + + texture2DRect(tex, texCoord[13]) * wx.b\n\ + + texture2DRect(tex, texCoord[12]) * wx.a) * wy.a;\n\ + }\n\ +"}; + +static const char *FilterBicubicMitchellNetravaliFastFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[1];\n\ + uniform sampler2DRect tex;\n\ + \n\ + void main()\n\ + {\n\ + vec2 texCenterPosition = floor(texCoord[0] - 0.5) + 0.5;\n\ + vec2 f = abs(texCoord[0] - texCenterPosition);\n\ + \n\ + vec2 w0 = (1.0 - 9.0*f + 15.0*f*f - 7.0*f*f*f) / 18.0;\n\ + vec2 w1 = (16.0 - 36.0*f*f + 21.0*f*f*f) / 18.0;\n\ + vec2 w3 = (7.0*f*f*f - 6.0*f*f) / 18.0;\n\ + vec2 w2 = 1.0 - w0 - w1 - w3;\n\ + \n\ + vec2 s0 = w0 + w1;\n\ + vec2 s1 = w2 + w3;\n\ + \n\ + vec2 t0 = texCenterPosition - 1.0 + (w1 / s0);\n\ + vec2 t1 = texCenterPosition + 1.0 + (w3 / s1);\n\ + \n\ + gl_FragColor = (texture2DRect(tex, vec2(t0.x, t0.y)) * s0.x +\n\ + texture2DRect(tex, vec2(t1.x, t0.y)) * s1.x) * s0.y +\n\ + (texture2DRect(tex, vec2(t0.x, t1.y)) * s0.x +\n\ + texture2DRect(tex, vec2(t1.x, t1.y)) * s1.x) * s1.y;\n\ + }\n\ +"}; + +static const char *FilterLanczos2FragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + #define PI 3.1415926535897932384626433832795\n\ + #define RADIUS 2.0\n\ + #define FIX(c) max(abs(c), 1e-5)\n\ + \n\ + varying vec2 texCoord[16];\n\ + uniform sampler2DRect tex;\n\ + \n\ + vec4 WeightLanczos2(float f)\n\ + {\n\ + vec4 sample = FIX(PI * vec4(1.0 + f, f, 1.0 - f, 2.0 - f));\n\ + return ( sin(sample) * sin(sample / RADIUS) / (sample * sample) );\n\ + }\n\ + \n\ + //---------------------------------------\n\ + // Input Pixel Mapping: 06|07|08|09\n\ + // 05|00|01|10\n\ + // 04|03|02|11\n\ + // 15|14|13|12\n\ + \n\ + void main()\n\ + {\n\ + vec2 f = fract(texCoord[0]);\n\ + vec4 wx = WeightLanczos2(f.x);\n\ + vec4 wy = WeightLanczos2(f.y);\n\ + \n\ + // Normalize weights\n\ + wx /= dot(wx, vec4(1.0));\n\ + wy /= dot(wy, vec4(1.0));\n\ + \n\ + gl_FragColor = (texture2DRect(tex, texCoord[ 6]) * wx.r\n\ + + texture2DRect(tex, texCoord[ 7]) * wx.g\n\ + + texture2DRect(tex, texCoord[ 8]) * wx.b\n\ + + texture2DRect(tex, texCoord[ 9]) * wx.a) * wy.r\n\ + + (texture2DRect(tex, texCoord[ 5]) * wx.r\n\ + + texture2DRect(tex, texCoord[ 0]) * wx.g\n\ + + texture2DRect(tex, texCoord[ 1]) * wx.b\n\ + + texture2DRect(tex, texCoord[10]) * wx.a) * wy.g\n\ + + (texture2DRect(tex, texCoord[ 4]) * wx.r\n\ + + texture2DRect(tex, texCoord[ 3]) * wx.g\n\ + + texture2DRect(tex, texCoord[ 2]) * wx.b\n\ + + texture2DRect(tex, texCoord[11]) * wx.a) * wy.b\n\ + + (texture2DRect(tex, texCoord[15]) * wx.r\n\ + + texture2DRect(tex, texCoord[14]) * wx.g\n\ + + texture2DRect(tex, texCoord[13]) * wx.b\n\ + + texture2DRect(tex, texCoord[12]) * wx.a) * wy.a;\n\ + }\n\ +"}; + +static const char *FilterLanczos3FragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + #define PI 3.1415926535897932384626433832795\n\ + #define RADIUS 3.0\n\ + #define FIX(c) max(abs(c), 1e-5)\n\ + \n\ + // It would be nice to pass all 36 sample coordinates to the fragment\n\ + // shader, but since I want this to work on older GPUs, passing 36\n\ + // coordinates would result in 72 varying floats. Since most older GPUs\n\ + // can't support that many varying floats, I'm only going to pass the\n\ + // center coordinate, and then calculate the other sample coordinates\n\ + // from within the fragment shader.\n\ + //\n\ + // Note that sampling in this manner causes 36 dependent texel reads,\n\ + // which may incur a performance penalty. However, I think that having\n\ + // compatibility is better in this case, since any newer GPU (most from\n\ + // 2008 and later) will be fast enough to overcome the penalty.\n\ + \n\ + varying vec2 texCoord[1];\n\ + uniform sampler2DRect tex;\n\ + \n\ + vec3 weight3(float x)\n\ + {\n\ + vec3 sample = FIX(2.0 * PI * vec3(x - 1.5, x - 0.5, x + 0.5));\n\ + return ( sin(sample) * sin(sample / RADIUS) / (sample * sample) );\n\ + }\n\ + \n\ + void main()\n\ + {\n\ + vec2 tc = floor(texCoord[0] - 0.5) + 0.5;\n\ + vec2 f = abs(texCoord[0] - tc);\n\ + vec3 wx1 = weight3(0.5 - f.x * 0.5);\n\ + vec3 wx2 = weight3(1.0 - f.x * 0.5);\n\ + vec3 wy1 = weight3(0.5 - f.y * 0.5);\n\ + vec3 wy2 = weight3(1.0 - f.y * 0.5);\n\ + \n\ + // Normalize weights\n\ + float sumX = dot(wx1, vec3(1.0)) + dot(wx2, vec3(1.0));\n\ + float sumY = dot(wy1, vec3(1.0)) + dot(wy2, vec3(1.0));\n\ + wx1 /= sumX;\n\ + wx2 /= sumX;\n\ + wy1 /= sumY;\n\ + wy2 /= sumY;\n\ + \n\ + gl_FragColor = (texture2DRect(tex, tc + vec2(-2.0,-2.0)) * wx1.r\n\ + + texture2DRect(tex, tc + vec2(-1.0,-2.0)) * wx2.r\n\ + + texture2DRect(tex, tc + vec2( 0.0,-2.0)) * wx1.g\n\ + + texture2DRect(tex, tc + vec2( 1.0,-2.0)) * wx2.g\n\ + + texture2DRect(tex, tc + vec2( 2.0,-2.0)) * wx1.b\n\ + + texture2DRect(tex, tc + vec2( 3.0,-2.0)) * wx2.b) * wy1.r\n\ + + (texture2DRect(tex, tc + vec2(-2.0,-1.0)) * wx1.r\n\ + + texture2DRect(tex, tc + vec2(-1.0,-1.0)) * wx2.r\n\ + + texture2DRect(tex, tc + vec2( 0.0,-1.0)) * wx1.g\n\ + + texture2DRect(tex, tc + vec2( 1.0,-1.0)) * wx2.g\n\ + + texture2DRect(tex, tc + vec2( 2.0,-1.0)) * wx1.b\n\ + + texture2DRect(tex, tc + vec2( 3.0,-1.0)) * wx2.b) * wy2.r\n\ + + (texture2DRect(tex, tc + vec2(-2.0, 0.0)) * wx1.r\n\ + + texture2DRect(tex, tc + vec2(-1.0, 0.0)) * wx2.r\n\ + + texture2DRect(tex, tc + vec2( 0.0, 0.0)) * wx1.g\n\ + + texture2DRect(tex, tc + vec2( 1.0, 0.0)) * wx2.g\n\ + + texture2DRect(tex, tc + vec2( 2.0, 0.0)) * wx1.b\n\ + + texture2DRect(tex, tc + vec2( 3.0, 0.0)) * wx2.b) * wy1.g\n\ + + (texture2DRect(tex, tc + vec2(-2.0, 1.0)) * wx1.r\n\ + + texture2DRect(tex, tc + vec2(-1.0, 1.0)) * wx2.r\n\ + + texture2DRect(tex, tc + vec2( 0.0, 1.0)) * wx1.g\n\ + + texture2DRect(tex, tc + vec2( 1.0, 1.0)) * wx2.g\n\ + + texture2DRect(tex, tc + vec2( 2.0, 1.0)) * wx1.b\n\ + + texture2DRect(tex, tc + vec2( 3.0, 1.0)) * wx2.b) * wy2.g\n\ + + (texture2DRect(tex, tc + vec2(-2.0, 2.0)) * wx1.r\n\ + + texture2DRect(tex, tc + vec2(-1.0, 2.0)) * wx2.r\n\ + + texture2DRect(tex, tc + vec2( 0.0, 2.0)) * wx1.g\n\ + + texture2DRect(tex, tc + vec2( 1.0, 2.0)) * wx2.g\n\ + + texture2DRect(tex, tc + vec2( 2.0, 2.0)) * wx1.b\n\ + + texture2DRect(tex, tc + vec2( 3.0, 2.0)) * wx2.b) * wy1.b\n\ + + (texture2DRect(tex, tc + vec2(-2.0, 3.0)) * wx1.r\n\ + + texture2DRect(tex, tc + vec2(-1.0, 3.0)) * wx2.r\n\ + + texture2DRect(tex, tc + vec2( 0.0, 3.0)) * wx1.g\n\ + + texture2DRect(tex, tc + vec2( 1.0, 3.0)) * wx2.g\n\ + + texture2DRect(tex, tc + vec2( 2.0, 3.0)) * wx1.b\n\ + + texture2DRect(tex, tc + vec2( 3.0, 3.0)) * wx2.b) * wy2.b;\n\ + }\n\ +"}; + +static const char *Scalar2xScanlineFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[1];\n\ + uniform sampler2DRect tex;\n\ + \n\ + //---------------------------------------\n\ + // Input Pixel Mapping: 00\n\ + //\n\ + // Output Pixel Mapping: A|B\n\ + // C|D\n\ + \n\ + void main()\n\ + {\n\ + vec2 f = step(0.5, fract(texCoord[0]));\n\ + vec4 outA = texture2DRect(tex, texCoord[0]) * vec4(1.000, 1.000, 1.000, 1.000);\n\ + vec4 outB = texture2DRect(tex, texCoord[0]) * vec4(0.875, 0.875, 0.875, 1.000);\n\ + vec4 outC = texture2DRect(tex, texCoord[0]) * vec4(0.875, 0.875, 0.875, 1.000);\n\ + vec4 outD = texture2DRect(tex, texCoord[0]) * vec4(0.750, 0.750, 0.750, 1.000);\n\ + \n\ + gl_FragColor = mix( mix(outA, outB, f.x), mix(outC, outD, f.x), f.y );\n\ + }\n\ +"}; + +static const char *Scalar2xEPXFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[9];\n\ + uniform sampler2DRect tex;\n\ + \n\ + const vec3 dt = vec3(65536.0, 256.0, 1.0);\n\ + \n\ + float reduce(vec3 color)\n\ + {\n\ + return dot(color, dt);\n\ + }\n\ + \n\ + //---------------------------------------\n\ + // Input Pixel Mapping: --|07|--\n\ + // 05|00|01\n\ + // --|03|--\n\ + //\n\ + // Output Pixel Mapping: A|B\n\ + // C|D\n\ + \n\ + void main()\n\ + {\n\ + vec2 f = step(0.5, fract(texCoord[0]));\n\ + vec3 pU = texture2DRect(tex, texCoord[7]).rgb;\n\ + vec3 pL = texture2DRect(tex, texCoord[5]).rgb;\n\ + vec3 pC = texture2DRect(tex, texCoord[0]).rgb;\n\ + vec3 pR = texture2DRect(tex, texCoord[1]).rgb;\n\ + vec3 pD = texture2DRect(tex, texCoord[3]).rgb;\n\ + float rU = reduce(pU);\n\ + float rL = reduce(pL);\n\ + float rR = reduce(pR);\n\ + float rD = reduce(pD);\n\ + \n\ + vec3 outA = pC;\n\ + vec3 outB = pC;\n\ + vec3 outC = pC;\n\ + vec3 outD = pC;\n\ + \n\ + if (rL != rR && rU != rD) \n\ + {\n\ + if (rU == rL) outA = pU;\n\ + if (rR == rU) outB = pR;\n\ + if (rL == rD) outC = pL;\n\ + if (rD == rR) outD = pD;\n\ + }\n\ + \n\ + gl_FragColor.rgb = mix( mix(outA, outB, f.x), mix(outC, outD, f.x), f.y );\n\ + gl_FragColor.a = 1.0;\n\ + }\n\ +"}; + +static const char *Scalar2xEPXPlusFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[9];\n\ + uniform sampler2DRect tex;\n\ + //---------------------------------------\n\ + // Input Pixel Mapping: --|07|--\n\ + // 05|00|01\n\ + // --|03|--\n\ + //\n\ + // Output Pixel Mapping: A|B\n\ + // C|D\n\ + \n\ + void main()\n\ + {\n\ + vec2 f = step(0.5, fract(texCoord[0]));\n\ + vec3 pU = texture2DRect(tex, texCoord[7]).rgb;\n\ + vec3 pL = texture2DRect(tex, texCoord[5]).rgb;\n\ + vec3 pC = texture2DRect(tex, texCoord[0]).rgb;\n\ + vec3 pR = texture2DRect(tex, texCoord[1]).rgb;\n\ + vec3 pD = texture2DRect(tex, texCoord[3]).rgb;\n\ + \n\ + vec3 outA = ( distance(pL, pU) < min(distance(pL, pD), distance(pR, pU)) ) ? mix(pL, pU, 0.5) : pC;\n\ + vec3 outB = ( distance(pR, pU) < min(distance(pL, pU), distance(pR, pD)) ) ? mix(pR, pU, 0.5) : pC;\n\ + vec3 outC = ( distance(pL, pD) < min(distance(pL, pU), distance(pR, pD)) ) ? mix(pL, pD, 0.5) : pC;\n\ + vec3 outD = ( distance(pR, pD) < min(distance(pL, pD), distance(pR, pU)) ) ? mix(pR, pD, 0.5) : pC;\n\ + \n\ + gl_FragColor.rgb = mix( mix(outA, outB, f.x), mix(outC, outD, f.x), f.y );\n\ + gl_FragColor.a = 1.0;\n\ + }\n\ +"}; + +static const char *Scalar2xSaIFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[16];\n\ + uniform sampler2DRect tex;\n\ + \n\ + const vec3 dt = vec3(65536.0, 256.0, 1.0);\n\ + \n\ + float GetResult(float v1, float v2, float v3, float v4)\n\ + {\n\ + return sign(abs(v1-v3)+abs(v1-v4))-sign(abs(v2-v3)+abs(v2-v4));\n\ + }\n\ + \n\ + float reduce(vec3 color)\n\ + {\n\ + return dot(color, dt);\n\ + }\n\ + //---------------------------------------\n\ + // Input Pixel Mapping: 06|07|08|09\n\ + // 05|00|01|10\n\ + // 04|03|02|11\n\ + // 15|14|13|12\n\ + //\n\ + // Output Pixel Mapping: A|B\n\ + // C|D\n\ + \n\ + //---------------------------------------\n\ + // 2xSaI Pixel Mapping: I|E|F|J\n\ + // G|A|B|K\n\ + // H|C|D|L\n\ + // M|N|O|P\n\ + \n\ + void main()\n\ + {\n\ + vec2 f = step(0.5, fract(texCoord[0]));\n\ + \n\ + float Iv = reduce( texture2DRect(tex, texCoord[6]).rgb );\n\ + float Ev = reduce( texture2DRect(tex, texCoord[7]).rgb );\n\ + float Fv = reduce( texture2DRect(tex, texCoord[8]).rgb );\n\ + float Jv = reduce( texture2DRect(tex, texCoord[9]).rgb );\n\ + \n\ + float Gv = reduce( texture2DRect(tex, texCoord[5]).rgb );\n\ + vec3 Ac = texture2DRect(tex, texCoord[0]).rgb; float Av = reduce(Ac);\n\ + vec3 Bc = texture2DRect(tex, texCoord[1]).rgb; float Bv = reduce(Bc);\n\ + float Kv = reduce( texture2DRect(tex, texCoord[10]).rgb );\n\ + \n\ + float Hv = reduce( texture2DRect(tex, texCoord[4]).rgb );\n\ + vec3 Cc = texture2DRect(tex, texCoord[3]).rgb; float Cv = reduce(Cc);\n\ + vec3 Dc = texture2DRect(tex, texCoord[2]).rgb; float Dv = reduce(Dc);\n\ + float Lv = reduce( texture2DRect(tex, texCoord[11]).rgb );\n\ + \n\ + float Mv = reduce( texture2DRect(tex, texCoord[15]).rgb );\n\ + float Nv = reduce( texture2DRect(tex, texCoord[14]).rgb );\n\ + float Ov = reduce( texture2DRect(tex, texCoord[13]).rgb );\n\ + // Pv is unused, so skip this one.\n\ + \n\ + vec3 outA = Ac;\n\ + vec3 outB = Ac;\n\ + vec3 outC = Ac;\n\ + vec3 outD = Ac;\n\ + \n\ + bool compAD = (Av == Dv);\n\ + bool compBC = (Bv == Cv);\n\ + \n\ + if (compAD && !compBC)\n\ + {\n\ + outB = ((Av == Ev) && (Bv == Lv)) || ((Av == Cv) && (Av == Fv) && (Bv != Ev) && (Bv == Jv)) ? Ac : mix(Ac, Bc, 0.5);\n\ + outC = ((Av == Gv) && (Cv == Ov)) || ((Av == Bv) && (Av == Hv) && (Cv != Gv) && (Cv == Mv)) ? Ac : mix(Ac, Cc, 0.5);\n\ + }\n\ + else if (!compAD && compBC)\n\ + {\n\ + outB = ((Bv == Fv) && (Av == Hv)) || ((Bv == Ev) && (Bv == Dv) && (Av != Fv) && (Av == Iv)) ? Bc : mix(Ac, Bc, 0.5);\n\ + outC = ((Cv == Hv) && (Av == Fv)) || ((Cv == Gv) && (Cv == Dv) && (Av != Hv) && (Av == Iv)) ? Cc : mix(Ac, Cc, 0.5);\n\ + outD = Bc;\n\ + }\n\ + else if (compAD && compBC)\n\ + {\n\ + outB = (Av == Bv) ? Ac : mix(Ac, Bc, 0.5);\n\ + outC = (Av == Bv) ? Ac : mix(Ac, Cc, 0.5);\n\ + \n\ + float r = (Av == Bv) ? 1.0 : GetResult(Av, Bv, Gv, Ev) - GetResult(Bv, Av, Kv, Fv) - GetResult(Bv, Av, Hv, Nv) + GetResult(Av, Bv, Lv, Ov);\n\ + outD = (r > 0.0) ? Ac : ( (r < 0.0) ? Bc : mix( mix(Ac, Bc, 0.5), mix(Cc, Dc, 0.5), 0.5) );\n\ + }\n\ + else\n\ + {\n\ + outB = ((Av == Cv) && (Av == Fv) && (Bv != Ev) && (Bv == Jv)) ? Ac : ( ((Bv == Ev) && (Bv == Dv) && (Av != Fv) && (Av == Iv)) ? Bc : mix(Ac, Bc, 0.5) );\n\ + outC = ((Av == Bv) && (Av == Hv) && (Cv != Gv) && (Cv == Mv)) ? Ac : ( ((Cv == Gv) && (Cv == Dv) && (Av != Hv) && (Av == Iv)) ? Cc : mix(Ac, Cc, 0.5) );\n\ + outD = mix( mix(Ac, Bc, 0.5), mix(Cc, Dc, 0.5), 0.5 );\n\ + }\n\ + \n\ + gl_FragColor.rgb = mix( mix(outA, outB, f.x), mix(outC, outD, f.x), f.y );\n\ + gl_FragColor.a = 1.0;\n\ + }\n\ +"}; + +static const char *ScalarSuper2xSaIFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[16];\n\ + uniform sampler2DRect tex;\n\ + \n\ + const vec3 dt = vec3(65536.0, 256.0, 1.0);\n\ + \n\ + float GetResult(float v1, float v2, float v3, float v4)\n\ + {\n\ + return sign(abs(v1-v3)+abs(v1-v4))-sign(abs(v2-v3)+abs(v2-v4));\n\ + }\n\ + \n\ + float reduce(vec3 color)\n\ + {\n\ + return dot(color, dt);\n\ + }\n\ + \n\ + //---------------------------------------\n\ + // Input Pixel Mapping: 06|07|08|09\n\ + // 05|00|01|10\n\ + // 04|03|02|11\n\ + // 15|14|13|12\n\ + //\n\ + // Output Pixel Mapping: A|B\n\ + // C|D\n\ + \n\ + //---------------------------------------\n\ + // S2xSaI Pixel Mapping: I|E|F|J\n\ + // G|A|B|K\n\ + // H|C|D|L\n\ + // M|N|O|P\n\ + \n\ + void main()\n\ + {\n\ + vec2 f = step(0.5, fract(texCoord[0]));\n\ + \n\ + float Iv = reduce( texture2DRect(tex, texCoord[6]).rgb );\n\ + float Ev = reduce( texture2DRect(tex, texCoord[7]).rgb );\n\ + float Fv = reduce( texture2DRect(tex, texCoord[8]).rgb );\n\ + float Jv = reduce( texture2DRect(tex, texCoord[9]).rgb );\n\ + \n\ + float Gv = reduce( texture2DRect(tex, texCoord[5]).rgb );\n\ + vec3 Ac = texture2DRect(tex, texCoord[0]).rgb; float Av = reduce(Ac);\n\ + vec3 Bc = texture2DRect(tex, texCoord[1]).rgb; float Bv = reduce(Bc);\n\ + float Kv = reduce( texture2DRect(tex, texCoord[10]).rgb );\n\ + \n\ + float Hv = reduce( texture2DRect(tex, texCoord[4]).rgb );\n\ + vec3 Cc = texture2DRect(tex, texCoord[3]).rgb; float Cv = reduce(Cc);\n\ + vec3 Dc = texture2DRect(tex, texCoord[2]).rgb; float Dv = reduce(Dc);\n\ + float Lv = reduce( texture2DRect(tex, texCoord[11]).rgb );\n\ + \n\ + float Mv = reduce( texture2DRect(tex, texCoord[15]).rgb );\n\ + float Nv = reduce( texture2DRect(tex, texCoord[14]).rgb );\n\ + float Ov = reduce( texture2DRect(tex, texCoord[13]).rgb );\n\ + float Pv = reduce( texture2DRect(tex, texCoord[12]).rgb );\n\ + \n\ + bool compAD = (Av == Dv);\n\ + bool compBC = (Bv == Cv);\n\ + \n\ + vec3 outA = ( (compBC && !compAD && (Hv == Cv) && (Cv != Fv)) || ((Gv == Cv) && (Dv == Cv) && (Hv != Av) && (Cv != Iv)) ) ? mix(Ac, Cc, 0.5) : Ac;\n\ + vec3 outB = Bc;\n\ + vec3 outC = ( (compAD && !compBC && (Gv == Av) && (Av != Ov)) || ((Av == Hv) && (Av == Bv) && (Gv != Cv) && (Av != Mv)) ) ? mix(Ac, Cc, 0.5) : Cc;\n\ + vec3 outD = Dc;\n\ + \n\ + if (compBC && !compAD)\n\ + {\n\ + outB = outD = Cc;\n\ + }\n\ + else if (!compBC && compAD)\n\ + {\n\ + outB = outD = Ac;\n\ + }\n\ + else if (compBC && compAD)\n\ + {\n\ + float r = GetResult(Bv, Av, Hv, Nv) + GetResult(Bv, Av, Gv, Ev) + GetResult(Bv, Av, Ov, Lv) + GetResult(Bv, Av, Fv, Kv);\n\ + outB = outD = (r > 0.0) ? Bc : ( (r < 0.0) ? Ac : mix(Ac, Bc, 0.5) );\n\ + }\n\ + else\n\ + {\n\ + outB = ( (Bv == Dv) && (Bv == Ev) && (Av != Fv) && (Bv != Iv) ) ? mix(Ac, Bc, 0.75) : ( ( (Av == Cv) && (Av == Fv) && (Ev != Bv) && (Av != Jv) ) ? mix(Ac, Bc, 0.25) : mix(Ac, Bc, 0.5) );\n\ + outD = ( (Bv == Dv) && (Dv == Nv) && (Cv != Ov) && (Dv != Mv) ) ? mix(Cc, Dc, 0.75) : ( ( (Av == Cv) && (Cv == Ov) && (Nv != Dv) && (Cv != Pv) ) ? mix(Cc, Dc, 0.25) : mix(Cc, Dc, 0.5) );\n\ + }\n\ + \n\ + gl_FragColor.rgb = mix( mix(outA, outB, f.x), mix(outC, outD, f.x), f.y );\n\ + gl_FragColor.a = 1.0;\n\ + }\n\ +"}; + +static const char *ScalarSuperEagle2xFragShader_110 = {"\ + #version 110\n\ + #extension GL_ARB_texture_rectangle : require\n\ + \n\ + varying vec2 texCoord[16];\n\ + uniform sampler2DRect tex;\n\ + \n\ + const vec3 dt = vec3(65536.0, 256.0, 1.0);\n\ + \n\ + float GetResult(float v1, float v2, float v3, float v4)\n\ + {\n\ + return sign(abs(v1-v3)+abs(v1-v4))-sign(abs(v2-v3)+abs(v2-v4));\n\ + }\n\ + \n\ + float reduce(vec3 color)\n\ + {\n\ + return dot(color, dt);\n\ + }\n\ + \n\ + //---------------------------------------\n\ + // Input Pixel Mapping: --|07|08|--\n\ + // 05|00|01|10\n\ + // 04|03|02|11\n\ + // --|14|13|--\n\ + //\n\ + // Output Pixel Mapping: A|B\n\ + // C|D\n\ + \n\ + //---------------------------------------\n\ + // SEagle Pixel Mapping: -|E|F|-\n\ + // G|A|B|K\n\ + // H|C|D|L\n\ + // -|N|O|-\n\ + \n\ + void main()\n\ + {\n\ + vec2 f = step(0.5, fract(texCoord[0]));\n\ + \n\ + float Ev = reduce( texture2DRect(tex, texCoord[7]).rgb );\n\ + float Fv = reduce( texture2DRect(tex, texCoord[8]).rgb );\n\ + \n\ + float Gv = reduce( texture2DRect(tex, texCoord[5]).rgb );\n\ + vec3 Ac = texture2DRect(tex, texCoord[0]).rgb; float Av = reduce(Ac);\n\ + vec3 Bc = texture2DRect(tex, texCoord[1]).rgb; float Bv = reduce(Bc);\n\ + float Kv = reduce( texture2DRect(tex, texCoord[10]).rgb );\n\ + \n\ + float Hv = reduce( texture2DRect(tex, texCoord[4]).rgb );\n\ + vec3 Cc = texture2DRect(tex, texCoord[3]).rgb; float Cv = reduce(Cc);\n\ + vec3 Dc = texture2DRect(tex, texCoord[2]).rgb; float Dv = reduce(Dc);\n\ + float Lv = reduce( texture2DRect(tex, texCoord[11]).rgb );\n\ + \n\ + float Nv = reduce( texture2DRect(tex, texCoord[14]).rgb );\n\ + float Ov = reduce( texture2DRect(tex, texCoord[13]).rgb );\n\ + \n\ + vec3 outA = Ac;\n\ + vec3 outB = Bc;\n\ + vec3 outC = Cc;\n\ + vec3 outD = Dc;\n\ + bool compAD = (Av == Dv);\n\ + bool compBC = (Bv == Cv);\n\ + \n\ + if (compBC && !compAD)\n\ + {\n\ + outA = (Cv == Hv || Bv == Fv) ? mix(Ac, Cc, 0.75) : mix(Ac, Bc, 0.5);\n\ + //outA = mix( mix(Ac, Bc, 0.5), mix(Ac, Cc, 0.75), float(Cv == Hv || Bv == Fv) );\n\ + outB = Cc;\n\ + //outC = Cc;\n\ + outD = mix( mix(Dc, Cc, 0.5), mix(Dc, Cc, 0.75), float(Bv == Kv || Cv == Nv) );\n\ + }\n\ + else if (!compBC && compAD)\n\ + {\n\ + //outA = Ac;\n\ + outB = mix( mix(Ac, Bc, 0.5), mix(Ac, Bc, 0.25), float(Av == Ev || Dv == Lv) );\n\ + outC = mix( mix(Cc, Dc, 0.5), mix(Ac, Cc, 0.25), float(Dv == Ov || Av == Gv) );\n\ + outD = Ac;\n\ + }\n\ + else if (compBC && compAD)\n\ + {\n\ + float r = GetResult(Bv, Av, Hv, Nv) + GetResult(Bv, Av, Gv, Ev) + GetResult(Bv, Av, Ov, Lv) + GetResult(Bv, Av, Fv, Kv);\n\ + if (r > 0.0)\n\ + {\n\ + outA = mix(Ac, Bc, 0.5);\n\ + outB = Cc;\n\ + //outC = Cc;\n\ + outD = outA;\n\ + }\n\ + else if (r < 0.0)\n\ + {\n\ + //outA = Ac;\n\ + outB = mix(Ac, Bc, 0.5);\n\ + outC = outB;\n\ + outD = Ac;\n\ + }\n\ + else\n\ + {\n\ + //outA = Ac;\n\ + outB = Cc;\n\ + //outC = Cc;\n\ + outD = Ac;\n\ + }\n\ + }\n\ + else\n\ + {\n\ + outA = mix(mix(Bc, Cc, 0.5), Ac, 0.75);\n\ + outB = mix(mix(Ac, Dc, 0.5), Bc, 0.75);\n\ + outC = mix(mix(Ac, Dc, 0.5), Cc, 0.75);\n\ + outD = mix(mix(Bc, Cc, 0.5), Dc, 0.75);\n\ + }\n\ + \n\ + gl_FragColor.rgb = mix( mix(outA, outB, f.x), mix(outC, outD, f.x), f.y );\n\ + gl_FragColor.a = 1.0;\n\ + }\n\ "}; enum OGLVertexAttributeID @@ -67,90 +994,787 @@ enum OGLVertexAttributeID OGLVertexAttributeID_TexCoord0 = 8 }; +static const GLint filterVtxBuffer[8] = {-1, -1, 1, -1, 1, 1, -1, 1}; +static const GLubyte filterElementBuffer[6] = {0, 1, 2, 2, 3, 0}; +static const GLubyte outputElementBuffer[12] = {0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4}; + +OGLInfo::OGLInfo() +{ + _versionMajor = 0; + _versionMinor = 0; + _versionRevision = 0; + + _isVBOSupported = false; + _isPBOSupported = false; + _isShaderSupported = false; + _isFBOSupported = false; +} + +OGLInfo* OGLInfo::GetVersionedObjectOGL() +{ + OGLInfo *oglInfoObject = NULL; + + const char *oglVersionString = (const char *)glGetString(GL_VERSION); + if (oglVersionString == NULL) + { + return oglInfoObject; + } + + size_t versionStringLength = 0; + + // First, check for the dot in the revision string. There should be at + // least one present. + const char *versionStrEnd = strstr(oglVersionString, "."); + if (versionStrEnd == NULL) + { + return oglInfoObject; + } + + // Next, check for the space before the vendor-specific info (if present). + versionStrEnd = strstr(oglVersionString, " "); + if (versionStrEnd == NULL) + { + // If a space was not found, then the vendor-specific info is not present, + // and therefore the entire string must be the version number. + versionStringLength = strlen(oglVersionString); + } + else + { + // If a space was found, then the vendor-specific info is present, + // and therefore the version number is everything before the space. + versionStringLength = versionStrEnd - oglVersionString; + } + + // Copy the version substring and parse it. + char *versionSubstring = (char *)malloc(versionStringLength * sizeof(char)); + strncpy(versionSubstring, oglVersionString, versionStringLength); + + unsigned int major = 0; + unsigned int minor = 0; + unsigned int revision = 0; + + sscanf(versionSubstring, "%u.%u.%u", &major, &minor, &revision); + + free(versionSubstring); + versionSubstring = NULL; + + // We finally have the version read. Now create an OGLInfo + // object based on the OpenGL version. + if ((major >= 4) || + (major >= 3 && minor >= 2)) + { + oglInfoObject = new OGLInfo_3_2; + } + else if ((major >= 3) || + (major >= 2 && minor >= 1)) + { + oglInfoObject = new OGLInfo_2_1; + } + else if (major >= 2) + { + oglInfoObject = new OGLInfo_2_0; + } + else if (major >= 1 && minor >= 5) + { + oglInfoObject = new OGLInfo_1_2; + } + + return oglInfoObject; +} + +bool OGLInfo::IsVBOSupported() +{ + return this->_isVBOSupported; +} + +bool OGLInfo::IsPBOSupported() +{ + return this->_isPBOSupported; +} + +bool OGLInfo::IsShaderSupported() +{ + return this->_isShaderSupported; +} + +bool OGLInfo::IsFBOSupported() +{ + return this->_isFBOSupported; +} + +OGLInfo_1_2::OGLInfo_1_2() +{ + _versionMajor = 1; + _versionMinor = 2; + _versionRevision = 0; + + // Check the OpenGL capabilities for this renderer + std::set oglExtensionSet; + this->GetExtensionSetOGL(&oglExtensionSet); + + _isVBOSupported = this->IsExtensionPresent(oglExtensionSet, "GL_ARB_vertex_buffer_object"); + +#if !defined(GL_ARB_shader_objects) || \ + !defined(GL_ARB_vertex_shader) || \ + !defined(GL_ARB_fragment_shader) || \ + !defined(GL_ARB_vertex_program) + + _isShaderSupported = false; +#else + _isShaderSupported = this->IsExtensionPresent(oglExtensionSet, "GL_ARB_shader_objects") && + this->IsExtensionPresent(oglExtensionSet, "GL_ARB_vertex_shader") && + this->IsExtensionPresent(oglExtensionSet, "GL_ARB_fragment_shader") && + this->IsExtensionPresent(oglExtensionSet, "GL_ARB_vertex_program"); +#endif + +#if !defined(GL_ARB_pixel_buffer_object) && !defined(GL_EXT_pixel_buffer_object) + _isPBOSupported = false; +#else + _isPBOSupported = this->IsExtensionPresent(oglExtensionSet, "GL_ARB_vertex_buffer_object") && + (this->IsExtensionPresent(oglExtensionSet, "GL_ARB_pixel_buffer_object") || + this->IsExtensionPresent(oglExtensionSet, "GL_EXT_pixel_buffer_object")); +#endif + + // Don't use ARB versions since we're using the EXT versions for backwards compatibility. +#if !defined(GL_EXT_framebuffer_object) + _isFBOSupported = false; +#else + _isFBOSupported = this->IsExtensionPresent(oglExtensionSet, "GL_EXT_framebuffer_object"); +#endif +} + +void OGLInfo_1_2::GetExtensionSetOGL(std::set *oglExtensionSet) +{ + std::string oglExtensionString = std::string((const char *)glGetString(GL_EXTENSIONS)); + + size_t extStringStartLoc = 0; + size_t delimiterLoc = oglExtensionString.find_first_of(' ', extStringStartLoc); + while (delimiterLoc != std::string::npos) + { + std::string extensionName = oglExtensionString.substr(extStringStartLoc, delimiterLoc - extStringStartLoc); + oglExtensionSet->insert(extensionName); + + extStringStartLoc = delimiterLoc + 1; + delimiterLoc = oglExtensionString.find_first_of(' ', extStringStartLoc); + } + + if (extStringStartLoc - oglExtensionString.length() > 0) + { + std::string extensionName = oglExtensionString.substr(extStringStartLoc, oglExtensionString.length() - extStringStartLoc); + oglExtensionSet->insert(extensionName); + } +} + +bool OGLInfo_1_2::IsExtensionPresent(const std::set &oglExtensionSet, const std::string &extensionName) const +{ + if (oglExtensionSet.size() == 0) + { + return false; + } + + return (oglExtensionSet.find(extensionName) != oglExtensionSet.end()); +} + +OGLInfo_2_0::OGLInfo_2_0() +{ + _versionMajor = 2; + _versionMinor = 0; + _versionRevision = 0; + _isVBOSupported = true; + _isShaderSupported = true; +} + +OGLInfo_2_1::OGLInfo_2_1() +{ + _versionMajor = 2; + _versionMinor = 1; + _versionRevision = 0; + _isVBOSupported = true; + _isPBOSupported = true; + _isShaderSupported = true; +} + +OGLInfo_3_2::OGLInfo_3_2() +{ + _versionMajor = 3; + _versionMinor = 2; + _versionRevision = 0; + _isVBOSupported = true; + _isPBOSupported = true; + _isShaderSupported = true; + _isFBOSupported = true; +} + +void OGLInfo_3_2::GetExtensionSetOGL(std::set *oglExtensionSet) +{ +#ifdef GL_VERSION_3_2 + GLint extensionCount = 0; + + glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount); + for (unsigned int i = 0; i < extensionCount; i++) + { + std::string extensionName = std::string((const char *)glGetStringi(GL_EXTENSIONS, i)); + oglExtensionSet->insert(extensionName); + } +#endif +} + +#pragma mark - + +OGLShaderProgram::OGLShaderProgram() +{ + _vertexID = 0; + _fragmentID = 0; + + _programID = glCreateProgram(); + if (_programID == 0) + { + printf("OpenGL Error - Failed to create shader program.\n"); + } +} + +OGLShaderProgram::~OGLShaderProgram() +{ + glDetachShader(this->_programID, this->_vertexID); + glDetachShader(this->_programID, this->_fragmentID); + glDeleteProgram(this->_programID); + glDeleteShader(this->_vertexID); + glDeleteShader(this->_fragmentID); +} + +GLuint OGLShaderProgram::LoadShaderOGL(GLenum shaderType, const char *shaderProgram) +{ + GLint shaderStatus = GL_TRUE; + + GLuint shaderID = glCreateShader(shaderType); + if (shaderID == 0) + { + printf("OpenGL Error - Failed to create %s.\n", + (shaderType == GL_VERTEX_SHADER) ? "GL_VERTEX_SHADER" : ((shaderType == GL_FRAGMENT_SHADER) ? "GL_FRAGMENT_SHADER" : "OTHER SHADER TYPE")); + return shaderID; + } + + glShaderSource(shaderID, 1, (const GLchar **)&shaderProgram, NULL); + glCompileShader(shaderID); + glGetShaderiv(shaderID, GL_COMPILE_STATUS, &shaderStatus); + if (shaderStatus == GL_FALSE) + { + static const size_t logBytes = 16384; // 16KB should be more than enough + GLchar *logBuf = (GLchar *)calloc(logBytes, sizeof(GLchar)); + GLsizei logSize = 0; + glGetShaderInfoLog(shaderID, logBytes * sizeof(GLchar), &logSize, logBuf); + + printf("OpenGL Error - Failed to compile %s.\n%s\n", + (shaderType == GL_VERTEX_SHADER) ? "GL_VERTEX_SHADER" : ((shaderType == GL_FRAGMENT_SHADER) ? "GL_FRAGMENT_SHADER" : "OTHER SHADER TYPE"), + (char *)logBuf); + + glDeleteShader(shaderID); + return shaderID; + } + + return shaderID; +} + +GLuint OGLShaderProgram::GetVertexShaderID() +{ + return this->_vertexID; +} + +void OGLShaderProgram::SetVertexShaderOGL(const char *shaderProgram) +{ + if (this->_vertexID != 0) + { + glDetachShader(this->_programID, this->_vertexID); + glDeleteShader(this->_vertexID); + } + + this->_vertexID = this->LoadShaderOGL(GL_VERTEX_SHADER, shaderProgram); + + if (this->_vertexID != 0) + { + glAttachShader(this->_programID, this->_vertexID); + glBindAttribLocation(this->_programID, OGLVertexAttributeID_Position, "inPosition"); + glBindAttribLocation(this->_programID, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); + } + + if (this->_vertexID != 0 && this->_fragmentID != 0) + { + this->LinkOGL(); + } +} + +GLuint OGLShaderProgram::GetFragmentShaderID() +{ + return this->_fragmentID; +} + +void OGLShaderProgram::SetFragmentShaderOGL(const char *shaderProgram) +{ + if (this->_fragmentID != 0) + { + glDetachShader(this->_programID, this->_fragmentID); + glDeleteShader(this->_fragmentID); + } + + this->_fragmentID = this->LoadShaderOGL(GL_FRAGMENT_SHADER, shaderProgram); + + if (this->_fragmentID != 0) + { + glAttachShader(this->_programID, this->_fragmentID); + } + + if (this->_vertexID != 0 && this->_fragmentID != 0) + { + this->LinkOGL(); + } +} + +void OGLShaderProgram::SetVertexAndFragmentShaderOGL(const char *vertShaderProgram, const char *fragShaderProgram) +{ + if (this->_vertexID != 0) + { + glDetachShader(this->_programID, this->_vertexID); + glDeleteShader(this->_vertexID); + } + + if (this->_fragmentID != 0) + { + glDetachShader(this->_programID, this->_fragmentID); + glDeleteShader(this->_fragmentID); + } + + this->_vertexID = this->LoadShaderOGL(GL_VERTEX_SHADER, vertShaderProgram); + this->_fragmentID = this->LoadShaderOGL(GL_FRAGMENT_SHADER, fragShaderProgram); + + if (this->_vertexID != 0) + { + glAttachShader(this->_programID, this->_vertexID); + glBindAttribLocation(this->_programID, OGLVertexAttributeID_Position, "inPosition"); + glBindAttribLocation(this->_programID, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); + } + + if (this->_fragmentID != 0) + { + glAttachShader(this->_programID, this->_fragmentID); + } + + if (this->_vertexID != 0 && this->_fragmentID != 0) + { + this->LinkOGL(); + } +} + +GLuint OGLShaderProgram::GetProgramID() +{ + return this->_programID; +} + +bool OGLShaderProgram::LinkOGL() +{ + bool result = false; + GLint shaderStatus = GL_FALSE; + + glLinkProgram(this->_programID); + glGetProgramiv(this->_programID, GL_LINK_STATUS, &shaderStatus); + if (shaderStatus == GL_FALSE) + { + printf("OpenGL Error - Failed to link shader program.\n"); + return result; + } + + glValidateProgram(this->_programID); + + result = true; + return result; +} + +#pragma mark - OGLVideoOutput::OGLVideoOutput() { - _gapScalar = 0.0f; - _normalWidth = GPU_DISPLAY_WIDTH; - _normalHeight = GPU_DISPLAY_HEIGHT*2.0 + (DS_DISPLAY_GAP*_gapScalar); + _info = OGLInfo::GetVersionedObjectOGL(); + _layerList = new std::vector; + _layerList->reserve(8); + + // Render State Setup (common to both shaders and fixed-function pipeline) + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_DITHER); + glDisable(GL_STENCIL_TEST); + + // Set up fixed-function pipeline render states. + if (!this->_info->IsShaderSupported()) + { + glDisable(GL_ALPHA_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_FOG); + glEnable(GL_TEXTURE_2D); + } + + // Set up clear attributes + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); +} + +OGLVideoOutput::~OGLVideoOutput() +{ + for (size_t i = 0; i < _layerList->size(); i++) + { + delete (*_layerList)[i]; + } + + delete _layerList; + delete _info; +} + +void OGLVideoOutput::InitLayers() +{ + for (size_t i = 0; i < _layerList->size(); i++) + { + delete (*_layerList)[i]; + } + + this->_layerList->clear(); + this->_layerList->push_back(new OGLDisplayLayer(this)); +} + +OGLInfo* OGLVideoOutput::GetInfo() +{ + return this->_info; +} + +GLsizei OGLVideoOutput::GetViewportWidth() +{ + return this->_viewportWidth; +} + +GLsizei OGLVideoOutput::GetViewportHeight() +{ + return this->_viewportHeight; +} + +OGLDisplayLayer* OGLVideoOutput::GetDisplayLayer() +{ + return (OGLDisplayLayer *)this->_layerList->at(0); +} + +void OGLVideoOutput::SetViewportSizeOGL(GLsizei w, GLsizei h) +{ + this->_viewportWidth = w; + this->_viewportHeight = h; + glViewport(0, 0, w, h); + + for (size_t i = 0; i < _layerList->size(); i++) + { + (*_layerList)[i]->SetViewportSizeOGL(w, h); + } +} + +void OGLVideoOutput::ProcessOGL(const uint16_t *videoData, GLsizei w, GLsizei h) +{ + for (size_t i = 0; i < _layerList->size(); i++) + { + (*_layerList)[i]->ProcessOGL(videoData, w, h); + } +} + +void OGLVideoOutput::RenderOGL() +{ + for (size_t i = 0; i < _layerList->size(); i++) + { + (*_layerList)[i]->RenderOGL(); + } +} + +#pragma mark - + +OGLFilter::OGLFilter() +{ + OGLFilterInit(1, 1, 1); +} + +OGLFilter::OGLFilter(GLsizei srcWidth, GLsizei srcHeight, GLfloat scale = 1) +{ + OGLFilterInit(srcWidth, srcHeight, scale); +} + +OGLFilter::~OGLFilter() +{ + glDeleteFramebuffersEXT(1, &this->_fboID); + glDeleteTextures(1, &this->_texDstID); + glDeleteVertexArraysAPPLE(1, &this->_vaoID); + glDeleteBuffers(1, &this->_vboVtxID); + glDeleteBuffers(1, &this->_vboTexCoordID); + glDeleteBuffers(1, &this->_vboElementID); +} + +void OGLFilter::GetSupport(int vfTypeID, bool *outSupportCPU, bool *outSupportShader) +{ + const char *cpuTypeIDString = VideoFilter::GetTypeStringByID((VideoFilterTypeID)vfTypeID); + *outSupportCPU = (strstr(cpuTypeIDString, VIDEOFILTERTYPE_UNKNOWN_STRING) == NULL); + *outSupportShader = (vfTypeID == VideoFilterTypeID_Nearest1_5X) || + (vfTypeID == VideoFilterTypeID_Nearest2X) || + (vfTypeID == VideoFilterTypeID_Scanline) || + (vfTypeID == VideoFilterTypeID_EPX) || + (vfTypeID == VideoFilterTypeID_EPXPlus) || + (vfTypeID == VideoFilterTypeID_2xSaI) || + (vfTypeID == VideoFilterTypeID_Super2xSaI) || + (vfTypeID == VideoFilterTypeID_SuperEagle); +} + +void OGLFilter::OGLFilterInit(GLsizei srcWidth, GLsizei srcHeight, GLfloat scale) +{ + _program = new OGLShaderProgram; + + _scale = scale; + _srcWidth = srcWidth; + _srcHeight = srcHeight; + _dstWidth = _srcWidth * _scale; + _dstHeight = _srcHeight * _scale; + + _texCoordBuffer[0] = 0; + _texCoordBuffer[1] = 0; + _texCoordBuffer[2] = _srcWidth; + _texCoordBuffer[3] = 0; + _texCoordBuffer[4] = _srcWidth; + _texCoordBuffer[5] = _srcHeight; + _texCoordBuffer[6] = 0; + _texCoordBuffer[7] = _srcHeight; + + glGenTextures(1, &_texDstID); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texDstID); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, _dstWidth, _dstHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + + glGenFramebuffersEXT(1, &_fboID); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fboID); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, _texDstID, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + glGenBuffers(1, &_vboVtxID); + glGenBuffers(1, &_vboTexCoordID); + glGenBuffers(1, &_vboElementID); + + glBindBuffer(GL_ARRAY_BUFFER, _vboVtxID); + glBufferData(GL_ARRAY_BUFFER, sizeof(filterVtxBuffer), filterVtxBuffer, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, _vboTexCoordID); + glBufferData(GL_ARRAY_BUFFER, sizeof(_texCoordBuffer), _texCoordBuffer, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboElementID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(filterElementBuffer), filterElementBuffer, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glGenVertexArraysAPPLE(1, &_vaoID); + glBindVertexArrayAPPLE(_vaoID); + + glBindBuffer(GL_ARRAY_BUFFER, _vboVtxID); + glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_INT, GL_FALSE, 0, 0); + glBindBuffer(GL_ARRAY_BUFFER, _vboTexCoordID); + glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_INT, GL_FALSE, 0, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboElementID); + + glEnableVertexAttribArray(OGLVertexAttributeID_Position); + glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); + + glBindVertexArrayAPPLE(0); +} + +OGLShaderProgram* OGLFilter::GetProgram() +{ + return this->_program; +} + +GLuint OGLFilter::GetDstTexID() +{ + return this->_texDstID; +} + +GLsizei OGLFilter::GetDstWidth() +{ + return this->_dstWidth; +} + +GLsizei OGLFilter::GetDstHeight() +{ + return this->_dstHeight; +} + +void OGLFilter::SetSrcSizeOGL(GLsizei w, GLsizei h) +{ + this->_srcWidth = w; + this->_srcHeight = h; + this->_dstWidth = this->_srcWidth * this->_scale; + this->_dstHeight = this->_srcHeight * this->_scale; + + this->_texCoordBuffer[2] = w; + this->_texCoordBuffer[4] = w; + this->_texCoordBuffer[5] = h; + this->_texCoordBuffer[7] = h; + + glBindBuffer(GL_ARRAY_BUFFER, this->_vboTexCoordID); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(this->_texCoordBuffer) , this->_texCoordBuffer); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + uint32_t *tempDstBuffer = (uint32_t *)calloc(this->_dstWidth * this->_dstHeight, sizeof(uint32_t)); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDstID); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_dstWidth, this->_dstHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, tempDstBuffer); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + free(tempDstBuffer); +} + +GLfloat OGLFilter::GetScale() +{ + return this->_scale; +} + +void OGLFilter::SetScaleOGL(GLfloat scale) +{ + this->_scale = scale; + this->_dstWidth = this->_srcWidth * this->_scale; + this->_dstHeight = this->_srcHeight * this->_scale; + + uint32_t *tempDstBuffer = (uint32_t *)calloc(this->_dstWidth * this->_dstHeight, sizeof(uint32_t)); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDstID); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_dstWidth, this->_dstHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, tempDstBuffer); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + free(tempDstBuffer); +} + +GLuint OGLFilter::RunFilterOGL(GLuint srcTexID, GLsizei viewportWidth, GLsizei viewportHeight) +{ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->_fboID); + glBindVertexArrayAPPLE(this->_vaoID); + glUseProgram(this->_program->GetProgramID()); + glViewport(0, 0, this->_dstWidth, this->_dstHeight); + + glClear(GL_COLOR_BUFFER_BIT); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexID); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + + glBindVertexArrayAPPLE(0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glViewport(0, 0, viewportWidth, viewportHeight); + + return this->GetDstTexID(); +} + +void OGLFilter::DownloadDstBufferOGL(uint32_t *dstBuffer, size_t lineOffset, size_t readLineCount) +{ + if (dstBuffer == NULL) + { + return; + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->_fboID); + glReadPixels(0, lineOffset, this->_dstWidth, readLineCount, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, dstBuffer); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +} + +#pragma mark - + +OGLFilterDeposterize::OGLFilterDeposterize(GLsizei srcWidth, GLsizei srcHeight) +{ + SetSrcSizeOGL(srcWidth, srcHeight); + + glGenTextures(1, &_texIntermediateID); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texIntermediateID); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, _dstWidth, _dstHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + + _program->SetVertexShaderOGL(Sample3x3_VertShader_110); + _program->SetFragmentShaderOGL(FilterDeposterizeFragShader_110); +} + +OGLFilterDeposterize::~OGLFilterDeposterize() +{ + glDeleteTextures(1, &this->_texIntermediateID); +} + +GLuint OGLFilterDeposterize::RunFilterOGL(GLuint srcTexID, GLsizei viewportWidth, GLsizei viewportHeight) +{ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->_fboID); + glBindVertexArrayAPPLE(this->_vaoID); + glUseProgram(this->_program->GetProgramID()); + glViewport(0, 0, this->_dstWidth, this->_dstHeight); + + glClear(GL_COLOR_BUFFER_BIT); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, this->_texIntermediateID, 0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexID); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, this->_texDstID, 0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texIntermediateID); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + + glBindVertexArrayAPPLE(0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glViewport(0, 0, viewportWidth, viewportHeight); + + return this->GetDstTexID(); +} + +#pragma mark - + +OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO) +{ + _output = oglVO; + _needUploadVertices = true; + _useDeposterize = false; + _displayMode = DS_DISPLAY_TYPE_DUAL; _displayOrder = DS_DISPLAY_ORDER_MAIN_FIRST; _displayOrientation = DS_DISPLAY_ORIENTATION_VERTICAL; - _rotation = 0.0f; - _displayTexFilter = GL_NEAREST; - _glTexBackWidth = GetNearestPositivePOT((uint32_t)_normalWidth); - _glTexBackHeight = GetNearestPositivePOT((uint32_t)_normalHeight); - _glTexBack = (GLvoid *)calloc(_glTexBackWidth * _glTexBackHeight, sizeof(uint32_t)); + _normalWidth = GPU_DISPLAY_WIDTH; + _normalHeight = GPU_DISPLAY_HEIGHT*2.0 + (DS_DISPLAY_GAP*_gapScalar); + _rotation = 0.0f; _vfSingle = new VideoFilter(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, VideoFilterTypeID_None, 0); _vfDual = new VideoFilter(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT*2, VideoFilterTypeID_None, 2); _vf = _vfDual; - UpdateVertices(); - UpdateTexCoords(1.0f, 2.0f); + _displayTexFilter = GL_NEAREST; + _glTexBackWidth = _normalWidth; + _glTexBackHeight = _normalHeight; + _vtxBufferOffset = 0; - - // Set up initial vertex elements - vtxIndexBuffer[0] = 0; vtxIndexBuffer[1] = 1; vtxIndexBuffer[2] = 2; - vtxIndexBuffer[3] = 2; vtxIndexBuffer[4] = 3; vtxIndexBuffer[5] = 0; - - vtxIndexBuffer[6] = 4; vtxIndexBuffer[7] = 5; vtxIndexBuffer[8] = 6; - vtxIndexBuffer[9] = 6; vtxIndexBuffer[10] = 7; vtxIndexBuffer[11] = 4; -} - -OGLVideoOutput::~OGLVideoOutput() -{ - free(_glTexBack); - delete _vfSingle; - delete _vfDual; - _vf = NULL; -} - -void OGLVideoOutput::InitializeOGL() -{ - // Check the OpenGL capabilities for this renderer - std::set oglExtensionSet; - GetExtensionSetOGL(&oglExtensionSet); + UpdateVertices(); + UpdateTexCoords(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT * 2); // Set up textures - glGenTextures(1, &this->_displayTexID); - glBindTexture(GL_TEXTURE_2D, this->_displayTexID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glBindTexture(GL_TEXTURE_2D, 0); + glGenTextures(1, &_texCPUFilterDstID); + glGenTextures(1, &_texInputVideoDataID); + _texOutputVideoDataID = _texInputVideoDataID; + _texPrevOutputVideoDataID = _texInputVideoDataID; - // Set up shaders (but disable on PowerPC, since it doesn't seem to work there) -#if defined(__i386__) || defined(__x86_64__) - _isShaderSupported = IsExtensionPresent(oglExtensionSet, "GL_ARB_shader_objects") && - IsExtensionPresent(oglExtensionSet, "GL_ARB_vertex_shader") && - IsExtensionPresent(oglExtensionSet, "GL_ARB_fragment_shader") && - IsExtensionPresent(oglExtensionSet, "GL_ARB_vertex_program"); -#else - this->_isShaderSupported = false; -#endif - if (this->_isShaderSupported) - { - bool isShaderSetUp = SetupShadersOGL(vertexProgram_100, fragmentProgram_100); - if (isShaderSetUp) - { - glUseProgram(this->_shaderProgram); - - this->_uniformAngleDegrees = glGetUniformLocation(this->_shaderProgram, "angleDegrees"); - this->_uniformScalar = glGetUniformLocation(this->_shaderProgram, "scalar"); - this->_uniformViewSize = glGetUniformLocation(this->_shaderProgram, "viewSize"); - - glUniform1f(this->_uniformAngleDegrees, 0.0f); - glUniform1f(this->_uniformScalar, 1.0f); - glUniform2f(this->_uniformViewSize, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT*2.0 + (DS_DISPLAY_GAP*this->_gapScalar)); - } - else - { - this->_isShaderSupported = false; - } - } + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texCPUFilterDstID); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texInputVideoDataID); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + GLvoid *emptyTex = calloc(GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT * 2, sizeof(uint32_t)); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT * 2, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, emptyTex); + free(emptyTex); + emptyTex = NULL; + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); // Set up VBOs glGenBuffersARB(1, &this->_vboVertexID); @@ -164,14 +1788,14 @@ void OGLVideoOutput::InitializeOGL() glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->_vboElementID); - glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(GLubyte) * 12, this->vtxIndexBuffer, GL_STATIC_DRAW_ARB); + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(GLubyte) * 12, outputElementBuffer, GL_STATIC_DRAW_ARB); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); // Set up VAO glGenVertexArraysAPPLE(1, &this->_vaoMainStatesID); glBindVertexArrayAPPLE(this->_vaoMainStatesID); - if (this->_isShaderSupported) + if (this->_output->GetInfo()->IsShaderSupported()) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboVertexID); glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_INT, GL_FALSE, 0, 0); @@ -196,116 +1820,153 @@ void OGLVideoOutput::InitializeOGL() glBindVertexArrayAPPLE(0); - // Render State Setup (common to both shaders and fixed-function pipeline) - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDisable(GL_DITHER); - glDisable(GL_STENCIL_TEST); - - // Set up fixed-function pipeline render states. - if (!_isShaderSupported) + _canUseShaderOutput = this->_output->GetInfo()->IsShaderSupported(); + if (_canUseShaderOutput) { - glDisable(GL_ALPHA_TEST); - glDisable(GL_LIGHTING); - glDisable(GL_FOG); - glEnable(GL_TEXTURE_2D); + _finalOutputProgram = new OGLShaderProgram; + _finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110); + + const GLuint finalOutputProgramID = _finalOutputProgram->GetProgramID(); + glUseProgram(finalOutputProgramID); + _uniformFinalOutputAngleDegrees = glGetUniformLocation(finalOutputProgramID, "angleDegrees"); + _uniformFinalOutputScalar = glGetUniformLocation(finalOutputProgramID, "scalar"); + _uniformFinalOutputViewSize = glGetUniformLocation(finalOutputProgramID, "viewSize"); + glUseProgram(0); + } + else + { + _finalOutputProgram = NULL; } - // Set up clear attributes - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); + _canUseShaderBasedFilters = (_canUseShaderOutput && _output->GetInfo()->IsFBOSupported()); + if (_canUseShaderBasedFilters) + { + _filterDeposterize = new OGLFilterDeposterize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT * 2); + + _shaderFilter = new OGLFilter(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT * 2, 1); + OGLShaderProgram *shaderFilterProgram = _shaderFilter->GetProgram(); + shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110); + } + else + { + _filterDeposterize = NULL; + _shaderFilter = NULL; + } + + _useShaderBasedPixelScaler = false; + _filtersPreferGPU = true; + _outputFilter = OutputFilterTypeID_Bilinear; } -void OGLVideoOutput::TerminateOGL() +OGLDisplayLayer::~OGLDisplayLayer() { - glDeleteTextures(1, &this->_displayTexID); - glDeleteVertexArraysAPPLE(1, &this->_vaoMainStatesID); glDeleteBuffersARB(1, &this->_vboVertexID); glDeleteBuffersARB(1, &this->_vboTexCoordID); glDeleteBuffersARB(1, &this->_vboElementID); + glDeleteTextures(1, &this->_texCPUFilterDstID); + glDeleteTextures(1, &this->_texInputVideoDataID); - if (this->_isShaderSupported) + if (_canUseShaderOutput) { glUseProgram(0); - - glDetachShader(this->_shaderProgram, this->_vertexShaderID); - glDetachShader(this->_shaderProgram, this->_fragmentShaderID); - - glDeleteProgram(this->_shaderProgram); - glDeleteShader(this->_vertexShaderID); - glDeleteShader(this->_fragmentShaderID); + delete this->_finalOutputProgram; } + + if (_canUseShaderBasedFilters) + { + delete this->_filterDeposterize; + delete this->_shaderFilter; + } + + delete this->_vfSingle; + delete this->_vfDual; } -int OGLVideoOutput::GetDisplayMode() +bool OGLDisplayLayer::GetFiltersPreferGPU() +{ + return this->_filtersPreferGPU; +} + +void OGLDisplayLayer::SetFiltersPreferGPUOGL(bool preferGPU) +{ + this->_filtersPreferGPU = preferGPU; + this->SetPixelScalerOGL(this->_pixelScaler); +} + +int OGLDisplayLayer::GetMode() { return this->_displayMode; } -void OGLVideoOutput::SetDisplayMode(int dispMode) +void OGLDisplayLayer::SetMode(int dispMode) { this->_displayMode = dispMode; this->_vf = (dispMode == DS_DISPLAY_TYPE_DUAL) ? this->_vfDual : this->_vfSingle; - this->CalculateDisplayNormalSize(&this->_normalWidth, &this->_normalHeight); + this->GetNormalSize(&this->_normalWidth, &this->_normalHeight); this->UpdateVertices(); } -int OGLVideoOutput::GetDisplayOrientation() +int OGLDisplayLayer::GetOrientation() { return this->_displayOrientation; } -void OGLVideoOutput::SetDisplayOrientation(int dispOrientation) +void OGLDisplayLayer::SetOrientation(int dispOrientation) { this->_displayOrientation = dispOrientation; - this->CalculateDisplayNormalSize(&this->_normalWidth, &this->_normalHeight); + this->GetNormalSize(&this->_normalWidth, &this->_normalHeight); this->UpdateVertices(); } -GLfloat OGLVideoOutput::GetGapScalar() +GLfloat OGLDisplayLayer::GetGapScalar() { return this->_gapScalar; } -void OGLVideoOutput::SetGapScalar(GLfloat theScalar) +void OGLDisplayLayer::SetGapScalar(GLfloat theScalar) { this->_gapScalar = theScalar; - this->CalculateDisplayNormalSize(&this->_normalWidth, &this->_normalHeight); + this->GetNormalSize(&this->_normalWidth, &this->_normalHeight); this->UpdateVertices(); } -GLfloat OGLVideoOutput::GetRotation() +GLfloat OGLDisplayLayer::GetRotation() { return this->_rotation; } -void OGLVideoOutput::SetRotation(GLfloat theRotation) +void OGLDisplayLayer::SetRotation(GLfloat theRotation) { this->_rotation = theRotation; } -bool OGLVideoOutput::GetDisplayBilinear() +bool OGLDisplayLayer::GetBilinear() { return (this->_displayTexFilter == GL_LINEAR); } -void OGLVideoOutput::SetDisplayBilinearOGL(bool useBilinear) +void OGLDisplayLayer::SetBilinear(bool useBilinear) { this->_displayTexFilter = (useBilinear) ? GL_LINEAR : GL_NEAREST; - - glBindTexture(GL_TEXTURE_2D, this->_displayTexID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter); - glBindTexture(GL_TEXTURE_2D, 0); } -int OGLVideoOutput::GetDisplayOrder() +bool OGLDisplayLayer::GetSourceDeposterize() +{ + return this->_useDeposterize; +} + +void OGLDisplayLayer::SetSourceDeposterize(bool useDeposterize) +{ + this->_useDeposterize = useDeposterize; +} + +int OGLDisplayLayer::GetOrder() { return this->_displayOrder; } -void OGLVideoOutput::SetDisplayOrder(int dispOrder) +void OGLDisplayLayer::SetOrder(int dispOrder) { this->_displayOrder = dispOrder; @@ -317,254 +1978,11 @@ void OGLVideoOutput::SetDisplayOrder(int dispOrder) { this->_vtxBufferOffset = (2 * 8); } + + this->_needUploadVertices = true; } -void OGLVideoOutput::SetViewportSizeOGL(GLsizei w, GLsizei h) -{ - this->_viewportWidth = w; - this->_viewportHeight = h; - const CGSize checkSize = GetTransformedBounds(this->_normalWidth, this->_normalHeight, 1.0, this->_rotation); - const GLdouble s = GetMaxScalarInBounds(checkSize.width, checkSize.height, w, h); - - glViewport(0, 0, w, h); - - if (this->_isShaderSupported) - { - glUniform2f(this->_uniformViewSize, w, h); - glUniform1f(this->_uniformScalar, s); - } - else - { - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(-w/2, -w/2 + w, -h/2, -h/2 + h, -1.0, 1.0); - glRotatef(CLOCKWISE_DEGREES(this->_rotation), 0.0f, 0.0f, 1.0f); - glScalef(s, s, 1.0f); - } -} - -void OGLVideoOutput::UpdateDisplayTransformationOGL() -{ - const CGSize checkSize = GetTransformedBounds(this->_normalWidth, this->_normalHeight, 1.0, this->_rotation); - const GLdouble s = GetMaxScalarInBounds(checkSize.width, checkSize.height, this->_viewportWidth, this->_viewportHeight); - - if (this->_isShaderSupported) - { - glUniform1f(this->_uniformAngleDegrees, this->_rotation); - glUniform1f(this->_uniformScalar, s); - } - else - { - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glRotatef(CLOCKWISE_DEGREES(this->_rotation), 0.0f, 0.0f, 1.0f); - glScalef(s, s, 1.0f); - } -} - -void OGLVideoOutput::SetVideoFilterOGL(const VideoFilterTypeID videoFilterTypeID) -{ - this->_vfSingle->ChangeFilterByID(videoFilterTypeID); - this->_vfDual->ChangeFilterByID(videoFilterTypeID); - - const GLsizei vfDstWidth = this->_vf->GetDstWidth(); - const GLsizei vfDstHeight = (this->_displayMode == DS_DISPLAY_TYPE_DUAL) ? this->_vf->GetDstHeight() : this->_vf->GetDstHeight() * 2; - - // Convert textures to Power-of-Two to support older GPUs - // Example: Radeon X1600M on the 2006 MacBook Pro - const GLsizei potW = GetNearestPositivePOT((uint32_t)vfDstWidth); - const GLsizei potH = GetNearestPositivePOT((uint32_t)vfDstHeight); - const size_t texBackSize = potW * potH * sizeof(uint32_t); - - if (this->_glTexBackWidth != potW || this->_glTexBackHeight != potH) - { - this->_glTexBackWidth = potW; - this->_glTexBackHeight = potH; - - this->_glTexBack = (GLvoid *)realloc(this->_glTexBack, texBackSize); - if (this->_glTexBack == NULL) - { - return; - } - } - - memset(this->_glTexBack, 0, texBackSize); - - const GLfloat s = (GLfloat)vfDstWidth / (GLfloat)potW; - const GLfloat t = (GLfloat)vfDstHeight / (GLfloat)potH; - this->UpdateTexCoords(s, t); - - glBindTexture(GL_TEXTURE_2D, this->_displayTexID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)potW, (GLsizei)potH, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_glTexBack); - glBindTexture(GL_TEXTURE_2D, 0); - this->UploadTexCoordsOGL(); -} - -void OGLVideoOutput::CalculateDisplayNormalSize(double *w, double *h) -{ - if (w == NULL || h == NULL) - { - return; - } - - if (this->_displayMode != DS_DISPLAY_TYPE_DUAL) - { - *w = GPU_DISPLAY_WIDTH; - *h = GPU_DISPLAY_HEIGHT; - return; - } - - if (this->_displayOrientation == DS_DISPLAY_ORIENTATION_VERTICAL) - { - *w = GPU_DISPLAY_WIDTH; - *h = GPU_DISPLAY_HEIGHT * 2.0 + (DS_DISPLAY_GAP * this->_gapScalar); - } - else - { - *w = GPU_DISPLAY_WIDTH * 2.0 + (DS_DISPLAY_GAP * this->_gapScalar); - *h = GPU_DISPLAY_HEIGHT; - } -} - -void OGLVideoOutput::GetExtensionSetOGL(std::set *oglExtensionSet) -{ - std::string oglExtensionString = std::string((const char *)glGetString(GL_EXTENSIONS)); - - size_t extStringStartLoc = 0; - size_t delimiterLoc = oglExtensionString.find_first_of(' ', extStringStartLoc); - while (delimiterLoc != std::string::npos) - { - std::string extensionName = oglExtensionString.substr(extStringStartLoc, delimiterLoc - extStringStartLoc); - oglExtensionSet->insert(extensionName); - - extStringStartLoc = delimiterLoc + 1; - delimiterLoc = oglExtensionString.find_first_of(' ', extStringStartLoc); - } - - if (extStringStartLoc - oglExtensionString.length() > 0) - { - std::string extensionName = oglExtensionString.substr(extStringStartLoc, oglExtensionString.length() - extStringStartLoc); - oglExtensionSet->insert(extensionName); - } -} - -bool OGLVideoOutput::IsExtensionPresent(const std::set &oglExtensionSet, const std::string &extensionName) const -{ - if (oglExtensionSet.size() == 0) - { - return false; - } - - return (oglExtensionSet.find(extensionName) != oglExtensionSet.end()); -} - -bool OGLVideoOutput::SetupShadersOGL(const char *vertexProgram, const char *fragmentProgram) -{ - bool result = false; - GLint shaderStatus = GL_TRUE; - - this->_vertexShaderID = glCreateShader(GL_VERTEX_SHADER); - if (this->_vertexShaderID == 0) - { - printf("OpenGL Error - Failed to create vertex shader."); - return result; - } - - glShaderSource(this->_vertexShaderID, 1, (const GLchar **)&vertexProgram, NULL); - glCompileShader(this->_vertexShaderID); - glGetShaderiv(this->_vertexShaderID, GL_COMPILE_STATUS, &shaderStatus); - if (shaderStatus == GL_FALSE) - { - glDeleteShader(this->_vertexShaderID); - printf("OpenGL Error - Failed to compile vertex shader."); - return result; - } - - this->_fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); - if (this->_fragmentShaderID == 0) - { - glDeleteShader(this->_vertexShaderID); - printf("OpenGL Error - Failed to create fragment shader."); - return result; - } - - glShaderSource(this->_fragmentShaderID, 1, (const GLchar **)&fragmentProgram, NULL); - glCompileShader(this->_fragmentShaderID); - glGetShaderiv(this->_fragmentShaderID, GL_COMPILE_STATUS, &shaderStatus); - if (shaderStatus == GL_FALSE) - { - glDeleteShader(this->_vertexShaderID); - glDeleteShader(this->_fragmentShaderID); - printf("OpenGL Error - Failed to compile fragment shader."); - return result; - } - - this->_shaderProgram = glCreateProgram(); - if (this->_shaderProgram == 0) - { - glDeleteShader(this->_vertexShaderID); - glDeleteShader(this->_fragmentShaderID); - printf("OpenGL Error - Failed to create shader program."); - return result; - } - - glAttachShader(this->_shaderProgram, this->_vertexShaderID); - glAttachShader(this->_shaderProgram, this->_fragmentShaderID); - - this->SetupShaderIO_OGL(); - - glLinkProgram(this->_shaderProgram); - glGetProgramiv(this->_shaderProgram, GL_LINK_STATUS, &shaderStatus); - if (shaderStatus == GL_FALSE) - { - glDeleteProgram(this->_shaderProgram); - glDeleteShader(this->_vertexShaderID); - glDeleteShader(this->_fragmentShaderID); - printf("OpenGL Error - Failed to link shader program."); - return result; - } - - glValidateProgram(this->_shaderProgram); - - result = true; - return result; -} - -void OGLVideoOutput::SetupShaderIO_OGL() -{ - glBindAttribLocation(this->_shaderProgram, OGLVertexAttributeID_Position, "inPosition"); - glBindAttribLocation(this->_shaderProgram, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); -} - -void OGLVideoOutput::UploadVerticesOGL() -{ - glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboVertexID); - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(GLint) * (2 * 8), this->vtxBuffer + this->_vtxBufferOffset); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); -} - -void OGLVideoOutput::UploadTexCoordsOGL() -{ - glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboTexCoordID); - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(GLfloat) * (2 * 8), this->texCoordBuffer); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); -} - -void OGLVideoOutput::UploadDisplayTextureOGL(const GLvoid *textureData, const GLenum texPixelFormat, const GLenum texPixelType, GLsizei texWidth, GLsizei texHeight) -{ - if (textureData == NULL) - { - return; - } - - const GLint lineOffset = (this->_displayMode == DS_DISPLAY_TYPE_TOUCH) ? texHeight : 0; - - glBindTexture(GL_TEXTURE_2D, this->_displayTexID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lineOffset, texWidth, texHeight, texPixelFormat, texPixelType, textureData); - glBindTexture(GL_TEXTURE_2D, 0); -} - -void OGLVideoOutput::UpdateVertices() +void OGLDisplayLayer::UpdateVertices() { const GLfloat w = GPU_DISPLAY_WIDTH; const GLfloat h = GPU_DISPLAY_HEIGHT; @@ -612,9 +2030,11 @@ void OGLVideoOutput::UpdateVertices() memcpy(vtxBuffer + (1 * 8), vtxBuffer + (0 * 8), sizeof(GLint) * (1 * 8)); // Second display memcpy(vtxBuffer + (2 * 8), vtxBuffer + (0 * 8), sizeof(GLint) * (2 * 8)); // Second display } + + this->_needUploadVertices = true; } -void OGLVideoOutput::UpdateTexCoords(GLfloat s, GLfloat t) +void OGLDisplayLayer::UpdateTexCoords(GLfloat s, GLfloat t) { texCoordBuffer[0] = 0.0f; texCoordBuffer[1] = 0.0f; texCoordBuffer[2] = s; texCoordBuffer[3] = 0.0f; @@ -627,36 +2047,326 @@ void OGLVideoOutput::UpdateTexCoords(GLfloat s, GLfloat t) texCoordBuffer[14] = 0.0f; texCoordBuffer[15] = t; } -void OGLVideoOutput::PrerenderOGL(const GLvoid *textureData, GLsizei texWidth, GLsizei texHeight) +bool OGLDisplayLayer::CanUseShaderBasedFilters() { - GLenum texPixelFormat = GL_RGBA; - GLenum texPixelType = GL_UNSIGNED_SHORT_1_5_5_5_REV; - uint32_t *vfTextureData = (uint32_t *)textureData; - - VideoFilter *currentFilter = this->_vf; - if (currentFilter->GetTypeID() != VideoFilterTypeID_None) + return this->_canUseShaderBasedFilters; +} + +void OGLDisplayLayer::GetNormalSize(double *w, double *h) +{ + if (w == NULL || h == NULL) { - if (texPixelType == GL_UNSIGNED_SHORT_1_5_5_5_REV) + return; + } + + if (this->_displayMode != DS_DISPLAY_TYPE_DUAL) + { + *w = GPU_DISPLAY_WIDTH; + *h = GPU_DISPLAY_HEIGHT; + return; + } + + if (this->_displayOrientation == DS_DISPLAY_ORIENTATION_VERTICAL) + { + *w = GPU_DISPLAY_WIDTH; + *h = GPU_DISPLAY_HEIGHT * 2.0 + (DS_DISPLAY_GAP * this->_gapScalar); + } + else + { + *w = GPU_DISPLAY_WIDTH * 2.0 + (DS_DISPLAY_GAP * this->_gapScalar); + *h = GPU_DISPLAY_HEIGHT; + } +} + +void OGLDisplayLayer::UploadVerticesOGL() +{ + glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboVertexID); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(GLint) * (2 * 8), this->vtxBuffer + this->_vtxBufferOffset); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + this->_needUploadVertices = false; +} + +void OGLDisplayLayer::UploadTexCoordsOGL() +{ + glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboTexCoordID); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(GLfloat) * (2 * 8), this->texCoordBuffer); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); +} + +void OGLDisplayLayer::UploadTransformationOGL() +{ + const double w = this->_viewportWidth; + const double h = this->_viewportHeight; + const CGSize checkSize = GetTransformedBounds(this->_normalWidth, this->_normalHeight, 1.0, this->_rotation); + const GLdouble s = GetMaxScalarInBounds(checkSize.width, checkSize.height, w, h); + + if (this->_output->GetInfo()->IsShaderSupported()) + { + glUniform2f(this->_uniformFinalOutputViewSize, w, h); + glUniform1f(this->_uniformFinalOutputAngleDegrees, this->_rotation); + glUniform1f(this->_uniformFinalOutputScalar, s); + } + else + { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-w/2.0, -w/2.0 + w, -h/2.0, -h/2.0 + h, -1.0, 1.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glRotatef(CLOCKWISE_DEGREES(this->_rotation), 0.0f, 0.0f, 1.0f); + glScalef(s, s, 1.0f); + } +} + +int OGLDisplayLayer::GetOutputFilter() +{ + return this->_outputFilter; +} + +void OGLDisplayLayer::SetOutputFilterOGL(const int filterID) +{ + this->_displayTexFilter = GL_NEAREST; + + if (this->_canUseShaderBasedFilters) + { + this->_outputFilter = filterID; + + switch (filterID) { - RGB555ToBGRA8888Buffer((const uint16_t *)vfTextureData, (uint32_t *)currentFilter->GetSrcBufferPtr(), texWidth * texHeight); - texPixelFormat = GL_BGRA; - texPixelType = GL_UNSIGNED_INT_8_8_8_8_REV; + case OutputFilterTypeID_NearestNeighbor: + this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110); + break; + + case OutputFilterTypeID_Bilinear: + this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110); + this->_displayTexFilter = GL_LINEAR; + break; + + case OutputFilterTypeID_BicubicBSpline: + this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterBicubicBSplineFragShader_110); + break; + + case OutputFilterTypeID_BicubicMitchell: + this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterBicubicMitchellNetravaliFragShader_110); + break; + + case OutputFilterTypeID_Lanczos2: + this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterLanczos2FragShader_110); + break; + + case OutputFilterTypeID_Lanczos3: + this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, FilterLanczos3FragShader_110); + break; + + default: + this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110); + this->_outputFilter = OutputFilterTypeID_NearestNeighbor; + break; + } + } + else + { + if (filterID == OutputFilterTypeID_Bilinear) + { + this->_displayTexFilter = GL_LINEAR; + this->_outputFilter = filterID; } else { - memcpy(currentFilter->GetSrcBufferPtr(), vfTextureData, texWidth * texHeight * sizeof(uint32_t)); + this->_outputFilter = OutputFilterTypeID_NearestNeighbor; } - - vfTextureData = currentFilter->RunFilter(); - texWidth = currentFilter->GetDstWidth(); - texHeight = currentFilter->GetDstHeight(); } - - this->UploadDisplayTextureOGL(vfTextureData, texPixelFormat, texPixelType, texWidth, texHeight); } -void OGLVideoOutput::RenderOGL() +int OGLDisplayLayer::GetPixelScaler() { + return this->_pixelScaler; +} + +void OGLDisplayLayer::SetPixelScalerOGL(const int filterID) +{ + if (this->_canUseShaderBasedFilters && this->_filtersPreferGPU) // Try a shader-based filter first + { + OGLShaderProgram *shaderFilterProgram = _shaderFilter->GetProgram(); + this->_useShaderBasedPixelScaler = true; + this->_pixelScaler = filterID; + + VideoFilterAttributes vfAttr = VideoFilter::GetAttributesByID((VideoFilterTypeID)filterID); + GLfloat vfScale = (GLfloat)vfAttr.scaleMultiply / (GLfloat)vfAttr.scaleDivide; + + switch (filterID) + { + case VideoFilterTypeID_Nearest1_5X: + shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110); + break; + + case VideoFilterTypeID_Nearest2X: + shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110); + break; + + case VideoFilterTypeID_Scanline: + shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, Scalar2xScanlineFragShader_110); + break; + + case VideoFilterTypeID_EPX: + shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, Scalar2xEPXFragShader_110); + break; + + case VideoFilterTypeID_EPXPlus: + shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, Scalar2xEPXPlusFragShader_110); + break; + + case VideoFilterTypeID_2xSaI: + shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scalar2xSaIFragShader_110); + break; + + case VideoFilterTypeID_Super2xSaI: + shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, ScalarSuper2xSaIFragShader_110); + break; + + case VideoFilterTypeID_SuperEagle: + shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, ScalarSuperEagle2xFragShader_110); + break; + + default: + shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110); + this->_useShaderBasedPixelScaler = false; + this->_pixelScaler = VideoFilterTypeID_None; + vfScale = 1.0f; + break; + } + + _shaderFilter->SetScaleOGL(vfScale); + } + else + { + this->_useShaderBasedPixelScaler = false; + } + + if (!this->_useShaderBasedPixelScaler) // Try a CPU-based filter, or just set to None + { + const char *cpuTypeIDString = VideoFilter::GetTypeStringByID((VideoFilterTypeID)filterID); + if (strstr(cpuTypeIDString, VIDEOFILTERTYPE_UNKNOWN_STRING) == NULL) + { + this->SetCPUFilterOGL((VideoFilterTypeID)filterID); + this->_pixelScaler = filterID; + } + else + { + this->SetCPUFilterOGL(VideoFilterTypeID_None); + this->_pixelScaler = VideoFilterTypeID_None; + } + } +} + +void OGLDisplayLayer::SetCPUFilterOGL(const VideoFilterTypeID videoFilterTypeID) +{ + bool needResizeTexture = false; + this->_vfSingle->ChangeFilterByID(videoFilterTypeID); + this->_vfDual->ChangeFilterByID(videoFilterTypeID); + + const GLsizei vfDstWidth = this->_vf->GetDstWidth(); + const GLsizei vfDstHeight = (this->_displayMode == DS_DISPLAY_TYPE_DUAL) ? this->_vf->GetDstHeight() : this->_vf->GetDstHeight() * 2; + + if (this->_glTexBackWidth != vfDstWidth || this->_glTexBackHeight != vfDstHeight) + { + this->_glTexBackWidth = vfDstWidth; + this->_glTexBackHeight = vfDstHeight; + needResizeTexture = true; + } + + if (needResizeTexture) + { + uint32_t *texBack = (uint32_t *)calloc(this->_glTexBackWidth * this->_glTexBackHeight, sizeof(uint32_t)); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, vfDstWidth, vfDstHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, texBack); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + free(texBack); + } +} + +void OGLDisplayLayer::ProcessOGL(const uint16_t *videoData, GLsizei w, GLsizei h) +{ + VideoFilter *currentFilter = this->_vf; + GLint lineOffset = (this->_displayMode == DS_DISPLAY_TYPE_TOUCH) ? h : 0; + + // Determine whether we should take CPU-based path or a GPU-based path + if ((currentFilter->GetTypeID() != VideoFilterTypeID_None) && !this->_useShaderBasedPixelScaler) + { + if (!(this->_canUseShaderBasedFilters && this->_useDeposterize)) // Pure CPU-based path + { + RGB555ToBGRA8888Buffer((const uint16_t *)videoData, (uint32_t *)currentFilter->GetSrcBufferPtr(), w * h); + } + else // Hybrid CPU/GPU-based path (may cause a performance hit on pixel download) + { + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texInputVideoDataID); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, lineOffset, w, h, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, videoData); + + this->_filterDeposterize->RunFilterOGL(this->_texInputVideoDataID, this->_viewportWidth, this->_viewportHeight); + + const GLsizei readLineCount = (this->_displayMode == DS_DISPLAY_TYPE_DUAL) ? GPU_DISPLAY_HEIGHT * 2 : GPU_DISPLAY_HEIGHT; + this->_filterDeposterize->DownloadDstBufferOGL(currentFilter->GetSrcBufferPtr(), lineOffset, readLineCount); + } + + uint32_t *texData = currentFilter->RunFilter(); + w = currentFilter->GetDstWidth(); + h = currentFilter->GetDstHeight(); + lineOffset = (this->_displayMode == DS_DISPLAY_TYPE_TOUCH) ? h : 0; + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, lineOffset, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, texData); + + this->_texOutputVideoDataID = this->_texCPUFilterDstID; + this->UpdateTexCoords(w, (this->_displayMode == DS_DISPLAY_TYPE_DUAL) ? h : h*2); + } + else // Pure GPU-based path + { + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texInputVideoDataID); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, lineOffset, w, h, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, videoData); + + if (this->_canUseShaderBasedFilters && this->_useDeposterize) + { + this->_texOutputVideoDataID = this->_filterDeposterize->RunFilterOGL(this->_texInputVideoDataID, this->_viewportWidth, this->_viewportHeight); + } + else + { + this->_texOutputVideoDataID = this->_texInputVideoDataID; + } + + if (this->_displayMode != DS_DISPLAY_TYPE_DUAL) + { + h *= 2; + } + + if (this->_useShaderBasedPixelScaler) + { + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texOutputVideoDataID); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + this->_texOutputVideoDataID = this->_shaderFilter->RunFilterOGL(this->_texOutputVideoDataID, this->_viewportWidth, this->_viewportHeight); + w = this->_shaderFilter->GetDstWidth(); + h = this->_shaderFilter->GetDstHeight(); + } + + this->UpdateTexCoords(w, h); + } + + this->UploadTexCoordsOGL(); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); +} + +void OGLDisplayLayer::RenderOGL() +{ + glUseProgram(this->_finalOutputProgram->GetProgramID()); + this->UploadTransformationOGL(); + + if (_needUploadVertices) + { + this->UploadVerticesOGL(); + } + // Enable vertex attributes glBindVertexArrayAPPLE(this->_vaoMainStatesID); @@ -664,9 +2374,11 @@ void OGLVideoOutput::RenderOGL() const GLubyte *elementPointer = !(this->_displayMode == DS_DISPLAY_TYPE_TOUCH) ? 0 : (GLubyte *)(vtxElementCount * sizeof(GLubyte)); glClear(GL_COLOR_BUFFER_BIT); - glBindTexture(GL_TEXTURE_2D, this->_displayTexID); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texOutputVideoDataID); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter); glDrawElements(GL_TRIANGLES, vtxElementCount, GL_UNSIGNED_BYTE, elementPointer); - glBindTexture(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); // Disable vertex attributes glBindVertexArrayAPPLE(0); diff --git a/desmume/src/cocoa/OGLDisplayOutput.h b/desmume/src/cocoa/OGLDisplayOutput.h index 26e5e9c02..10544c5b2 100644 --- a/desmume/src/cocoa/OGLDisplayOutput.h +++ b/desmume/src/cocoa/OGLDisplayOutput.h @@ -27,87 +27,280 @@ #include #include "../filter/videofilter.h" +class OGLVideoOutput; -class OGLVideoOutput +enum +{ + OutputFilterTypeID_NearestNeighbor = 0, + OutputFilterTypeID_Bilinear = 1, + OutputFilterTypeID_BicubicBSpline = 2, + OutputFilterTypeID_BicubicMitchell = 3, + OutputFilterTypeID_Lanczos2 = 4, + OutputFilterTypeID_Lanczos3 = 5 +}; + +class OGLInfo { protected: + unsigned int _versionMajor; + unsigned int _versionMinor; + unsigned int _versionRevision; + + bool _isVBOSupported; + bool _isPBOSupported; + bool _isShaderSupported; + bool _isFBOSupported; + +public: + OGLInfo(); + virtual ~OGLInfo() {}; + + static OGLInfo* GetVersionedObjectOGL(); + + bool IsVBOSupported(); + bool IsPBOSupported(); + bool IsShaderSupported(); + bool IsFBOSupported(); + + virtual void GetExtensionSetOGL(std::set *oglExtensionSet) = 0; + virtual bool IsExtensionPresent(const std::set &oglExtensionSet, const std::string &extensionName) const = 0; +}; + +class OGLInfo_1_2 : public OGLInfo +{ +public: + OGLInfo_1_2(); + + virtual void GetExtensionSetOGL(std::set *oglExtensionSet); + virtual bool IsExtensionPresent(const std::set &oglExtensionSet, const std::string &extensionName) const; +}; + +class OGLInfo_2_0 : public OGLInfo_1_2 +{ +public: + OGLInfo_2_0(); +}; + +class OGLInfo_2_1 : public OGLInfo_2_0 +{ +public: + OGLInfo_2_1(); +}; + +class OGLInfo_3_2 : public OGLInfo_2_0 +{ +public: + OGLInfo_3_2(); + + virtual void GetExtensionSetOGL(std::set *oglExtensionSet); +}; + +class OGLShaderProgram +{ +protected: + GLuint _vertexID; + GLuint _fragmentID; + GLuint _programID; + + virtual GLuint LoadShaderOGL(GLenum shaderType, const char *shaderProgram); + virtual bool LinkOGL(); + +public: + OGLShaderProgram(); + virtual ~OGLShaderProgram(); + + GLuint GetVertexShaderID(); + void SetVertexShaderOGL(const char *shaderProgram); + GLuint GetFragmentShaderID(); + void SetFragmentShaderOGL(const char *shaderProgram); + void SetVertexAndFragmentShaderOGL(const char *vertShaderProgram, const char *fragShaderProgram); + GLuint GetProgramID(); +}; + +class OGLFilter +{ +private: + void OGLFilterInit(GLsizei srcWidth, GLsizei srcHeight, GLfloat scale); + +protected: + OGLShaderProgram *_program; + GLuint _texDstID; + GLint _texCoordBuffer[8]; + + GLuint _fboID; + GLuint _vaoID; + GLuint _vboVtxID; + GLuint _vboTexCoordID; + GLuint _vboElementID; + + GLfloat _scale; + GLsizei _srcWidth; + GLsizei _srcHeight; + GLsizei _dstWidth; + GLsizei _dstHeight; + +public: + OGLFilter(); + OGLFilter(GLsizei srcWidth, GLsizei srcHeight, GLfloat scale); + virtual ~OGLFilter(); + static void GetSupport(int vfTypeID, bool *outSupportCPU, bool *outSupportShader); + + OGLShaderProgram* GetProgram(); + GLuint GetDstTexID(); + GLsizei GetDstWidth(); + GLsizei GetDstHeight(); + void SetSrcSizeOGL(GLsizei w, GLsizei h); + GLfloat GetScale(); + void SetScaleOGL(GLfloat scale); + virtual GLuint RunFilterOGL(GLuint srcTexID, GLsizei viewportWidth, GLsizei viewportHeight); + void DownloadDstBufferOGL(uint32_t *dstBuffer, size_t lineOffset, size_t readLineCount); +}; + +class OGLFilterDeposterize : public OGLFilter +{ +protected: + GLuint _texIntermediateID; + +public: + OGLFilterDeposterize(GLsizei srcWidth, GLsizei srcHeight); + ~OGLFilterDeposterize(); + + virtual GLuint RunFilterOGL(GLuint srcTexID, GLsizei viewportWidth, GLsizei viewportHeight); +}; + +class OGLVideoLayer +{ +protected: + OGLVideoOutput *_output; + GLsizei _viewportWidth; + GLsizei _viewportHeight; + +public: + OGLVideoLayer() {}; + ~OGLVideoLayer() {}; + + void SetViewportSizeOGL(GLsizei w, GLsizei h) + { + this->_viewportWidth = w; + this->_viewportHeight = h; + }; + + virtual void ProcessOGL(const uint16_t *videoData, GLsizei w, GLsizei h) {}; + virtual void RenderOGL() {}; +}; + +class OGLDisplayLayer : public OGLVideoLayer +{ +protected: + bool _canUseShaderBasedFilters; + bool _canUseShaderOutput; + + bool _needUploadVertices; + bool _useDeposterize; + bool _useShaderBasedPixelScaler; + bool _filtersPreferGPU; + int _outputFilter; + int _pixelScaler; + + OGLFilterDeposterize *_filterDeposterize; + OGLFilter *_shaderFilter; + OGLShaderProgram *_finalOutputProgram; + VideoFilter *_vfSingle; VideoFilter *_vfDual; VideoFilter *_vf; - bool _isShaderSupported; - double _normalWidth; - double _normalHeight; int _displayMode; int _displayOrder; int _displayOrientation; - - GLint _displayTexFilter; - GLsizei _viewportWidth; - GLsizei _viewportHeight; + double _normalWidth; + double _normalHeight; GLfloat _gapScalar; GLfloat _rotation; - GLvoid *_glTexBack; + GLint _displayTexFilter; + GLuint _texCPUFilterDstID; GLsizei _glTexBackWidth; GLsizei _glTexBackHeight; - GLuint _displayTexID; + GLint vtxBuffer[4 * 8]; + GLfloat texCoordBuffer[2 * 8]; + size_t _vtxBufferOffset; + + GLuint _texInputVideoDataID; + GLuint _texOutputVideoDataID; + GLuint _texPrevOutputVideoDataID; + GLuint _vaoMainStatesID; GLuint _vboVertexID; GLuint _vboTexCoordID; GLuint _vboElementID; - GLuint _vaoMainStatesID; - GLuint _vertexShaderID; - GLuint _fragmentShaderID; - GLuint _shaderProgram; - GLint _uniformAngleDegrees; - GLint _uniformScalar; - GLint _uniformViewSize; + GLint _uniformFinalOutputAngleDegrees; + GLint _uniformFinalOutputScalar; + GLint _uniformFinalOutputViewSize; - GLint vtxBuffer[4 * 8]; - GLfloat texCoordBuffer[2 * 8]; - GLubyte vtxIndexBuffer[12]; - size_t _vtxBufferOffset; + virtual void UploadVerticesOGL(); + virtual void UploadTexCoordsOGL(); + virtual void UploadTransformationOGL(); - void CalculateDisplayNormalSize(double *w, double *h); void UpdateVertices(); void UpdateTexCoords(GLfloat s, GLfloat t); - void GetExtensionSetOGL(std::set *oglExtensionSet); - bool IsExtensionPresent(const std::set &oglExtensionSet, const std::string &extensionName) const; - bool SetupShadersOGL(const char *vertexProgram, const char *fragmentProgram); - void SetupShaderIO_OGL(); +public: + OGLDisplayLayer(OGLVideoOutput *oglVO); + ~OGLDisplayLayer(); + + bool GetFiltersPreferGPU(); + void SetFiltersPreferGPUOGL(bool preferGPU); + + int GetMode(); + void SetMode(int dispMode); + int GetOrientation(); + void SetOrientation(int dispOrientation); + int GetOrder(); + void SetOrder(int dispOrder); + GLfloat GetGapScalar(); + void SetGapScalar(GLfloat theScalar); + GLfloat GetRotation(); + void SetRotation(GLfloat theRotation); + bool GetBilinear(); + void SetBilinear(bool useBilinear); + bool GetSourceDeposterize(); + void SetSourceDeposterize(bool useDeposterize); + + bool CanUseShaderBasedFilters(); + void GetNormalSize(double *w, double *h); + + int GetOutputFilter(); + virtual void SetOutputFilterOGL(const int filterID); + int GetPixelScaler(); + virtual void SetPixelScalerOGL(const int filterID); + virtual void SetCPUFilterOGL(const VideoFilterTypeID videoFilterTypeID); + virtual void ProcessOGL(const uint16_t *videoData, GLsizei w, GLsizei h); + virtual void RenderOGL(); +}; + +class OGLVideoOutput +{ +protected: + OGLInfo *_info; + GLsizei _viewportWidth; + GLsizei _viewportHeight; + std::vector *_layerList; public: OGLVideoOutput(); ~OGLVideoOutput(); - virtual void InitializeOGL(); - virtual void TerminateOGL(); - - virtual void UploadVerticesOGL(); - virtual void UploadTexCoordsOGL(); - virtual void UploadDisplayTextureOGL(const GLvoid *textureData, const GLenum texPixelFormat, const GLenum texPixelType, GLsizei texWidth, GLsizei texHeight); - - virtual void PrerenderOGL(const GLvoid *textureData, GLsizei texWidth, GLsizei texHeight); + virtual void InitLayers(); + virtual OGLInfo* GetInfo(); + virtual GLsizei GetViewportWidth(); + virtual GLsizei GetViewportHeight(); + OGLDisplayLayer* GetDisplayLayer(); + + virtual void ProcessOGL(const uint16_t *videoData, GLsizei w, GLsizei h); virtual void RenderOGL(); virtual void SetViewportSizeOGL(GLsizei w, GLsizei h); - virtual void UpdateDisplayTransformationOGL(); - virtual void SetVideoFilterOGL(const VideoFilterTypeID videoFilterTypeID); - - int GetDisplayMode(); - void SetDisplayMode(int dispMode); - int GetDisplayOrientation(); - void SetDisplayOrientation(int dispOrientation); - GLfloat GetGapScalar(); - void SetGapScalar(GLfloat theScalar); - GLfloat GetRotation(); - void SetRotation(GLfloat theRotation); - bool GetDisplayBilinear(); - void SetDisplayBilinearOGL(bool useBilinear); - int GetDisplayOrder(); - void SetDisplayOrder(int dispOrder); }; #endif // _OGLDISPLAYOUTPUT_H_ diff --git a/desmume/src/cocoa/cocoa_globals.h b/desmume/src/cocoa/cocoa_globals.h index da2856091..b1c608425 100644 --- a/desmume/src/cocoa/cocoa_globals.h +++ b/desmume/src/cocoa/cocoa_globals.h @@ -423,12 +423,12 @@ enum MESSAGE_RESIZE_VIEW, MESSAGE_TRANSFORM_VIEW, MESSAGE_REDRAW_VIEW, + MESSAGE_REPROCESS_AND_REDRAW, MESSAGE_SET_GPU_STATE_FLAGS, MESSAGE_CHANGE_DISPLAY_TYPE, MESSAGE_CHANGE_DISPLAY_ORIENTATION, MESSAGE_CHANGE_DISPLAY_ORDER, MESSAGE_CHANGE_DISPLAY_GAP, - MESSAGE_CHANGE_VIDEO_FILTER, MESSAGE_SET_RENDER3D_METHOD, MESSAGE_SET_RENDER3D_HIGH_PRECISION_COLOR_INTERPOLATION, MESSAGE_SET_RENDER3D_EDGE_MARKING, diff --git a/desmume/src/cocoa/cocoa_output.h b/desmume/src/cocoa/cocoa_output.h index c108b5b3c..b47c27814 100644 --- a/desmume/src/cocoa/cocoa_output.h +++ b/desmume/src/cocoa/cocoa_output.h @@ -135,9 +135,6 @@ typedef struct - (void) doDisplayOrientationChanged:(NSInteger)displayOrientationID; - (void) doDisplayOrderChanged:(NSInteger)displayOrderID; - (void) doDisplayGapChanged:(float)displayGapScalar; -- (void) doBilinearOutputChanged:(BOOL)useBilinear; -- (void) doVerticalSyncChanged:(BOOL)useVerticalSync; -- (void) doVideoFilterChanged:(NSInteger)videoFilterTypeID; @end @@ -176,9 +173,9 @@ typedef struct - (void) handleResizeView:(NSData *)rectData; - (void) handleTransformView:(NSData *)transformData; - (void) handleRedrawView; +- (void) handleReprocessAndRedraw; - (void) handleChangeDisplayOrientation:(NSData *)displayOrientationIdData; - (void) handleChangeDisplayOrder:(NSData *)displayOrderIdData; - (void) handleChangeDisplayGap:(NSData *)displayGapScalarData; -- (void) handleChangeVideoFilter:(NSData *)videoFilterTypeIdData; @end diff --git a/desmume/src/cocoa/cocoa_output.mm b/desmume/src/cocoa/cocoa_output.mm index bf60059c8..60c1f83cb 100644 --- a/desmume/src/cocoa/cocoa_output.mm +++ b/desmume/src/cocoa/cocoa_output.mm @@ -858,6 +858,10 @@ [self handleEmuFrameProcessed:[messageComponents objectAtIndex:0] attributes:[messageComponents objectAtIndex:1]]; break; + case MESSAGE_REPROCESS_AND_REDRAW: + [self handleReprocessAndRedraw]; + break; + case MESSAGE_RESIZE_VIEW: [self handleResizeView:[messageComponents objectAtIndex:0]]; break; @@ -882,10 +886,6 @@ [self handleChangeDisplayGap:[messageComponents objectAtIndex:0]]; break; - case MESSAGE_CHANGE_VIDEO_FILTER: - [self handleChangeVideoFilter:[messageComponents objectAtIndex:0]]; - break; - default: [super handlePortMessage:portMessage]; break; @@ -939,6 +939,11 @@ [(id)delegate doRedraw]; } +- (void) handleReprocessAndRedraw +{ + [self handleEmuFrameProcessed:self.frameData attributes:self.frameAttributesData]; +} + - (void) handleChangeDisplayOrientation:(NSData *)displayOrientationIdData { if (delegate == nil || ![delegate respondsToSelector:@selector(doDisplayOrientationChanged:)]) @@ -972,16 +977,4 @@ [(id)delegate doDisplayGapChanged:gapScalar]; } -- (void) handleChangeVideoFilter:(NSData *)videoFilterTypeIdData -{ - if (delegate == nil || ![delegate respondsToSelector:@selector(doVideoFilterChanged:)]) - { - return; - } - - const NSInteger theType = *(NSInteger *)[videoFilterTypeIdData bytes]; - [(id)delegate doVideoFilterChanged:theType]; - [self handleEmuFrameProcessed:self.frameData attributes:self.frameAttributesData]; -} - @end diff --git a/desmume/src/cocoa/translations/English.lproj/MainMenu.strings b/desmume/src/cocoa/translations/English.lproj/MainMenu.strings index eef8ecd1c0537467a99e2318fea32ca28b2b1899..37d9a843ad398e563a8fc6deaee2c95613749fb4 100644 GIT binary patch delta 6578 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 diff --git a/desmume/src/cocoa/translations/English.lproj/MainMenu.xib b/desmume/src/cocoa/translations/English.lproj/MainMenu.xib index 48eceb2b1..38acabeab 100644 --- a/desmume/src/cocoa/translations/English.lproj/MainMenu.xib +++ b/desmume/src/cocoa/translations/English.lproj/MainMenu.xib @@ -2,18 +2,20 @@ 1050 - 13B42 + 12F45 851 - 1265 - 696.00 + 1187.40 + 626.00 com.apple.InterfaceBuilder.CocoaPlugin 851 YES - - + + + + YES @@ -1258,9 +1260,110 @@ + + + YES + YES + + + 2147483647 + + + + + + Video Source Filters + + 2147483647 + + + submenuAction: + + Video Source Filters + + YES + + + Deposterize + + 2147483647 + + + + + + + + + Video Output Filter + + 2147483647 + + + submenuAction: + + Video Output Filter + + YES + + + Nearest Neighbor + + 2147483647 + + + + + + Bilinear + + 2147483647 + + + 1 + + + + Bicubic (B-Spline) + + 2147483647 + + + 2 + + + + Bicubic (Mitchell-Netravali) + + 2147483647 + + + 3 + + + + Lanczos2 + + 2147483647 + + + 4 + + + + Lanczos3 + + 2147483647 + + + 5 + + + + - Display Video Output + Video Pixel Scaler 2147483647 @@ -1268,53 +1371,9 @@ submenuAction: - Display Video Output + Video Pixel Scaler YES - - - Show Settings... - - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Use Bilinear Filtered Output - - 2147483647 - - - - - - Use Vertical Sync - - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - None @@ -1323,6 +1382,69 @@ + + + Nearest 2x + + 2147483647 + + + 11 + + + + Scanline + + 2147483647 + + + 9 + + + + EPX + + 2147483647 + + + 14 + + + + EPX+ + + 2147483647 + + + 15 + + + + Super Eagle + + 2147483647 + + + 8 + + + + 2xSaI + + 2147483647 + + + 6 + + + + Super 2xSaI + + 2147483647 + + + 7 + LQ2x @@ -1413,117 +1535,17 @@ 22 - - - 2xSaI - - 2147483647 - - - 6 - - - - Super 2xSaI - - 2147483647 - - - 7 - - - - Super Eagle - - 2147483647 - - - 8 - - - - Scanline - - 2147483647 - - - 9 - - - - Bilinear - - 2147483647 - - - 10 - - - - Nearest 2x - - 2147483647 - - - 11 - - - - Nearest 1.5x - - 2147483647 - - - 12 - - - - Nearest+ 1.5x - - 2147483647 - - - 13 - - - - EPX - - 2147483647 - - - 14 - - - - EPX+ - - 2147483647 - - - 15 - - - - EPX 1.5x - - 2147483647 - - - 16 - - - - EPX+ 1.5x - - 2147483647 - - - 17 - + + + Show Video Settings… + + 2147483647 + + + YES @@ -2463,7 +2485,6 @@ NO - 1 @@ -2487,7 +2508,6 @@ NO - 1 {550, 450} @@ -2720,11 +2740,9 @@ {1.7976931348623157e+308, 1.7976931348623157e+308} - + 256 {400, 100} - - {{0, 0}, {1440, 878}} {1.7976931348623157e+308, 1.7976931348623157e+308} @@ -2763,7 +2781,6 @@ NO - 1 @@ -2802,7 +2819,6 @@ NO - 1 @@ -2821,7 +2837,6 @@ L3d3dy5hZHZhbnNjZW5lLmNvbS9vZmZsaW5lL2RhdGFzL0FEVkFOc0NFbmVfUlRvb2xEUy56aXA NO - 1 {{1, 1}, {484, 81}} @@ -2880,7 +2895,6 @@ L3d3dy5hZHZhbnNjZW5lLmNvbS9vZmZsaW5lL2RhdGFzL0FEVkFOc0NFbmVfUlRvb2xEUy56aXA NO - 1 @@ -2919,7 +2933,6 @@ L3d3dy5hZHZhbnNjZW5lLmNvbS9vZmZsaW5lL2RhdGFzL0FEVkFOc0NFbmVfUlRvb2xEUy56aXA NO - 1 {{1, 1}, {484, 45}} @@ -3199,7 +3212,6 @@ L3d3dy5hZHZhbnNjZW5lLmNvbS9vZmZsaW5lL2RhdGFzL0FEVkFOc0NFbmVfUlRvb2xEUy56aXA NO - 1 @@ -3276,7 +3288,6 @@ L3d3dy5hZHZhbnNjZW5lLmNvbS9vZmZsaW5lL2RhdGFzL0FEVkFOc0NFbmVfUlRvb2xEUy56aXA NO - 1 @@ -3765,7 +3776,6 @@ L3d3dy5hZHZhbnNjZW5lLmNvbS9vZmZsaW5lL2RhdGFzL0FEVkFOc0NFbmVfUlRvb2xEUy56aXA NO - 1 {640, 495} @@ -3779,7 +3789,7 @@ L3d3dy5hZHZhbnNjZW5lLmNvbS9vZmZsaW5lL2RhdGFzL0FEVkFOc0NFbmVfUlRvb2xEUy56aXA 12 - {{13, 10}, {463, 401}} + {{13, 10}, {463, 412}} YES @@ -3816,7 +3826,6 @@ L3d3dy5hZHZhbnNjZW5lLmNvbS9vZmZsaW5lL2RhdGFzL0FEVkFOc0NFbmVfUlRvb2xEUy56aXA NO - 1 @@ -3834,7 +3843,6 @@ L3d3dy5hZHZhbnNjZW5lLmNvbS9vZmZsaW5lL2RhdGFzL0FEVkFOc0NFbmVfUlRvb2xEUy56aXA NO - 1 @@ -4018,7 +4026,6 @@ L3d3dy5hZHZhbnNjZW5lLmNvbS9vZmZsaW5lL2RhdGFzL0FEVkFOc0NFbmVfUlRvb2xEUy56aXA NO - 1 @@ -4036,7 +4043,6 @@ L3d3dy5hZHZhbnNjZW5lLmNvbS9vZmZsaW5lL2RhdGFzL0FEVkFOc0NFbmVfUlRvb2xEUy56aXA NO - 1 @@ -4214,7 +4220,7 @@ L3d3dy5hZHZhbnNjZW5lLmNvbS9vZmZsaW5lL2RhdGFzL0FEVkFOc0NFbmVfUlRvb2xEUy56aXA - {{6, 206}, {431, 116}} + {{6, 217}, {431, 116}} {0, 0} @@ -4824,7 +4830,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -4907,7 +4912,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -4951,7 +4955,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -4969,7 +4972,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -4987,7 +4989,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -5005,7 +5006,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -5023,14 +5023,13 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {429, 141}} - {{6, 45}, {431, 157}} + {{6, 56}, {431, 157}} {0, 0} @@ -5051,7 +5050,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - {{10, 33}, {443, 355}} + {{10, 33}, {443, 366}} Display Views @@ -5060,14 +5059,14 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 2 - + 256 YES 268 - {{119, 278}, {151, 26}} + {{167, 270}, {151, 26}} YES @@ -5099,6 +5098,83 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 YES + + + Nearest 2x + + 2147483647 + + + _popUpItemAction: + 11 + + + + + Scanline + + 2147483647 + + + _popUpItemAction: + 9 + + + + + EPX + + 2147483647 + + + _popUpItemAction: + 14 + + + + + EPX+ + + 2147483647 + + + _popUpItemAction: + 15 + + + + + Super Eagle + + 2147483647 + + + _popUpItemAction: + 8 + + + + + 2xSaI + + 2147483647 + + + _popUpItemAction: + 6 + + + + + Super 2xSaI + + 2147483647 + + + _popUpItemAction: + 7 + + LQ2x @@ -5209,138 +5285,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 22 - - - 2xSaI - - 2147483647 - - - _popUpItemAction: - 6 - - - - - Super 2xSaI - - 2147483647 - - - _popUpItemAction: - 7 - - - - - Super Eagle - - 2147483647 - - - _popUpItemAction: - 8 - - - - - Scanline - - 2147483647 - - - _popUpItemAction: - 9 - - - - - Bilinear - - 2147483647 - - - _popUpItemAction: - 10 - - - - - Nearest 2x - - 2147483647 - - - _popUpItemAction: - 11 - - - - - Nearest 1.5x - - 2147483647 - - - _popUpItemAction: - 12 - - - - - Nearest+ 1.5x - - 2147483647 - - - _popUpItemAction: - 13 - - - - - EPX - - 2147483647 - - - _popUpItemAction: - 14 - - - - - EPX+ - - 2147483647 - - - _popUpItemAction: - 15 - - - - - EPX 1.5x - - 2147483647 - - - _popUpItemAction: - 16 - - - - - EPX+ 1.5x - - 2147483647 - - - _popUpItemAction: - 17 - - YES @@ -5367,7 +5311,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NeXT TIFF v4.0 pasteboard type - {{118, 9}, {262, 262}} + {{167, 7}, {262, 262}} YES @@ -5384,7 +5328,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{10, 251}, {106, 17}} + {{59, 249}, {106, 17}} YES @@ -5398,62 +5342,155 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 268 - {{10, 284}, {106, 17}} + {{59, 276}, {106, 17}} YES 68157504 71304192 - Video Filter: + Pixel Scaler: NO - 1 - + 268 - {{119, 328}, {196, 18}} + {{167, 297}, {151, 26}} - YES - - -2080374784 - 0 - Use Bilinear Filtered Output + + -2076180416 + 2048 - - 1211912448 - 2 - - + + 109199360 + 129 - 200 - 25 + 400 + 75 + + + Bilinear + + 2147483647 + 1 + + + _popUpItemAction: + 1 + + + YES + + OtherViews + + YES + + + Nearest Neighbor + + 2147483647 + + + _popUpItemAction: + + + + + + Bicubic (B-Spline) + + 2147483647 + + + _popUpItemAction: + 2 + + + + + Bicubic (Mitchell-Netravali) + + 2147483647 + + + _popUpItemAction: + 3 + + + + + Lanczos2 + + 2147483647 + + + _popUpItemAction: + 4 + + + + + Lanczos3 + + 2147483647 + + + _popUpItemAction: + 5 + + + + YES + + + 1 + 1 + YES + YES + 2 + + NO + + + + 268 + {{59, 303}, {106, 17}} + + + YES + + 68157504 + 71304192 + Output Filter: + + + + NO 268 - {{119, 308}, {154, 18}} + {{168, 347}, {129, 18}} YES 67108864 0 - Use Vertical Sync + Use vertical sync 1211912448 @@ -5467,18 +5504,106 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO + + + 12 + + YES + + + 274 + + YES + + + 268 + {{16, 192}, {98, 18}} + + _NS:682 + YES + + 67108864 + 0 + Deposterize + + _NS:682 + + 1211912448 + 2 + + + + + 200 + 25 + + NO + + + {{1, 1}, {151, 218}} + + _NS:21 + + + {{6, 6}, {153, 234}} + + _NS:18 + {0, 0} + + 67108864 + 0 + Source Filters + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + + 1 + 0 + 2 + NO + + + + 268 + {{168, 327}, {206, 18}} + + _NS:682 + YES + + -2080374784 + 0 + Run filters on GPU if possible + + _NS:682 + + 1211912448 + 2 + + + + + 200 + 25 + + NO + - {{10, 33}, {443, 355}} - + {{10, 33}, {443, 366}} + + - Video Output + Video Settings 4 - + 256 YES @@ -5495,7 +5620,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{16, 121}, {239, 18}} + {{16, 150}, {239, 18}} YES @@ -5518,7 +5643,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{16, 101}, {154, 18}} + {{16, 130}, {154, 18}} YES @@ -5541,7 +5666,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{16, 81}, {91, 18}} + {{16, 110}, {91, 18}} YES @@ -5564,7 +5689,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{215, 13}, {60, 22}} + {{215, 42}, {60, 22}} YES @@ -5691,17 +5816,16 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 268 - {{15, 15}, {195, 17}} + {{15, 44}, {195, 17}} YES 68157504 - 71304192 + 4195328 Depth Comparison Threshold: @@ -5709,12 +5833,11 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 268 - {{276, 10}, {19, 27}} + {{276, 39}, {19, 27}} YES @@ -5731,7 +5854,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{16, 61}, {129, 18}} + {{16, 90}, {129, 18}} YES @@ -5754,7 +5877,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{16, 41}, {225, 18}} + {{16, 70}, {225, 18}} YES @@ -5774,12 +5897,139 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO + + + 268 + {{145, 10}, {150, 26}} + + YES + + -2076180416 + 2048 + + + 109199360 + 129 + + + 400 + 75 + + + Automatic + + 2147483647 + 1 + + + _popUpItemAction: + + + YES + + OtherViews + + YES + + + + Single-Threaded + + 2147483647 + + + _popUpItemAction: + 1 + + + + + 2 Threads + + 2147483647 + + + _popUpItemAction: + 2 + + + + + 4 Threads + + 2147483647 + + + _popUpItemAction: + 4 + + + + + 8 Threads + + 2147483647 + + + _popUpItemAction: + 8 + + + + + 16 Threads + + 2147483647 + + + _popUpItemAction: + 16 + + + + + 32 Threads + + 2147483647 + + + _popUpItemAction: + 32 + + + + + + 1 + YES + YES + 2 + + NO + + + + 268 + {{15, 16}, {128, 17}} + + YES + + 68157504 + 4195328 + Rendering Threads: + + + + + + NO + - {{1, 1.57421875}, {310, 147}} + {{1, 1}, {310, 176}} - {{64, 99}, {312, 163.57421875}} + {{64, 74}, {312, 192}} {0, 0} @@ -5802,7 +6052,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{207, 323}, {169, 26}} + {{207, 326}, {169, 26}} YES @@ -5869,7 +6119,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{37, 329}, {168, 17}} + {{37, 332}, {168, 17}} YES @@ -5882,113 +6132,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 - - - - 268 - {{195, 13}, {181, 26}} - - YES - - -2076180416 - 2048 - - - 109199360 - 129 - - - 400 - 75 - - - Automatic - - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - OtherViews - - YES - - - - Single-Threaded - - 2147483647 - - - _popUpItemAction: - 1 - - - - - 2 Threads - - 2147483647 - - - _popUpItemAction: - 2 - - - - - 4 Threads - - 2147483647 - - - _popUpItemAction: - 4 - - - - - 8 Threads - - 2147483647 - - - _popUpItemAction: - 8 - - - - - - 1 - YES - YES - 2 - - NO - - - - 268 - {{37, 19}, {156, 17}} - - YES - - 68157504 - 71304192 - Rendering Threads: - - - - - - NO - 1 @@ -6028,7 +6171,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - {{64, 267}, {312, 54}} + {{64, 270}, {312, 54}} {0, 0} @@ -6086,7 +6229,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - {{64, 41}, {312, 54}} + {{64, 16}, {312, 54}} {0, 0} @@ -6107,26 +6250,25 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - {{10, 33}, {443, 355}} - + {{10, 33}, {443, 366}} 3D Rendering - + 0 YES YES YES - + - {489, 425} + {489, 437} NSView @@ -6209,7 +6351,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -7026,7 +7167,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -7462,7 +7602,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -7539,7 +7678,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -7790,7 +7928,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -7808,7 +7945,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -7849,7 +7985,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -7867,7 +8002,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -8012,7 +8146,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -8030,7 +8163,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -8397,7 +8529,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -8438,7 +8569,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -8569,7 +8699,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -8609,7 +8738,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {452, 115} @@ -8650,7 +8778,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -9044,7 +9171,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -9165,7 +9291,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -9273,7 +9398,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {620, 267} @@ -9323,7 +9447,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -9404,7 +9527,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -9422,7 +9544,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -9503,7 +9624,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {314, 74}} @@ -9591,7 +9711,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -9631,7 +9750,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {350, 263} @@ -9814,7 +9932,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -9876,7 +9993,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {350, 125} @@ -10059,7 +10175,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -10121,7 +10236,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {350, 125} @@ -10162,7 +10276,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -10202,7 +10315,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -10220,7 +10332,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -10238,7 +10349,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -10256,7 +10366,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -10274,7 +10383,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -10292,7 +10400,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -10333,7 +10440,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -10415,7 +10521,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -10953,7 +11058,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {516, 283} @@ -10994,7 +11098,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -11086,7 +11189,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -11126,7 +11228,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {314, 46}} @@ -11248,7 +11349,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -11268,7 +11368,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {314, 39}} @@ -11315,7 +11414,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -11335,7 +11433,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {350, 240} @@ -11378,7 +11475,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -11398,7 +11494,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -11416,7 +11511,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -11434,7 +11528,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -11452,7 +11545,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -11470,7 +11562,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -11488,7 +11579,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -11904,7 +11994,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -11966,7 +12055,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -12027,7 +12115,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -12399,7 +12486,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -12460,7 +12546,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {380, 200} @@ -12500,7 +12585,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -12562,7 +12646,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -12995,7 +13078,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13036,7 +13118,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13054,7 +13135,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13171,7 +13251,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13217,7 +13296,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13299,7 +13377,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13317,7 +13394,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13421,7 +13497,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13439,7 +13514,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13818,7 +13892,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13836,7 +13909,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13939,7 +14011,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13958,7 +14029,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13977,7 +14047,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -13996,7 +14065,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {500, 416} @@ -14093,7 +14161,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 255 NO - 1 @@ -14111,7 +14178,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -14129,7 +14195,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {328, 134} @@ -14156,7 +14221,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -14174,7 +14238,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -14222,7 +14285,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -14240,7 +14302,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -14375,7 +14436,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -14393,7 +14453,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -14437,7 +14496,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -14510,7 +14568,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -14528,7 +14585,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -14547,7 +14603,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -14565,7 +14620,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -15051,7 +15105,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {320, 290} @@ -15115,7 +15168,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {320, 290} @@ -15173,7 +15225,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -15214,7 +15265,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -15529,7 +15579,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -15571,7 +15620,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -15675,7 +15723,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16078,7 +16125,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {512, 66}} @@ -16142,7 +16188,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {400, 320} @@ -16172,7 +16217,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16192,7 +16236,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16212,7 +16255,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {400, 320} @@ -16242,7 +16284,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16263,7 +16304,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16283,7 +16323,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16303,7 +16342,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16352,7 +16390,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16402,7 +16439,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {400, 320} @@ -16432,7 +16468,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16580,7 +16615,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16799,7 +16833,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {400, 320} @@ -16877,7 +16910,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16897,7 +16929,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16965,7 +16996,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -16985,7 +17015,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {400, 320} @@ -17073,7 +17102,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {400, 320} @@ -17139,7 +17167,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {400, 320} @@ -17169,7 +17196,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -17315,7 +17341,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {400, 320} @@ -17381,7 +17406,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {400, 320} @@ -17689,7 +17713,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {250, 85}} @@ -18173,7 +18196,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -18191,7 +18213,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {250, 86}} @@ -18593,7 +18614,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -18630,7 +18650,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -18648,7 +18667,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -18666,7 +18684,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -18684,7 +18701,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -18702,7 +18718,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -18722,7 +18737,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -18742,7 +18756,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {260, 328} @@ -18996,7 +19009,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -19068,7 +19080,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -19440,7 +19451,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -19459,7 +19469,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -19478,7 +19487,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -19497,7 +19505,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -19516,7 +19523,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -19557,7 +19563,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -19575,7 +19580,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -19618,7 +19622,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {258, 88}} @@ -19665,7 +19668,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -19686,7 +19688,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {254, 262} @@ -19949,9 +19950,9 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 279 2 - {{1004, 135}, {204, 601}} + {{1004, 23}, {204, 713}} -461896704 - Set Video Output + Video Settings NSPanel @@ -19966,7 +19967,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 {{20, 18}, {164, 19}} - YES -2080374784 @@ -19996,13 +19996,12 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{18, 14}, {132, 458}} + {{18, 14}, {132, 358}} - YES NO - 23 + 18 1 YES @@ -20027,10 +20026,10 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 67108864 131072 - LQ2x + Nearest 2x - 1 + 11 1211912448 0 @@ -20133,10 +20132,10 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 1140850688 131072 - LQ2xS + Scanline - 2 + 9 1211912448 0 @@ -20180,10 +20179,10 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 1140850688 131072 - HQ2x + EPX - 3 + 14 1211912448 0 @@ -20194,10 +20193,10 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 1140850688 131072 - HQ2xS + EPX+ - 4 + 15 1211912448 0 @@ -20206,118 +20205,6 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 75 - 67108864 - 131072 - HQ4x - - - 5 - 1211912448 - 0 - - - 400 - 75 - - - 1140850688 - 131072 - HQ4XS - - - 18 - 1211912448 - 0 - - - 400 - 75 - - - 67108864 - 131072 - 2xBRZ - - - 19 - 1211912448 - 0 - - - 400 - 75 - - - 1140850688 - 131072 - 3xBRZ - - - 20 - 1211912448 - 0 - - - 400 - 75 - - - 67108864 - 131072 - 4xBRZ - - - 21 - 1211912448 - 0 - - - 400 - 75 - - - 67108864 - 131072 - 5xBRZ - - - 22 - 1211912448 - 0 - - - 400 - 75 - - - 1140850688 - 131072 - 2xSaI - - - 6 - 1211912448 - 0 - - - 400 - 75 - - - 67108864 - 131072 - Super 2xSaI - - - 7 - 1211912448 - 0 - - - 400 - 75 - - 67108864 131072 Super Eagle @@ -20331,13 +20218,125 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 400 75 + + 1140850688 + 131072 + 2xSaI + + + 6 + 1211912448 + 0 + + + 400 + 75 + + + 67108864 + 131072 + Super 2xSaI + + + 7 + 1211912448 + 0 + + + 400 + 75 + + + 1140850688 + 131072 + LQ2x + + + 1 + 1211912448 + 0 + + + 400 + 75 + + + 67108864 + 131072 + LQ2xS + + + 2 + 1211912448 + 0 + + + 400 + 75 + + + 67108864 + 131072 + HQ2x + + + 3 + 1211912448 + 0 + + + 400 + 75 + + + 1140850688 + 131072 + HQ2xS + + + 4 + 1211912448 + 0 + + + 400 + 75 + + + 67108864 + 131072 + HQ4x + + + 5 + 1211912448 + 0 + + + 400 + 75 + + + 67108864 + 131072 + HQ4xS + + + 18 + 1211912448 + 0 + + + 400 + 75 + 67108864 131072 - Scanline + 2xBRZ - 9 + 19 1211912448 0 @@ -20348,10 +20347,10 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 67108864 131072 - Bilinear + 3xBRZ - 10 + 20 1211912448 0 @@ -20362,10 +20361,10 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 67108864 131072 - Nearest 2x + 4xBRZ - 11 + 21 1211912448 0 @@ -20376,10 +20375,10 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 67108864 131072 - Nearest 1.5x + 5xBRZ - 12 + 22 1211912448 0 @@ -20420,71 +20419,6 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 400 75 - - 67108864 - 131072 - Nearest+ 1.5x - - - 13 - 1211912448 - 0 - - 400 - 75 - - - 67108864 - 131072 - EPX - - - 14 - 1211912448 - 0 - - 400 - 75 - - - 67108864 - 131072 - EPX+ - - - 15 - 1211912448 - 0 - - 400 - 75 - - - 67108864 - 131072 - EPX 1.5x - - - 16 - 1211912448 - 0 - - 400 - 75 - - - 67108864 - 131072 - EPX+ 1.5x - - - 17 - 1211912448 - 0 - - 400 - 75 - {132, 18} {4, 2} @@ -20601,21 +20535,19 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - {{1, 1}, {168, 482}} + {{1, 1}, {168, 382}} - - {{17, 41}, {170, 498}} + {{17, 41}, {170, 398}} - {0, 0} 67108864 0 - Video Filters + Pixel Scaler @@ -20629,43 +20561,17 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 2 NO - - - 268 - {{17, 565}, {169, 18}} - - - - YES - - -2080374784 - 131072 - Use Bilinear Filtered Output - - - 1211912448 - 2 - - - - - 200 - 25 - - NO - 268 - {{17, 545}, {135, 18}} + {{17, 685}, {111, 18}} - YES 67108864 131072 - Use Vertical Sync + Use vertical sync 1211912448 @@ -20679,11 +20585,381 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO + + + 268 + {{17, 665}, {178, 18}} + + _NS:682 + YES + + -2080374784 + 131072 + Run filters on GPU if possible + + _NS:682 + + 1211912448 + 2 + + + + + 200 + 25 + + NO + + + + 12 + + YES + + + 274 + + YES + + + 268 + {{15, 12}, {86, 18}} + + _NS:682 + YES + + -2080374784 + 131072 + Deposterize + + _NS:682 + + 1211912448 + 2 + + + + + 200 + 25 + + NO + + + {{1, 1}, {168, 38}} + + _NS:21 + + + {{17, 605}, {170, 54}} + + _NS:18 + {0, 0} + + 67108864 + 0 + Source Filters + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + + 1 + 0 + 2 + NO + + + + 12 + + YES + + + 274 + + YES + + + 268 + {{18, 14}, {132, 118}} + + _NS:736 + YES + NO + 6 + 1 + + YES + + 67108864 + 131072 + Nearest Neighbor + + + 1211912448 + 0 + + + + 200 + 25 + + + -2080374784 + 131072 + Bilinear + + + 1 + 1211912448 + 0 + + 549453824 + {18, 18} + + YES + + YES + + + + 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 +AAAAAF1KAAA0kQAACCVYWVogAAAAAAAAdCAAALRgAAAjPVhZWiAAAAAAAAAlbAAAFyoAAKfDWFlaIAAA +AAAAAPNSAAEAAAABFs9zZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbGN1 +cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAY3VydgAAAAAAAAABAc0AAHZjZ3QAAAAAAAAAAAAD +AQAAAQACBAUGBwkKCw0ODxASExQWFxgaGxweHyAiIyQmJygpKywtLzAxMjM1Njc4OTs8PT5AQUJDREZH +SElKS0xOT1BRUlNUVVZXWFlaW1xdXl9hYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gIGCg4SF +hoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnZ6foKGio6SlpqanqKmqq6ytra6vsLGysrO0tba3uLi5uru8 +vL2+v8DBwcLDxMXGxsfIycrKy8zNzs7P0NHS0tPU1dbW19jZ2drb3Nzd3t/g4eLi4+Tl5ufo6enq6+zt +7u/w8fHy8/T19vf4+fr7/P3+/v8AAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR8gISIjJCUnKCkq +Ky0uLzAxMzQ1Njc4OTo7PD0/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaWltcXV5fYGFiY2RlZmdo +aWprbG1ub3BxcnN0dXZ3d3h5ent8fH1+f4CBgoKDhIWGh4iIiYqLjI2Oj5CRkpOUlJWWl5iZmpucnZ2e +n6ChoqOkpaamp6ipqqusra6vsLCxsrO0tba3uLm5uru8vb6/wMHCw8TFx8jJysvMzc7P0NDR0tPU1dbX +2Nna29ze3+Dh4uPk5ebn6err7O3u7/Hy8/T19vf5+vv8/f7/AAIDAwQFBgcICQoKCwwNDg8QERITFBUW +FxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODg5Ojs8PT4+P0BBQkNDREVGR0hJSUpLTE1O +Tk9QUVJSU1RVVVZXWFhZWltbXF1eXl9gYWFiY2RkZWZnZ2hpaWprbGxtbm5vcHFxcnNzdHV1dnd4eHl6 +ent8fH1+fn+AgYGCg4SEhYaHiImJiouMjY6Oj5CRkpOTlJWWl5iZmZqbnJ2en6ChoqOkpaanqKmqq6yt +rq+xsrO0tba3uLq7vL2+wMHDxMbHycrMzs/R0tTW19nb3d7g4uTm6Ors7vDy9Pb4+vz+/wAAbmRpbgAA +AAAAAAY2AACXGgAAVjoAAFPKAACJ3gAAJ8IAABaoAABQDQAAVDkAAiuFAAIZmQABeFEAAwEAAAIAAAAA +AAEABgANABcAIwAxAEAAUgBlAHsAkwCrAMUA4gD/AR8BPwFhAYUBqgHQAfgCIAJLAncCpQLSAwIDMwNl +A5gDzgQFBD0EdQSvBOsFKQVnBacF6AYqBm4GtQb8B0UHkgfkCDkIkAjnCT4JmAn0ClAKrQsLC2sLygwq +DIwM8Q1XDcAOKA6SDv4PbA/bEE0QxBE7EbQSMRKwEzITuRREFNAVYBXxFocXHhfAGGIZBBmsGlQa+RuU +HC4czh1yHhQeux9jIA0gvCFoIhkizyOJJEEk+SW6JnknOygFKMspkypiKzIsASzXLawuhy9gMD4xGzH8 +MtszvzSgNYY2cjdcOEw5OTorOxs8CD0EPfU+6z/nQOFB2ELUQ9VE00XcRttH5EjxSgBLCUwdTTFOUE9v +UI9Rt1LdVAVVNlZsV6VY4FohW21ct135X09goGH0Y0tkqGYFZ19oxGova5ptCG54b/BxbnLsdG119Xd/ +eQh6knwqfcV/W4D4gpSEO4Xih4CJKorYjIqOOY/jkZuTWJUOlsyYiZpSnB6d4Z+soX+jWqUvpxOo+6rj +rMuuwLC4sra0rra0uL+60LzfvwDBHcLdxLXGhchYyi7MCs3lz7rRmtOA1WPXR9kq2xPc/97s4M/iveSn +5o3obupT7ELuLPAM8fLz0PW396H5f/tZ/T3//wAAAAEAAwALABYAJQA3AE0AZQCBAJ8AwQDlAQsBNQFh +AZABwQH1AisCZAKfAtwDHANfA6MD6gQ0BH8EzQT1BR0FcAXEBhsGdAbPBy0HXAeMB+4IUgi4CSAJVAmK +CfYKZArVC0cLgQu8DDIMqw0mDaIOIQ6hDyQPqRAvELgQ/RFDEc8SXRLuE4AUFRSrFUMV3RZ5FxcXthhY +GPwZoRpIGvEbnBxJHPgdqB5bHw8fxSB9ITch8iKwJDAk8yW3Jn4nRigQKNwpqSp5K0osHCzxLccuoC95 +MFUxMzISMvMz1TS5NaA2hzdxOFw5STo4Oyg8Gj4DPvs/9EDuQepD6ETpRexG8Uf3SP9LFEwhTTBOQE9S +UGZSklOrVMVV4Vb/WB5ZP1phW4Vcq13SXvthUmJ/Y69k4GYSZ0dofGm0au1tZG6ib+FxInJlc6l073Y2 +d396FXtjfLJ+A39VgKmB/4NWhK+GCYjCiiGLgYzjjkePrJESknuT5Ja8mCuZm5sMnH+d9J9qoOGiWqPV +pVGmz6eOqE6pzqtRrNSuWq/gsWmy8rR+tgu5Kbq6vE294b93wQ7Cp8RBxd3He8kZyrrLisxbzf/Po9FK +0vHUm9ZF1/HZn9tO3Cbc/96x4GTiGePQ5YjnQegf6Pzquex27jbv9/G583z0X/VC9wj40Pqa/GX+Mf// +AAAAAQADAAsAJQA3AE0AZQCBAJ8AwQELATUBYQGQAcEB9QIrAmQCnwLcAxwDXwOjA+oENAR/BM0FHQVw +BcQGGwZ0Bs8HLQeMB+4IUgi4CSAJign2CmQK1QtHC7wMMgyrDSYNog4hDqEPJA+pEC8QuBFDEl0S7hOA +FBUUqxVDFnkXFxe2GFgY/BpIGvEbnBxJHPgdqB8PH8UgfSE3IfIjbyQwJPMltydGKBAo3Cp5K0osHC3H +LqAveTEzMhIy8zS5NaA2hzhcOUk6ODwaPQ4+Az/0QO5C6EPoROlG8Uf3SglLFEwhTkBPUlF7UpJUxVXh +Vv9ZP1phXKtd0mAlYVJjr2TgZhJofGm0au1tZG6ib+FxInJldO92Nnd/eMl6FXyyfgN/VYCpgf+Er4YJ +h2WIwoohi4GOR4+skRKSe5PklVCWvJgrmZubDJx/nfSfaqDholqj1aVRps+oTqnOq1Gs1K2Xrlqv4LFp +svK0frYLt5m5Kbnxurq8Tb3hv3fBDsHawqfEQcUPxd3He8hKyRnKusuKzFvN/87Rz6PQdtFK0vHTxtSb +1kXXG9fx2MjZn9tO3Cbc/93Y3rHfiuBk4hni9ePQ5KzliOZk50HoH+j86drqueuX7HbtVu427xbv9/DX +8bnymvN89F/1QvYl9wj37PjQ+bX6mvt//GX9S/4x//8AAGRlc2MAAAAAAAAACkNvbG9yIExDRAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAABIAAAAcAEMAbwBsAG8AcgAgAEwAQwBE +AABtbW9kAAAAAAAABhAAAJxOAAAAAL5zkQAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABDb3B5cmlnaHQg +QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA + + + + + + + + 400 + 75 + + + 67108864 + 131072 + Bicubic (B-Spline) + + + 2 + 1211912448 + 0 + + 400 + 75 + + + 67108864 + 131072 + Bicubic (Mitchell) + + + 3 + 1211912448 + 0 + + 400 + 75 + + + 67108864 + 131072 + Lanczos2 + + + 4 + 1211912448 + 0 + + 400 + 75 + + + 67108864 + 131072 + Lanczos3 + + + 5 + 1211912448 + 0 + + 400 + 75 + + + {132, 18} + {4, 2} + 1151868928 + NSActionCell + + 67108864 + 131072 + Radio + + 1211912448 + 0 + + 549453824 + {18, 18} + + YES + + YES + + + + TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw +IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/ +29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5 +dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA +AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG +AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/ +0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/ +7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/ +5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/ +3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD +AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns +AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/ +6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/ +/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/ +///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl +YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA +AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD +AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu +AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQEAAAMAAAABABIAAAEB +AAMAAAABABIAAAECAAMAAAAEAAAFugEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES +AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABABIAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS +AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + + + + + + + + 400 + 75 + + 1 + + + + + + + {{1, 1}, {168, 142}} + + _NS:21 + + + {{17, 443}, {170, 158}} + + _NS:18 + {0, 0} + + 67108864 + 0 + Output Filter + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + + 1 + 0 + 2 + NO + - {204, 601} + {204, 713} - - + {{0, 0}, {1440, 878}} {1.7976931348623157e+308, 1.7976931348623157e+308} @@ -20693,7 +20969,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 279 2 - {{149, 82}, {301, 586}} + {{149, 201}, {301, 467}} -461896704 3D Rendering Settings NSPanel @@ -20718,7 +20994,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{15, 122}, {206, 18}} + {{15, 145}, {206, 18}} YES @@ -20742,7 +21018,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{15, 102}, {134, 18}} + {{15, 125}, {134, 18}} YES @@ -20766,7 +21042,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{15, 82}, {81, 18}} + {{15, 105}, {81, 18}} YES @@ -20790,7 +21066,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{185, 16}, {45, 19}} + {{185, 39}, {45, 19}} YES @@ -20869,18 +21145,17 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 268 - {{15, 18}, {165, 14}} + {{15, 41}, {165, 14}} YES 68157504 - 71435264 + 4326400 Depth Comparison Threshold: @@ -20888,12 +21163,29 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 + + + + 268 + {{15, 15}, {109, 14}} + + + YES + + 68157504 + 4326400 + Rendering Threads: + + + + + + NO 268 - {{231, 11}, {19, 27}} + {{231, 34}, {19, 27}} YES @@ -20911,7 +21203,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{15, 62}, {113, 18}} + {{15, 85}, {113, 18}} YES @@ -20935,7 +21227,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 - {{15, 42}, {194, 18}} + {{15, 65}, {194, 18}} YES @@ -20956,13 +21248,126 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO + + + 268 + {{126, 10}, {124, 22}} + + + _NS:791 + YES + + -2076180416 + 133120 + + _NS:791 + + 109199360 + 129 + + + 400 + 75 + + + Automatic + + 2147483647 + 1 + + + _popUpItemAction: + + + YES + + OtherViews + + YES + + + + Single-Threaded + + 2147483647 + + + _popUpItemAction: + 1 + + + + + 2 Threads + + 2147483647 + + + _popUpItemAction: + 2 + + + + + 4 Threads + + 2147483647 + + + _popUpItemAction: + 4 + + + + + 8 Threads + + 2147483647 + + + _popUpItemAction: + 8 + + + + + 16 Threads + + 2147483647 + + + _popUpItemAction: + 16 + + + + + 32 Threads + + 2147483647 + + + _popUpItemAction: + 32 + + + + + + 1 + YES + YES + 2 + + NO + - {{1, 1}, {265, 148}} + {{1, 1}, {265, 171}} - {{17, 241}, {267, 164}} + {{17, 99}, {267, 187}} {0, 0} @@ -21282,7 +21687,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - {{17, 468}, {267, 98}} + {{17, 349}, {267, 98}} {0, 0} @@ -21303,364 +21708,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 2 NO - - - 12 - - YES - - - 274 - - YES - - - 268 - {{18, 14}, {120, 98}} - - - YES - NO - 5 - 1 - - YES - - -2080374784 - 131072 - Automatic - - - 1211912448 - 0 - - - - 200 - 25 - - - 67108864 - 131072 - Single-Threaded - - - 1 - 1211912448 - 0 - - 549453824 - {18, 18} - - YES - - YES - - - - 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 -AAAAAF1KAAA0kQAACCVYWVogAAAAAAAAdCAAALRgAAAjPVhZWiAAAAAAAAAlbAAAFyoAAKfDWFlaIAAA -AAAAAPNSAAEAAAABFs9zZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbGN1 -cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAY3VydgAAAAAAAAABAc0AAHZjZ3QAAAAAAAAAAAAD -AQAAAQACBAUGBwkKCw0ODxASExQWFxgaGxweHyAiIyQmJygpKywtLzAxMjM1Njc4OTs8PT5AQUJDREZH -SElKS0xOT1BRUlNUVVZXWFlaW1xdXl9hYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gIGCg4SF -hoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnZ6foKGio6SlpqanqKmqq6ytra6vsLGysrO0tba3uLi5uru8 -vL2+v8DBwcLDxMXGxsfIycrKy8zNzs7P0NHS0tPU1dbW19jZ2drb3Nzd3t/g4eLi4+Tl5ufo6enq6+zt -7u/w8fHy8/T19vf4+fr7/P3+/v8AAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR8gISIjJCUnKCkq -Ky0uLzAxMzQ1Njc4OTo7PD0/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaWltcXV5fYGFiY2RlZmdo -aWprbG1ub3BxcnN0dXZ3d3h5ent8fH1+f4CBgoKDhIWGh4iIiYqLjI2Oj5CRkpOUlJWWl5iZmpucnZ2e -n6ChoqOkpaamp6ipqqusra6vsLCxsrO0tba3uLm5uru8vb6/wMHCw8TFx8jJysvMzc7P0NDR0tPU1dbX -2Nna29ze3+Dh4uPk5ebn6err7O3u7/Hy8/T19vf5+vv8/f7/AAIDAwQFBgcICQoKCwwNDg8QERITFBUW -FxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODg5Ojs8PT4+P0BBQkNDREVGR0hJSUpLTE1O -Tk9QUVJSU1RVVVZXWFhZWltbXF1eXl9gYWFiY2RkZWZnZ2hpaWprbGxtbm5vcHFxcnNzdHV1dnd4eHl6 -ent8fH1+fn+AgYGCg4SEhYaHiImJiouMjY6Oj5CRkpOTlJWWl5iZmZqbnJ2en6ChoqOkpaanqKmqq6yt -rq+xsrO0tba3uLq7vL2+wMHDxMbHycrMzs/R0tTW19nb3d7g4uTm6Ors7vDy9Pb4+vz+/wAAbmRpbgAA -AAAAAAY2AACXGgAAVjoAAFPKAACJ3gAAJ8IAABaoAABQDQAAVDkAAiuFAAIZmQABeFEAAwEAAAIAAAAA -AAEABgANABcAIwAxAEAAUgBlAHsAkwCrAMUA4gD/AR8BPwFhAYUBqgHQAfgCIAJLAncCpQLSAwIDMwNl -A5gDzgQFBD0EdQSvBOsFKQVnBacF6AYqBm4GtQb8B0UHkgfkCDkIkAjnCT4JmAn0ClAKrQsLC2sLygwq -DIwM8Q1XDcAOKA6SDv4PbA/bEE0QxBE7EbQSMRKwEzITuRREFNAVYBXxFocXHhfAGGIZBBmsGlQa+RuU -HC4czh1yHhQeux9jIA0gvCFoIhkizyOJJEEk+SW6JnknOygFKMspkypiKzIsASzXLawuhy9gMD4xGzH8 -MtszvzSgNYY2cjdcOEw5OTorOxs8CD0EPfU+6z/nQOFB2ELUQ9VE00XcRttH5EjxSgBLCUwdTTFOUE9v -UI9Rt1LdVAVVNlZsV6VY4FohW21ct135X09goGH0Y0tkqGYFZ19oxGova5ptCG54b/BxbnLsdG119Xd/ -eQh6knwqfcV/W4D4gpSEO4Xih4CJKorYjIqOOY/jkZuTWJUOlsyYiZpSnB6d4Z+soX+jWqUvpxOo+6rj -rMuuwLC4sra0rra0uL+60LzfvwDBHcLdxLXGhchYyi7MCs3lz7rRmtOA1WPXR9kq2xPc/97s4M/iveSn -5o3obupT7ELuLPAM8fLz0PW396H5f/tZ/T3//wAAAAEAAwALABYAJQA3AE0AZQCBAJ8AwQDlAQsBNQFh -AZABwQH1AisCZAKfAtwDHANfA6MD6gQ0BH8EzQT1BR0FcAXEBhsGdAbPBy0HXAeMB+4IUgi4CSAJVAmK -CfYKZArVC0cLgQu8DDIMqw0mDaIOIQ6hDyQPqRAvELgQ/RFDEc8SXRLuE4AUFRSrFUMV3RZ5FxcXthhY -GPwZoRpIGvEbnBxJHPgdqB5bHw8fxSB9ITch8iKwJDAk8yW3Jn4nRigQKNwpqSp5K0osHCzxLccuoC95 -MFUxMzISMvMz1TS5NaA2hzdxOFw5STo4Oyg8Gj4DPvs/9EDuQepD6ETpRexG8Uf3SP9LFEwhTTBOQE9S -UGZSklOrVMVV4Vb/WB5ZP1phW4Vcq13SXvthUmJ/Y69k4GYSZ0dofGm0au1tZG6ib+FxInJlc6l073Y2 -d396FXtjfLJ+A39VgKmB/4NWhK+GCYjCiiGLgYzjjkePrJESknuT5Ja8mCuZm5sMnH+d9J9qoOGiWqPV -pVGmz6eOqE6pzqtRrNSuWq/gsWmy8rR+tgu5Kbq6vE294b93wQ7Cp8RBxd3He8kZyrrLisxbzf/Po9FK -0vHUm9ZF1/HZn9tO3Cbc/96x4GTiGePQ5YjnQegf6Pzquex27jbv9/G583z0X/VC9wj40Pqa/GX+Mf// -AAAAAQADAAsAJQA3AE0AZQCBAJ8AwQELATUBYQGQAcEB9QIrAmQCnwLcAxwDXwOjA+oENAR/BM0FHQVw -BcQGGwZ0Bs8HLQeMB+4IUgi4CSAJign2CmQK1QtHC7wMMgyrDSYNog4hDqEPJA+pEC8QuBFDEl0S7hOA -FBUUqxVDFnkXFxe2GFgY/BpIGvEbnBxJHPgdqB8PH8UgfSE3IfIjbyQwJPMltydGKBAo3Cp5K0osHC3H -LqAveTEzMhIy8zS5NaA2hzhcOUk6ODwaPQ4+Az/0QO5C6EPoROlG8Uf3SglLFEwhTkBPUlF7UpJUxVXh -Vv9ZP1phXKtd0mAlYVJjr2TgZhJofGm0au1tZG6ib+FxInJldO92Nnd/eMl6FXyyfgN/VYCpgf+Er4YJ -h2WIwoohi4GOR4+skRKSe5PklVCWvJgrmZubDJx/nfSfaqDholqj1aVRps+oTqnOq1Gs1K2Xrlqv4LFp -svK0frYLt5m5Kbnxurq8Tb3hv3fBDsHawqfEQcUPxd3He8hKyRnKusuKzFvN/87Rz6PQdtFK0vHTxtSb -1kXXG9fx2MjZn9tO3Cbc/93Y3rHfiuBk4hni9ePQ5KzliOZk50HoH+j86drqueuX7HbtVu427xbv9/DX -8bnymvN89F/1QvYl9wj37PjQ+bX6mvt//GX9S/4x//8AAGRlc2MAAAAAAAAACkNvbG9yIExDRAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAABIAAAAcAEMAbwBsAG8AcgAgAEwAQwBE -AABtbW9kAAAAAAAABhAAAJxOAAAAAL5zkQAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABDb3B5cmlnaHQg -QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA - - - - - - - - 400 - 75 - - - 67108864 - 131072 - 2 Threads - - - 2 - 1211912448 - 0 - - 12779520 - - YES - - YES - - - - YES - - YES - size - state - value - widget - - - YES - regular - normal - - radiobutton - - - {18, 18} - 0 - YES - NSCalibratedRGBColorSpace - - - - - - - 400 - 75 - - - 67108864 - 131072 - 4 Threads - - - 4 - 1211912448 - 0 - - - 400 - 75 - - - 67108864 - 131072 - 8 Threads - - - 8 - 1211912448 - 0 - - 400 - 75 - - - {120, 18} - {4, 2} - 1151868928 - NSActionCell - - 67108864 - 131072 - Radio - - 1211912448 - 0 - - 549453824 - {18, 18} - - YES - - YES - - - - TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw -IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/ -29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5 -dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA -AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG -AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/ -0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/ -7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/ -5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/ -3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD -AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns -AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/ -6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/ -/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/ -///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl -YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA -AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD -AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu -AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgEAAAMAAAABABIAAAEB -AAMAAAABABIAAAECAAMAAAAEAAAFxgEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES -AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABABIAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS -AAMAAAABAAEAAAFTAAMAAAAEAAAFzodzAAcAAAxIAAAF1gAAAAAACAAIAAgACAABAAEAAQABAAAMSExp -bm8CEAAAbW50clJHQiBYWVogB84AAgAJAAYAMQAAYWNzcE1TRlQAAAAASUVDIHNSR0IAAAAAAAAAAAAA -AAAAAPbWAAEAAAAA0y1IUCAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAARY3BydAAAAVAAAAAzZGVzYwAAAYQAAABsd3RwdAAAAfAAAAAUYmtwdAAAAgQAAAAUclhZWgAA -AhgAAAAUZ1hZWgAAAiwAAAAUYlhZWgAAAkAAAAAUZG1uZAAAAlQAAABwZG1kZAAAAsQAAACIdnVlZAAA -A0wAAACGdmlldwAAA9QAAAAkbHVtaQAAA/gAAAAUbWVhcwAABAwAAAAkdGVjaAAABDAAAAAMclRSQwAA -BDwAAAgMZ1RSQwAABDwAAAgMYlRSQwAABDwAAAgMdGV4dAAAAABDb3B5cmlnaHQgKGMpIDE5OTggSGV3 -bGV0dC1QYWNrYXJkIENvbXBhbnkAAGRlc2MAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAA -AAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA -b6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9kZXNjAAAAAAAA -ABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAuSUVDIDYx -OTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAuSUVDIDYxOTY2 -LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRl -c2MAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBpbiBJRUM2MTk2Ni0yLjEAAAAAAAAA -AAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAB2aWV3AAAAAAATpP4AFF8uABDPFAAD7cwABBMLAANcngAAAAFYWVogAAAAAABM -CVYAUAAAAFcf521lYXMAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAKPAAAAAnNpZyAAAAAAQ1JUIGN1 -cnYAAAAAAAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANwA7AEAARQBKAE8AVABZAF4AYwBoAG0AcgB3 -AHwAgQCGAIsAkACVAJoAnwCkAKkArgCyALcAvADBAMYAywDQANUA2wDgAOUA6wDwAPYA+wEBAQcBDQET -ARkBHwElASsBMgE4AT4BRQFMAVIBWQFgAWcBbgF1AXwBgwGLAZIBmgGhAakBsQG5AcEByQHRAdkB4QHp -AfIB+gIDAgwCFAIdAiYCLwI4AkECSwJUAl0CZwJxAnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAML -AxYDIQMtAzgDQwNPA1oDZgNyA34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGMEcQR+ -BIwEmgSoBLYExATTBOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXlBfYGBgYWBicGNwZI -BlkGagZ7BowGnQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4CAsIHwgyCEYIWghu -CIIIlgiqCL4I0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsKEQonCj0KVApqCoEKmAquCsUK3Arz -CwsLIgs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxcDHUMjgynDMAM2QzzDQ0NJg1ADVoNdA2ODakNww3e -DfgOEw4uDkkOZA5/DpsOtg7SDu4PCQ8lD0EPXg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExEx -EU8RbRGMEaoRyRHoEgcSJhJFEmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSLFK0UzhTw -FRIVNBVWFXgVmxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUYihivGNUY+hkg -GUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHscoxzMHPUdHh1HHXAdmR3D -HeweFh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwgmCDEIPAhHCFIIXUhoSHOIfsiJyJVIoIiryLd -IwojOCNmI5QjwiPwJB8kTSR8JKsk2iUJJTglaCWXJccl9yYnJlcmhya3JugnGCdJJ3onqyfcKA0oPyhx -KKIo1CkGKTgpaymdKdAqAio1KmgqmyrPKwIrNitpK50r0SwFLDksbiyiLNctDC1BLXYtqy3hLhYuTC6C -Lrcu7i8kL1ovkS/HL/4wNTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy1DMNM0YzfzO4M/E0KzRlNJ402DUT -NU01hzXCNf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5BTlCOX85vDn5OjY6dDqyOu87LTtrO6o76Dwn -PGU8pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/iQCNAZECmQOdBKUFqQaxB7kIwQnJCtUL3QzpDfUPA -RANER0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVHe0fASAVIS0iRSNdJHUljSalJ8Eo3Sn1KxEsMS1NLmkvi -TCpMcky6TQJNSk2TTdxOJU5uTrdPAE9JT5NP3VAnUHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSP -VNtVKFV1VcJWD1ZcVqlW91dEV5JX4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3J -XhpebF69Xw9fYV+zYAVgV2CqYPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhnPWeT -Z+loP2iWaOxpQ2maafFqSGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/RcCtwhnDgcTpxlXHw -cktypnMBc11zuHQUdHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5KnmJeed6RnqlewR7Y3vCfCF8gXzh -fUF9oX4BfmJ+wn8jf4R/5YBHgKiBCoFrgc2CMIKSgvSDV4O6hB2EgITjhUeFq4YOhnKG14c7h5+IBIhp -iM6JM4mZif6KZIrKizCLlov8jGOMyo0xjZiN/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSK -lPSVX5XJljSWn5cKl3WX4JhMmLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFH -obaiJqKWowajdqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKrdavprFys0K1ErbiuLa6h -rxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbwt2i34LhZuNG5SrnCuju6tbsuu6e8Ibyb -vRW9j74KvoS+/796v/XAcMDswWfB48JfwtvDWMPUxFHEzsVLxcjGRsbDx0HHv8g9yLzJOsm5yjjKt8s2 -y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 -2vvbgNwF3IrdEN2W3hzeot8p36/gNuC94UThzOJT4tvjY+Pr5HPk/OWE5g3mlucf56noMui86Ubp0Opb -6uXrcOv77IbtEe2c7ijutO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe9m32+/eK+Bn4qPk4+cf6V/rn -+3f8B/yY/Sn9uv5L/tz/bf//A - - - - - - - - 400 - 75 - - - - - - - - {{1, 1}, {265, 122}} - - - - - {{17, 41}, {267, 138}} - - - {0, 0} - - 67108864 - 0 - Rendering Threads - - - - 3 - MCAwLjgwMDAwMDAxMTkAA - - - - 1 - 0 - 2 - NO - 12 @@ -21701,7 +21748,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - {{17, 410}, {267, 54}} + {{17, 291}, {267, 54}} {0, 0} @@ -21762,7 +21809,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - {{17, 183}, {267, 54}} + {{17, 41}, {267, 54}} {0, 0} @@ -21784,7 +21831,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - {301, 586} + {301, 467} @@ -22813,7 +22860,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23253,7 +23299,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23272,7 +23317,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23291,7 +23335,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23310,7 +23353,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23333,7 +23375,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23353,7 +23394,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23373,7 +23413,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23393,7 +23432,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {408, 116}} @@ -23449,7 +23487,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23468,7 +23505,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23487,7 +23523,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23506,7 +23541,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23525,7 +23559,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23544,7 +23577,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23564,7 +23596,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23584,7 +23615,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23604,7 +23634,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23624,7 +23653,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23644,7 +23672,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23664,7 +23691,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {216, 400}} @@ -23720,7 +23746,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23739,7 +23764,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23758,7 +23782,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23777,7 +23800,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23796,7 +23818,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23815,7 +23836,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23834,7 +23854,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23853,7 +23872,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23872,7 +23890,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23892,7 +23909,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23912,7 +23928,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23932,7 +23947,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23952,7 +23966,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23972,7 +23985,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -23992,7 +24004,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24012,7 +24023,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {324, 192}} @@ -24068,7 +24078,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24088,7 +24097,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24107,7 +24115,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24127,7 +24134,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24146,7 +24152,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24166,7 +24171,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24185,7 +24189,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24205,7 +24208,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {324, 104}} @@ -24261,7 +24263,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24281,7 +24282,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24300,7 +24300,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24319,7 +24318,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {{1, 1}, {324, 60}} @@ -24368,7 +24366,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 {1.7976931348623157e+308, 1.7976931348623157e+308} - + 256 YES @@ -24411,7 +24409,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24429,7 +24426,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24447,7 +24443,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24465,7 +24460,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24549,7 +24543,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24567,7 +24560,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24613,6 +24605,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 {213, 198} + {{0, 0}, {1920, 1178}} {1.7976931348623157e+308, 1.7976931348623157e+308} @@ -24672,7 +24665,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24690,7 +24682,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24708,7 +24699,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24726,7 +24716,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24744,7 +24733,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24762,7 +24750,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -24841,7 +24828,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25382,7 +25368,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 {450, 35} @@ -25438,7 +25423,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25628,7 +25612,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25668,7 +25651,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25686,7 +25668,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25726,7 +25707,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25744,7 +25724,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25784,7 +25763,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25802,7 +25780,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25820,7 +25797,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25838,7 +25814,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25857,7 +25832,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25876,7 +25850,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -25953,7 +25926,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26285,7 +26257,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26325,7 +26296,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26343,7 +26313,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26361,7 +26330,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26379,7 +26347,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26419,7 +26386,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26437,7 +26403,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26477,7 +26442,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26495,7 +26459,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26513,7 +26476,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26531,7 +26493,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26550,7 +26511,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26569,7 +26529,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26659,7 +26618,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NO - 1 @@ -26931,6 +26889,20 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 frameJumpType frameJumpFramesForward frameJumpToFrame + mainWindow.outputFilter + mainWindow.videoSourceDeposterize + mainWindow.videoFiltersPreferGPU + mainWindow.view.videoSourceDeposterize + mainWindow.view.outputFilter + mainWindow.view.sourceDeposterize + mainWindow.view.srcDeposterize + mainWindow.view.videoFilterType + mainWindow.view.pixelScaler + mainWindow.view.videoFiltersPreferGPU + mainWindow.view.useVerticalSync + mainWindow.videoOutputFilter + mainWindow.videoPixelScaler + mainWindow.view.canUseShaderBasedFilters EmuControllerDelegate @@ -27215,8 +27187,9 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 YES - Render3D_TextureAlignmentHack - Render3D_FragmentSamplingHack + DisplayView_OutputFilter + DisplayView_Deposterize + DisplayView_FiltersPreferGPU YES @@ -27863,14 +27836,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 3354 - - - selectVideoFilterType: - - - - 3355 - selectVideoFilterType: @@ -27879,22 +27844,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 3356 - - - selectVideoFilterType: - - - - 3357 - - - - selectVideoFilterType: - - - - 3358 - selectVideoFilterType: @@ -27911,22 +27860,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 3360 - - - selectVideoFilterType: - - - - 3361 - - - - selectVideoFilterType: - - - - 3362 - prefWindowController @@ -28215,14 +28148,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 4127 - - - setUseBilinear: - - - - 4128 - value: values.SPU_AdvancedLogic @@ -30383,22 +30308,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 5974 - - - value: values.DisplayView_UseBilinearOutput - - - - - - value: values.DisplayView_UseBilinearOutput - value - values.DisplayView_UseBilinearOutput - 2 - - - 5975 - selectedTag: values.DisplayView_VideoFilter @@ -33726,54 +33635,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 6967 - - - selectedTag: selection.mainWindow.videoFilterType - - - - - - selectedTag: selection.mainWindow.videoFilterType - selectedTag - selection.mainWindow.videoFilterType - 2 - - - 6989 - - - - value: selection.mainWindow.useBilinearOutput - - - - - - value: selection.mainWindow.useBilinearOutput - value - selection.mainWindow.useBilinearOutput - 2 - - - 6990 - - - - value: selection.mainWindow.useVerticalSync - - - - - - value: selection.mainWindow.useVerticalSync - value - selection.mainWindow.useVerticalSync - 2 - - - 6991 - selectedTag: selection.selectedExportRomSaveID @@ -36240,182 +36101,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 8241 - - - makeKeyAndOrderFront: - - - - 8250 - - - - toggleVerticalSync: - - - - 8274 - - - - toggleBilinearFilteredOutput: - - - - 8275 - - - - changeVideoFilter: - - - - 8276 - - - - changeVideoFilter: - - - - 8277 - - - - changeVideoFilter: - - - - 8278 - - - - changeVideoFilter: - - - - 8279 - - - - changeVideoFilter: - - - - 8280 - - - - changeVideoFilter: - - - - 8281 - - - - changeVideoFilter: - - - - 8282 - - - - changeVideoFilter: - - - - 8283 - - - - changeVideoFilter: - - - - 8284 - - - - changeVideoFilter: - - - - 8285 - - - - changeVideoFilter: - - - - 8286 - - - - changeVideoFilter: - - - - 8287 - - - - changeVideoFilter: - - - - 8288 - - - - changeVideoFilter: - - - - 8289 - - - - changeVideoFilter: - - - - 8290 - - - - changeVideoFilter: - - - - 8291 - - - - changeVideoFilter: - - - - 8292 - - - - changeVideoFilter: - - - - 8293 - - - - changeVideoFilter: - - - - 8294 - toggleFullScreenDisplay: @@ -38056,38 +37741,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 9119 - - - changeVideoFilter: - - - - 9130 - - - - changeVideoFilter: - - - - 9132 - - - - changeVideoFilter: - - - - 9134 - - - - changeVideoFilter: - - - - 9136 - openReplay: @@ -38288,22 +37941,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 9178 - - - selectedTag: selection.cdsGPU.render3DThreads - - - - - - selectedTag: selection.cdsGPU.render3DThreads - selectedTag - selection.cdsGPU.render3DThreads - 2 - - - 9180 - value: selection.cdsGPU.render3DFragmentSamplingHack @@ -38336,6 +37973,454 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 9183 + + + makeKeyAndOrderFront: + + + + 9275 + + + + selectedTag: selection.cdsGPU.render3DThreads + + + + + + selectedTag: selection.cdsGPU.render3DThreads + selectedTag + selection.cdsGPU.render3DThreads + 2 + + + 9298 + + + + value: selection.mainWindow.view.useVerticalSync + + + + + + value: selection.mainWindow.view.useVerticalSync + value + selection.mainWindow.view.useVerticalSync + 2 + + + 9318 + + + + value: selection.mainWindow.videoSourceDeposterize + + + + + + value: selection.mainWindow.videoSourceDeposterize + value + selection.mainWindow.videoSourceDeposterize + 2 + + + 9319 + + + + selectedTag: selection.mainWindow.videoOutputFilter + + + + + + selectedTag: selection.mainWindow.videoOutputFilter + selectedTag + selection.mainWindow.videoOutputFilter + 2 + + + 9320 + + + + selectedTag: selection.mainWindow.videoPixelScaler + + + + + + selectedTag: selection.mainWindow.videoPixelScaler + selectedTag + selection.mainWindow.videoPixelScaler + 2 + + + 9321 + + + + value: selection.mainWindow.videoFiltersPreferGPU + + + + + + value: selection.mainWindow.videoFiltersPreferGPU + value + selection.mainWindow.videoFiltersPreferGPU + 2 + + + 9322 + + + + selectedTag: values.DisplayView_OutputFilter + + + + + + selectedTag: values.DisplayView_OutputFilter + selectedTag + values.DisplayView_OutputFilter + 2 + + + 9323 + + + + value: values.DisplayView_Deposterize + + + + + + value: values.DisplayView_Deposterize + value + values.DisplayView_Deposterize + 2 + + + 9324 + + + + changeVideoOutputFilter: + + + + 9325 + + + + changeVideoOutputFilter: + + + + 9326 + + + + changeVideoOutputFilter: + + + + 9327 + + + + changeVideoOutputFilter: + + + + 9328 + + + + changeVideoOutputFilter: + + + + 9329 + + + + changeVideoOutputFilter: + + + + 9330 + + + + changeVideoPixelScaler: + + + + 9331 + + + + changeVideoPixelScaler: + + + + 9332 + + + + changeVideoPixelScaler: + + + + 9333 + + + + changeVideoPixelScaler: + + + + 9334 + + + + changeVideoPixelScaler: + + + + 9335 + + + + changeVideoPixelScaler: + + + + 9336 + + + + changeVideoPixelScaler: + + + + 9337 + + + + changeVideoPixelScaler: + + + + 9338 + + + + changeVideoPixelScaler: + + + + 9339 + + + + changeVideoPixelScaler: + + + + 9340 + + + + changeVideoPixelScaler: + + + + 9341 + + + + changeVideoPixelScaler: + + + + 9342 + + + + changeVideoPixelScaler: + + + + 9343 + + + + changeVideoPixelScaler: + + + + 9344 + + + + changeVideoPixelScaler: + + + + 9345 + + + + changeVideoPixelScaler: + + + + 9346 + + + + changeVideoPixelScaler: + + + + 9347 + + + + changeVideoPixelScaler: + + + + 9348 + + + + toggleVideoSourceDeposterize: + + + + 9349 + + + + value: values.DisplayView_FiltersPreferGPU + + + + + + value: values.DisplayView_FiltersPreferGPU + value + values.DisplayView_FiltersPreferGPU + 2 + + + 9350 + + + + enabled: selection.mainWindow.view.canUseShaderBasedFilters + + + + + + enabled: selection.mainWindow.view.canUseShaderBasedFilters + enabled + selection.mainWindow.view.canUseShaderBasedFilters + 2 + + + 9352 + + + + enabled: selection.mainWindow.view.canUseShaderBasedFilters + + + + + + enabled: selection.mainWindow.view.canUseShaderBasedFilters + enabled + selection.mainWindow.view.canUseShaderBasedFilters + 2 + + + 9353 + + + + enabled: selection.mainWindow.view.canUseShaderBasedFilters + + + + + + enabled: selection.mainWindow.view.canUseShaderBasedFilters + enabled + selection.mainWindow.view.canUseShaderBasedFilters + 2 + + + 9354 + + + + enabled: selection.mainWindow.view.canUseShaderBasedFilters + + + + + + enabled: selection.mainWindow.view.canUseShaderBasedFilters + enabled + selection.mainWindow.view.canUseShaderBasedFilters + 2 + + + 9355 + + + + enabled: selection.mainWindow.view.canUseShaderBasedFilters + + + + + + enabled: selection.mainWindow.view.canUseShaderBasedFilters + enabled + selection.mainWindow.view.canUseShaderBasedFilters + 2 + + + 9356 + + + + enabled: selection.mainWindow.view.canUseShaderBasedFilters + + + + + + enabled: selection.mainWindow.view.canUseShaderBasedFilters + enabled + selection.mainWindow.view.canUseShaderBasedFilters + 2 + + + 9357 + @@ -38593,6 +38678,10 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 + + + + @@ -38882,10 +38971,12 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 YES + - - + + + @@ -39906,12 +39997,15 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 YES - - + - + + + + + @@ -39942,25 +40036,20 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - - - - - - - - - - - + + + + + + + @@ -40037,26 +40126,11 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - 1642 - - - 1643 - - 1644 - - - - - 1645 - - - 1646 @@ -40067,16 +40141,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - 1648 - - - - - 1649 - - - 1650 @@ -41427,20 +41491,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - 3689 - - - YES - - - - - - 3690 - - - 3712 @@ -41673,30 +41723,14 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 YES - - - + - - 3692 - - - YES - - - - - - 3693 - - - 3648 @@ -41720,11 +41754,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - - - - @@ -41836,9 +41865,8 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - + @@ -41855,6 +41883,8 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 + + @@ -41965,6 +41995,8 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 + + @@ -42136,54 +42168,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - 3878 - - - YES - - - - - - 3879 - - - YES - - - - - - - - - - - 3880 - - - - - 3881 - - - - - 3882 - - - - - 3883 - - - - - 3884 - - - 3885 @@ -42193,71 +42177,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - 3888 - - - YES - - - - - - 3889 - - - YES - - - - - - 3890 - - - YES - - - - - - - - - - 3894 - - - - - 3893 - - - - - 3892 - - - - - 3891 - - - - - 3896 - - - YES - - - - - - 3897 - - - 3899 @@ -45580,11 +45499,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - 6236 - - - 6238 @@ -46335,16 +46249,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - 6634 - - - - - 6635 - - - 6651 @@ -49638,11 +49542,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 YES - - - - - @@ -49650,50 +49549,20 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - - - - - - - - - - - + + + + + + + - - 8247 - - - - - 8248 - - - - - 8249 - - - - - 8251 - - - - - 8252 - - - 8253 @@ -49749,26 +49618,11 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - 8264 - - - 8265 - - 8266 - - - - - 8267 - - - 8268 @@ -49779,16 +49633,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - 8270 - - - - - 8271 - - - 8295 @@ -51568,26 +51412,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - 9124 - - - - - 9125 - - - - - 9126 - - - - - 9127 - - - 3665 @@ -51709,6 +51533,465 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 + + 9184 + + + YES + + + + + + 9185 + + + YES + + + + + + 9186 + + + + + 9187 + + + YES + + + + + + 9188 + + + YES + + + + + + + + + + + 9195 + + + + + 9206 + + + + + 9208 + + + + + 9209 + + + + + 9210 + + + + + 9211 + + + + + 9236 + + + YES + + + + + + 9237 + + + YES + + + + + + 9238 + + + + + 9257 + + + YES + + + + + + 9258 + + + + + 3888 + + + YES + + + + + + 3889 + + + YES + + + + + + 3890 + + + YES + + + + + + + + + + + + 6634 + + + + + 3891 + + + + + 3892 + + + + + 3893 + + + + + 3894 + + + + + 3896 + + + YES + + + + + + 3897 + + + + + 9259 + + + + + 9260 + + + + + 9261 + + + + + 9262 + + + YES + + + + + + 9263 + + + YES + + + + + + 9264 + + + + + 9265 + + + YES + + + + + + 9266 + + + YES + + + + + + + + + + + 9267 + + + + + 9269 + + + + + 9270 + + + + + 9271 + + + + + 9272 + + + + + 9273 + + + + + 9274 + + + + + 9276 + + + YES + + + + + + 9277 + + + + + 9278 + + + YES + + + + + + 9279 + + + YES + + + + + + 9280 + + + YES + + + + + + 9281 + + + + + 9282 + + + YES + + + + + + + + + + + + 9283 + + + + + 9284 + + + + + 9285 + + + + + 9286 + + + + + 9287 + + + + + 9288 + + + + + 9289 + + + + + 9290 + + + YES + + + + + + 9291 + + + + + 9292 + + + YES + + + + + + 9293 + + + YES + + + + + + 9294 + + + YES + + + + + + + + + + + + 9295 + + + + + 9296 + + + + + 9297 + + + + + 9299 + + + + + 9300 + + + + + 9301 + + + + + 9302 + + + @@ -51793,12 +52076,14 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 1584.IBPluginDependency 1615.IBAttributePlaceholdersKey 1615.IBPluginDependency + 1615.IBViewBoundsToFrameTransform 1616.IBPluginDependency 1619.IBPluginDependency 1620.IBPluginDependency 1621.IBPluginDependency 1626.IBAttributePlaceholdersKey 1626.IBPluginDependency + 1626.IBViewBoundsToFrameTransform 1627.IBPluginDependency 1628.IBEditorWindowLastContentRect 1628.IBPluginDependency @@ -51806,8 +52091,10 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 1630.IBPluginDependency 1631.IBPluginDependency 1632.IBPluginDependency + 1632.IBViewBoundsToFrameTransform 1633.IBPluginDependency 1634.IBPluginDependency + 1634.IBViewBoundsToFrameTransform 1635.IBPluginDependency 1636.IBPluginDependency 1637.IBPluginDependency @@ -51815,15 +52102,11 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 1639.IBPluginDependency 1640.IBPluginDependency 1641.IBPluginDependency - 1642.IBPluginDependency 1643.IBPluginDependency - 1644.IBPluginDependency - 1645.IBPluginDependency 1646.IBPluginDependency 1647.IBPluginDependency - 1648.IBPluginDependency - 1649.IBPluginDependency 1650.IBPluginDependency + 1650.IBViewBoundsToFrameTransform 1651.IBPluginDependency 1679.IBPluginDependency 1679.designableToolbarItemIdentifier @@ -51837,6 +52120,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 1682.IBPluginDependency 1721.IBPluginDependency 1855.IBPluginDependency + 1856.IBEditorWindowLastContentRect 1856.IBPluginDependency 1856.IBWindowTemplateEditedContentRect 1856.NSWindowTemplate.visibleAtLaunch @@ -52150,12 +52434,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 3665.IBPluginDependency 3666.IBPluginDependency 3667.IBPluginDependency - 3689.IBAttributePlaceholdersKey - 3689.IBPluginDependency - 3690.IBPluginDependency - 3692.IBAttributePlaceholdersKey - 3692.IBPluginDependency - 3693.IBPluginDependency 3709.IBPluginDependency 3712.IBPluginDependency 3712.IBWindowTemplateEditedContentRect @@ -52220,6 +52498,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 3782.IBViewBoundsToFrameTransform 3783.IBPluginDependency 3784.IBPluginDependency + 3784.IBViewBoundsToFrameTransform 3786.IBPluginDependency 3786.IBViewBoundsToFrameTransform 3787.IBPluginDependency @@ -52281,18 +52560,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 3849.IBPluginDependency 3849.IBViewBoundsToFrameTransform 3850.IBPluginDependency - 3878.IBPluginDependency - 3878.IBViewBoundsToFrameTransform - 3879.IBPluginDependency - 3880.IBAttributePlaceholdersKey - 3880.IBPluginDependency - 3881.IBAttributePlaceholdersKey - 3881.IBPluginDependency - 3882.IBPluginDependency - 3883.IBAttributePlaceholdersKey - 3883.IBPluginDependency - 3884.IBAttributePlaceholdersKey - 3884.IBPluginDependency 3885.IBPluginDependency 3885.IBViewBoundsToFrameTransform 3886.IBAttributePlaceholdersKey @@ -52303,6 +52570,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 3888.IBPluginDependency 3888.IBViewBoundsToFrameTransform 3889.IBPluginDependency + 3890.IBEditorWindowLastContentRect 3890.IBPluginDependency 3891.IBAttributePlaceholdersKey 3891.IBPluginDependency @@ -52810,9 +53078,11 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 6135.IBPluginDependency 6159.IBAttributePlaceholdersKey 6159.IBPluginDependency + 6159.IBViewBoundsToFrameTransform 6160.IBPluginDependency 6161.IBAttributePlaceholdersKey 6161.IBPluginDependency + 6161.IBViewBoundsToFrameTransform 6162.IBPluginDependency 6168.IBPluginDependency 6169.IBEditorWindowLastContentRect @@ -52843,7 +53113,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 6233.IBPluginDependency 6234.IBAttributePlaceholdersKey 6234.IBPluginDependency - 6236.IBPluginDependency 6238.IBPluginDependency 627.IBEditorWindowLastContentRect 627.IBPluginDependency @@ -52973,8 +53242,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 6631.IBPluginDependency 6634.IBAttributePlaceholdersKey 6634.IBPluginDependency - 6635.IBAttributePlaceholdersKey - 6635.IBPluginDependency 6651.IBPluginDependency 6652.IBPluginDependency 6931.IBPluginDependency @@ -53494,12 +53761,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 8245.IBPluginDependency 8246.IBEditorWindowLastContentRect 8246.IBPluginDependency - 8247.IBPluginDependency - 8248.IBPluginDependency - 8249.IBPluginDependency 825.IBPluginDependency - 8251.IBPluginDependency - 8252.IBPluginDependency 8253.IBPluginDependency 8254.IBPluginDependency 8255.IBPluginDependency @@ -53512,15 +53774,10 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 8261.IBPluginDependency 8262.IBPluginDependency 8263.IBPluginDependency - 8264.IBPluginDependency 8265.IBPluginDependency - 8266.IBPluginDependency - 8267.IBPluginDependency 8268.IBPluginDependency 8269.IBPluginDependency 827.IBPluginDependency - 8270.IBPluginDependency - 8271.IBPluginDependency 828.IBPluginDependency 829.IBPluginDependency 8295.IBPluginDependency @@ -53966,14 +54223,90 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 9156.IBPluginDependency 9156.IBViewBoundsToFrameTransform 9157.IBPluginDependency + 9184.IBAttributePlaceholdersKey + 9184.IBPluginDependency + 9184.IBViewBoundsToFrameTransform + 9185.IBPluginDependency + 9185.IBViewBoundsToFrameTransform + 9186.IBPluginDependency + 9187.IBPluginDependency + 9188.IBEditorWindowLastContentRect + 9188.IBPluginDependency + 9195.IBPluginDependency 92.IBPluginDependency + 9206.IBPluginDependency + 9208.IBPluginDependency + 9209.IBPluginDependency + 9210.IBPluginDependency + 9211.IBPluginDependency + 9236.IBPluginDependency + 9236.IBViewBoundsToFrameTransform + 9237.IBAttributePlaceholdersKey + 9237.IBPluginDependency + 9237.IBViewBoundsToFrameTransform + 9238.IBPluginDependency 924.IBPluginDependency 925.IBPluginDependency + 9257.IBAttributePlaceholdersKey + 9257.IBPluginDependency + 9257.IBViewBoundsToFrameTransform + 9258.IBPluginDependency + 9259.IBAttributePlaceholdersKey + 9259.IBPluginDependency 926.IBPluginDependency + 9260.IBAttributePlaceholdersKey + 9260.IBPluginDependency + 9261.IBPluginDependency + 9262.IBPluginDependency + 9263.IBEditorWindowLastContentRect + 9263.IBPluginDependency + 9264.IBPluginDependency + 9265.IBPluginDependency + 9266.IBEditorWindowLastContentRect + 9266.IBPluginDependency + 9267.IBPluginDependency + 9269.IBPluginDependency 927.IBPluginDependency + 9270.IBPluginDependency + 9271.IBPluginDependency + 9272.IBPluginDependency + 9273.IBPluginDependency + 9274.IBPluginDependency + 9276.IBAttributePlaceholdersKey + 9276.IBPluginDependency + 9276.IBViewBoundsToFrameTransform + 9277.IBPluginDependency + 9278.IBPluginDependency + 9278.IBViewBoundsToFrameTransform + 9279.IBPluginDependency + 9279.IBViewBoundsToFrameTransform 928.IBPluginDependency + 9280.IBAttributePlaceholdersKey + 9280.IBPluginDependency + 9280.IBViewBoundsToFrameTransform + 9281.IBPluginDependency + 9282.IBPluginDependency + 9282.IBViewBoundsToFrameTransform + 9283.IBPluginDependency + 9284.IBPluginDependency + 9285.IBPluginDependency 929.IBPluginDependency + 9290.IBPluginDependency + 9290.IBViewBoundsToFrameTransform + 9291.IBPluginDependency + 9292.IBPluginDependency + 9292.IBViewBoundsToFrameTransform + 9293.IBPluginDependency + 9294.IBEditorWindowLastContentRect + 9294.IBPluginDependency + 9295.IBPluginDependency + 9296.IBPluginDependency + 9297.IBPluginDependency + 9299.IBPluginDependency 930.IBPluginDependency + 9300.IBPluginDependency + 9301.IBPluginDependency + 9302.IBPluginDependency 931.IBPluginDependency 932.IBPluginDependency 933.IBPluginDependency @@ -54129,7 +54462,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{13, 431}, {489, 425}} + {{51, 132}, {489, 437}} com.apple.InterfaceBuilder.CocoaPlugin InitialTabViewItem @@ -54140,6 +54473,9 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABBUAAAw8yAAA + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -54149,24 +54485,28 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 ToolTip - Sets the default video filter for new DS display views, producing a variety of visual effects. The incurred CPU usage is dependent on which filter is used. + Sets the default pixel scaler for new DS display views, producing a variety of visual effects. CPU usage is dependent on which scaler is used. com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDKAAAw7EAAA + com.apple.InterfaceBuilder.CocoaPlugin - {{144, 295}, {151, 463}} - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin + {{271, 196}, {151, 363}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + AUMnAABChgAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABCbAAAw6IAAA + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -54178,6 +54518,9 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABCbAAAw6+AAA + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin Input @@ -54191,8 +54534,9 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + {{0, 931}, {213, 198}} com.apple.InterfaceBuilder.CocoaPlugin - {{1388, 659}, {213, 198}} + {{0, 931}, {213, 198}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -54560,7 +54904,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{384, 835}, {512, 20}} + {{796, 1136}, {512, 20}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -54569,7 +54913,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{658, 542}, {315, 293}} + {{1070, 773}, {315, 363}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -54634,7 +54978,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - P4AAAL+AAABBkAAAxCKAAA + P4AAAL+AAABBkAAAw7kAAA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -54655,26 +54999,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - - ToolTip - - ToolTip - - Enable to use bilinear interpolation on the final video output by default. This creates a smoothed, but slightly blurry, image effect. - - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - ToolTip - - ToolTip - - Enable to use bilinear interpolation on the final video output. This creates a smoothed, but slightly blurry, image effect. - - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin {{1328, 256}, {288, 511}} @@ -54825,10 +55149,13 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - P4AAAL+AAABBcAAAwegAAA + P4AAAL+AAABBcAAAwywAAA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + AUGIAABCsAAAA + com.apple.InterfaceBuilder.CocoaPlugin AUGIAABDhzSAA @@ -54836,9 +55163,9 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{42, 72}, {301, 586}} + {{503, 588}, {301, 467}} com.apple.InterfaceBuilder.CocoaPlugin - {{42, 72}, {301, 586}} + {{503, 588}, {301, 467}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -54848,7 +55175,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - AUKAAABCvAAAA + AUKAAABC5gAAA com.apple.InterfaceBuilder.CocoaPlugin @@ -54957,7 +55284,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin - P4AAAL+AAABDTwAAw6sAAA + P4AAAL+AAABDTwAAw7MAAA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -54981,49 +55308,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - P4AAAL+AAABCFAAAw6mAAA - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - AUGIAABCJAAAA - - com.apple.InterfaceBuilder.CocoaPlugin - - ToolTip - - ToolTip - - DeSmuME automatically chooses the best number of rendering threads based on your hardware. - - - com.apple.InterfaceBuilder.CocoaPlugin - - ToolTip - - ToolTip - - Renders 3D on the same thread as the core emulation thread. Best performance option for single processor machines. - - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - ToolTip - - ToolTip - - Renders 3D on two separate threads. May improve 3D performance on multiprocessor machines, but slightly reduces performance on single processor machines. - - - com.apple.InterfaceBuilder.CocoaPlugin - - ToolTip - - ToolTip - - Renders 3D on four separate threads. May improve 3D performance on multiprocessor machines, but significantly reduces performance on single processor machines. - + P4AAAL+AAABCFAAAw7GAAA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -55053,9 +55338,10 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin - P4AAAL+AAABDQwAAwgAAAA + P4AAAL+AAABDLQAAwnAAAA com.apple.InterfaceBuilder.CocoaPlugin + {{797, 414}, {166, 143}} com.apple.InterfaceBuilder.CocoaPlugin ToolTip @@ -55095,12 +55381,12 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - P4AAAL+AAABCFAAAwegAAA + P4AAAL+AAABBcAAAwmQAAA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - AUKAAABDgwAAA + AUKAAABDjYAAA ToolTip @@ -55116,7 +55402,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{884, 773}, {132, 63}} + {{1081, 1073}, {132, 63}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -55817,7 +56103,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{864, 783}, {196, 53}} + {{1163, 1083}, {196, 53}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -55870,6 +56156,9 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABBiAAAxC9AAA + com.apple.InterfaceBuilder.CocoaPlugin ToolTip @@ -55880,13 +56169,16 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDhYAAw8QAAA + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{884, 733}, {123, 43}} + {{1081, 1033}, {123, 43}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{1129, 713}, {178, 43}} + {{1081, 1013}, {178, 43}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -55953,7 +56245,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin {{711, 700}, {400, 100}} com.apple.InterfaceBuilder.CocoaPlugin {{711, 700}, {400, 100}} @@ -56080,7 +56371,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - AUKAAABCEAAAA + AUPAgABCKAAAA ToolTip @@ -56121,15 +56412,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin - - ToolTip - - ToolTip - - Renders 3D on eight separate threads by default. May improve 3D performance on multiprocessor machines, but greatly reduces performance on single processor machines. - - - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -56505,7 +56787,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{973, 602}, {118, 133}} + {{1081, 903}, {118, 133}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -56572,7 +56854,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{884, 633}, {136, 163}} + {{1081, 933}, {136, 163}} com.apple.InterfaceBuilder.CocoaPlugin @@ -56652,7 +56934,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{884, 713}, {70, 103}} + {{1081, 1013}, {70, 103}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -56672,9 +56954,9 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin - {{861, 261}, {204, 601}} + {{1380, 181}, {204, 713}} com.apple.InterfaceBuilder.CocoaPlugin - {{861, 261}, {204, 601}} + {{1380, 181}, {204, 713}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -56820,17 +57102,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{973, 172}, {239, 543}} - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin + {{1385, 603}, {132, 363}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -57021,7 +57293,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin - P4AAAL+AAABBoAAAwgwAAA + P4AAAL+AAABBoAAAwxYAAA {{1184, 327}, {400, 320}} com.apple.InterfaceBuilder.CocoaPlugin @@ -57551,6 +57823,155 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 P4AAAL+AAABBoAAAwuLSAA com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Sets the default output filter for new DS display views. No CPU usage. The use of any output filter (other than Nearest Neighbor and Bilinear) requires the use of your GPU. + + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDKAAAw76AAA + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABCbAAAw70AAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{271, 464}, {235, 123}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + AUDAAABChAAAA + + + ToolTip + + ToolTip + + When set, helps to preserve the color gradations of the video. This can compensate for poor color blending from the original 16-bit NDS color palette, or for posterization caused by certain filters. No CPU usage, but requires the use of your GPU. + + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABBgAAAw1EAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + When set, filters will prefer to run on the GPU if possible. Otherwise, filters will prefer to run on the CPU if possible. + + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDKAAAw68AAA + + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Renders 3D on 16 separate threads by default. May improve 3D performance on multiprocessor machines, but greatly reduces performance on single processor machines. + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Renders 3D on 32 separate threads by default. May improve 3D performance on multiprocessor machines, but greatly reduces performance on single processor machines. + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{1385, 983}, {134, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{1385, 863}, {235, 123}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + When set, filters will prefer to run on the GPU if possible. Otherwise, filters will prefer to run on the CPU if possible. + + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABBiAAAxDYAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + AUGIAABEIwAAA + + com.apple.InterfaceBuilder.CocoaPlugin + + AUGIAABD9QAAA + + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + When set, helps to preserve the color gradations of the video. This can compensate for poor color blending from the original 16-bit NDS color palette, or for posterization caused by certain filters. No CPU usage, but requires the use of your GPU. + + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABBgAAAwjQAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABBkAAAw1UAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABBcAAAwWAAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDFgAAwxcAAA + + com.apple.InterfaceBuilder.CocoaPlugin + {{636, 598}, {138, 122}} + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -57622,7 +58043,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - 9183 + 9357 @@ -58158,18 +58579,18 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 changeRotation: changeRotationRelative: changeScale: - changeVideoFilter: + changeVideoOutputFilter: + changeVideoPixelScaler: changeVolume: copy: openRom: reset: saveScreenshotAs: - toggleBilinearFilteredOutput: toggleExecutePause: toggleFullScreenDisplay: toggleKeepMinDisplaySizeAtNormal: toggleStatusBar: - toggleVerticalSync: + toggleVideoSourceDeposterize: writeDefaultsDisplayGap: writeDefaultsDisplayRotation: writeDefaultsDisplayVideoSettings: @@ -58215,18 +58636,18 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 changeRotation: changeRotationRelative: changeScale: - changeVideoFilter: + changeVideoOutputFilter: + changeVideoPixelScaler: changeVolume: copy: openRom: reset: saveScreenshotAs: - toggleBilinearFilteredOutput: toggleExecutePause: toggleFullScreenDisplay: toggleKeepMinDisplaySizeAtNormal: toggleStatusBar: - toggleVerticalSync: + toggleVideoSourceDeposterize: writeDefaultsDisplayGap: writeDefaultsDisplayRotation: writeDefaultsDisplayVideoSettings: @@ -58267,7 +58688,11 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 id - changeVideoFilter: + changeVideoOutputFilter: + id + + + changeVideoPixelScaler: id @@ -58290,10 +58715,6 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 saveScreenshotAs: id - - toggleBilinearFilteredOutput: - id - toggleExecutePause: id @@ -58311,7 +58732,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 id - toggleVerticalSync: + toggleVideoSourceDeposterize: id @@ -60804,7 +61225,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 {698, 479} {111.60000000000001, 85.600000000000009} {515, 457} - {14, 14} + {15, 15} {8, 8} {512, 512} {11, 11} diff --git a/desmume/src/cocoa/userinterface/DisplayWindowController.h b/desmume/src/cocoa/userinterface/DisplayWindowController.h index dc5d23b75..e0c13826a 100644 --- a/desmume/src/cocoa/userinterface/DisplayWindowController.h +++ b/desmume/src/cocoa/userinterface/DisplayWindowController.h @@ -37,6 +37,15 @@ class OGLVideoOutput; InputManager *inputManager; OGLVideoOutput *oglv; CGFloat _displayRotation; + BOOL canUseShaderBasedFilters; + + BOOL _useVerticalSync; + + OSSpinLock spinlockUseVerticalSync; + OSSpinLock spinlockVideoFiltersPreferGPU; + OSSpinLock spinlockOutputFilter; + OSSpinLock spinlockSourceDeposterize; + OSSpinLock spinlockPixelScaler; // OpenGL context NSOpenGLContext *context; @@ -44,6 +53,12 @@ class OGLVideoOutput; } @property (retain) InputManager *inputManager; +@property (readonly) BOOL canUseShaderBasedFilters; +@property (assign) BOOL useVerticalSync; +@property (assign) BOOL videoFiltersPreferGPU; +@property (assign) BOOL sourceDeposterize; +@property (assign) NSInteger outputFilter; +@property (assign) NSInteger pixelScaler; - (void) drawVideoFrame; - (NSPoint) dsPointFromEvent:(NSEvent *)theEvent; @@ -75,13 +90,10 @@ class OGLVideoOutput; NSSize _normalSize; double _displayScale; double _displayRotation; - BOOL _useBilinearOutput; - BOOL _useVerticalSync; NSInteger _displayMode; NSInteger _displayOrientation; NSInteger _displayOrder; double _displayGap; - NSInteger _videoFilterType; NSInteger screenshotFileFormat; NSSize _minDisplayViewSize; @@ -92,13 +104,10 @@ class OGLVideoOutput; OSSpinLock spinlockNormalSize; OSSpinLock spinlockScale; OSSpinLock spinlockRotation; - OSSpinLock spinlockUseBilinearOutput; - OSSpinLock spinlockUseVerticalSync; OSSpinLock spinlockDisplayMode; OSSpinLock spinlockDisplayOrientation; OSSpinLock spinlockDisplayOrder; OSSpinLock spinlockDisplayGap; - OSSpinLock spinlockVideoFilterType; } @property (readonly) IBOutlet NSObject *dummyObject; @@ -114,13 +123,14 @@ class OGLVideoOutput; @property (readonly) NSSize normalSize; @property (assign) double displayScale; @property (assign) double displayRotation; -@property (assign) BOOL useBilinearOutput; -@property (assign) BOOL useVerticalSync; +@property (assign) BOOL videoFiltersPreferGPU; +@property (assign) BOOL videoSourceDeposterize; +@property (assign) NSInteger videoOutputFilter; +@property (assign) NSInteger videoPixelScaler; @property (assign) NSInteger displayMode; @property (assign) NSInteger displayOrientation; @property (assign) NSInteger displayOrder; @property (assign) double displayGap; -@property (assign) NSInteger videoFilterType; @property (assign) NSInteger screenshotFileFormat; @property (assign) BOOL isMinSizeNormal; @property (assign) BOOL isShowingStatusBar; @@ -153,9 +163,9 @@ class OGLVideoOutput; - (IBAction) changeDisplayOrientation:(id)sender; - (IBAction) changeDisplayOrder:(id)sender; - (IBAction) changeDisplayGap:(id)sender; -- (IBAction) toggleBilinearFilteredOutput:(id)sender; -- (IBAction) toggleVerticalSync:(id)sender; -- (IBAction) changeVideoFilter:(id)sender; +- (IBAction) toggleVideoSourceDeposterize:(id)sender; +- (IBAction) changeVideoOutputFilter:(id)sender; +- (IBAction) changeVideoPixelScaler:(id)sender; - (IBAction) writeDefaultsDisplayRotation:(id)sender; - (IBAction) writeDefaultsDisplayGap:(id)sender; diff --git a/desmume/src/cocoa/userinterface/DisplayWindowController.mm b/desmume/src/cocoa/userinterface/DisplayWindowController.mm index 066a47edc..29e7f31c0 100644 --- a/desmume/src/cocoa/userinterface/DisplayWindowController.mm +++ b/desmume/src/cocoa/userinterface/DisplayWindowController.mm @@ -48,13 +48,14 @@ @dynamic normalSize; @dynamic displayScale; @dynamic displayRotation; -@dynamic useBilinearOutput; -@dynamic useVerticalSync; +@dynamic videoFiltersPreferGPU; +@dynamic videoSourceDeposterize; +@dynamic videoOutputFilter; +@dynamic videoPixelScaler; @dynamic displayMode; @dynamic displayOrientation; @dynamic displayOrder; @dynamic displayGap; -@dynamic videoFilterType; @synthesize screenshotFileFormat; @dynamic isMinSizeNormal; @dynamic isShowingStatusBar; @@ -81,13 +82,10 @@ static std::tr1::unordered_map _screenMap spinlockNormalSize = OS_SPINLOCK_INIT; spinlockScale = OS_SPINLOCK_INIT; spinlockRotation = OS_SPINLOCK_INIT; - spinlockUseBilinearOutput = OS_SPINLOCK_INIT; - spinlockUseVerticalSync = OS_SPINLOCK_INIT; spinlockDisplayMode = OS_SPINLOCK_INIT; spinlockDisplayOrientation = OS_SPINLOCK_INIT; spinlockDisplayOrder = OS_SPINLOCK_INIT; spinlockDisplayGap = OS_SPINLOCK_INIT; - spinlockVideoFilterType = OS_SPINLOCK_INIT; screenshotFileFormat = NSTIFFFileType; @@ -224,42 +222,6 @@ static std::tr1::unordered_map _screenMap return angleDegrees; } -- (void) setUseBilinearOutput:(BOOL)theState -{ - OSSpinLockLock(&spinlockUseBilinearOutput); - _useBilinearOutput = theState; - OSSpinLockUnlock(&spinlockUseBilinearOutput); - - [[self view] doBilinearOutputChanged:theState]; -} - -- (BOOL) useBilinearOutput -{ - OSSpinLockLock(&spinlockUseBilinearOutput); - const BOOL theState = _useBilinearOutput; - OSSpinLockUnlock(&spinlockUseBilinearOutput); - - return theState; -} - -- (void) setUseVerticalSync:(BOOL)theState -{ - OSSpinLockLock(&spinlockUseVerticalSync); - _useVerticalSync = theState; - OSSpinLockUnlock(&spinlockUseVerticalSync); - - [[self view] doVerticalSyncChanged:theState]; -} - -- (BOOL) useVerticalSync -{ - OSSpinLockLock(&spinlockUseVerticalSync); - const BOOL theState = _useVerticalSync; - OSSpinLockUnlock(&spinlockUseVerticalSync); - - return theState; -} - - (void) setDisplayMode:(NSInteger)displayModeID { NSSize newDisplaySize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT); @@ -416,22 +378,48 @@ static std::tr1::unordered_map _screenMap return gapScalar; } -- (void) setVideoFilterType:(NSInteger)typeID +- (void) setVideoFiltersPreferGPU:(BOOL)theState { - OSSpinLockLock(&spinlockVideoFilterType); - _videoFilterType = typeID; - OSSpinLockUnlock(&spinlockVideoFilterType); - - [CocoaDSUtil messageSendOneWayWithInteger:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_CHANGE_VIDEO_FILTER integerValue:typeID]; + [[self view] setVideoFiltersPreferGPU:theState]; + [CocoaDSUtil messageSendOneWay:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_REPROCESS_AND_REDRAW]; } -- (NSInteger) videoFilterType +- (BOOL) videoFiltersPreferGPU { - OSSpinLockLock(&spinlockVideoFilterType); - const NSInteger typeID = _videoFilterType; - OSSpinLockUnlock(&spinlockVideoFilterType); - - return typeID; + return [[self view] videoFiltersPreferGPU]; +} + +- (void) setVideoSourceDeposterize:(BOOL)theState +{ + [[self view] setSourceDeposterize:theState]; + [CocoaDSUtil messageSendOneWay:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_REPROCESS_AND_REDRAW]; +} + +- (BOOL) videoSourceDeposterize +{ + return [[self view] sourceDeposterize]; +} + +- (void) setVideoOutputFilter:(NSInteger)filterID +{ + [[self view] setOutputFilter:filterID]; + [CocoaDSUtil messageSendOneWay:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_REPROCESS_AND_REDRAW]; +} + +- (NSInteger) videoOutputFilter +{ + return [[self view] outputFilter]; +} + +- (void) setVideoPixelScaler:(NSInteger)filterID +{ + [[self view] setPixelScaler:filterID]; + [CocoaDSUtil messageSendOneWay:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_REPROCESS_AND_REDRAW]; +} + +- (NSInteger) videoPixelScaler +{ + return [[self view] pixelScaler]; } - (void) setIsMinSizeNormal:(BOOL)theState @@ -533,9 +521,11 @@ static std::tr1::unordered_map _screenMap [self setDisplayOrder:[[NSUserDefaults standardUserDefaults] integerForKey:@"DisplayViewCombo_Order"]]; [self setDisplayScale:([[NSUserDefaults standardUserDefaults] doubleForKey:@"DisplayView_Size"] / 100.0)]; [self setDisplayRotation:[[NSUserDefaults standardUserDefaults] doubleForKey:@"DisplayView_Rotation"]]; - [self setVideoFilterType:[[NSUserDefaults standardUserDefaults] integerForKey:@"DisplayView_VideoFilter"]]; - [self setUseBilinearOutput:[[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayView_UseBilinearOutput"]]; - [self setUseVerticalSync:[[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayView_UseVerticalSync"]]; + [self setVideoFiltersPreferGPU:[[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayView_FiltersPreferGPU"]]; + [self setVideoSourceDeposterize:[[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayView_Deposterize"]]; + [self setVideoOutputFilter:[[NSUserDefaults standardUserDefaults] integerForKey:@"DisplayView_OutputFilter"]]; + [self setVideoPixelScaler:[[NSUserDefaults standardUserDefaults] integerForKey:@"DisplayView_VideoFilter"]]; + [[self view] setUseVerticalSync:[[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayView_UseVerticalSync"]]; } - (double) resizeWithTransform:(NSSize)normalBounds scalar:(double)scalar rotation:(double)angleDegrees @@ -861,19 +851,19 @@ static std::tr1::unordered_map _screenMap [self setDisplayGap:(double)[CocoaDSUtil getIBActionSenderTag:sender] / 100.0]; } -- (IBAction) toggleBilinearFilteredOutput:(id)sender +- (IBAction) toggleVideoSourceDeposterize:(id)sender { - [self setUseBilinearOutput:([self useBilinearOutput]) ? NO : YES]; + [self setVideoSourceDeposterize:![self videoSourceDeposterize]]; } -- (IBAction) toggleVerticalSync:(id)sender +- (IBAction) changeVideoOutputFilter:(id)sender { - [self setUseVerticalSync:([self useVerticalSync]) ? NO : YES]; + [self setVideoOutputFilter:[CocoaDSUtil getIBActionSenderTag:sender]]; } -- (IBAction) changeVideoFilter:(id)sender +- (IBAction) changeVideoPixelScaler:(id)sender { - [self setVideoFilterType:[CocoaDSUtil getIBActionSenderTag:sender]]; + [self setVideoPixelScaler:[CocoaDSUtil getIBActionSenderTag:sender]]; } - (IBAction) writeDefaultsDisplayRotation:(id)sender @@ -893,9 +883,11 @@ static std::tr1::unordered_map _screenMap - (IBAction) writeDefaultsDisplayVideoSettings:(id)sender { - [[NSUserDefaults standardUserDefaults] setInteger:[self videoFilterType] forKey:@"DisplayView_VideoFilter"]; - [[NSUserDefaults standardUserDefaults] setBool:[self useBilinearOutput] forKey:@"DisplayView_UseBilinearOutput"]; - [[NSUserDefaults standardUserDefaults] setBool:[self useVerticalSync] forKey:@"DisplayView_UseVerticalSync"]; + [[NSUserDefaults standardUserDefaults] setBool:[self videoFiltersPreferGPU] forKey:@"DisplayView_FiltersPreferGPU"]; + [[NSUserDefaults standardUserDefaults] setBool:[self videoSourceDeposterize] forKey:@"DisplayView_Deposterize"]; + [[NSUserDefaults standardUserDefaults] setInteger:[self videoOutputFilter] forKey:@"DisplayView_OutputFilter"]; + [[NSUserDefaults standardUserDefaults] setInteger:[self videoPixelScaler] forKey:@"DisplayView_VideoFilter"]; + [[NSUserDefaults standardUserDefaults] setBool:[[self view] useVerticalSync] forKey:@"DisplayView_UseVerticalSync"]; } #pragma mark NSUserInterfaceValidations Protocol @@ -991,25 +983,42 @@ static std::tr1::unordered_map _screenMap } } } - else if (theAction == @selector(toggleBilinearFilteredOutput:)) + else if (theAction == @selector(changeVideoOutputFilter:)) { if ([(id)theItem isMemberOfClass:[NSMenuItem class]]) { - [(NSMenuItem *)theItem setState:([self useBilinearOutput]) ? NSOnState : NSOffState]; + [(NSMenuItem *)theItem setState:([self videoOutputFilter] == [theItem tag]) ? NSOnState : NSOffState]; + enable = ([theItem tag] == OutputFilterTypeID_NearestNeighbor || [theItem tag] == OutputFilterTypeID_Bilinear) || [[self view] canUseShaderBasedFilters]; } } + else if (theAction == @selector(toggleVideoSourceDeposterize:)) + { + if ([(id)theItem isMemberOfClass:[NSMenuItem class]]) + { + [(NSMenuItem *)theItem setState:([self videoSourceDeposterize]) ? NSOnState : NSOffState]; + enable = [[self view] canUseShaderBasedFilters]; + } + + enable = [[self view] canUseShaderBasedFilters]; + } else if (theAction == @selector(toggleVerticalSync:)) { if ([(id)theItem isMemberOfClass:[NSMenuItem class]]) { - [(NSMenuItem *)theItem setState:([self useVerticalSync]) ? NSOnState : NSOffState]; + [(NSMenuItem *)theItem setState:([[self view] useVerticalSync]) ? NSOnState : NSOffState]; } } - else if (theAction == @selector(changeVideoFilter:)) + else if (theAction == @selector(changeVideoPixelScaler:)) { if ([(id)theItem isMemberOfClass:[NSMenuItem class]]) { - [(NSMenuItem *)theItem setState:([self videoFilterType] == [theItem tag]) ? NSOnState : NSOffState]; + [(NSMenuItem *)theItem setState:([self videoPixelScaler] == [theItem tag]) ? NSOnState : NSOffState]; + + bool isSupportingCPU = false; + bool isSupportingShader = false; + OGLFilter::GetSupport([theItem tag], &isSupportingCPU, &isSupportingShader); + + enable = isSupportingCPU || (isSupportingShader && [[self view] canUseShaderBasedFilters]); } } else if (theAction == @selector(toggleStatusBar:)) @@ -1079,10 +1088,6 @@ static std::tr1::unordered_map _screenMap // Setup default values per user preferences. [self setupUserDefaults]; - // Set the video filter source size now since the proper size is needed on initialization. - // If we don't do this, new windows could draw incorrectly. - [CocoaDSUtil messageSendOneWayWithInteger:[cdsVideoOutput receivePort] msgID:MESSAGE_CHANGE_VIDEO_FILTER integerValue:[self videoFilterType]]; - // Add the video thread to the output list. [emuControl addOutputToCore:cdsVideoOutput]; } @@ -1257,6 +1262,12 @@ static std::tr1::unordered_map _screenMap @implementation DisplayView @synthesize inputManager; +@synthesize canUseShaderBasedFilters; +@dynamic useVerticalSync; +@dynamic videoFiltersPreferGPU; +@dynamic sourceDeposterize; +@dynamic outputFilter; +@dynamic pixelScaler; - (id)initWithFrame:(NSRect)frameRect { @@ -1267,7 +1278,6 @@ static std::tr1::unordered_map _screenMap } inputManager = nil; - oglv = new OGLVideoOutput(); // Initialize the OpenGL context NSOpenGLPixelFormatAttribute attributes[] = { @@ -1285,9 +1295,25 @@ static std::tr1::unordered_map _screenMap CGLContextObj prevContext = CGLGetCurrentContext(); CGLSetCurrentContext(cglDisplayContext); - oglv->InitializeOGL(); + oglv = new OGLVideoOutput(); + oglv->InitLayers(); + oglv->GetDisplayLayer()->SetFiltersPreferGPUOGL(true); + oglv->GetDisplayLayer()->SetSourceDeposterize(false); + oglv->GetDisplayLayer()->SetOutputFilterOGL(OutputFilterTypeID_Bilinear); + oglv->GetDisplayLayer()->SetPixelScalerOGL(VideoFilterTypeID_None); CGLSetCurrentContext(prevContext); + OGLDisplayLayer *displayLayer = oglv->GetDisplayLayer(); + canUseShaderBasedFilters = (displayLayer->CanUseShaderBasedFilters()) ? YES : NO; + + _useVerticalSync = NO; + + spinlockUseVerticalSync = OS_SPINLOCK_INIT; + spinlockVideoFiltersPreferGPU = OS_SPINLOCK_INIT; + spinlockOutputFilter = OS_SPINLOCK_INIT; + spinlockSourceDeposterize = OS_SPINLOCK_INIT; + spinlockPixelScaler = OS_SPINLOCK_INIT; + return self; } @@ -1295,18 +1321,120 @@ static std::tr1::unordered_map _screenMap { CGLContextObj prevContext = CGLGetCurrentContext(); CGLSetCurrentContext(cglDisplayContext); - oglv->TerminateOGL(); + delete oglv; CGLSetCurrentContext(prevContext); [self setInputManager:nil]; [context clearDrawable]; [context release]; - delete oglv; - [super dealloc]; } +#pragma mark Dynamic Property Methods + +- (void) setUseVerticalSync:(BOOL)theState +{ + OSSpinLockLock(&spinlockUseVerticalSync); + _useVerticalSync = theState; + OSSpinLockUnlock(&spinlockUseVerticalSync); + + const GLint swapInt = (theState) ? 1 : 0; + + CGLLockContext(cglDisplayContext); + CGLSetCurrentContext(cglDisplayContext); + CGLSetParameter(cglDisplayContext, kCGLCPSwapInterval, &swapInt); + CGLUnlockContext(cglDisplayContext); +} + +- (BOOL) useVerticalSync +{ + OSSpinLockLock(&spinlockUseVerticalSync); + const BOOL theState = _useVerticalSync; + OSSpinLockUnlock(&spinlockUseVerticalSync); + + return theState; +} + +- (void) setVideoFiltersPreferGPU:(BOOL)theState +{ + OSSpinLockLock(&spinlockVideoFiltersPreferGPU); + + CGLLockContext(cglDisplayContext); + CGLSetCurrentContext(cglDisplayContext); + oglv->GetDisplayLayer()->SetFiltersPreferGPUOGL((theState) ? true : false); + CGLUnlockContext(cglDisplayContext); + + OSSpinLockUnlock(&spinlockVideoFiltersPreferGPU); +} + +- (BOOL) videoFiltersPreferGPU +{ + OSSpinLockLock(&spinlockVideoFiltersPreferGPU); + const BOOL theState = (oglv->GetDisplayLayer()->GetFiltersPreferGPU()) ? YES : NO; + OSSpinLockUnlock(&spinlockVideoFiltersPreferGPU); + + return theState; +} + +- (void) setSourceDeposterize:(BOOL)theState +{ + OSSpinLockLock(&spinlockSourceDeposterize); + oglv->GetDisplayLayer()->SetSourceDeposterize((theState) ? true : false); + OSSpinLockUnlock(&spinlockSourceDeposterize); +} + +- (BOOL) sourceDeposterize +{ + OSSpinLockLock(&spinlockSourceDeposterize); + const BOOL theState = (oglv->GetDisplayLayer()->GetSourceDeposterize()) ? YES : NO; + OSSpinLockUnlock(&spinlockSourceDeposterize); + + return theState; +} + +- (void) setOutputFilter:(NSInteger)filterID +{ + OSSpinLockLock(&spinlockOutputFilter); + + CGLLockContext(cglDisplayContext); + CGLSetCurrentContext(cglDisplayContext); + oglv->GetDisplayLayer()->SetOutputFilterOGL(filterID); + CGLUnlockContext(cglDisplayContext); + + OSSpinLockUnlock(&spinlockOutputFilter); +} + +- (NSInteger) outputFilter +{ + OSSpinLockLock(&spinlockOutputFilter); + const NSInteger filterID = oglv->GetDisplayLayer()->GetOutputFilter(); + OSSpinLockUnlock(&spinlockOutputFilter); + + return filterID; +} + +- (void) setPixelScaler:(NSInteger)filterID +{ + OSSpinLockLock(&spinlockPixelScaler); + + CGLLockContext(cglDisplayContext); + CGLSetCurrentContext(cglDisplayContext); + oglv->GetDisplayLayer()->SetPixelScalerOGL(filterID); + CGLUnlockContext(cglDisplayContext); + + OSSpinLockUnlock(&spinlockPixelScaler); +} + +- (NSInteger) pixelScaler +{ + OSSpinLockLock(&spinlockPixelScaler); + const NSInteger filterID = oglv->GetDisplayLayer()->GetPixelScaler(); + OSSpinLockUnlock(&spinlockPixelScaler); + + return filterID; +} + #pragma mark Class Methods - (void) drawVideoFrame @@ -1645,31 +1773,28 @@ static std::tr1::unordered_map _screenMap - (void)doProcessVideoFrame:(const void *)videoFrameData displayMode:(const NSInteger)frameDisplayMode width:(const NSInteger)frameWidth height:(const NSInteger)frameHeight { - const bool didDisplayModeChange = (oglv->GetDisplayMode() != frameDisplayMode); - if (didDisplayModeChange) + OGLDisplayLayer *display = oglv->GetDisplayLayer(); + + if (display->GetMode() != frameDisplayMode) { - oglv->SetDisplayMode(frameDisplayMode); + display->SetMode(frameDisplayMode); } CGLLockContext(cglDisplayContext); CGLSetCurrentContext(cglDisplayContext); - - if (didDisplayModeChange) - { - oglv->UploadVerticesOGL(); - } - - oglv->PrerenderOGL(videoFrameData, frameWidth, frameHeight); + oglv->ProcessOGL((uint16_t *)videoFrameData, frameWidth, frameHeight); [self drawVideoFrame]; - CGLUnlockContext(cglDisplayContext); } - (void)doResizeView:(NSRect)rect { + const GLsizei w = (GLsizei)rect.size.width; + const GLsizei h = (GLsizei)rect.size.height; + CGLLockContext(cglDisplayContext); CGLSetCurrentContext(cglDisplayContext); - oglv->SetViewportSizeOGL(rect.size.width, rect.size.height); + oglv->SetViewportSizeOGL(w, h); [self drawVideoFrame]; CGLUnlockContext(cglDisplayContext); } @@ -1677,13 +1802,10 @@ static std::tr1::unordered_map _screenMap - (void)doTransformView:(const DisplayOutputTransformData *)transformData { _displayRotation = (GLfloat)transformData->rotation; - oglv->SetRotation((GLfloat)transformData->rotation); - CGLLockContext(cglDisplayContext); - CGLSetCurrentContext(cglDisplayContext); - oglv->UpdateDisplayTransformationOGL(); - [self drawVideoFrame]; - CGLUnlockContext(cglDisplayContext); + OGLDisplayLayer *display = oglv->GetDisplayLayer(); + display->SetRotation((GLfloat)transformData->rotation); + [self doRedraw]; } - (void)doRedraw @@ -1696,95 +1818,42 @@ static std::tr1::unordered_map _screenMap - (void)doDisplayModeChanged:(NSInteger)displayModeID { - oglv->SetDisplayMode(displayModeID); - - CGLLockContext(cglDisplayContext); - CGLSetCurrentContext(cglDisplayContext); - oglv->UpdateDisplayTransformationOGL(); - oglv->UploadVerticesOGL(); - [self drawVideoFrame]; - CGLUnlockContext(cglDisplayContext); -} - -- (void)doBilinearOutputChanged:(BOOL)useBilinear -{ - const bool c99_useBilinear = (useBilinear) ? true : false; - - CGLLockContext(cglDisplayContext); - CGLSetCurrentContext(cglDisplayContext); - oglv->SetDisplayBilinearOGL(c99_useBilinear); - [self drawVideoFrame]; - CGLUnlockContext(cglDisplayContext); + OGLDisplayLayer *display = oglv->GetDisplayLayer(); + display->SetMode(displayModeID); + [self doRedraw]; } - (void)doDisplayOrientationChanged:(NSInteger)displayOrientationID { - oglv->SetDisplayOrientation(displayOrientationID); + OGLDisplayLayer *display = oglv->GetDisplayLayer(); + display->SetOrientation(displayOrientationID); - CGLLockContext(cglDisplayContext); - CGLSetCurrentContext(cglDisplayContext); - - oglv->UploadVerticesOGL(); - - if (oglv->GetDisplayMode() == DS_DISPLAY_TYPE_DUAL) + if (display->GetMode() == DS_DISPLAY_TYPE_DUAL) { - oglv->UpdateDisplayTransformationOGL(); - [self drawVideoFrame]; + [self doRedraw]; } - - CGLUnlockContext(cglDisplayContext); } - (void)doDisplayOrderChanged:(NSInteger)displayOrderID { - oglv->SetDisplayOrder(displayOrderID); + OGLDisplayLayer *display = oglv->GetDisplayLayer(); + display->SetOrder(displayOrderID); - CGLLockContext(cglDisplayContext); - CGLSetCurrentContext(cglDisplayContext); - - oglv->UploadVerticesOGL(); - if (oglv->GetDisplayMode() == DS_DISPLAY_TYPE_DUAL) + if (display->GetMode() == DS_DISPLAY_TYPE_DUAL) { - [self drawVideoFrame]; + [self doRedraw]; } - - CGLUnlockContext(cglDisplayContext); } - (void)doDisplayGapChanged:(float)displayGapScalar { - oglv->SetGapScalar((GLfloat)displayGapScalar); + OGLDisplayLayer *display = oglv->GetDisplayLayer(); + display->SetGapScalar((GLfloat)displayGapScalar); - CGLLockContext(cglDisplayContext); - CGLSetCurrentContext(cglDisplayContext); - - oglv->UploadVerticesOGL(); - - if (oglv->GetDisplayMode() == DS_DISPLAY_TYPE_DUAL) + if (display->GetMode() == DS_DISPLAY_TYPE_DUAL) { - oglv->UpdateDisplayTransformationOGL(); - [self drawVideoFrame]; + [self doRedraw]; } - - CGLUnlockContext(cglDisplayContext); -} - -- (void)doVerticalSyncChanged:(BOOL)useVerticalSync -{ - const GLint swapInt = (useVerticalSync) ? 1 : 0; - - CGLLockContext(cglDisplayContext); - CGLSetCurrentContext(cglDisplayContext); - CGLSetParameter(cglDisplayContext, kCGLCPSwapInterval, &swapInt); - CGLUnlockContext(cglDisplayContext); -} - -- (void)doVideoFilterChanged:(NSInteger)videoFilterTypeID -{ - CGLLockContext(cglDisplayContext); - CGLSetCurrentContext(cglDisplayContext); - oglv->SetVideoFilterOGL((const VideoFilterTypeID)videoFilterTypeID); - CGLUnlockContext(cglDisplayContext); } @end diff --git a/desmume/src/cocoa/userinterface/appDelegate.mm b/desmume/src/cocoa/userinterface/appDelegate.mm index 6916bce66..310026273 100644 --- a/desmume/src/cocoa/userinterface/appDelegate.mm +++ b/desmume/src/cocoa/userinterface/appDelegate.mm @@ -606,9 +606,11 @@ const NSInteger displayOrientation = [(NSNumber *)[windowProperties valueForKey:@"displayOrientation"] integerValue]; const NSInteger displayOrder = [(NSNumber *)[windowProperties valueForKey:@"displayOrder"] integerValue]; const double displayGap = [(NSNumber *)[windowProperties valueForKey:@"displayGap"] doubleValue]; - const NSInteger videoFilterType = [(NSNumber *)[windowProperties valueForKey:@"videoFilterType"] integerValue]; + const BOOL videoFiltersPreferGPU = [(NSNumber *)[windowProperties valueForKey:@"videoFiltersPreferGPU"] boolValue]; + const BOOL videoSourceDeposterize = [(NSNumber *)[windowProperties valueForKey:@"videoSourceDeposterize"] boolValue]; + const NSInteger videoPixelScaler = [(NSNumber *)[windowProperties valueForKey:@"videoFilterType"] integerValue]; + const NSInteger videoOutputFilter = [(NSNumber *)[windowProperties valueForKey:@"videoOutputFilter"] integerValue]; const NSInteger screenshotFileFormat = [(NSNumber *)[windowProperties valueForKey:@"screenshotFileFormat"] integerValue]; - const BOOL useBilinearOutput = [(NSNumber *)[windowProperties valueForKey:@"useBilinearOutput"] boolValue]; const BOOL useVerticalSync = [(NSNumber *)[windowProperties valueForKey:@"useVerticalSync"] boolValue]; const BOOL isMinSizeNormal = [(NSNumber *)[windowProperties valueForKey:@"isMinSizeNormal"] boolValue]; const BOOL isShowingStatusBar = [(NSNumber *)[windowProperties valueForKey:@"isShowingStatusBar"] boolValue]; @@ -625,15 +627,17 @@ [windowController setIsMinSizeNormal:isMinSizeNormal]; [windowController setIsShowingStatusBar:isShowingStatusBar]; - [windowController setVideoFilterType:videoFilterType]; + [windowController setVideoFiltersPreferGPU:videoFiltersPreferGPU]; + [windowController setVideoSourceDeposterize:videoSourceDeposterize]; + [windowController setVideoPixelScaler:videoPixelScaler]; + [windowController setVideoOutputFilter:videoOutputFilter]; [windowController setDisplayMode:displayMode]; [windowController setDisplayRotation:displayRotation]; [windowController setDisplayOrientation:displayOrientation]; [windowController setDisplayOrder:displayOrder]; [windowController setDisplayGap:displayGap]; [windowController setScreenshotFileFormat:screenshotFileFormat]; - [windowController setUseBilinearOutput:useBilinearOutput]; - [windowController setUseVerticalSync:useVerticalSync]; + [[windowController view] setUseVerticalSync:useVerticalSync]; [windowController setDisplayScale:displayScale]; [[windowController masterWindow] setFrameOrigin:NSMakePoint(frameX, frameY)]; @@ -702,10 +706,12 @@ [NSNumber numberWithInteger:[windowController displayOrientation]], @"displayOrientation", [NSNumber numberWithInteger:[windowController displayOrder]], @"displayOrder", [NSNumber numberWithDouble:[windowController displayGap]], @"displayGap", - [NSNumber numberWithInteger:[windowController videoFilterType]], @"videoFilterType", + [NSNumber numberWithBool:[windowController videoFiltersPreferGPU]], @"videoFiltersPreferGPU", + [NSNumber numberWithInteger:[windowController videoPixelScaler]], @"videoFilterType", [NSNumber numberWithInteger:[windowController screenshotFileFormat]], @"screenshotFileFormat", - [NSNumber numberWithBool:[windowController useBilinearOutput]], @"useBilinearOutput", - [NSNumber numberWithBool:[windowController useVerticalSync]], @"useVerticalSync", + [NSNumber numberWithInteger:[windowController videoOutputFilter]], @"videoOutputFilter", + [NSNumber numberWithBool:[windowController videoSourceDeposterize]], @"videoSourceDeposterize", + [NSNumber numberWithBool:[[windowController view] useVerticalSync]], @"useVerticalSync", [NSNumber numberWithBool:[windowController isMinSizeNormal]], @"isMinSizeNormal", [NSNumber numberWithBool:[windowController isShowingStatusBar]], @"isShowingStatusBar", [NSNumber numberWithBool:isInFullScreenMode], @"isInFullScreenMode",