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); DrawString(text,x,y);
// Disable blend // Disable blend
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }

View File

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

View File

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

View File

@ -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,32 +222,38 @@ 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;
sourceX += ti.sourceW;
}
destY += sourceH * 2.0f / height;
sourceY += sourceH;
}
}
void VideoOutGL::CreateTexture(int w, int h, const TextureInfo& ti, GLenum format) {
CHECK_INIT_ERROR(glBindTexture(GL_TEXTURE_2D, ti.textureID)); 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)); 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); wxLogDebug("VideoOutGL::InitTextures: Using texture size: %dx%d\n", w, h);
@ -239,19 +263,8 @@ void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp, boo
GLint mode = supportsGlClampToEdge ? GL_CLAMP_TO_EDGE : GL_CLAMP; 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_S, mode));
CHECK_INIT_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode)); CHECK_INIT_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode));
destX += ti.destW;
sourceX += ti.sourceW;
}
destY += float(sourceH) / height;
sourceY += sourceH;
} }
// Store the information needed to know when the grid must be recreated
frameWidth = width;
frameHeight = height;
frameFormat = format;
}
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() {

View File

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