Skip to content

Commit

Permalink
[gl/gles/win/renderer] - pass the video orientation down to the gl re…
Browse files Browse the repository at this point in the history
…nderer and rotate the video texture accordingly, this handles linuxgl (software, vaapi, vdpau, vda), linuxgles (software, vtb) and windows gl renderers (all except DXVA2 hw decoder) - fixes xbmc#12231
  • Loading branch information
Memphiz committed Aug 1, 2012
1 parent decdfb9 commit 048cd71
Show file tree
Hide file tree
Showing 13 changed files with 256 additions and 131 deletions.
75 changes: 75 additions & 0 deletions xbmc/cores/VideoRenderers/BaseRenderer.cpp
Expand Up @@ -38,6 +38,15 @@ CBaseRenderer::CBaseRenderer()
m_sourceHeight = 480;
m_resolution = RES_DESKTOP;
m_fps = 0.0f;
m_renderOrientation = 0;
m_oldRenderOrientation = 0;
m_oldDestRect.SetRect(0.0f, 0.0f, 0.0f, 0.0f);

for(int i=0; i < 4; i++)
{
m_rotatedDestCoords[i].x = 0;
m_rotatedDestCoords[i].y = 0;
}
}

CBaseRenderer::~CBaseRenderer()
Expand Down Expand Up @@ -232,6 +241,63 @@ void CBaseRenderer::GetVideoRect(CRect &source, CRect &dest)
dest = m_destRect;
}

inline void CBaseRenderer::ReorderDrawPoints()
{
// 0 - top left, 1 - top right, 2 - bottom right, 3 - bottom left
float origMat[4][2] = {{m_destRect.x1, m_destRect.y1},
{m_destRect.x2, m_destRect.y1},
{m_destRect.x2, m_destRect.y2},
{m_destRect.x1, m_destRect.y2}};
bool changeAspect = false;
int pointOffset = 0;

switch (m_renderOrientation)
{
case 90:
pointOffset = 1;
changeAspect = true;
break;
case 180:
pointOffset = 2;
break;
case 270:
pointOffset = 3;
changeAspect = true;
break;
}

int diff = (m_destRect.Height() - m_destRect.Width()) / 2;

for (int destIdx=0, srcIdx=pointOffset; destIdx < 4; destIdx++, srcIdx = ++srcIdx % 4)
{
m_rotatedDestCoords[destIdx].x = origMat[srcIdx][0];
m_rotatedDestCoords[destIdx].y = origMat[srcIdx][1];

if (changeAspect)
{
switch (srcIdx)
{
case 0:
m_rotatedDestCoords[destIdx].x -= diff;
m_rotatedDestCoords[destIdx].y += diff;
break;
case 1:
m_rotatedDestCoords[destIdx].x += diff;
m_rotatedDestCoords[destIdx].y += diff;
break;
case 2:
m_rotatedDestCoords[destIdx].x += diff;
m_rotatedDestCoords[destIdx].y -= diff;
break;
case 3:
m_rotatedDestCoords[destIdx].x -= diff;
m_rotatedDestCoords[destIdx].y -= diff;
break;
}
}
}
}

void CBaseRenderer::CalcNormalDisplayRect(float offsetX, float offsetY, float screenWidth, float screenHeight, float inputFrameRatio, float zoomAmount, float verticalShift)
{
// if view window is empty, set empty destination
Expand Down Expand Up @@ -308,6 +374,15 @@ void CBaseRenderer::CalcNormalDisplayRect(float offsetX, float offsetY, float sc
m_sourceRect.y2 += (m_destRect.y2 - original.y2) * scaleY;
}
}

if (m_oldDestRect != m_destRect || m_oldRenderOrientation != m_renderOrientation)
{
// adapt the drawing rect points if we have to rotate
// and either destrect or orientation changed
ReorderDrawPoints();
m_oldDestRect = m_destRect;
m_oldRenderOrientation = m_renderOrientation;
}
}

//***************************************************************************************
Expand Down
10 changes: 10 additions & 0 deletions xbmc/cores/VideoRenderers/BaseRenderer.h
Expand Up @@ -90,12 +90,22 @@ class CBaseRenderer
void CalculateFrameAspectRatio(unsigned int desired_width, unsigned int desired_height);
void ManageDisplay();

virtual void ReorderDrawPoints();//might be overwritten (by egl e.x.)

RESOLUTION m_resolution; // the resolution we're running in
unsigned int m_sourceWidth;
unsigned int m_sourceHeight;
float m_sourceFrameRatio;
float m_fps;

unsigned int m_renderOrientation; // orientation of the video in degress counter clockwise
unsigned int m_oldRenderOrientation; // orientation of the previous frame
// for drawing the texture with glVertex4f (holds all 4 corner points of the destination rect
// with correct orientation based on m_renderOrientation
// 0 - top left, 1 - top right, 2 - bottom right, 3 - bottom left
CPoint m_rotatedDestCoords[4];

CRect m_destRect;
CRect m_oldDestRect; // destrect of the previous frame
CRect m_sourceRect;
};
90 changes: 46 additions & 44 deletions xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
Expand Up @@ -267,10 +267,11 @@ bool CLinuxRendererGL::ValidateRenderTarget()
return false;
}

