diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index 9744a82ef..cbb87bcb1 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -35,7 +35,6 @@ #include "gfx3d.h" #include "debug.h" #include "NDSSystem.h" -#include "readwrite.h" #include "matrix.h" #include "emufile.h" @@ -7456,6 +7455,8 @@ void GPUSubsystem::Reset() this->_willFrameSkip = false; this->_videoFrameCount = 0; this->_render3DFrameCount = 0; + this->_backlightIntensityTotal[NDSDisplayID_Main] = 0.0f; + this->_backlightIntensityTotal[NDSDisplayID_Touch] = 0.0f; this->ClearWithColor(0xFFFF); @@ -7476,6 +7477,9 @@ void GPUSubsystem::Reset() this->_displayInfo.engineID[NDSDisplayID_Main] = GPUEngineID_Main; this->_displayInfo.engineID[NDSDisplayID_Touch] = GPUEngineID_Sub; + this->_displayInfo.backlightIntensity[NDSDisplayID_Main] = 1.0f; + this->_displayInfo.backlightIntensity[NDSDisplayID_Touch] = 1.0f; + this->_display[NDSDisplayID_Main]->SetEngineByID(GPUEngineID_Main); this->_display[NDSDisplayID_Touch]->SetEngineByID(GPUEngineID_Sub); @@ -8111,6 +8115,12 @@ void GPUSubsystem::RenderLine(const size_t l) this->_displayInfo.needConvertColorFormat[NDSDisplayID_Main] = (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev); this->_displayInfo.needConvertColorFormat[NDSDisplayID_Touch] = (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev); + // Set the average backlight intensity and then reset the current total. + this->_displayInfo.backlightIntensity[NDSDisplayID_Main] = this->_backlightIntensityTotal[NDSDisplayID_Main] / 263.0f; + this->_displayInfo.backlightIntensity[NDSDisplayID_Touch] = this->_backlightIntensityTotal[NDSDisplayID_Touch] / 263.0f; + this->_backlightIntensityTotal[NDSDisplayID_Main] = 0.0f; + this->_backlightIntensityTotal[NDSDisplayID_Touch] = 0.0f; + this->_engineMain->UpdateMasterBrightnessDisplayInfo(this->_displayInfo); this->_engineSub->UpdateMasterBrightnessDisplayInfo(this->_displayInfo); @@ -8135,6 +8145,32 @@ void GPUSubsystem::RenderLine(const size_t l) } } +void GPUSubsystem::UpdateAverageBacklightIntensityTotal() +{ + // The values in this table are, more or less, arbitrarily chosen. + // + // It would be nice to get some real testing done on a hardware NDS to have some more + // accurate intensity values for each backlight level. + static const float backlightLevelToIntensityTable[] = {0.100, 0.300, 0.600, 1.000}; + + IOREG_POWERMANCTL POWERMANCTL; + IOREG_BACKLIGHTCTL BACKLIGHTCTL; + POWERMANCTL.value = MMU.powerMan_Reg[0]; + BACKLIGHTCTL.value = MMU.powerMan_Reg[4]; + + if (POWERMANCTL.MainBacklight_Enable != 0) + { + const BacklightLevel level = ((BACKLIGHTCTL.ExternalPowerState != 0) && (BACKLIGHTCTL.ForceMaxBrightnessWithExtPower_Enable != 0)) ? BacklightLevel_Maximum : (BacklightLevel)BACKLIGHTCTL.Level; + this->_backlightIntensityTotal[NDSDisplayID_Main] += backlightLevelToIntensityTable[level]; + } + + if (POWERMANCTL.TouchBacklight_Enable != 0) + { + const BacklightLevel level = ((BACKLIGHTCTL.ExternalPowerState != 0) && (BACKLIGHTCTL.ForceMaxBrightnessWithExtPower_Enable != 0)) ? BacklightLevel_Maximum : (BacklightLevel)BACKLIGHTCTL.Level; + this->_backlightIntensityTotal[NDSDisplayID_Touch] += backlightLevelToIntensityTable[level]; + } +} + void GPUSubsystem::ClearWithColor(const u16 colorBGRA5551) { u16 color16 = colorBGRA5551; diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index 680f122de..113f5da1d 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -764,6 +764,70 @@ typedef struct } GPU_IOREG; // 0x04000000, 0x04001000: GPU registers #include "PACKED_END.h" +typedef union +{ + u8 value; + + struct + { +#ifndef MSB_FIRST + u8 SoundAmp_Enable:1; // 0: Sound amplifier; 0=Disable, 1=Enable + u8 SoundAmp_Mute:1; // 1: Sound amplifier mute control; 0=Normal, 1=Mute + u8 TouchBacklight_Enable:1; // 2: Touch display backlight; 0=Disable, 1=Enable + u8 MainBacklight_Enable:1; // 3: Main display backlight; 0=Disable, 1=Enable + u8 PowerLEDBlink_Enable:1; // 4: Power LED blink control; 0=Disable (Power LED remains steadily ON), 1=Enable + u8 PowerLEDBlinkSpeed:1; // 5: Power LED blink speed when enabled; 0=Slow, 1=Fast + u8 SystemPowerState:2; // 6: NDS system power state; 0=System is powered ON, 1=System is powered OFF + u8 :1; // 7: Unused bit (should always be read as 0) +#else + u8 :1; // 7: Unused bit (should always be read as 0) + u8 SystemPowerState:2; // 6: NDS system power state; 0=System is powered ON, 1=System is powered OFF + u8 PowerLEDBlinkSpeed:1; // 5: Power LED blink speed when enabled; 0=Slow, 1=Fast + u8 PowerLEDBlink_Enable:1; // 4: Power LED blink control; 0=Disable (LED is steady ON), 1=Enable + u8 MainBacklight_Enable:1; // 3: Main display backlight; 0=Disable, 1=Enable + u8 TouchBacklight_Enable:1; // 2: Touch display backlight; 0=Disable, 1=Enable + u8 SoundAmp_Mute:1; // 1: Sound amplifier mute control; 0=Normal, 1=Mute + u8 SoundAmp_Enable:1; // 0: Sound amplifier; 0=Disable, 1=Enable +#endif + }; +} IOREG_POWERMANCTL; + +typedef union +{ + u8 value; + + struct + { +#ifndef MSB_FIRST + u8 Level:2; // 0-1: Backlight brightness level; + // 0=Low + // 1=Medium + // 2=High + // 3=Maximum + u8 ForceMaxBrightnessWithExtPower_Enable:1; // 2: Forces maximum brightness if external power is present, interacts with Bit 3; 0=Disable, 1=Enable + u8 ExternalPowerState:1; // 3: External power state; 0=External power is not present, 1=External power is present + u8 :4; // 4-7: Unknown bits (should always be read as 4) +#else + u8 :4; // 4-7: Unknown bits (should always be read as 4) + u8 ExternalPowerState:1; // 3: External power state; 0=External power is not present, 1=External power is present + u8 ForceMaxBrightnessWithExtPower_Enable:1; // 2: Forces maximum brightness if external power is present, interacts with Bit 3; 0=Disable, 1=Enable + u8 Level:2; // 0-1: Backlight brightness level; + // 0=Low + // 1=Medium + // 2=High + // 3=Maximum +#endif + }; +} IOREG_BACKLIGHTCTL; + +enum BacklightLevel +{ + BacklightLevel_Low = 0, + BacklightLevel_Medium = 1, + BacklightLevel_High = 2, + BacklightLevel_Maximum = 3 +}; + enum ColorEffect { ColorEffect_Disable = 0, @@ -1115,6 +1179,10 @@ typedef struct u8 masterBrightnessMode[2][GPU_FRAMEBUFFER_NATIVE_HEIGHT]; // The master brightness mode of each display line. u8 masterBrightnessIntensity[2][GPU_FRAMEBUFFER_NATIVE_HEIGHT]; // The master brightness intensity of each display line. + float backlightIntensity[2]; // Reports the intensity of the backlight. + // 0.000 - The backlight is completely off. + // 1.000 - The backlight is at its maximum brightness. + // Postprocessing information. These fields report the status of each postprocessing step. @@ -1671,6 +1739,7 @@ private: GPUEngineA *_engineMain; GPUEngineB *_engineSub; NDSDisplay *_display[2]; + float _backlightIntensityTotal[2]; u32 _videoFrameCount; // Internal variable that increments when a video frame is completed. Resets every 60 video frames. u32 _render3DFrameCount; // The current 3D rendering frame count, saved to this variable once every 60 video frames. @@ -1757,6 +1826,7 @@ public: void ResolveDisplayToCustomFramebuffer(const NDSDisplayID displayID, NDSDisplayInfo &mutableInfo); template void RenderLine(const size_t l); + void UpdateAverageBacklightIntensityTotal(); void ClearWithColor(const u16 colorBGRA5551); }; diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index ca703a584..c515fa1e6 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -1533,6 +1533,8 @@ static void execHardware_hstart() { gfx3d_VBlankEndSignal(frameSkipper.ShouldSkip3D()); } + + GPU->UpdateAverageBacklightIntensityTotal(); if (nds.VCount == 263) { diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp b/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp index cc702823a..9b0b2b2dc 100644 --- a/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp +++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp @@ -332,10 +332,11 @@ static const char *BicubicSample6x6Output_VertShader_110 = {"\ static const char *PassthroughOutputFragShader_110 = {"\ VARYING vec2 texCoord[1];\n\ uniform sampler2DRect tex;\n\ + uniform float backlightIntensity;\n\ \n\ void main()\n\ {\n\ - OUT_FRAG_COLOR.rgb = SAMPLE3_TEX_RECT(tex, texCoord[0]);\n\ + OUT_FRAG_COLOR.rgb = SAMPLE3_TEX_RECT(tex, texCoord[0]) * backlightIntensity;\n\ OUT_FRAG_COLOR.a = 1.0;\n\ }\n\ "}; @@ -583,6 +584,7 @@ static const char *FilterDeposterizeFragShader_110 = {"\ static const char *FilterBicubicBSplineFragShader_110 = {"\ VARYING vec2 texCoord[16];\n\ uniform sampler2DRect tex;\n\ + uniform float backlightIntensity;\n\ \n\ vec4 WeightBSpline(float f)\n\ {\n\ @@ -624,6 +626,7 @@ static const char *FilterBicubicBSplineFragShader_110 = {"\ + SAMPLE3_TEX_RECT(tex, texCoord[14]) * wx.g\n\ + SAMPLE3_TEX_RECT(tex, texCoord[13]) * wx.b\n\ + SAMPLE3_TEX_RECT(tex, texCoord[12]) * wx.a) * wy.a;\n\ + OUT_FRAG_COLOR.rgb *= backlightIntensity;\n\ OUT_FRAG_COLOR.a = 1.0;\n\ }\n\ "}; @@ -631,6 +634,7 @@ static const char *FilterBicubicBSplineFragShader_110 = {"\ static const char *FilterBicubicBSplineFastFragShader_110 = {"\ VARYING vec2 texCoord[1];\n\ uniform sampler2DRect tex;\n\ + uniform float backlightIntensity;\n\ \n\ void main()\n\ {\n\ @@ -652,6 +656,7 @@ static const char *FilterBicubicBSplineFastFragShader_110 = {"\ SAMPLE3_TEX_RECT(tex, vec2(t1.x, t0.y)) * s1.x) * s0.y +\n\ (SAMPLE3_TEX_RECT(tex, vec2(t0.x, t1.y)) * s0.x +\n\ SAMPLE3_TEX_RECT(tex, vec2(t1.x, t1.y)) * s1.x) * s1.y;\n\ + OUT_FRAG_COLOR.rgb *= backlightIntensity;\n\ OUT_FRAG_COLOR.a = 1.0;\n\ }\n\ "}; @@ -659,6 +664,7 @@ static const char *FilterBicubicBSplineFastFragShader_110 = {"\ static const char *FilterBicubicMitchellNetravaliFragShader_110 = {"\ VARYING vec2 texCoord[16];\n\ uniform sampler2DRect tex;\n\ + uniform float backlightIntensity;\n\ \n\ vec4 WeightMitchellNetravali(float f)\n\ {\n\ @@ -700,6 +706,7 @@ static const char *FilterBicubicMitchellNetravaliFragShader_110 = {"\ + SAMPLE3_TEX_RECT(tex, texCoord[14]) * wx.g\n\ + SAMPLE3_TEX_RECT(tex, texCoord[13]) * wx.b\n\ + SAMPLE3_TEX_RECT(tex, texCoord[12]) * wx.a) * wy.a;\n\ + OUT_FRAG_COLOR.rgb *= backlightIntensity;\n\ OUT_FRAG_COLOR.a = 1.0;\n\ }\n\ "}; @@ -707,6 +714,7 @@ static const char *FilterBicubicMitchellNetravaliFragShader_110 = {"\ static const char *FilterBicubicMitchellNetravaliFastFragShader_110 = {"\ VARYING vec2 texCoord[1];\n\ uniform sampler2DRect tex;\n\ + uniform float backlightIntensity;\n\ \n\ void main()\n\ {\n\ @@ -728,6 +736,7 @@ static const char *FilterBicubicMitchellNetravaliFastFragShader_110 = {"\ SAMPLE3_TEX_RECT(tex, vec2(t1.x, t0.y)) * s1.x) * s0.y +\n\ (SAMPLE3_TEX_RECT(tex, vec2(t0.x, t1.y)) * s0.x +\n\ SAMPLE3_TEX_RECT(tex, vec2(t1.x, t1.y)) * s1.x) * s1.y;\n\ + OUT_FRAG_COLOR.rgb *= backlightIntensity;\n\ OUT_FRAG_COLOR.a = 1.0;\n\ }\n\ "}; @@ -739,6 +748,7 @@ static const char *FilterLanczos2FragShader_110 = {"\ \n\ VARYING vec2 texCoord[16];\n\ uniform sampler2DRect tex;\n\ + uniform float backlightIntensity;\n\ \n\ vec4 WeightLanczos2(float f)\n\ {\n\ @@ -778,6 +788,7 @@ static const char *FilterLanczos2FragShader_110 = {"\ + SAMPLE3_TEX_RECT(tex, texCoord[14]) * wx.g\n\ + SAMPLE3_TEX_RECT(tex, texCoord[13]) * wx.b\n\ + SAMPLE3_TEX_RECT(tex, texCoord[12]) * wx.a) * wy.a;\n\ + OUT_FRAG_COLOR.rgb *= backlightIntensity;\n\ OUT_FRAG_COLOR.a = 1.0;\n\ }\n\ "}; @@ -795,6 +806,7 @@ static const char *FilterLanczos3FragShader_110 = {"\ VARYING vec2 texCoord[16];\n\ #endif\n\ uniform sampler2DRect tex;\n\ + uniform float backlightIntensity;\n\ \n\ vec3 weight3(float x)\n\ {\n\ @@ -938,6 +950,7 @@ static const char *FilterLanczos3FragShader_110 = {"\ + SAMPLE3_TEX_RECT(tex, texCoord[ 0] + vec2( 2.0, 3.0)) * wx1.b\n\ + SAMPLE3_TEX_RECT(tex, texCoord[ 0] + vec2( 3.0, 3.0)) * wx2.b) * wy2.b;\n\ #endif\n\ + OUT_FRAG_COLOR.rgb *= backlightIntensity;\n\ OUT_FRAG_COLOR.a = 1.0;\n\ }\n\ "}; @@ -5695,6 +5708,7 @@ OGLImage::OGLImage(OGLContextInfo *contextInfo, GLsizei imageWidth, GLsizei imag _uniformScalar = glGetUniformLocation(finalOutputProgramID, "scalar"); _uniformViewSize = glGetUniformLocation(finalOutputProgramID, "viewSize"); _uniformRenderFlipped = glGetUniformLocation(finalOutputProgramID, "renderFlipped"); + _uniformBacklightIntensity = glGetUniformLocation(finalOutputProgramID, "backlightIntensity"); glUseProgram(0); } else @@ -6225,7 +6239,12 @@ void OGLImage::ProcessOGL() void OGLImage::RenderOGL() { - glUseProgram(this->_finalOutputProgram->GetProgramID()); + if (this->_canUseShaderOutput) + { + glUseProgram(this->_finalOutputProgram->GetProgramID()); + glUniform1f(this->_uniformBacklightIntensity, 1.0f); + } + this->UploadTransformationOGL(); if (this->_needUploadVertices) @@ -6712,6 +6731,7 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO) _uniformScalar = glGetUniformLocation(finalOutputProgramID, "scalar"); _uniformViewSize = glGetUniformLocation(finalOutputProgramID, "viewSize"); _uniformRenderFlipped = glGetUniformLocation(finalOutputProgramID, "renderFlipped"); + _uniformBacklightIntensity = glGetUniformLocation(finalOutputProgramID, "backlightIntensity"); glUseProgram(0); } else @@ -7204,8 +7224,9 @@ void OGLDisplayLayer::ProcessOGL() void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) { const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo(); + const bool isShaderSupported = this->_output->GetContextInfo()->IsShaderSupported(); - if (this->_output->GetContextInfo()->IsShaderSupported()) + if (isShaderSupported) { glUseProgram(this->_finalOutputProgram->GetProgramID()); @@ -7258,6 +7279,11 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) { if (this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Main)) { + if (isShaderSupported) + { + glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[NDSDisplayID_Main]); + } + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[NDSDisplayID_Main]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[NDSDisplayID_Main]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[NDSDisplayID_Main]); @@ -7270,6 +7296,11 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) { if (this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Touch)) { + if (isShaderSupported) + { + glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[NDSDisplayID_Touch]); + } + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[NDSDisplayID_Touch]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[NDSDisplayID_Touch]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[NDSDisplayID_Touch]); @@ -7291,6 +7322,11 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) { if (this->_output->IsSelectedDisplayEnabled(majorDisplayID)) { + if (isShaderSupported) + { + glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[majorDisplayID]); + } + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[majorDisplayID]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[majorDisplayID]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[majorDisplayID]); @@ -7305,6 +7341,11 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) if (this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Main)) { + if (isShaderSupported) + { + glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[NDSDisplayID_Main]); + } + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[NDSDisplayID_Main]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[NDSDisplayID_Main]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[NDSDisplayID_Main]); @@ -7313,6 +7354,11 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) if (this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Touch)) { + if (isShaderSupported) + { + glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[NDSDisplayID_Touch]); + } + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[NDSDisplayID_Touch]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[NDSDisplayID_Touch]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[NDSDisplayID_Touch]); diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.h b/desmume/src/frontend/cocoa/OGLDisplayOutput.h index 49a58e190..404f132a5 100644 --- a/desmume/src/frontend/cocoa/OGLDisplayOutput.h +++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.h @@ -213,6 +213,7 @@ protected: GLint _uniformScalar; GLint _uniformViewSize; GLint _uniformRenderFlipped; + GLint _uniformBacklightIntensity; void UploadVerticesOGL(); void UploadTexCoordsOGL(); @@ -259,6 +260,7 @@ protected: GLint _uniformScalar; GLint _uniformViewSize; GLint _uniformRenderFlipped; + GLint _uniformBacklightIntensity; public: virtual ~OGLVideoLayer() {}; diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm index 2f8df6f43..f2d0a72c0 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm @@ -1629,6 +1629,8 @@ // Draw the NDS displays. if (_willDrawDisplays) { + const NDSDisplayInfo &displayInfo = cdp->GetEmuDisplayInfo(); + [rce setRenderPipelineState:outputPipelineState]; [rce setVertexBuffer:_displayVtxPositionBuffer offset:0 atIndex:0]; [rce setVertexBuffer:_displayTexCoordBuffer offset:0 atIndex:1]; @@ -1640,6 +1642,7 @@ { if (cdp->IsSelectedDisplayEnabled(NDSDisplayID_Main)) { + [rce setFragmentBytes:&displayInfo.backlightIntensity[NDSDisplayID_Main] length:sizeof(displayInfo.backlightIntensity[NDSDisplayID_Main]) atIndex:0]; [rce setFragmentTexture:_texDisplayOutput[NDSDisplayID_Main] atIndex:0]; [rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4]; } @@ -1650,6 +1653,7 @@ { if (cdp->IsSelectedDisplayEnabled(NDSDisplayID_Touch)) { + [rce setFragmentBytes:&displayInfo.backlightIntensity[NDSDisplayID_Touch] length:sizeof(displayInfo.backlightIntensity[NDSDisplayID_Touch]) atIndex:0]; [rce setFragmentTexture:_texDisplayOutput[NDSDisplayID_Touch] atIndex:0]; [rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:4 vertexCount:4]; } @@ -1669,6 +1673,7 @@ { if (cdp->IsSelectedDisplayEnabled(majorDisplayID)) { + [rce setFragmentBytes:&displayInfo.backlightIntensity[majorDisplayID] length:sizeof(displayInfo.backlightIntensity[majorDisplayID]) atIndex:0]; [rce setFragmentTexture:_texDisplayOutput[majorDisplayID] atIndex:0]; [rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:majorDisplayVtx vertexCount:4]; } @@ -1681,12 +1686,14 @@ if (cdp->IsSelectedDisplayEnabled(NDSDisplayID_Main)) { + [rce setFragmentBytes:&displayInfo.backlightIntensity[NDSDisplayID_Main] length:sizeof(displayInfo.backlightIntensity[NDSDisplayID_Main]) atIndex:0]; [rce setFragmentTexture:_texDisplayOutput[NDSDisplayID_Main] atIndex:0]; [rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4]; } if (cdp->IsSelectedDisplayEnabled(NDSDisplayID_Touch)) { + [rce setFragmentBytes:&displayInfo.backlightIntensity[NDSDisplayID_Touch] length:sizeof(displayInfo.backlightIntensity[NDSDisplayID_Touch]) atIndex:0]; [rce setFragmentTexture:_texDisplayOutput[NDSDisplayID_Touch] atIndex:0]; [rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:4 vertexCount:4]; } diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayViewShaders.metal b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayViewShaders.metal index ec691915e..a21f2f863 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayViewShaders.metal +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayViewShaders.metal @@ -226,17 +226,21 @@ vertex DisplayVtx display_output_bicubic_vertex(const device float2 *inPosition //--------------------------------------- // Input Pixel Mapping: 00 -fragment float4 output_filter_nearest(const DisplayVtx vtx [[stage_in]], const texture2d tex [[texture(0)]]) +fragment float4 output_filter_nearest(const DisplayVtx vtx [[stage_in]], + const texture2d tex [[texture(0)]], + const device float *inBacklightIntensity [[buffer(0)]]) { - return tex.sample(genSampler, vtx.texCoord); + return float4(tex.sample(genSampler, vtx.texCoord).rgb * *inBacklightIntensity, 1.0f); } //--------------------------------------- // Input Pixel Mapping: 00|01 // 02|03 -fragment float4 output_filter_bilinear(const DisplayVtx vtx [[stage_in]], const texture2d tex [[texture(0)]]) +fragment float4 output_filter_bilinear(const DisplayVtx vtx [[stage_in]], + const texture2d tex [[texture(0)]], + const device float *inBacklightIntensity [[buffer(0)]]) { - return tex.sample(outputSamplerBilinear, vtx.texCoord); + return float4(tex.sample(outputSamplerBilinear, vtx.texCoord).rgb * *inBacklightIntensity, 1.0f); } //--------------------------------------- @@ -244,7 +248,9 @@ fragment float4 output_filter_bilinear(const DisplayVtx vtx [[stage_in]], const // 04|05|06|07 // 08|09|10|11 // 12|13|14|15 -fragment float4 output_filter_bicubic_bspline(const DisplayVtx vtx [[stage_in]], const texture2d tex [[texture(0)]]) +fragment float4 output_filter_bicubic_bspline(const DisplayVtx vtx [[stage_in]], + const texture2d tex [[texture(0)]], + const device float *inBacklightIntensity [[buffer(0)]]) { float2 f = fract(vtx.texCoord); float4 wx = bicubic_weight_bspline(f.x); @@ -271,7 +277,7 @@ fragment float4 output_filter_bicubic_bspline(const DisplayVtx vtx [[stage_in]], + tex.sample(genSampler, vtx.texCoord, int2( 1, 2)) * wx.b + tex.sample(genSampler, vtx.texCoord, int2( 2, 2)) * wx.a) * wy.a; - return float4(outFragment.rgb, 1.0f); + return float4(outFragment.rgb * *inBacklightIntensity, 1.0f); } //--------------------------------------- @@ -279,7 +285,9 @@ fragment float4 output_filter_bicubic_bspline(const DisplayVtx vtx [[stage_in]], // 04|05|06|07 // 08|09|10|11 // 12|13|14|15 -fragment float4 output_filter_bicubic_mitchell_netravali(const DisplayVtx vtx [[stage_in]], const texture2d tex [[texture(0)]]) +fragment float4 output_filter_bicubic_mitchell_netravali(const DisplayVtx vtx [[stage_in]], + const texture2d tex [[texture(0)]], + const device float *inBacklightIntensity [[buffer(0)]]) { float2 f = fract(vtx.texCoord); float4 wx = bicubic_weight_mitchell_netravali(f.x); @@ -306,7 +314,7 @@ fragment float4 output_filter_bicubic_mitchell_netravali(const DisplayVtx vtx [[ + tex.sample(genSampler, vtx.texCoord, int2( 1, 2)) * wx.b + tex.sample(genSampler, vtx.texCoord, int2( 2, 2)) * wx.a) * wy.a; - return float4(outFragment.rgb, 1.0f); + return float4(outFragment.rgb * *inBacklightIntensity, 1.0f); } //--------------------------------------- @@ -314,7 +322,9 @@ fragment float4 output_filter_bicubic_mitchell_netravali(const DisplayVtx vtx [[ // 04|05|06|07 // 08|09|10|11 // 12|13|14|15 -fragment float4 output_filter_lanczos2(const DisplayVtx vtx [[stage_in]], const texture2d tex [[texture(0)]]) +fragment float4 output_filter_lanczos2(const DisplayVtx vtx [[stage_in]], + const texture2d tex [[texture(0)]], + const device float *inBacklightIntensity [[buffer(0)]]) { const float2 f = fract(vtx.texCoord); float4 wx = bicubic_weight_lanczos2(f.x); @@ -341,7 +351,7 @@ fragment float4 output_filter_lanczos2(const DisplayVtx vtx [[stage_in]], const + tex.sample(genSampler, vtx.texCoord, int2( 1, 2)) * wx.b + tex.sample(genSampler, vtx.texCoord, int2( 2, 2)) * wx.a) * wy.a; - return float4(outFragment.rgb, 1.0f); + return float4(outFragment.rgb * *inBacklightIntensity, 1.0f); } //--------------------------------------- @@ -351,7 +361,9 @@ fragment float4 output_filter_lanczos2(const DisplayVtx vtx [[stage_in]], const // 18|19|20|21|22|23 // 24|25|26|27|28|29 // 30|31|32|33|34|35 -fragment float4 output_filter_lanczos3(const DisplayVtx vtx [[stage_in]], const texture2d tex [[texture(0)]]) +fragment float4 output_filter_lanczos3(const DisplayVtx vtx [[stage_in]], + const texture2d tex [[texture(0)]], + const device float *inBacklightIntensity [[buffer(0)]]) { const float2 f = fract(vtx.texCoord); float3 wx1 = bicubic_weight_lanczos3(0.5f - f.x * 0.5f); @@ -404,7 +416,7 @@ fragment float4 output_filter_lanczos3(const DisplayVtx vtx [[stage_in]], const + tex.sample(genSampler, vtx.texCoord, int2( 2, 3)) * wx1.b + tex.sample(genSampler, vtx.texCoord, int2( 3, 3)) * wx2.b) * wy2.b; - return float4(outFragment.rgb, 1.0f); + return float4(outFragment.rgb * *inBacklightIntensity, 1.0f); } #pragma mark NDS Emulation Functions diff --git a/desmume/src/frontend/posix/cli/main.cpp b/desmume/src/frontend/posix/cli/main.cpp index 3666f5f36..5c7a1b67e 100644 --- a/desmume/src/frontend/posix/cli/main.cpp +++ b/desmume/src/frontend/posix/cli/main.cpp @@ -1,6 +1,6 @@ /* main.c - this file is part of DeSmuME * - * Copyright (C) 2006-2015 DeSmuME Team + * Copyright (C) 2006-2017 DeSmuME Team * Copyright (C) 2007 Pascal Giard (evilynux) * * This file is free software; you can redistribute it and/or modify @@ -138,7 +138,6 @@ public: #ifdef INCLUDE_OPENGL_2D int opengl_2d; - int soft_colour_convert; #endif int firmware_language; @@ -155,7 +154,6 @@ init_config( class configured_features *config) { #ifdef INCLUDE_OPENGL_2D config->opengl_2d = 0; - config->soft_colour_convert = 0; #endif /* use the default language */ @@ -184,7 +182,6 @@ fill_config( class configured_features *config, "SAVETYPE"}, #ifdef INCLUDE_OPENGL_2D { "opengl-2d", 0, 0, G_OPTION_ARG_NONE, &config->opengl_2d, "Enables using OpenGL for screen rendering", NULL}, - { "soft-convert", 0, 0, G_OPTION_ARG_NONE, &config->soft_colour_convert, "Use software colour conversion during OpenGL screen rendering. May produce better or worse frame rates depending on hardware.", NULL}, #endif { "fwlang", 0, 0, G_OPTION_ARG_INT, &config->firmware_language, "Set the language in the firmware, LANG as follows:\n" @@ -274,9 +271,9 @@ joinThread_gdb( void *thread_handle) { static int initGL( GLuint *screen_texture) { GLenum errCode; - u16 blank_texture[256 * 512]; + u16 blank_texture[256 * 256]; - memset(blank_texture, 0x001f, sizeof(blank_texture)); + memset(blank_texture, 0, sizeof(blank_texture)); /* Enable Texture Mapping */ glEnable( GL_TEXTURE_2D ); @@ -294,19 +291,25 @@ initGL( GLuint *screen_texture) { glDepthFunc( GL_LEQUAL ); /* Create The Texture */ - glGenTextures( 1, &screen_texture[0]); + glGenTextures(2, screen_texture); - glBindTexture( GL_TEXTURE_2D, screen_texture[0]); + for (int i = 0; i < 2; i++) + { + glBindTexture(GL_TEXTURE_2D, screen_texture[i]); - /* Generate The Texture */ - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 256, 512, - 0, GL_RGBA, - GL_UNSIGNED_SHORT_1_5_5_5_REV, - blank_texture); + /* Generate The Texture */ + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, + 0, GL_RGBA, + GL_UNSIGNED_SHORT_1_5_5_5_REV, + blank_texture); - /* Linear Filtering */ - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + /* Linear Filtering */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } if ((errCode = glGetError()) != GL_NO_ERROR) { const GLubyte *errString; @@ -368,9 +371,8 @@ resizeWindow( u16 width, u16 height, GLuint *screen_texture) { static void -opengl_Draw( GLuint *texture, int software_convert) { - GLenum errCode; - u16 *gpuFramebuffer = (u16 *)GPU->GetDisplayInfo().masterNativeBuffer; +opengl_Draw(GLuint *texture) { + const NDSDisplayInfo &displayInfo = GPU->GetDisplayInfo(); /* Clear The Screen And The Depth Buffer */ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); @@ -378,54 +380,39 @@ opengl_Draw( GLuint *texture, int software_convert) { /* Move Into The Screen 5 Units */ glLoadIdentity( ); - /* Select screen Texture */ - glBindTexture( GL_TEXTURE_2D, texture[0]); - if ( software_convert) { - int i; - u8 converted[256 * 384 * 3]; + /* Draw the main screen as a textured quad */ + glBindTexture(GL_TEXTURE_2D, texture[NDSDisplayID_Main]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, + GL_RGBA, + GL_UNSIGNED_SHORT_1_5_5_5_REV, + displayInfo.renderedBuffer[NDSDisplayID_Main]); - for ( i = 0; i < (256 * 384); i++) { - converted[(i * 3) + 0] = ((gpuFramebuffer[i] >> 0) & 0x1f) << 3; - converted[(i * 3) + 1] = ((gpuFramebuffer[i] >> 5) & 0x1f) << 3; - converted[(i * 3) + 2] = ((gpuFramebuffer[i] >> 10) & 0x1f) << 3; - } + GLfloat backlightIntensity = displayInfo.backlightIntensity[NDSDisplayID_Main]; - glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 256, 384, - GL_RGB, - GL_UNSIGNED_BYTE, - converted); - } - else { - glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 256, 384, - GL_RGBA, - GL_UNSIGNED_SHORT_1_5_5_5_REV, - gpuFramebuffer); - } + glBegin(GL_QUADS); + glTexCoord2f(0.00f, 0.00f); glVertex2f( 0.0f, 0.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glTexCoord2f(1.00f, 0.00f); glVertex2f(256.0f, 0.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glTexCoord2f(1.00f, 0.75f); glVertex2f(256.0f, 192.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glTexCoord2f(0.00f, 0.75f); glVertex2f( 0.0f, 192.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glEnd(); - if ((errCode = glGetError()) != GL_NO_ERROR) { - const GLubyte *errString; + /* Draw the touch screen as a textured quad */ + glBindTexture(GL_TEXTURE_2D, texture[NDSDisplayID_Touch]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, + GL_RGBA, + GL_UNSIGNED_SHORT_1_5_5_5_REV, + displayInfo.renderedBuffer[NDSDisplayID_Touch]); - errString = gluErrorString(errCode); - fprintf( stderr, "GL subimage failed: %s\n", errString); - } + backlightIntensity = displayInfo.backlightIntensity[NDSDisplayID_Touch]; + glBegin(GL_QUADS); + glTexCoord2f(0.00f, 0.00f); glVertex2f( 0.0f, 192.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glTexCoord2f(1.00f, 0.00f); glVertex2f(256.0f, 192.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glTexCoord2f(1.00f, 0.75f); glVertex2f(256.0f, 384.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glTexCoord2f(0.00f, 0.75f); glVertex2f( 0.0f, 384.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glEnd(); - /* Draw the screen as a textured quad */ - glBegin( GL_QUADS); - glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 0.0f, 0.0f, 0.0f ); - glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 256.0f, 0.0f, 0.0f ); - glTexCoord2f( 1.0f, 0.75f ); glVertex3f( 256.0f, 384.0f, 0.0f ); - glTexCoord2f( 0.0f, 0.75f ); glVertex3f( 0.0f, 384.0f, 0.0f ); - glEnd( ); - - if ((errCode = glGetError()) != GL_NO_ERROR) { - const GLubyte *errString; - - errString = gluErrorString(errCode); - fprintf( stderr, "GL draw failed: %s\n", errString); - } - - /* Draw it to the screen */ + /* Flush the drawing to the screen */ SDL_GL_SwapBuffers( ); } #endif @@ -510,7 +497,7 @@ int main(int argc, char ** argv) { #endif #ifdef INCLUDE_OPENGL_2D - GLuint screen_texture[1]; + GLuint screen_texture[2]; #endif /* this holds some info about our display */ const SDL_VideoInfo *videoInfo; @@ -772,7 +759,7 @@ int main(int argc, char ** argv) { #ifdef INCLUDE_OPENGL_2D if ( my_config.opengl_2d) { - opengl_Draw( screen_texture, my_config.soft_colour_convert); + opengl_Draw(screen_texture); ctrls_cfg.resize_cb = &resizeWindow; } else diff --git a/desmume/src/frontend/posix/gtk-glade/gdk_gl.cpp b/desmume/src/frontend/posix/gtk-glade/gdk_gl.cpp index 184b2aaae..0c24cab65 100755 --- a/desmume/src/frontend/posix/gtk-glade/gdk_gl.cpp +++ b/desmume/src/frontend/posix/gtk-glade/gdk_gl.cpp @@ -1,6 +1,6 @@ /* gdk_gl.cpp - this file is part of DeSmuME * - * Copyright (C) 2007-2016 DeSmuME Team + * Copyright (C) 2007-2017 DeSmuME Team * Copyright (C) 2007 Damien Nozay (damdoum) * Author: damdoum at users.sourceforge.net * @@ -33,7 +33,6 @@ #define _DUP4(a) a,a,a,a #define _DUP2(a) a,a -GLuint Textures[2]; // free number we can use in tools 0-1 reserved for screens static int free_gl_drawable=2; GdkGLConfig *my_glConfig=NULL; @@ -41,10 +40,7 @@ GdkGLContext *my_glContext[8]={_DUP8(NULL)}; GdkGLDrawable *my_glDrawable[8]={_DUP8(NULL)}; GtkWidget *pDrawingTexArea; -GLuint screen_texture[1]; - -/* enable software colour format conversion */ -static int gtk_glade_use_software_colour_convert; +GLuint screen_texture[2]; #undef _DUP8 #undef _DUP4 @@ -141,32 +137,45 @@ int init_GL_free(GtkWidget * widget) { return r; } -void init_GL_capabilities( int use_software_convert) { +void init_GL_capabilities() { - uint16_t blank_texture[256 * 512]; + uint16_t blank_texture[256 * 256]; + memset(blank_texture, 0, sizeof(blank_texture)); + my_glConfig = gdk_gl_config_new_by_mode ( (GdkGLConfigMode) (GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE) ); - gtk_glade_use_software_colour_convert = use_software_convert; // initialize 1st drawing area init_GL(pDrawingArea,0,0); my_gl_Clear(0); if (!my_gl_Begin(0)) return; - // generate ONE texture (display) + glEnable(GL_TEXTURE_2D); - glGenTextures(2, Textures); + glGenTextures(2, screen_texture); - /* Generate The Texture */ - glBindTexture( GL_TEXTURE_2D, Textures[0]); - memset(blank_texture, 0, sizeof(blank_texture)); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 256, 512, - 0, GL_RGBA, - GL_UNSIGNED_SHORT_1_5_5_5_REV, - blank_texture); + /* Generate The Texture */ + for (int i = 0; i < 2; i++) + { + glBindTexture(GL_TEXTURE_2D, screen_texture[i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + +#define MyFILTER GL_LINEAR +//#define MyFILTER GL_NEAREST + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MyFILTER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MyFILTER); +#undef MyFILTER + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, + 0, GL_RGBA, + GL_UNSIGNED_SHORT_1_5_5_5_REV, + blank_texture); + } + my_gl_End(0); // initialize 2nd drawing area (sharing context) @@ -192,52 +201,44 @@ void reshape (GtkWidget * widget, int screen) { /* TEXTURING */ /************************************************/ -static void my_gl_Texture2D() { - glBindTexture(GL_TEXTURE_2D, Textures[0]); -#define MyFILTER GL_LINEAR -//#define MyFILTER GL_NEAREST - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MyFILTER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MyFILTER); -#undef MyFILTER -} - static void -my_gl_ScreenTex( int software_convert) { - u16 *gpuFramebuffer = (u16 *)GPU->GetDisplayInfo().masterNativeBuffer; - - if ( software_convert) { - u8 converted[256 * 384 * 3]; - int i; - - for ( i = 0; i < (256 * 384); i++) { - converted[(i * 3) + 0] = ((gpuFramebuffer[i] >> 0) & 0x1f) << 3; - converted[(i * 3) + 1] = ((gpuFramebuffer[i] >> 5) & 0x1f) << 3; - converted[(i * 3) + 2] = ((gpuFramebuffer[i] >> 10) & 0x1f) << 3; - } - - glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 256, 384, - GL_RGB, - GL_UNSIGNED_BYTE, - converted); - } - else { - glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 256, 384, - GL_RGBA, - GL_UNSIGNED_SHORT_1_5_5_5_REV, - gpuFramebuffer); - } +my_gl_ScreenTex() { + const NDSDisplayInfo &displayInfo = GPU->GetDisplayInfo(); + + glBindTexture(GL_TEXTURE_2D, screen_texture[NDSDisplayID_Main]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, + GL_RGBA, + GL_UNSIGNED_SHORT_1_5_5_5_REV, + displayInfo.renderedBuffer[NDSDisplayID_Main]); + + glBindTexture(GL_TEXTURE_2D, screen_texture[NDSDisplayID_Touch]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, + GL_RGBA, + GL_UNSIGNED_SHORT_1_5_5_5_REV, + displayInfo.renderedBuffer[NDSDisplayID_Touch]); } static void my_gl_ScreenTexApply(int screen) { - float off = (screen)?0.375:0; - - glColor4ub(255,255,255,255); + const NDSDisplayInfo &displayInfo = GPU->GetDisplayInfo(); + + GLfloat backlightIntensity = displayInfo.backlightIntensity[NDSDisplayID_Main]; + + glBindTexture(GL_TEXTURE_2D, screen_texture[NDSDisplayID_Main]); glBegin(GL_QUADS); - // texcoords 0.375 means 192, 1 means 256 - glTexCoord2f(0.0, off+0.000); glVertex2d(-1.0, 1.0); - glTexCoord2f(1.0, off+0.000); glVertex2d( 1.0, 1.0); - glTexCoord2f(1.0, off+0.375); glVertex2d( 1.0,-1.0); - glTexCoord2f(0.0, off+0.375); glVertex2d(-1.0,-1.0); + glTexCoord2f(0.00f, 0.00f); glVertex2f(-1.0f, 1.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glTexCoord2f(1.00f, 0.00f); glVertex2f( 1.0f, 1.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glTexCoord2f(1.00f, 0.75f); glVertex2f( 1.0f, 0.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glTexCoord2f(0.00f, 0.75f); glVertex2f(-1.0f, 0.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glEnd(); + + backlightIntensity = displayInfo.backlightIntensity[NDSDisplayID_Touch]; + + glBindTexture(GL_TEXTURE_2D, screen_texture[NDSDisplayID_Touch]); + glBegin(GL_QUADS); + glTexCoord2f(0.00f, 0.00f); glVertex2f(-1.0f, 0.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glTexCoord2f(1.00f, 0.00f); glVertex2f( 1.0f, 0.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glTexCoord2f(1.00f, 0.75f); glVertex2f( 1.0f, -1.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); + glTexCoord2f(0.00f, 0.75f); glVertex2f(-1.0f, -1.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); glEnd(); } @@ -247,7 +248,6 @@ static void my_gl_ScreenTexApply(int screen) { gboolean screen (GtkWidget * widget, int viewportscreen) { int screen; - GPUEngineBase * gpu; // we take care to draw the right thing the right place // we need to rearrange widgets not to use this trick @@ -271,10 +271,8 @@ gboolean screen (GtkWidget * widget, int viewportscreen) { if (desmume_running()) { // rotate glRotatef(ScreenRotate, 0.0, 0.0, 1.0); - // create the texture for both display - my_gl_Texture2D(); if (viewportscreen==0) { - my_gl_ScreenTex( gtk_glade_use_software_colour_convert); + my_gl_ScreenTex(); } } diff --git a/desmume/src/frontend/posix/gtk-glade/main.cpp b/desmume/src/frontend/posix/gtk-glade/main.cpp index e2cf7b16d..220ff4b32 100755 --- a/desmume/src/frontend/posix/gtk-glade/main.cpp +++ b/desmume/src/frontend/posix/gtk-glade/main.cpp @@ -90,7 +90,6 @@ GPU3DInterface *core3DList[] = { */ struct configured_features { int load_slot; - int software_colour_convert; int opengl_2d; int engine_3d; int disable_limiter; @@ -110,8 +109,6 @@ init_configured_features( struct configured_features *config) { config->arm9_gdb_port = 0; config->arm7_gdb_port = 0; - config->software_colour_convert = 0; - config->opengl_2d = 0; config->engine_3d = 1; @@ -137,12 +134,6 @@ fill_configured_features( struct configured_features *config, g_print( _("OPTIONS:\n")); g_print( _("\ --load-slot=NUM Load game saved under NUM position.\n\n")); -#ifdef GTKGLEXT_AVAILABLE - g_print( _("\ - --soft-convert Use software colour conversion during OpenGL\n\ - screen rendering. May produce better or worse\n\ - frame rates depending on hardware.\n\n")); -#endif g_print( _("\ --3d-engine=ENGINE Selects 3D rendering engine\n\ 0 = disabled\n\ @@ -198,9 +189,6 @@ fill_configured_features( struct configured_features *config, // FIXME: to be implemented config->opengl_2d = 1; } - else if ( strcmp( argv[i], "--soft-convert") == 0) { - config->software_colour_convert = 1; - } #define MAX3DEMU 2 #else #define MAX3DEMU 1 @@ -466,7 +454,7 @@ common_gtk_glade_main( struct configured_features *my_config) { glade_xml_signal_autoconnect_StringObject(xml); glade_xml_signal_autoconnect_StringObject(xml_tools); - init_GL_capabilities( my_config->software_colour_convert); + init_GL_capabilities(); /* check command line file */ if( my_config->nds_file) { diff --git a/desmume/src/frontend/windows/main.cpp b/desmume/src/frontend/windows/main.cpp old mode 100644 new mode 100755 index 250a41f03..3886dc259 --- a/desmume/src/frontend/windows/main.cpp +++ b/desmume/src/frontend/windows/main.cpp @@ -1567,25 +1567,25 @@ struct GLDISPLAY active = false; } - - - //http://stackoverflow.com/questions/589064/how-to-enable-vertical-sync-in-opengl - bool WGLExtensionSupported(const char *extension_name) - { - // this is pointer to function which returns pointer to string with list of all wgl extensions - PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglGetExtensionsStringEXT = NULL; - - // determine pointer to wglGetExtensionsStringEXT function - _wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT"); - - if (strstr(_wglGetExtensionsStringEXT(), extension_name) == NULL) - { - // string was not found - return false; - } - - // extension is supported - return true; + + + //http://stackoverflow.com/questions/589064/how-to-enable-vertical-sync-in-opengl + bool WGLExtensionSupported(const char *extension_name) + { + // this is pointer to function which returns pointer to string with list of all wgl extensions + PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglGetExtensionsStringEXT = NULL; + + // determine pointer to wglGetExtensionsStringEXT function + _wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT"); + + if (strstr(_wglGetExtensionsStringEXT(), extension_name) == NULL) + { + // string was not found + return false; + } + + // extension is supported + return true; } void setvsync(bool vsync) @@ -1598,17 +1598,17 @@ struct GLDISPLAY //even if it doesn't work, we'll track it haveVsync = wantVsync; - if (!WGLExtensionSupported("WGL_EXT_swap_control")) return; - + if (!WGLExtensionSupported("WGL_EXT_swap_control")) return; + //http://stackoverflow.com/questions/589064/how-to-enable-vertical-sync-in-opengl - PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; - PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = NULL; - { - // Extension is supported, init pointers. - wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); - - // this is another function from WGL_EXT_swap_control extension - wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT"); + PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; + PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = NULL; + { + // Extension is supported, init pointers. + wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); + + // this is another function from WGL_EXT_swap_control extension + wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT"); } wglSwapIntervalEXT(wantVsync ? 1 : 0); @@ -1625,6 +1625,8 @@ static void OGL_DoDisplay() { if(!gldisplay.begin()) return; + const NDSDisplayInfo &displayInfo = GPU->GetDisplayInfo(); + static GLuint tex = 0; if(tex == 0) glGenTextures(1,&tex); @@ -1641,8 +1643,8 @@ static void OGL_DoDisplay() //the ds screen fills the texture entirely, so we dont have garbage at edge to worry about, //but we need to make sure this is clamped for when filtering is selected - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); if(GetStyle()&DWS_FILTER) { @@ -1700,7 +1702,7 @@ static void OGL_DoDisplay() int r = (color_rev>>0)&0xFF; int g = (color_rev>>8)&0xFF; int b = (color_rev>>16)&0xFF; - glClearColor(r/255.0f,g/255.0f,b/255.0f,1); + glClearColor(r/255.0f,g/255.0f,b/255.0f,1.0f); glEnable(GL_SCISSOR_TEST); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_SCISSOR_TEST); @@ -1708,7 +1710,7 @@ static void OGL_DoDisplay() RECT srcRects [2]; - const bool isMainGPUFirst = (GPU->GetDisplayInfo().engineID[NDSDisplayID_Main] == GPUEngineID_Main); + const bool isMainGPUFirst = (displayInfo.engineID[NDSDisplayID_Main] == GPUEngineID_Main); if(video.swap == 0) { @@ -1776,12 +1778,21 @@ static void OGL_DoDisplay() float u[] = {u1,u2,u2,u1}; float v[] = {v1,v1,v2,v2}; + const GLfloat backlightIntensity = displayInfo.backlightIntensity[i]; + + glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); glTexCoord2f(u[(ofs+0)%4],v[(ofs+0)%4]); glVertex2i(dr[i].left,dr[i].top); + + glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); glTexCoord2f(u[(ofs+1)%4],v[(ofs+1)%4]); glVertex2i(dr[i].right,dr[i].top); + + glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); glTexCoord2f(u[(ofs+2)%4],v[(ofs+2)%4]); glVertex2i(dr[i].right,dr[i].bottom); + + glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); glTexCoord2f(u[(ofs+3)%4],v[(ofs+3)%4]); glVertex2i(dr[i].left,dr[i].bottom); } @@ -4251,14 +4262,14 @@ void ScreenshotToClipboard(bool extraInfo) bmi.bV4Height = -height; if(gpu_bpp == 15) { - bmi.bV4Size = sizeof(bmi); - bmi.bV4Planes = 1; - bmi.bV4BitCount = 16; - bmi.bV4V4Compression = BI_RGB | BI_BITFIELDS; - bmi.bV4RedMask = 0x001F; - bmi.bV4GreenMask = 0x03E0; - bmi.bV4BlueMask = 0x7C00; - bmi.bV4Width = width; + bmi.bV4Size = sizeof(bmi); + bmi.bV4Planes = 1; + bmi.bV4BitCount = 16; + bmi.bV4V4Compression = BI_RGB | BI_BITFIELDS; + bmi.bV4RedMask = 0x001F; + bmi.bV4GreenMask = 0x03E0; + bmi.bV4BlueMask = 0x7C00; + bmi.bV4Width = width; bmi.bV4Height = -height; SetDIBitsToDevice(hMemDC, 0, 0, width, height, 0, 0, 0, height, dispInfo.masterCustomBuffer, (BITMAPINFO*)&bmi, DIB_RGB_COLORS); @@ -7293,9 +7304,9 @@ const char* OpenLuaScript(const char* filename, const char* extraDirToCheck, boo } else { - #pragma warning( push ) - //'type cast': pointer truncation from 'HWND' to 'int' - //it's just a hash key. it's probably safe + #pragma warning( push ) + //'type cast': pointer truncation from 'HWND' to 'int' + //it's just a hash key. it's probably safe #pragma warning( disable : 4311 ) RequestAbortLuaScript((int)scriptHWnd, "terminated to restart because of a call to emu.openscript"); #pragma warning( pop )