mirror of https://github.com/odrling/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
|
@ -145,6 +145,7 @@ void OpenGLText::DoPrint(wxString text,int x,int y) {
|
|||
DrawString(text,x,y);
|
||||
|
||||
// Disable blend
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
|
|
|
@ -240,7 +240,7 @@ void VideoDisplay::SetFrameRange(int from, int to) {
|
|||
/// @brief Render the currently visible frame
|
||||
void VideoDisplay::Render() try {
|
||||
if (!IsShownOnScreen()) return;
|
||||
if (!wxIsMainThread()) throw _T("Error: trying to render from non-primary thread");
|
||||
wxASSERT(wxIsMainThread());
|
||||
|
||||
VideoContext *context = VideoContext::Get();
|
||||
wxASSERT(context);
|
||||
|
@ -260,14 +260,6 @@ void VideoDisplay::Render() try {
|
|||
wxASSERT(pw > 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
|
||||
dx1 = 0;
|
||||
dy1 = 0;
|
||||
|
@ -293,21 +285,7 @@ void VideoDisplay::Render() try {
|
|||
}
|
||||
}
|
||||
|
||||
// Set viewport
|
||||
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->SetViewport(dx1, dy1, dx2, dy2);
|
||||
videoOut->Render(sw, sh);
|
||||
|
||||
DrawTVEffects();
|
||||
|
@ -325,13 +303,6 @@ catch (const VideoOutException &err) {
|
|||
err.GetMessage().c_str());
|
||||
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 (...) {
|
||||
wxLogError(
|
||||
_T("An error occurred trying to render the video frame to screen.\n")
|
||||
|
|
|
@ -70,17 +70,15 @@ private:
|
|||
/// The height of the display
|
||||
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.
|
||||
int dx1;
|
||||
/// The x-coordinate of the bottom right of the area containing video.
|
||||
/// Always equal to the width of the video unless the display is detatched and is wider than the video.
|
||||
/// The width of the screen area containing video
|
||||
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.
|
||||
int dy1;
|
||||
/// The y-coordinate of the bottom of the area containing video.
|
||||
/// Always equal to the height of the video unless the display is detatched and is taller than the video.
|
||||
/// The height of the screen area containing video
|
||||
int dy2;
|
||||
|
||||
/// The x position of the mouse
|
||||
|
|
|
@ -70,18 +70,30 @@ struct VideoOutGL::TextureInfo {
|
|||
int sourceH;
|
||||
int sourceW;
|
||||
|
||||
int textureH;
|
||||
int textureW;
|
||||
|
||||
float destH;
|
||||
float destW;
|
||||
float destX;
|
||||
float destY;
|
||||
float destX1;
|
||||
float destY1;
|
||||
float destX2;
|
||||
float destY2;
|
||||
|
||||
float texTop;
|
||||
float texBottom;
|
||||
float texLeft;
|
||||
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
|
||||
|
@ -152,6 +164,10 @@ void VideoOutGL::DetectOpenGLCapabilities() {
|
|||
void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp, bool flipped) {
|
||||
// Do nothing if the frame size and format are unchanged
|
||||
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);
|
||||
|
||||
DetectOpenGLCapabilities();
|
||||
|
@ -172,10 +188,10 @@ void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp, boo
|
|||
|
||||
// Calculate the position information for each texture
|
||||
int sourceY = 0;
|
||||
float destY = 0.0f;
|
||||
float destY = -1.0f;
|
||||
for (int i = 0; i < textureRows; i++) {
|
||||
int sourceX = 0;
|
||||
float destX = 0.0f;
|
||||
float destX = -1.0f;
|
||||
|
||||
int sourceH = maxTextureSize;
|
||||
int textureH = maxTextureSize;
|
||||
|
@ -184,13 +200,15 @@ void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp, boo
|
|||
sourceH = height % maxTextureSize;
|
||||
textureH = SmallestPowerOf2(sourceH);
|
||||
}
|
||||
|
||||
for (int j = 0; j < textureCols; j++) {
|
||||
TextureInfo& ti = textureList[i * textureCols + j];
|
||||
|
||||
// Copy the current position information into the struct
|
||||
ti.destX = destX;
|
||||
ti.destY = destY;
|
||||
ti.destX1 = destX;
|
||||
ti.destY1 = destY;
|
||||
ti.sourceH = sourceH;
|
||||
ti.textureID = textureIdList[i * textureCols + j];
|
||||
|
||||
ti.sourceW = maxTextureSize;
|
||||
int textureW = maxTextureSize;
|
||||
|
@ -204,54 +222,49 @@ void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp, boo
|
|||
int h = textureH;
|
||||
if (!supportsRectangularTextures) w = h = MAX(w, h);
|
||||
|
||||
if (supportsGlClampToEdge) {
|
||||
ti.texLeft = 0.0f;
|
||||
ti.texTop = 0.0f;
|
||||
}
|
||||
else {
|
||||
CreateTexture(w, h, ti, format);
|
||||
|
||||
if (!supportsGlClampToEdge) {
|
||||
// Stretch the texture a half pixel in each direction to eliminate the border
|
||||
ti.texLeft = 1.0f / (2 * w);
|
||||
ti.texTop = 1.0f / (2 * h);
|
||||
}
|
||||
|
||||
ti.destW = float(w) / width;
|
||||
ti.destH = float(h) / height;
|
||||
|
||||
ti.textureID = textureIdList[i * textureCols + j];
|
||||
ti.dataOffset = sourceY * width * bpp + sourceX * bpp;
|
||||
ti.destX2 = ti.destX1 + w * 2.0f / width;
|
||||
ti.destY2 = ti.destY1 + h * 2.0f / height;
|
||||
|
||||
ti.texRight = 1.0f - ti.texLeft;
|
||||
ti.texBottom = 1.0f - ti.texTop;
|
||||
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.texTop = 1.0f - ti.texTop - float(h - ti.sourceH) / h;
|
||||
|
||||
ti.dataOffset = (height - sourceY - ti.sourceH) * width * bpp + sourceX * bpp;
|
||||
}
|
||||
|
||||
// Actually create the texture and set the scaling mode
|
||||
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;
|
||||
destX = ti.destX2;
|
||||
sourceX += ti.sourceW;
|
||||
}
|
||||
destY += float(sourceH) / height;
|
||||
destY += sourceH * 2.0f / height;
|
||||
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) {
|
||||
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));
|
||||
}
|
||||
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) {
|
||||
// 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));
|
||||
|
||||
for (unsigned i = 0; i < textureList.size(); 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(glColor4f(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(ti.texLeft, ti.texTop); glVertex2f(destX, destY);
|
||||
glTexCoord2f(ti.texRight, ti.texTop); glVertex2f(destX + destW, destY);
|
||||
glTexCoord2f(ti.texRight, ti.texBottom); glVertex2f(destX + destW, destY + destH);
|
||||
glTexCoord2f(ti.texLeft, ti.texBottom); glVertex2f(destX, destY + destH);
|
||||
glTexCoord2f(ti.texLeft, ti.texTop); glVertex2f(ti.destX1, ti.destY1);
|
||||
glTexCoord2f(ti.texRight, ti.texTop); glVertex2f(ti.destX2, ti.destY1);
|
||||
glTexCoord2f(ti.texRight, ti.texBottom); glVertex2f(ti.destX2, ti.destY2);
|
||||
glTexCoord2f(ti.texLeft, ti.texBottom); glVertex2f(ti.destX1, ti.destY2);
|
||||
glEnd();
|
||||
if (GLenum err = glGetError()) throw VideoOutRenderException(L"GL_QUADS", err);
|
||||
}
|
||||
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() {
|
||||
|
|
|
@ -78,13 +78,22 @@ private:
|
|||
|
||||
void DetectOpenGLCapabilities();
|
||||
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& operator=(const VideoOutGL&);
|
||||
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
|
||||
/// @param frame The frame to be displayed
|
||||
void UploadFrameData(const AegiVideoFrame& frame);
|
||||
|
||||
/// @brief Render a frame
|
||||
/// @param sw The current script width
|
||||
/// @param sh The current script height
|
||||
|
|
Loading…
Reference in New Issue