bool CLinuxRendererGL::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format)
bool CLinuxRendererGL::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation)
{
m_sourceWidth = width;
m_sourceHeight = height;
m_renderOrientation = orientation;
m_fps = fps;

// Save the flags.
Expand Down Expand Up @@ -698,39 +699,39 @@ void CLinuxRendererGL::DrawBlackBars()
glBegin(GL_QUADS);

//top quad
if (m_destRect.y1 > 0.0)
if (m_rotatedDestCoords[0].y > 0.0)
{
glVertex4f(0.0, 0.0, 0.0, 1.0);
glVertex4f(g_graphicsContext.GetWidth(), 0.0, 0.0, 1.0);
glVertex4f(g_graphicsContext.GetWidth(), m_destRect.y1, 0.0, 1.0);
glVertex4f(0.0, m_destRect.y1, 0.0, 1.0);
glVertex4f(0.0, 0.0, 0.0, 1.0);
glVertex4f(g_graphicsContext.GetWidth(), 0.0, 0.0, 1.0);
glVertex4f(g_graphicsContext.GetWidth(), m_rotatedDestCoords[0].y, 0.0, 1.0);
glVertex4f(0.0, m_rotatedDestCoords[0].y, 0.0, 1.0);
}

//bottom quad
if (m_destRect.y2 < g_graphicsContext.GetHeight())
if (m_rotatedDestCoords[2].y < g_graphicsContext.GetHeight())
{
glVertex4f(0.0, m_destRect.y2, 0.0, 1.0);
glVertex4f(g_graphicsContext.GetWidth(), m_destRect.y2, 0.0, 1.0);
glVertex4f(0.0, m_rotatedDestCoords[2].y, 0.0, 1.0);
glVertex4f(g_graphicsContext.GetWidth(), m_rotatedDestCoords[2].y, 0.0, 1.0);
glVertex4f(g_graphicsContext.GetWidth(), g_graphicsContext.GetHeight(), 0.0, 1.0);
glVertex4f(0.0, g_graphicsContext.GetHeight(), 0.0, 1.0);
}

//left quad
if (m_destRect.x1 > 0.0)
if (m_rotatedDestCoords[0].x > 0.0)
{
glVertex4f(0.0, m_destRect.y1, 0.0, 1.0);
glVertex4f(m_destRect.x1, m_destRect.y1, 0.0, 1.0);
glVertex4f(m_destRect.x1, m_destRect.y2, 0.0, 1.0);
glVertex4f(0.0, m_destRect.y2, 0.0, 1.0);
glVertex4f(0.0, m_rotatedDestCoords[0].y, 0.0, 1.0);
glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0.0, 1.0);
glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[2].y, 0.0, 1.0);
glVertex4f(0.0, m_rotatedDestCoords[2].y, 0.0, 1.0);
}

//right quad
if (m_destRect.x2 < g_graphicsContext.GetWidth())
if (m_rotatedDestCoords[2].x < g_graphicsContext.GetWidth())
{
glVertex4f(m_destRect.x2, m_destRect.y1, 0.0, 1.0);
glVertex4f(g_graphicsContext.GetWidth(), m_destRect.y1, 0.0, 1.0);
glVertex4f(g_graphicsContext.GetWidth(), m_destRect.y2, 0.0, 1.0);
glVertex4f(m_destRect.x2, m_destRect.y2, 0.0, 1.0);
glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[0].y, 0.0, 1.0);
glVertex4f(g_graphicsContext.GetWidth(), m_rotatedDestCoords[0].y, 0.0, 1.0);
glVertex4f(g_graphicsContext.GetWidth(), m_rotatedDestCoords[2].y, 0.0, 1.0);
glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0.0, 1.0);
}

glEnd();
Expand Down Expand Up @@ -1258,22 +1259,22 @@ void CLinuxRendererGL::RenderSinglePass(int index, int field)
glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1);
glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y1);
glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y1);
glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f );
glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0, 1.0f );//top left

glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y1);
glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y1);
glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y1);
glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f);
glVertex4f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y, 0, 1.0f );//top right

glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y2);
glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y2);
glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y2);
glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f);
glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0, 1.0f );//bottom right

glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y2);
glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y2);
glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y2);
glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f);
glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0, 1.0f );//bottom left

glEnd();
VerifyGLState();
Expand Down Expand Up @@ -1471,16 +1472,16 @@ void CLinuxRendererGL::RenderMultiPass(int index, int field)
glBegin(GL_QUADS);

glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , 0.0f);
glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f );
glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0, 1.0f );

glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, 0.0f);
glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f);
glVertex4f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y, 0, 1.0f );

glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, imgheight);
glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f);

glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0, 1.0f );
glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , imgheight);
glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f);
glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0, 1.0f );

glEnd();

