win32: use npot textures in OGL if available, use glsl viewport callback

This commit is contained in:
OV2 2018-05-22 21:27:40 +02:00
parent 3b5ca2397b
commit 69f5e03ac5
4 changed files with 87 additions and 44 deletions

View File

@ -210,8 +210,6 @@ COpenGL::COpenGL(void)
hWnd = NULL; hWnd = NULL;
drawTexture = 0; drawTexture = 0;
initDone = false; initDone = false;
quadTextureSize = 0;
filterScale = 0;
afterRenderWidth = 0; afterRenderWidth = 0;
afterRenderHeight = 0; afterRenderHeight = 0;
fullscreen = false; fullscreen = false;
@ -336,8 +334,6 @@ void COpenGL::DeInitialize()
} }
hWnd = NULL; hWnd = NULL;
initDone = false; initDone = false;
quadTextureSize = 0;
filterScale = 0;
afterRenderWidth = 0; afterRenderWidth = 0;
afterRenderHeight = 0; afterRenderHeight = 0;
shaderFunctionsLoaded = false; shaderFunctionsLoaded = false;
@ -355,28 +351,32 @@ void COpenGL::DeInitialize()
cgAvailable = false; cgAvailable = false;
} }
void COpenGL::CreateDrawSurface() void COpenGL::CreateDrawSurface(unsigned int width, unsigned int height)
{ {
unsigned int neededSize;
HRESULT hr; HRESULT hr;
//we need at least 512 pixels (SNES_WIDTH * 2) so we can start with that value if (!NPOTAvailable()) {
quadTextureSize = 512; unsigned int neededSize = max(width, height);
neededSize = SNES_WIDTH * filterScale; //we need at least 512 pixels (SNES_WIDTH * 2) so we can start with that value
while(quadTextureSize < neededSize) unsigned int quadTextureSize = 512;
quadTextureSize *=2; while (quadTextureSize < neededSize)
quadTextureSize *= 2;
width = height = quadTextureSize;
}
if(!drawTexture) { if(!drawTexture) {
outTextureWidth = width;
outTextureHeight = height;
glGenTextures(1,&drawTexture); glGenTextures(1,&drawTexture);
glBindTexture(GL_TEXTURE_2D,drawTexture); glBindTexture(GL_TEXTURE_2D,drawTexture);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,quadTextureSize,quadTextureSize,0,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,NULL); glTexImage2D(GL_TEXTURE_2D,0,GL_RGB, outTextureWidth, outTextureHeight,0,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,NULL);
if(pboFunctionsLoaded) { if(pboFunctionsLoaded) {
glGenBuffers(1,&drawBuffer); glGenBuffers(1,&drawBuffer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER,drawBuffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER,drawBuffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER,quadTextureSize*quadTextureSize*2,NULL,GL_STREAM_DRAW); glBufferData(GL_PIXEL_UNPACK_BUFFER, outTextureWidth*outTextureHeight *2,NULL,GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER,0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER,0);
} else { } else {
noPboBuffer = new BYTE[quadTextureSize*quadTextureSize*2]; noPboBuffer = new BYTE[outTextureWidth*outTextureHeight *2];
} }
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
@ -400,12 +400,10 @@ void COpenGL::DestroyDrawSurface()
} }
} }
bool COpenGL::ChangeDrawSurfaceSize(unsigned int scale) bool COpenGL::ChangeDrawSurfaceSize(unsigned int width, unsigned int height)
{ {
filterScale = scale;
DestroyDrawSurface(); DestroyDrawSurface();
CreateDrawSurface(); CreateDrawSurface(width, height);
SetupVertices(); SetupVertices();
return true; return true;
} }
@ -421,8 +419,8 @@ void COpenGL::SetupVertices()
vertices[6] = 0.0f; vertices[6] = 0.0f;
vertices[7] = 1.0f; vertices[7] = 1.0f;
float tX = (float)afterRenderWidth / (float)quadTextureSize; float tX = (float)afterRenderWidth / (float)outTextureWidth;
float tY = (float)afterRenderHeight / (float)quadTextureSize; float tY = (float)afterRenderHeight / (float)outTextureHeight;
texcoords[0] = 0.0f; texcoords[0] = 0.0f;
texcoords[1] = tY; texcoords[1] = tY;
@ -435,6 +433,24 @@ void COpenGL::SetupVertices()
glTexCoordPointer(2, GL_FLOAT, 0, texcoords); glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
} }
void wOGLViewportCallback(int source_width, int source_height,
int viewport_x, int viewport_y,
int viewport_width, int viewport_height,
int *out_dst_x, int *out_dst_y,
int *out_dst_width, int *out_dst_height)
{
/* get window size here instead of using viewport passed in - we limited the viewport before the glsl render
call already, this is simply to position smaller outputs correctly in the actual viewport
*/
RECT windowSize;
GetClientRect(GUI.hWnd, &windowSize);
RECT displayRect = CalculateDisplayRect(source_width, source_height, windowSize.right, windowSize.bottom);
*out_dst_x = displayRect.left;
*out_dst_y = displayRect.top;
*out_dst_width = displayRect.right - displayRect.left;
*out_dst_height = displayRect.bottom - displayRect.top;
}
void COpenGL::Render(SSurface Src) void COpenGL::Render(SSurface Src)
{ {
SSurface Dst; SSurface Dst;
@ -445,11 +461,9 @@ void COpenGL::Render(SSurface Src)
if(!initDone) return; if(!initDone) return;
//create a new draw surface if the filter scale changes //create a new draw surface if the filter scale changes
//at least factor 2 so we can display unscaled hi-res images dstRect = GetFilterOutputSize(Src);
newFilterScale = max(2,max(GetFilterScale(GUI.ScaleHiRes),GetFilterScale(GUI.Scale))); if(outTextureWidth != dstRect.right || outTextureHeight != dstRect.bottom)
if(newFilterScale!=filterScale) { ChangeDrawSurfaceSize(dstRect.right, dstRect.bottom);
ChangeDrawSurfaceSize(newFilterScale);
}
if(pboFunctionsLoaded) { if(pboFunctionsLoaded) {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, drawBuffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, drawBuffer);
@ -457,9 +471,9 @@ void COpenGL::Render(SSurface Src)
} else { } else {
Dst.Surface = noPboBuffer; Dst.Surface = noPboBuffer;
} }
Dst.Height = quadTextureSize; Dst.Height = outTextureHeight;
Dst.Width = quadTextureSize; Dst.Width = outTextureWidth;
Dst.Pitch = quadTextureSize * 2; Dst.Pitch = outTextureWidth * 2;
RenderMethod (Src, Dst, &dstRect); RenderMethod (Src, Dst, &dstRect);
if(!Settings.AutoDisplayMessages) { if(!Settings.AutoDisplayMessages) {
@ -478,7 +492,7 @@ void COpenGL::Render(SSurface Src)
} }
glBindTexture(GL_TEXTURE_2D,drawTexture); glBindTexture(GL_TEXTURE_2D,drawTexture);
glPixelStorei(GL_UNPACK_ROW_LENGTH, quadTextureSize); glPixelStorei(GL_UNPACK_ROW_LENGTH, outTextureWidth);
glTexSubImage2D (GL_TEXTURE_2D,0,0,0,dstRect.right-dstRect.left,dstRect.bottom-dstRect.top,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,pboFunctionsLoaded?0:noPboBuffer); glTexSubImage2D (GL_TEXTURE_2D,0,0,0,dstRect.right-dstRect.left,dstRect.bottom-dstRect.top,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,pboFunctionsLoaded?0:noPboBuffer);
if(pboFunctionsLoaded) if(pboFunctionsLoaded)
@ -490,7 +504,7 @@ void COpenGL::Render(SSurface Src)
displayRect = CalculateDisplayRect(windowSize.right, windowSize.bottom, windowSize.right, windowSize.bottom); displayRect = CalculateDisplayRect(windowSize.right, windowSize.bottom, windowSize.right, windowSize.bottom);
if (shader_type == OGL_SHADER_GLSL) { if (shader_type == OGL_SHADER_GLSL) {
glslShader->render(drawTexture, afterRenderWidth, afterRenderHeight, displayRect.right - displayRect.left, displayRect.bottom - displayRect.top, displayRect.left, displayRect.top); glslShader->render(drawTexture, afterRenderWidth, afterRenderHeight, displayRect.left, displayRect.top, displayRect.right - displayRect.left, displayRect.bottom - displayRect.top, wOGLViewportCallback);
} }
else { else {
if(shader_type == OGL_SHADER_CG) { if(shader_type == OGL_SHADER_CG) {
@ -498,7 +512,7 @@ void COpenGL::Render(SSurface Src)
xySize xywindowSize = { (double)windowSize.right, (double)windowSize.bottom }; xySize xywindowSize = { (double)windowSize.right, (double)windowSize.bottom };
xySize viewportSize = { (double)(displayRect.right - displayRect.left), xySize viewportSize = { (double)(displayRect.right - displayRect.left),
(double)(displayRect.bottom - displayRect.top) }; (double)(displayRect.bottom - displayRect.top) };
xySize textureSize = { (double)quadTextureSize, (double)quadTextureSize }; xySize textureSize = { (double)outTextureWidth, (double)outTextureHeight };
cgShader->Render(drawTexture, textureSize, inputSize, viewportSize, xywindowSize); cgShader->Render(drawTexture, textureSize, inputSize, viewportSize, xywindowSize);
} }
if (Settings.BilinearFilter) { if (Settings.BilinearFilter) {

View File

@ -221,8 +221,8 @@ private:
bool initDone; bool initDone;
bool fullscreen; bool fullscreen;
unsigned int quadTextureSize; unsigned int outTextureWidth;
unsigned int filterScale; unsigned int outTextureHeight;
unsigned int afterRenderWidth, afterRenderHeight; unsigned int afterRenderWidth, afterRenderHeight;
bool shaderFunctionsLoaded; bool shaderFunctionsLoaded;
@ -249,9 +249,9 @@ private:
bool SetShadersGLSL(const TCHAR *glslFileName); bool SetShadersGLSL(const TCHAR *glslFileName);
bool LoadShaderFunctions(); bool LoadShaderFunctions();
bool LoadPBOFunctions(); bool LoadPBOFunctions();
void CreateDrawSurface(void); void CreateDrawSurface(unsigned int width, unsigned int height);
void DestroyDrawSurface(void); void DestroyDrawSurface(void);
bool ChangeDrawSurfaceSize(unsigned int scale); bool ChangeDrawSurfaceSize(unsigned int width, unsigned int height);
void SetupVertices(); void SetupVertices();
bool ShaderAailable(); bool ShaderAailable();
bool NPOTAvailable(); bool NPOTAvailable();

View File

@ -477,6 +477,42 @@ inline static bool GetFilterBlendSupport(RenderFilter filterID)
} }
} }
inline void SetRect(RECT* rect, int width, int height, int scale)
{
rect->left = 0;
rect->right = width * scale;
rect->top = 0;
rect->bottom = (height - (GUI.HeightExtend ? 0 : 15)) * scale;
}
RECT GetFilterOutputSize(SSurface Src)
{
RECT rect;
RenderFilter filterID = GUI.Scale;
if (Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) {
filterID = GUI.ScaleHiRes;
}
// default to fixed factor
SetRect(&rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, GetFilterScale(filterID));
// handle special cases
switch (filterID)
{
case FILTER_NONE:
SetRect(&rect, Src.Width, Src.Height, 1);
break;
case FILTER_BLARGGCOMP:
case FILTER_BLARGGSVID:
case FILTER_BLARGGRGB:
SetRect(&rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 2);
rect.right = SNES_NTSC_OUT_WIDTH(256);
break;
default:
break;
}
return rect;
}
void SelectRenderMethod() void SelectRenderMethod()
{ {
TRenderMethod OldRenderMethod = _RenderMethod; TRenderMethod OldRenderMethod = _RenderMethod;
@ -701,15 +737,6 @@ inline void ThreeHalfLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){
} }
} }
inline void SetRect(RECT* rect, int width, int height, int scale)
{
rect->left = 0;
rect->right = width * scale;
rect->top = 0;
rect->bottom = (height - (GUI.HeightExtend?0:15)) * scale;
}
#define AVERAGE_565(el0, el1) (((el0) & (el1)) + ((((el0) ^ (el1)) & 0xF7DE) >> 1)) #define AVERAGE_565(el0, el1) (((el0) & (el1)) + ((((el0) ^ (el1)) & 0xF7DE) >> 1))
void RenderMergeHires(void *src, int srcPitch , void* dst, int dstPitch, unsigned int width, unsigned int height) void RenderMergeHires(void *src, int srcPitch , void* dst, int dstPitch, unsigned int width, unsigned int height)
{ {

View File

@ -212,4 +212,6 @@ void SelectRenderMethod();
void InitRenderFilters(); void InitRenderFilters();
void DeInitRenderFilters(); void DeInitRenderFilters();
RECT GetFilterOutputSize(SSurface Src);
#endif #endif