forked from mia/Aegisub
Move more of the purely OpenGL-related code into VideoOutGL from VideoDisplay and simplify the calculation of the texture grid positions slightly.
Originally committed to SVN as r4037.
This commit is contained in:
parent
ba088237d7
commit
7ffc3d4080
5 changed files with 93 additions and 86 deletions
|
@ -145,6 +145,7 @@ void OpenGLText::DoPrint(wxString text,int x,int y) {
|
||||||
DrawString(text,x,y);
|
DrawString(text,x,y);
|
||||||
|
|
||||||
// Disable blend
|
// Disable blend
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,7 +240,7 @@ void VideoDisplay::SetFrameRange(int from, int to) {
|
||||||
/// @brief Render the currently visible frame
|
/// @brief Render the currently visible frame
|
||||||
void VideoDisplay::Render() try {
|
void VideoDisplay::Render() try {
|
||||||
if (!IsShownOnScreen()) return;
|
if (!IsShownOnScreen()) return;
|
||||||
if (!wxIsMainThread()) throw _T("Error: trying to render from non-primary thread");
|
wxASSERT(wxIsMainThread());
|
||||||
|
|
||||||
VideoContext *context = VideoContext::Get();
|
VideoContext *context = VideoContext::Get();
|
||||||
wxASSERT(context);
|
wxASSERT(context);
|
||||||
|
@ -260,14 +260,6 @@ void VideoDisplay::Render() try {
|
||||||
wxASSERT(pw > 0);
|
wxASSERT(pw > 0);
|
||||||
wxASSERT(ph > 0);
|
wxASSERT(ph > 0);
|
||||||
|
|
||||||
// Clear frame buffer
|
|
||||||
glClearColor(0,0,0,0);
|
|
||||||
if (glGetError()) throw _T("Error setting glClearColor().");
|
|
||||||
glClearStencil(0);
|
|
||||||
if (glGetError()) throw _T("Error setting glClearStencil().");
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
||||||
if (glGetError()) throw _T("Error calling glClear().");
|
|
||||||
|
|
||||||
// Freesized transform
|
// Freesized transform
|
||||||
dx1 = 0;
|
dx1 = 0;
|
||||||
dy1 = 0;
|
dy1 = 0;
|
||||||
|
@ -293,21 +285,7 @@ void VideoDisplay::Render() try {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set viewport
|
videoOut->SetViewport(dx1, dy1, dx2, dy2);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glLoadIdentity();
|
|
||||||
glViewport(dx1,dy1,dx2,dy2);
|
|
||||||
if (glGetError()) throw _T("Error setting GL viewport.");
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadIdentity();
|
|
||||||
glOrtho(0.0f,sw,sh,0.0f,-1000.0f,1000.0f);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
if (glGetError()) throw _T("Error setting up matrices (wtf?).");
|
|
||||||
glShadeModel(GL_FLAT);
|
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
if (glGetError()) throw _T("Error disabling blending.");
|
|
||||||
|
|
||||||
videoOut->Render(sw, sh);
|
videoOut->Render(sw, sh);
|
||||||
|
|
||||||
DrawTVEffects();
|
DrawTVEffects();
|
||||||
|
@ -325,13 +303,6 @@ catch (const VideoOutException &err) {
|
||||||
err.GetMessage().c_str());
|
err.GetMessage().c_str());
|
||||||
VideoContext::Get()->Reset();
|
VideoContext::Get()->Reset();
|
||||||
}
|
}
|
||||||
catch (const wxChar *err) {
|
|
||||||
wxLogError(
|
|
||||||
_T("An error occurred trying to render the video frame to screen.\n")
|
|
||||||
_T("Error message reported: %s"),
|
|
||||||
err);
|
|
||||||
VideoContext::Get()->Reset();
|
|
||||||
}
|
|
||||||
catch (...) {
|
catch (...) {
|
||||||
wxLogError(
|
wxLogError(
|
||||||
_T("An error occurred trying to render the video frame to screen.\n")
|
_T("An error occurred trying to render the video frame to screen.\n")
|
||||||
|
|
|
@ -70,17 +70,15 @@ private:
|
||||||
/// The height of the display
|
/// The height of the display
|
||||||
int h;
|
int h;
|
||||||
|
|
||||||
/// The x-coordinate of the top left of the area containing video.
|
/// The x-coordinate of the bottom left of the area containing video.
|
||||||
/// Always zero unless the display is detatched and is wider than the video.
|
/// Always zero unless the display is detatched and is wider than the video.
|
||||||
int dx1;
|
int dx1;
|
||||||
/// The x-coordinate of the bottom right of the area containing video.
|
/// The width of the screen area containing video
|
||||||
/// Always equal to the width of the video unless the display is detatched and is wider than the video.
|
|
||||||
int dx2;
|
int dx2;
|
||||||
/// The y-coordinate of the top left of the area containing video.
|
/// The y-coordinate of the bottom left of the area containing video.
|
||||||
/// Always zero unless the display is detatched and is taller than the video.
|
/// Always zero unless the display is detatched and is taller than the video.
|
||||||
int dy1;
|
int dy1;
|
||||||
/// The y-coordinate of the bottom of the area containing video.
|
/// The height of the screen area containing video
|
||||||
/// Always equal to the height of the video unless the display is detatched and is taller than the video.
|
|
||||||
int dy2;
|
int dy2;
|
||||||
|
|
||||||
/// The x position of the mouse
|
/// The x position of the mouse
|
||||||
|
|
|
@ -70,18 +70,30 @@ struct VideoOutGL::TextureInfo {
|
||||||
int sourceH;
|
int sourceH;
|
||||||
int sourceW;
|
int sourceW;
|
||||||
|
|
||||||
int textureH;
|
float destX1;
|
||||||
int textureW;
|
float destY1;
|
||||||
|
float destX2;
|
||||||
float destH;
|
float destY2;
|
||||||
float destW;
|
|
||||||
float destX;
|
|
||||||
float destY;
|
|
||||||
|
|
||||||
float texTop;
|
float texTop;
|
||||||
float texBottom;
|
float texBottom;
|
||||||
float texLeft;
|
float texLeft;
|
||||||
float texRight;
|
float texRight;
|
||||||
|
|
||||||
|
TextureInfo()
|
||||||
|
: textureID(0)
|
||||||
|
, dataOffset(0)
|
||||||
|
, sourceH(0)
|
||||||
|
, sourceW(0)
|
||||||
|
, destX1(0)
|
||||||
|
, destY1(0)
|
||||||
|
, destX2(0)
|
||||||
|
, destY2(0)
|
||||||
|
, texTop(0)
|
||||||
|
, texBottom(1.0f)
|
||||||
|
, texLeft(0)
|
||||||
|
, texRight(1.0f)
|
||||||
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Test if a texture can be created
|
/// @brief Test if a texture can be created
|
||||||
|
@ -152,6 +164,10 @@ void VideoOutGL::DetectOpenGLCapabilities() {
|
||||||
void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp, bool flipped) {
|
void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp, bool flipped) {
|
||||||
// Do nothing if the frame size and format are unchanged
|
// Do nothing if the frame size and format are unchanged
|
||||||
if (width == frameWidth && height == frameHeight && format == frameFormat && flipped == frameFlipped) return;
|
if (width == frameWidth && height == frameHeight && format == frameFormat && flipped == frameFlipped) return;
|
||||||
|
frameWidth = width;
|
||||||
|
frameHeight = height;
|
||||||
|
frameFormat = format;
|
||||||
|
frameFlipped = flipped;
|
||||||
wxLogDebug("VideoOutGL::InitTextures: Video size: %dx%d\n", width, height);
|
wxLogDebug("VideoOutGL::InitTextures: Video size: %dx%d\n", width, height);
|
||||||
|
|
||||||
DetectOpenGLCapabilities();
|
DetectOpenGLCapabilities();
|
||||||
|
@ -172,10 +188,10 @@ void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp, boo
|
||||||
|
|
||||||
// Calculate the position information for each texture
|
// Calculate the position information for each texture
|
||||||
int sourceY = 0;
|
int sourceY = 0;
|
||||||
float destY = 0.0f;
|
float destY = -1.0f;
|
||||||
for (int i = 0; i < textureRows; i++) {
|
for (int i = 0; i < textureRows; i++) {
|
||||||
int sourceX = 0;
|
int sourceX = 0;
|
||||||
float destX = 0.0f;
|
float destX = -1.0f;
|
||||||
|
|
||||||
int sourceH = maxTextureSize;
|
int sourceH = maxTextureSize;
|
||||||
int textureH = maxTextureSize;
|
int textureH = maxTextureSize;
|
||||||
|
@ -184,13 +200,15 @@ void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp, boo
|
||||||
sourceH = height % maxTextureSize;
|
sourceH = height % maxTextureSize;
|
||||||
textureH = SmallestPowerOf2(sourceH);
|
textureH = SmallestPowerOf2(sourceH);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < textureCols; j++) {
|
for (int j = 0; j < textureCols; j++) {
|
||||||
TextureInfo& ti = textureList[i * textureCols + j];
|
TextureInfo& ti = textureList[i * textureCols + j];
|
||||||
|
|
||||||
// Copy the current position information into the struct
|
// Copy the current position information into the struct
|
||||||
ti.destX = destX;
|
ti.destX1 = destX;
|
||||||
ti.destY = destY;
|
ti.destY1 = destY;
|
||||||
ti.sourceH = sourceH;
|
ti.sourceH = sourceH;
|
||||||
|
ti.textureID = textureIdList[i * textureCols + j];
|
||||||
|
|
||||||
ti.sourceW = maxTextureSize;
|
ti.sourceW = maxTextureSize;
|
||||||
int textureW = maxTextureSize;
|
int textureW = maxTextureSize;
|
||||||
|
@ -204,54 +222,49 @@ void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp, boo
|
||||||
int h = textureH;
|
int h = textureH;
|
||||||
if (!supportsRectangularTextures) w = h = MAX(w, h);
|
if (!supportsRectangularTextures) w = h = MAX(w, h);
|
||||||
|
|
||||||
if (supportsGlClampToEdge) {
|
CreateTexture(w, h, ti, format);
|
||||||
ti.texLeft = 0.0f;
|
|
||||||
ti.texTop = 0.0f;
|
if (!supportsGlClampToEdge) {
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Stretch the texture a half pixel in each direction to eliminate the border
|
// Stretch the texture a half pixel in each direction to eliminate the border
|
||||||
ti.texLeft = 1.0f / (2 * w);
|
ti.texLeft = 1.0f / (2 * w);
|
||||||
ti.texTop = 1.0f / (2 * h);
|
ti.texTop = 1.0f / (2 * h);
|
||||||
}
|
}
|
||||||
|
|
||||||
ti.destW = float(w) / width;
|
ti.destX2 = ti.destX1 + w * 2.0f / width;
|
||||||
ti.destH = float(h) / height;
|
ti.destY2 = ti.destY1 + h * 2.0f / height;
|
||||||
|
|
||||||
ti.textureID = textureIdList[i * textureCols + j];
|
|
||||||
ti.dataOffset = sourceY * width * bpp + sourceX * bpp;
|
|
||||||
|
|
||||||
ti.texRight = 1.0f - ti.texLeft;
|
ti.texRight = 1.0f - ti.texLeft;
|
||||||
ti.texBottom = 1.0f - ti.texTop;
|
|
||||||
if (flipped) {
|
if (flipped) {
|
||||||
|
ti.texBottom = 1.0f - ti.texTop;
|
||||||
|
ti.dataOffset = sourceY * width * bpp + sourceX * bpp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
ti.texBottom = ti.texTop - float(h - ti.sourceH) / h;
|
ti.texBottom = ti.texTop - float(h - ti.sourceH) / h;
|
||||||
ti.texTop = 1.0f - ti.texTop - float(h - ti.sourceH) / h;
|
ti.texTop = 1.0f - ti.texTop - float(h - ti.sourceH) / h;
|
||||||
|
|
||||||
ti.dataOffset = (height - sourceY - ti.sourceH) * width * bpp + sourceX * bpp;
|
ti.dataOffset = (height - sourceY - ti.sourceH) * width * bpp + sourceX * bpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually create the texture and set the scaling mode
|
destX = ti.destX2;
|
||||||
CHECK_INIT_ERROR(glBindTexture(GL_TEXTURE_2D, ti.textureID));
|
|
||||||
CHECK_INIT_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, format, GL_UNSIGNED_BYTE, NULL));
|
|
||||||
wxLogDebug("VideoOutGL::InitTextures: Using texture size: %dx%d\n", w, h);
|
|
||||||
CHECK_INIT_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
|
||||||
CHECK_INIT_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
|
||||||
|
|
||||||
GLint mode = supportsGlClampToEdge ? GL_CLAMP_TO_EDGE : GL_CLAMP;
|
|
||||||
CHECK_INIT_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode));
|
|
||||||
CHECK_INIT_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode));
|
|
||||||
|
|
||||||
destX += ti.destW;
|
|
||||||
sourceX += ti.sourceW;
|
sourceX += ti.sourceW;
|
||||||
}
|
}
|
||||||
destY += float(sourceH) / height;
|
destY += sourceH * 2.0f / height;
|
||||||
sourceY += sourceH;
|
sourceY += sourceH;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the information needed to know when the grid must be recreated
|
|
||||||
frameWidth = width;
|
|
||||||
frameHeight = height;
|
|
||||||
frameFormat = format;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoOutGL::CreateTexture(int w, int h, const TextureInfo& ti, GLenum format) {
|
||||||
|
CHECK_INIT_ERROR(glBindTexture(GL_TEXTURE_2D, ti.textureID));
|
||||||
|
CHECK_INIT_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, format, GL_UNSIGNED_BYTE, NULL));
|
||||||
|
wxLogDebug("VideoOutGL::InitTextures: Using texture size: %dx%d\n", w, h);
|
||||||
|
CHECK_INIT_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
CHECK_INIT_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
|
||||||
|
GLint mode = supportsGlClampToEdge ? GL_CLAMP_TO_EDGE : GL_CLAMP;
|
||||||
|
CHECK_INIT_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode));
|
||||||
|
CHECK_INIT_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode));
|
||||||
|
}
|
||||||
|
|
||||||
void VideoOutGL::UploadFrameData(const AegiVideoFrame& frame) {
|
void VideoOutGL::UploadFrameData(const AegiVideoFrame& frame) {
|
||||||
if (frame.h == 0 || frame.w == 0) return;
|
if (frame.h == 0 || frame.w == 0) return;
|
||||||
|
|
||||||
|
@ -271,30 +284,45 @@ void VideoOutGL::UploadFrameData(const AegiVideoFrame& frame) {
|
||||||
|
|
||||||
CHECK_ERROR(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
CHECK_ERROR(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||||
}
|
}
|
||||||
|
void VideoOutGL::SetViewport(int x, int y, int width, int height) {
|
||||||
|
CHECK_ERROR(glViewport(x, y, width, height));
|
||||||
|
}
|
||||||
|
|
||||||
void VideoOutGL::Render(int sw, int sh) {
|
void VideoOutGL::Render(int sw, int sh) {
|
||||||
|
// Clear the frame buffer
|
||||||
|
CHECK_ERROR(glClearColor(0,0,0,0));
|
||||||
|
CHECK_ERROR(glClearStencil(0));
|
||||||
|
CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
|
||||||
|
|
||||||
|
|
||||||
|
CHECK_ERROR(glShadeModel(GL_FLAT));
|
||||||
|
CHECK_ERROR(glDisable(GL_BLEND));
|
||||||
|
|
||||||
|
CHECK_ERROR(glMatrixMode(GL_PROJECTION));
|
||||||
|
CHECK_ERROR(glLoadIdentity());
|
||||||
|
|
||||||
|
// Render the current frame
|
||||||
CHECK_ERROR(glEnable(GL_TEXTURE_2D));
|
CHECK_ERROR(glEnable(GL_TEXTURE_2D));
|
||||||
|
|
||||||
for (unsigned i = 0; i < textureList.size(); i++) {
|
for (unsigned i = 0; i < textureList.size(); i++) {
|
||||||
TextureInfo& ti = textureList[i];
|
TextureInfo& ti = textureList[i];
|
||||||
|
|
||||||
float destX = ti.destX * sw;
|
|
||||||
float destW = ti.destW * sw;
|
|
||||||
float destY = ti.destY * sh;
|
|
||||||
float destH = ti.destH * sh;
|
|
||||||
|
|
||||||
CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, ti.textureID));
|
CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, ti.textureID));
|
||||||
CHECK_ERROR(glColor4f(1.0f, 1.0f, 1.0f, 1.0f));
|
CHECK_ERROR(glColor4f(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glTexCoord2f(ti.texLeft, ti.texTop); glVertex2f(destX, destY);
|
glTexCoord2f(ti.texLeft, ti.texTop); glVertex2f(ti.destX1, ti.destY1);
|
||||||
glTexCoord2f(ti.texRight, ti.texTop); glVertex2f(destX + destW, destY);
|
glTexCoord2f(ti.texRight, ti.texTop); glVertex2f(ti.destX2, ti.destY1);
|
||||||
glTexCoord2f(ti.texRight, ti.texBottom); glVertex2f(destX + destW, destY + destH);
|
glTexCoord2f(ti.texRight, ti.texBottom); glVertex2f(ti.destX2, ti.destY2);
|
||||||
glTexCoord2f(ti.texLeft, ti.texBottom); glVertex2f(destX, destY + destH);
|
glTexCoord2f(ti.texLeft, ti.texBottom); glVertex2f(ti.destX1, ti.destY2);
|
||||||
glEnd();
|
glEnd();
|
||||||
if (GLenum err = glGetError()) throw VideoOutRenderException(L"GL_QUADS", err);
|
if (GLenum err = glGetError()) throw VideoOutRenderException(L"GL_QUADS", err);
|
||||||
}
|
}
|
||||||
CHECK_ERROR(glDisable(GL_TEXTURE_2D));
|
CHECK_ERROR(glDisable(GL_TEXTURE_2D));
|
||||||
|
|
||||||
|
CHECK_ERROR(glOrtho(0.0f, sw, sh, 0.0f, -1000.0f, 1000.0f));
|
||||||
|
CHECK_ERROR(glMatrixMode(GL_MODELVIEW));
|
||||||
|
CHECK_ERROR(glLoadIdentity());
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoOutGL::~VideoOutGL() {
|
VideoOutGL::~VideoOutGL() {
|
||||||
|
|
|
@ -78,13 +78,22 @@ private:
|
||||||
|
|
||||||
void DetectOpenGLCapabilities();
|
void DetectOpenGLCapabilities();
|
||||||
void InitTextures(int width, int height, GLenum format, int bpp, bool flipped);
|
void InitTextures(int width, int height, GLenum format, int bpp, bool flipped);
|
||||||
|
void CreateTexture(int w, int h, const TextureInfo& ti, GLenum format);
|
||||||
|
|
||||||
VideoOutGL(const VideoOutGL &);
|
VideoOutGL(const VideoOutGL &);
|
||||||
VideoOutGL& operator=(const VideoOutGL&);
|
VideoOutGL& operator=(const VideoOutGL&);
|
||||||
public:
|
public:
|
||||||
|
/// @brief Set the viewport
|
||||||
|
/// @param x Bottom left x coordinate
|
||||||
|
/// @param y Bottom left y coordinate
|
||||||
|
/// @param width Width in pixels of viewport
|
||||||
|
/// @param height Height in pixels of viewport
|
||||||
|
void SetViewport(int x, int y, int width, int height);
|
||||||
|
|
||||||
/// @brief Set the frame to be displayed when Render() is called
|
/// @brief Set the frame to be displayed when Render() is called
|
||||||
/// @param frame The frame to be displayed
|
/// @param frame The frame to be displayed
|
||||||
void UploadFrameData(const AegiVideoFrame& frame);
|
void UploadFrameData(const AegiVideoFrame& frame);
|
||||||
|
|
||||||
/// @brief Render a frame
|
/// @brief Render a frame
|
||||||
/// @param sw The current script width
|
/// @param sw The current script width
|
||||||
/// @param sh The current script height
|
/// @param sh The current script height
|
||||||
|
|
Loading…
Reference in a new issue