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:
Thomas Goyne 2010-01-24 19:05:20 +00:00
parent ba088237d7
commit 7ffc3d4080
5 changed files with 93 additions and 86 deletions

View file

@ -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);
}

View file

@ -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")

View file

@ -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

View file

@ -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() {

View file

@ -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