Rework HUD rendering with OpenGL.

-Fixes regression from commit 5906d44 where HUD would appear smaller when using HD scaling. (only fixed with OpenGL for now)
-Remove use of backlightIntensity for displaying. Fixes bug where screen would appear dark on the first frame after loading a save state. Underlying cause should probably still be fixed, though. (Why would the backlight level affect the display anyway? That setting on the DS is only present because it has its own physical screens and makes no sense here.)
This commit is contained in:
SuuperW 2018-07-12 11:23:23 -05:00
parent dc41f09189
commit 6fc7161f19
1 changed files with 88 additions and 103 deletions

View File

@ -1643,26 +1643,76 @@ struct GLDISPLAY
} gldisplay;
static void OGL_DrawTexture(RECT* srcRects, RECT* dstRects)
{
//use clear+scissor for gap
if (video.screengap > 0)
{
//adjust client rect into scissor rect (0,0 at bottomleft)
glScissor(dstRects[2].left, dstRects[2].bottom, dstRects[2].right - dstRects[2].left, dstRects[2].top - dstRects[2].bottom);
u32 color_rev = (u32)ScreenGapColor;
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.0f);
glEnable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
}
//draw two screens
glBegin(GL_QUADS);
for (int i = 0; i<2; i++)
{
//none of this makes any goddamn sense. dont even try.
int idx = i;
int ofs = 0;
switch (video.rotation)
{
case 0:
break;
case 90:
ofs = 3;
idx = 1 - i;
std::swap(srcRects[idx].right, srcRects[idx].bottom);
std::swap(srcRects[idx].left, srcRects[idx].top);
break;
case 180:
idx = 1 - i;
ofs = 2;
break;
case 270:
std::swap(srcRects[idx].right, srcRects[idx].bottom);
std::swap(srcRects[idx].left, srcRects[idx].top);
ofs = 1;
break;
}
float u1 = srcRects[idx].left / (float)video.width;
float u2 = srcRects[idx].right / (float)video.width;
float v1 = srcRects[idx].top / (float)video.height;
float v2 = srcRects[idx].bottom / (float)video.height;
float u[] = { u1,u2,u2,u1 };
float v[] = { v1,v1,v2,v2 };
glTexCoord2f(u[(ofs + 0) % 4], v[(ofs + 0) % 4]);
glVertex2i(dstRects[i].left, dstRects[i].top);
glTexCoord2f(u[(ofs + 1) % 4], v[(ofs + 1) % 4]);
glVertex2i(dstRects[i].right, dstRects[i].top);
glTexCoord2f(u[(ofs + 2) % 4], v[(ofs + 2) % 4]);
glVertex2i(dstRects[i].right, dstRects[i].bottom);
glTexCoord2f(u[(ofs + 3) % 4], v[(ofs + 3) % 4]);
glVertex2i(dstRects[i].left, dstRects[i].bottom);
}
glEnd();
}
static void OGL_DoDisplay()
{
if(!gldisplay.begin()) return;
const NDSDisplayInfo &displayInfo = GPU->GetDisplayInfo();
static GLuint tex = 0;
if(tex == 0)
glGenTextures(1,&tex);
glBindTexture(GL_TEXTURE_2D,tex);
if(gpu_bpp == 15)
{
//yeah, it's 32bits here still. we've converted it previously, for compositing the HUD
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, video.width, video.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, video.finalBuffer());
}
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, video.width, video.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, video.finalBuffer());
//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_TO_EDGE);
@ -1679,16 +1729,12 @@ static void OGL_DoDisplay()
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
}
glEnable(GL_TEXTURE_2D);
RECT rc;
HWND hwnd = MainWindow->getHWnd();
GetClientRect(hwnd,&rc);
int width = rc.right - rc.left;
int height = rc.bottom - rc.top;
glDisable(GL_LIGHTING);
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
@ -1698,41 +1744,22 @@ static void OGL_DoDisplay()
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//clear entire area, for cases where the screen is maximized
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
// get dest and src rects
RECT dr[] = {MainScreenRect, SubScreenRect, GapRect};
for(int i=0;i<2;i++) //dont change gap rect, for some reason
{
ScreenToClient(hwnd,(LPPOINT)&dr[i].left);
ScreenToClient(hwnd,(LPPOINT)&dr[i].right);
}
//clear entire area, for cases where the screen is maximized
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
//use clear+scissor for gap
if(video.screengap > 0)
{
//adjust client rect into scissor rect (0,0 at bottomleft)
dr[2].bottom = height - dr[2].bottom;
dr[2].top = height - dr[2].top;
glScissor(dr[2].left,dr[2].bottom,dr[2].right-dr[2].left,dr[2].top-dr[2].bottom);
u32 color_rev = (u32)ScreenGapColor;
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.0f);
glEnable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
}
dr[2].bottom = height - dr[2].bottom;
dr[2].top = height - dr[2].top;
RECT srcRects [2];
const bool isMainGPUFirst = (displayInfo.engineID[NDSDisplayID_Main] == GPUEngineID_Main);
const bool isMainGPUFirst = (GPU->GetDisplayInfo().engineID[NDSDisplayID_Main] == GPUEngineID_Main);
if(video.swap == 0)
{
@ -1764,62 +1791,17 @@ static void OGL_DoDisplay()
// srcRects[1].left,srcRects[1].top, srcRects[1].right-srcRects[1].left, srcRects[1].bottom-srcRects[1].top
// );
glEnable(GL_TEXTURE_2D);
// draw DS display
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, video.width, video.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, video.finalBuffer());
OGL_DrawTexture(srcRects, dr);
//draw two screens
glBegin(GL_QUADS);
for(int i=0;i<2;i++)
{
//none of this makes any goddamn sense. dont even try.
int idx = i;
int ofs = 0;
switch(video.rotation)
{
case 0:
break;
case 90:
ofs = 3;
idx = 1-i;
std::swap(srcRects[idx].right,srcRects[idx].bottom);
std::swap(srcRects[idx].left,srcRects[idx].top);
break;
case 180:
idx = 1-i;
ofs = 2;
break;
case 270:
std::swap(srcRects[idx].right,srcRects[idx].bottom);
std::swap(srcRects[idx].left,srcRects[idx].top);
ofs = 1;
break;
}
float u1 = srcRects[idx].left/(float)video.width;
float u2 = srcRects[idx].right/(float)video.width;
float v1 = srcRects[idx].top/(float)video.height;
float v2 = srcRects[idx].bottom/(float)video.height;
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);
}
glEnd();
// draw HUD
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2, 0, GL_BGRA, GL_UNSIGNED_BYTE, aggDraw.hud->buf().buf());
OGL_DrawTexture(srcRects, dr);
glDisable(GL_BLEND);
gldisplay.showPage();
@ -2029,7 +2011,10 @@ static void DoDisplay()
}
// draw HUD
aggDraw.hud->attach((u8*)video.buffer, video.prefilterWidth, video.prefilterHeight, video.prefilterWidth * 4);
if (ddhw || ddsw)
aggDraw.hud->attach((u8*)video.buffer, video.prefilterWidth, video.prefilterHeight, video.prefilterWidth * 4);
else
aggDraw.hud->clear();
DoDisplay_DrawHud();
//apply user's filter