Expand Down Expand Up @@ -1548,17 +1549,17 @@ void CLinuxRendererGL::RenderVDPAU(int index, int field)
glBegin(GL_QUADS);
if (m_textureTarget==GL_TEXTURE_2D)
{
glTexCoord2f(0.0, 0.0); glVertex2f(m_destRect.x1, m_destRect.y1);
glTexCoord2f(1.0, 0.0); glVertex2f(m_destRect.x2, m_destRect.y1);
glTexCoord2f(1.0, 1.0); glVertex2f(m_destRect.x2, m_destRect.y2);
glTexCoord2f(0.0, 1.0); glVertex2f(m_destRect.x1, m_destRect.y2);
glTexCoord2f(0.0, 0.0); glVertex2f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y);
glTexCoord2f(1.0, 0.0); glVertex2f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y);
glTexCoord2f(1.0, 1.0); glVertex2f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y);
glTexCoord2f(0.0, 1.0); glVertex2f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y);
}
else
{
glTexCoord2f(m_destRect.x1, m_destRect.y1); glVertex4f(m_destRect.x1, m_destRect.y1, 0.0f, 0.0f);
glTexCoord2f(m_destRect.x2, m_destRect.y1); glVertex4f(m_destRect.x2, m_destRect.y1, 1.0f, 0.0f);
glTexCoord2f(m_destRect.x2, m_destRect.y2); glVertex4f(m_destRect.x2, m_destRect.y2, 1.0f, 1.0f);
glTexCoord2f(m_destRect.x1, m_destRect.y2); glVertex4f(m_destRect.x1, m_destRect.y2, 0.0f, 1.0f);
glTexCoord2f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y); glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0.0f, 0.0f);
glTexCoord2f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y); glVertex4f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y, 1.0f, 0.0f);
glTexCoord2f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y); glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 1.0f, 1.0f);
glTexCoord2f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y); glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0.0f, 1.0f);
}
glEnd();
VerifyGLState();
Expand Down Expand Up @@ -1637,10 +1638,10 @@ void CLinuxRendererGL::RenderVAAPI(int index, int field)
VerifyGLState();

glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2f(m_destRect.x1, m_destRect.y1);
glTexCoord2f(1.0, 0.0); glVertex2f(m_destRect.x2, m_destRect.y1);
glTexCoord2f(1.0, 1.0); glVertex2f(m_destRect.x2, m_destRect.y2);
glTexCoord2f(0.0, 1.0); glVertex2f(m_destRect.x1, m_destRect.y2);
glTexCoord2f(0.0, 0.0); glVertex2f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y);
glTexCoord2f(1.0, 0.0); glVertex2f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y);
glTexCoord2f(1.0, 1.0); glVertex2f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y);
glTexCoord2f(0.0, 1.0); glVertex2f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y);
glEnd();

VerifyGLState();
Expand Down Expand Up @@ -1676,16 +1677,16 @@ void CLinuxRendererGL::RenderSoftware(int index, int field)

glBegin(GL_QUADS);
glTexCoord2f(planes[0].rect.x1, planes[0].rect.y1);
glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f );
glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0, 1.0f );

glTexCoord2f(planes[0].rect.x2, planes[0].rect.y1);
glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f);
glVertex4f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y, 0, 1.0f);

glTexCoord2f(planes[0].rect.x2, planes[0].rect.y2);
glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f);
glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0, 1.0f);

glTexCoord2f(planes[0].rect.x1, planes[0].rect.y2);
glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f);
glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0, 1.0f);

glEnd();

Expand Down Expand Up @@ -2838,6 +2839,7 @@ void CLinuxRendererGL::ToRGBFrame(YV12Image* im, unsigned flipIndexPlane, unsign
im->width, im->height, srcFormat,
im->width, im->height, PIX_FMT_BGRA,
SWS_FAST_BILINEAR | SwScaleCPUFlags(), NULL, NULL, NULL);

uint8_t *dst[] = { m_rgbBuffer, 0, 0, 0 };
int dstStride[] = { m_sourceWidth * 4, 0, 0, 0 };
m_dllSwScale->sws_scale(m_context, src, srcStride, 0, im->height, dst, dstStride);
Expand Down
4 changes: 2 additions & 2 deletions xbmc/cores/VideoRenderers/LinuxRendererGL.h
Expand Up @@ -130,7 +130,7 @@ class CLinuxRendererGL : public CBaseRenderer
bool RenderCapture(CRenderCapture* capture);

// Player functions
virtual bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format);
virtual bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_formatl, unsigned int orientation);
virtual bool IsConfigured() { return m_bConfigured; }
virtual int GetImage(YV12Image *image, int source = AUTOSOURCE, bool readonly = false);
virtual void ReleaseImage(int source, bool preserve = false);
Expand Down Expand Up @@ -235,7 +235,7 @@ class CLinuxRendererGL : public CBaseRenderer
unsigned short m_renderMethod;
RenderQuality m_renderQuality;
unsigned int m_flipindex; // just a counter to keep track of if a image has been uploaded

// Raw data used by renderer
int m_currentField;
int m_reloadShaders;
Expand Down

0 comments on commit 048cd71

Please sign in to comment.